/* * * http.c - part of Danovitsch Webcam * * Copyright (C) 2001 by Daan Vreeken * * Published under the terms of the GNU Public License 2.0 * (or any later version) * */ #include #include #include #include #include "general.h" #include "webcam.h" #include "io.h" #include "capture.h" #include "compress.h" #include "server.h" #include "http.h" char *HTTP_GetPostData(struct Connection *C, char *Name) { int Len = strlen(Name); char *Ptr = C->PostData; char *Ptr2; char *MaxPtr = C->PostData + C->PostLength; char *Arr; int Result; while ((Ptr
\n"); Print(C,"\n"); Print(C," \n"); while (Arr->ID!=NoID) { Print (C," \n"); PrintF(C," \n",Arr->Name); Print (C," \n"); if (Arr->Type==Type_Number) { PrintF(C," \n",Arr->MinVal,Arr->MaxVal); } else { Print(C," \n"); } Print (C," \n"); Arr++; } Print(C,"
NameValueRange
%s\n"); Print (C,"
\n"); switch (Arr->Type) { case Type_Number: PrintF(C," \n",Arr->Name); PrintF(C," \n",Arr->NumValue); PrintF(C," \n"); break; case Type_Text: PrintF(C," \n",Arr->Name); PrintF(C," \n"); PrintF(C," \n"); break; } PrintF(C,"
\n"); PrintF(C,"
%d - %dN/A
\n"); Print(C,"

Moo,
]:8)
\n"); } void HTTP_SpitoutFooter(struct Connection *C) { Print(C,"
\n"); Print(C,"Return to the main page...
\n"); Print(C,"


\n"); Print(C,"\n"); Print(C,"\n"); } void HTTP_FileSettings(struct Connection *C, char *FileName) { char *Setting; char *TxtValue; char *RedirectValue; int NumValue; struct Capture_SettingsArr *Arr = &Capture_Settings[0]; //try to set the settings... Setting=HTTP_GetPostData(C,"Setting="); TxtValue=HTTP_GetPostData(C,"Value="); RedirectValue=HTTP_GetPostData(C,"Redirect="); //spitout header Print(C,"\n"); if (RedirectValue!=NULL) { // This could be used to set a setting and then immediately redirect to another URL // simply add a hidden input field named 'Redirect' with the URL as it's value // Print(C,"\n"); free(RedirectValue); } Print(C,"\n"); Print(C,"

Settings interface


\n"); Print(C,"

\n"); //check for missing stuff... if ((Setting==NULL) || (TxtValue==NULL)) { //Hmmm... no setting to set, let's spit out a list of settings... if (Setting!=NULL) free(Setting); if (TxtValue!=NULL) free(TxtValue); HTTP_SpitoutSettings(C); HTTP_SpitoutFooter(C); return; } //just try to convert to a number sscanf(TxtValue,"%d",&NumValue); //lookup the setting while ((Arr->ID!=NoID) && (strcasecmp(Arr->Name,Setting))) Arr++; //try setting it... if (Arr->ID!=NoID) { PrintF(C,"Trying to set '%s' to '%s'...
\n",Setting,TxtValue); if (Capture_Set(Arr,Setting,NumValue,TxtValue)) Print(C," OK.
\n"); else Print(C," failed!
\n"); } else { Print(C,"Unknown setting!
\n"); Print(C,Setting); Print(C,"
\n"); } //list all settings HTTP_SpitoutSettings(C); //page footer HTTP_SpitoutFooter(C); free(Setting); free(TxtValue); } void HTTP_FileStats(struct Connection *C, char *FileName) { int Cnt; int State; struct Capture_SettingsArr *Setting = &Capture_Settings[0]; Debug(40,"Spitting out some stats..."); //page header Print(C," Stats page\n"); Print(C,"\n\n"); //stats info PrintF(C,"Server name : %s\n",Server_String); Print(C,"\n"); PrintF(C,"Active connections : %d\n",Clients); Print(C,"\n"); //connection state(s) Print(C,"Connection state(s) :\n"); for (Cnt=0; CntID!=NoID) { PrintF(C," %-20s: ",(char *)Setting->Name); switch (Setting->Type) { case Type_Number: PrintF(C,"%d",Setting->NumValue); break; case Type_Text: PrintF(C,Setting->TxtValue); break; default: Print(C,"Hugh?"); } Print(C,"\n"); Setting++; } Print(C,"\n"); //page footer Print(C,"Moo,\n]:8)\n"); } void HTTP_FileWebcam(struct Connection *C, char *FileName) { char *Ptr; int Position = 0; int Size = JPEGSize; Error("Someone wants an image\x07"); //Should we fetch a new image? if (TooOld(&JPEGTime,JPEGTimeout)) { Debug(120,"Creating new JPEG image..."); Compress_CreateJPEG(); Size=JPEGSize; gettimeofday(&JPEGTime,NULL); } Debug(90,"Sending: %d bytes",Size); //Dump image... Ptr=JPEGBuffer; if (JPEGBuffer!=NULL) while (Size>0) { if (Size>1000) Size-=SockSend(C,Ptr,1000); else Size-=SockSend(C,Ptr,Size); Ptr+=1000; } //let's count this one (unless it's /live/nocount.jpg) if (strcmp(FileName,"/live/nocount.jpg")) ImagesServed++; CountedImages++; ImagesSinceRestart++; } void HTTP_FileRoot (struct Connection *C, char *FileName) { Print (C,"\n"); PrintF(C,"\n"); PrintF(C," %d\n",Server_String); PrintF(C," \n",PageReloadInterval); Print (C,"\n"); Print (C,"\n"); PrintF(C,"

%s


\n",Server_String); Print (C,"

\n"); Print (C,"Live image
\n"); Print (C,"


\n"); Print (C,"\n"); Print (C,"\n"); } struct HTTP_ResponseArr HTTP_Responses[] = { {200,"HTTP/1.1 200 OK",0,""}, {404,"HTTP/1.1 404 File not found",1,"Error:
File not found"}, {501,"HTTP/1.1 501 Method Not Implemented",1,"Error:
Method not implemented"}, {0,"",0,""}}; struct HTTP_FileArr HTTP_Files[] = { {"/","text/html",&HTTP_FileRoot}, {"/live/webcam.jpg","image/jpeg",&HTTP_FileWebcam}, {"/live/nocount.jpg","image/jpeg",&HTTP_FileWebcam}, // /// /live/nocount.jpg gives exactly the same output as /live/webcam.jpg, // but the image-counter isn't updated... // {"/cgi-bin/stats","text/plain",&HTTP_FileStats}, {"/cgi-bin/settings","text/html",&HTTP_FileSettings}, {NULL,NULL,NULL}}; void HTTP_Header(struct Connection *C, int Code, char *ContentType) { struct HTTP_ResponseArr *Response = &HTTP_Responses[0]; //search for the header code while ((Response->Code!=Code) && (Response->Code!=0)) Response++; if (Response->Code==0) { Error("HUGH?! Got wrong HTTP code (%d)",Code); return; } ///Spitout the header PrintF(C,"%s\n",Response->Header); //Server strings... PrintF(C,"Server: %s\n",Server_String); Print(C,"Cache-Control: no-cache\n"); Print(C,"Connection: close\n"); Print(C,"Pragma: no-cache\n"); //Spitout content-type? if (ContentType!=NULL) PrintF(C,"Content-type: %s\n",ContentType); //Spitout an error document? if (Response->IsError) { Error("HTTP error: %s",Response->Header); Print(C,"Content-type: text/html\n"); Print(C,"\n"); Print(C,Response->ErrorDocument); return; } Print(C,"\n"); } void HTTP_Response(struct Connection *C) { char URLPart[8]; char *FileName; struct HTTP_FileArr *File = &HTTP_Files[0]; //cut off the 'http://foo.bar' piece (if it's there) strncpy((char *)&URLPart,C->RequestArg[1],8); URLPart[7]=0; if (!strcasecmp((char *)&URLPart,"http://")) { if (index(C->RequestArg[1]+8,'/')==NULL) { HTTP_Header(C,404,NULL); return; } else FileName=index(C->RequestArg[1]+8,'/'); } else FileName=C->RequestArg[1]; //little hack to cut off question marks '?' behind a filename... if (index(FileName,'?')!=NULL) *index(FileName,'?')=0; Debug(60,"Requested file: %s",FileName); //search for the file... while ((File->Name!=NULL) && (strcmp(File->Name,FileName))) File++; //give a 404 if we don't have it if (File->Name==NULL) { HTTP_Header(C,404,NULL); return; } Debug(50,"Request OK. sending data..."); HTTP_Header(C,200,(char *)File->ContentType); if (File->Handler!=NULL) File->Handler(C,FileName); }