static int CGIParseArgs(const char *Str, const char *Sep1, const char *Sep2, char **HashType, char **Encoding, char **LineEnding, char **Text, int *OutputLength, int *SegmentLength, char **SegmentChar, char **OptionsFile) { char *QName=NULL, *QValue=NULL, *Name=NULL, *Value=NULL; const char *ptr; int Flags=0; ptr=GetNameValuePair(Str, Sep1, Sep2, &QName, &QValue); while (ptr) { Name=HTTPUnQuote(Name,QName); Value=HTTPUnQuote(Value,QValue); if (strcasecmp(Name,"OptionsFile")==0) { Flags |= CGILoadOptionsFile(Value, HashType, Encoding, LineEnding, Text, OutputLength, SegmentLength, SegmentChar); *OptionsFile=CopyStr(*OptionsFile, Value); } if (strcasecmp(Name,"HashType")==0) *HashType=CopyStr(*HashType, Value); if (strcasecmp(Name,"PlainText")==0) { *Text=CopyStr(*Text, Value); Flags |= CGI_DOHASH; } if (strcasecmp(Name,"Encoding")==0) *Encoding=CopyStr(*Encoding, Value); if (strcasecmp(Name,"LineEnding")==0) *LineEnding=CopyStr(*LineEnding, Value); if (strcasecmp(Name,"SegmentChar")==0) *SegmentChar=CopyStr(*SegmentChar, Value); if (strcasecmp(Name,"HideText")==0) Flags |= CGI_HIDETEXT; if (strcasecmp(Name,"ShowText")==0) Flags |= CGI_SHOWTEXT; if (strcasecmp(Name,"OutputLength")==0) *OutputLength=atoi(Value); if (strcasecmp(Name,"SegmentLength")==0) *SegmentLength=atoi(Value); if (strcasecmp(Name,"NoOptions")==0) Flags |= CGI_NOOPTIONS; ptr=GetNameValuePair(ptr, Sep1, Sep2, &QName, &QValue); } if (Flags & CGI_SHOWTEXT) Flags &= ~CGI_HIDETEXT; Destroy(QName); Destroy(QValue); Destroy(Name); Destroy(Value); return(Flags); }
char *SanitizeQueryString(char *Buffer, char *Data) { char *Name=NULL, *Value=NULL, *Token=NULL, *ptr; char *RetStr=NULL; RetStr=CopyStr(Buffer,""); ptr=GetNameValuePair(Data,"&","=",&Name,&Value); while (ptr) { Token=HTTPUnQuote(Token, Value); StripTrailingWhitespace(Token); Value=SanitizeStr(Value,Token); if (RetStr && (*RetStr != '\0')) RetStr=MCatStr(RetStr,"&",Name,"=",Value,NULL); else RetStr=MCatStr(RetStr,Name,"=",Value,NULL); ptr=GetNameValuePair(ptr,"&","=",&Name,&Value); } DestroyString(Name); DestroyString(Value); DestroyString(Token); return(RetStr); }
void YouTubeFormatGetData(char *Data, char **URL, char **Code) { char *Name=NULL, *Value=NULL, *ptr; ptr=GetNameValuePair(Data,"&","=",&Name,&Value); while (ptr) { if (StrLen(Name)) { if (strcmp(Name,"sig")==0) *URL=MCatStr(*URL,"&signature=", Value, NULL); if (strcmp(Name,"url")==0) *URL=HTTPUnQuote(*URL,Value); if (strcmp(Name,"itag")==0) *Code=CopyStr(*Code,Value); } ptr=GetNameValuePair(ptr,"&","=",&Name,&Value); } DestroyString(Name); DestroyString(Value); }
char *SessionGetArgument(char *RetBuff, HTTPSession *Session, const char *ReqName) { char *Name=NULL, *Value=NULL, *RetStr=NULL, *ptr; ptr=GetNameValuePair(Session->Arguments, "&", "=", &Name, &Value); while (ptr) { if (strcasecmp(ReqName,Name)==0) { RetStr=HTTPUnQuote(RetBuff,Value); break; } ptr=GetNameValuePair(ptr, "&", "=", &Name, &Value); } DestroyString(Name); DestroyString(Value); return(RetStr); }
pid_t HandleIconRequest(STREAM *ClientCon, char *Data) { HTTPSession *Response; char *Name=NULL, *Value=NULL, *ptr, *tptr; char *Tempstr=NULL; ListNode *Vars; pid_t pid; pid=fork(); if (pid==0) { Response=ParseSessionInfo(Data); Vars=ListCreate(); ptr=GetNameValuePair(Response->Arguments,"&","=",&Name,&Tempstr); while (ptr) { Value=HTTPUnQuote(Value,Tempstr); SetVar(Vars,Name,Value); if (strcasecmp(Name,"MimeType")==0) { tptr=GetToken(Value,"/",&Tempstr,0); SetVar(Vars,"MimeClass",Tempstr); SetVar(Vars,"MimeSub",tptr); } ptr=GetNameValuePair(ptr,"&","=",&Name,&Tempstr); } if (! SwitchGroup(Response->Group)) { LogToFile(Settings.LogPath,"WARN: Failed to switch to group '%s' for mimeicons '%s'", Response->RealUser, Tempstr); } if (! SwitchUser(Response->RealUser)) { LogToFile(Settings.LogPath,"ERROR: Failed to switch to user '%s' when getting icons from '%s'", Response->SearchPath); LogFileFlushAll(TRUE); _exit(0); } STREAMWriteLine("READY\n",ClientCon); STREAMFlush(ClientCon); ptr=GetToken(Response->SearchPath,":",&Value,0); while (ptr) { Tempstr=SubstituteVarsInString(Tempstr,Value,Vars,0); if (access(Tempstr,R_OK)==0) break; ptr=GetToken(ptr,":",&Value,0); } //HTTPServerSendDocument(ClientCon, Response, Tempstr, HEADERS_SENDFILE|HEADERS_USECACHE|HEADERS_KEEPALIVE); HTTPServerSendDocument(ClientCon, Response, Tempstr, HEADERS_SENDFILE|HEADERS_USECACHE); //exit 1 means we can keep connection alive for reuse LogFileFlushAll(TRUE); _exit(1); } DestroyString(Name); DestroyString(Value); DestroyString(Tempstr); return(pid); }
//This function Extracts Text from a line that's found between two specified //chunks of text 'ItemStart' and 'ItemEnd' char *GenericExtractFromLine(char *Line, char *ItemName, char *ItemStart, char *ItemEnd, ListNode *Vars, int Flags) { char *ptr, *ptr2, *Token=NULL, *Item=NULL; int GTF=0; if (Flags & EXTRACT_WITHIN_QUOTES) GTF=GETTOKEN_QUOTES; if (StrLen(ItemStart)) ptr=Gettoken(Line,ItemStart,&Token,0); else ptr=Line; ptr=Gettoken(ptr,ItemEnd,&Token,GTF); //check if the start string occurs more than once in the Token that we've grabbed if (StrLen(ItemStart)) ptr2=strstr(Token,ItemStart); else ptr2=NULL; while (ptr2) { ptr2+=StrLen(ItemStart); memmove(Token,ptr2,Token+StrLen(Token)-ptr2+1); //because of memmove we can strstr in Token again ptr2=strstr(Token,ItemStart); } if (Flags & EXTRACT_INCLUDE_START) { Item=MCopyStr(Item,ItemStart,Token,NULL); Token=CopyStr(Token,Item); } if (Flags & EXTRACT_DEQUOTE) Item=HTTPUnQuote(Item,Token); else if (Flags & EXTRACT_DEHTMLQUOTE) Item=HtmlDeQuote(Item,Token); else if (Flags & EXTRACT_DESLASHQUOTE) Item=DeQuoteStr(Item,Token); else Item=CopyStr(Item,Token); StripLeadingWhitespace(Item); StripTrailingWhitespace(Item); StripQuotes(Item); if (Flags & EXTRACT_NOSPACES) { ptr2=strchr(Item,' '); while (ptr2) { *ptr2='+'; ptr2=strchr(ptr2,' '); } } //Do this without disturbing ptr, as we must return ptr ptr2=ItemName; if (Flags & EXTRACT_GUESSTYPE) { Token=ItemCodeFromFileExtension(Token, ItemName, Item); } SetVar(Vars,ptr2,Item); DestroyString(Token); DestroyString(Item); return(ptr); }
int HTTPServerReadHeaders(HTTPSession *Session) { char *Tempstr=NULL, *Token=NULL, *ptr; ListNode *Curr; int val; HTTPSessionClear(Session); Tempstr=STREAMReadLine(Tempstr,Session->S); if (! Tempstr) return(FALSE); StripTrailingWhitespace(Tempstr); //First line of the HTTP request is the 'Command' in the form "<method> <url>?<arguments> <HTTP version>" HTTPServerParseCommand(Session, Session->S, Tempstr); Tempstr=STREAMReadLine(Tempstr,Session->S); if (Tempstr) { StripTrailingWhitespace(Tempstr); StripLeadingWhitespace(Tempstr); } while (StrLen(Tempstr) ) { if (Settings.Flags & FLAG_LOG_VERBOSE) LogToFile(Settings.LogPath,"<< %s",Tempstr); ptr=GetToken(Tempstr,":",&Token,0); while (isspace(*ptr)) ptr++; val=MatchTokenFromList(Token,HeaderStrings,0); ListAddNamedItem(Session->Headers,Token,CopyStr(NULL,ptr)); switch (val) { case HEAD_PROXYAUTH: if (IsProxyMethod(Session->MethodID)) { ptr=GetToken(ptr,"\\S",&Token,0); HTTPServerHandleAuthHeader(Session,val,Token,ptr); Session->AuthFlags |= FLAG_AUTH_PRESENT; } break; case HEAD_AUTH: if (IsProxyMethod(Session->MethodID)) { Session->RemoteAuthenticate=CopyStr(Session->RemoteAuthenticate,ptr); } if (StrLen(Session->UserName)==0) { ptr=GetToken(ptr,"\\S",&Token,0); HTTPServerHandleAuthHeader(Session,val,Token,ptr); Session->AuthFlags |= FLAG_AUTH_PRESENT; } break; case HEAD_HOST: Session->Host=CopyStr(Session->Host,ptr); ptr=strchr(Session->Host,':'); if (! ptr) { Token=FormatStr(Token,":%d",Settings.Port); Session->Host=CatStr(Session->Host,Token); } break; case HEAD_DEST: Session->Destination=HTTPUnQuote(Session->Destination,ptr); break; case HEAD_CONTENT_TYPE: HTTPServerParsePostContentType(Session, ptr); break; case HEAD_CONTENT_LENGTH: Session->ContentSize=atoi(ptr); break; case HEAD_DEPTH: if (strcasecmp(ptr,"infinity")==0) Session->Depth=INT_MAX; else Session->Depth=atoi(ptr); break; case HEAD_OVERWRITE: if (*ptr=='T') Session->Flags |= SESSION_OVERWRITE; break; case HEAD_CONNECTION: if ((Settings.Flags & FLAG_KEEPALIVES) && (strcasecmp(ptr,"Keep-Alive")==0)) Session->Flags |= SESSION_KEEPALIVE; break; case HEAD_AGENT: Session->UserAgent=CopyStr(Session->UserAgent,ptr); Curr=ListGetNext(Settings.UserAgents); while (Curr) { if (fnmatch(Curr->Tag,Session->UserAgent,0)==0) { if (Settings.Flags & FLAG_LOG_VERBOSE) LogToFile(Settings.LogPath,"Applying User Agent Settings: %s",Curr->Item); ParseConfigItemList((char *) Curr->Item); } Curr=ListGetNext(Curr); } break; case HEAD_COOKIE: if (StrLen(Session->Cookies)) Session->Cookies=MCopyStr(Session->Cookies,"; ",ptr,NULL); else Session->Cookies=CopyStr(Session->Cookies,ptr); Session->AuthFlags |= FLAG_AUTH_PRESENT; break; case HEAD_REFERER: Session->ClientReferrer=CopyStr(Session->ClientReferrer,ptr); break; case HEAD_ACCEPT_ENCODING: ptr=GetToken(ptr,",",&Token,0); while (ptr) { if (strcmp(Token,"gzip")==0) Session->Flags|=SESSION_ENCODE_GZIP; if (strcmp(Token,"x-gzip")==0) Session->Flags|=SESSION_ENCODE_GZIP | SESSION_ENCODE_XGZIP; ptr=GetToken(ptr,",",&Token,0); } break; case HEAD_ICECAST: if (atoi(ptr)) Session->Flags |= SESSION_ICECAST; break; case HEAD_IFMOD_SINCE: Session->IfModifiedSince=DateStrToSecs("%a, %d %b %Y %H:%M:%S %Z",ptr,NULL); break; case HEAD_UPGRADE: if ((strcasecmp(ptr,"Upgrade")==0) && SSLAvailable()) { if (! HTTPServerActivateSSL(Session,Settings.SSLKeys)) return; } else if (strcasecmp(ptr,"websocket")==0) Session->MethodID = METHOD_WEBSOCKET; break; case HEAD_WEBSOCK_KEY: Session->ContentBoundary=CopyStr(Session->ContentBoundary, ptr); break; case HEAD_WEBSOCK_KEY1: Session->ContentBoundary=CopyStr(Session->ContentBoundary, ptr); if (Session->MethodID==METHOD_WEBSOCKET) Session->MethodID = METHOD_WEBSOCKET75; break; case HEAD_WEBSOCK_KEY2: Session->ContentType=CopyStr(Session->ContentType, ptr); if (Session->MethodID==METHOD_WEBSOCKET) Session->MethodID = METHOD_WEBSOCKET75; break; case HEAD_WEBSOCK_PROTOCOL: Session->ContentType=CopyStr(Session->ContentType, ptr); break; case HEAD_WEBSOCK_VERSION: break; case HEAD_ORIGIN: break; } Tempstr=STREAMReadLine(Tempstr,Session->S); StripTrailingWhitespace(Tempstr); StripLeadingWhitespace(Tempstr); } if (strstr(Session->Arguments,"AccessToken")) Session->AuthFlags |= FLAG_AUTH_PRESENT | FLAG_AUTH_ACCESS_TOKEN; Session->URL=HTTPUnQuote(Session->URL,Session->OriginalURL); if (*Session->URL=='/') Session->Path=CopyStr(Session->Path,Session->URL); else Session->Path=MCopyStr(Session->Path,"/",Session->URL,NULL); DestroyString(Tempstr); DestroyString(Token); return(TRUE); }
int HTTPServerProcessActions(STREAM *S, HTTPSession *Session) { typedef enum {ACT_NONE, ACT_GET, ACT_DEL, ACT_DEL_SELECTED, ACT_RENAME, ACT_EDIT, ACT_MKDIR, ACT_PACK, ACT_SAVE_PROPS, ACT_EDIT_WITH_ACCESSTOKEN, ACT_M3U, ACT_UPLOAD} TServerActs; char *QName=NULL, *QValue=NULL, *Name=NULL, *Value=NULL, *ptr; char *Arg1=NULL, *Arg2=NULL, *FileProperties=NULL, *SelectedFiles=NULL; TServerActs Action=ACT_NONE; int result=FALSE; //QName and QValue will be HTTP quoted, so arguments must be //dquoted after unpacking from the URL ptr=GetNameValuePair(Session->Arguments,"&","=",&QName,&QValue); while (ptr) { Name=HTTPUnQuote(Name,QName); Value=HTTPUnQuote(Value,QValue); QValue=CopyStr(QValue,""); switch (*Name) { case 'd': if (strncasecmp(Name,"del:",4)==0) { Action=ACT_DEL; Arg1=CopyStr(Arg1,Name+4); } else if (strncasecmp(Name,"delete-selected:",16)==0) { Action=ACT_DEL_SELECTED; Arg1=CopyStr(Arg1,Name+16); } break; case 'e': if (strncasecmp(Name,"edit:",5)==0) { Action=ACT_EDIT; Arg1=CopyStr(Arg1,Name+5); } break; case 'f': if (strncasecmp(Name,"fileproperty:",13)==0) FileProperties=MCatStr(FileProperties,"&",Name,"=",Value,NULL); break; case 'g': if (strncasecmp(Name,"get:",4)==0) { Action=ACT_GET; Arg1=CopyStr(Arg1,Name+4); } else if (strncasecmp(Name,"genaccess:",10)==0) { Action=ACT_EDIT_WITH_ACCESSTOKEN; Arg1=CopyStr(Arg1,Name+10); } break; case 'm': if (strncasecmp(Name,"mkdir:",6)==0) { Action=ACT_MKDIR; Arg1=CopyStr(Arg1,Name+6); } else if (strcasecmp(Name,"mkdir")==0) QValue=HTTPUnQuote(QValue,Value); else if (strncasecmp(Name,"m3u:",4)==0) { Action=ACT_M3U; Arg1=CopyStr(Arg1,Name+4); } break; case 'r': if (strncasecmp(Name,"renm:",5)==0) { Action=ACT_RENAME; Arg1=CopyStr(Arg1,Name+5); } else if (strcasecmp(Name,"renameto")==0) QValue=HTTPUnQuote(QValue,Value); break; case 'p': if (strncasecmp(Name,"pack:",5)==0) { Action=ACT_PACK; Arg1=CopyStr(Arg1,Name+5); } else if (strcasecmp(Name,"packtype")==0) QValue=HTTPUnQuote(QValue,Value); else if (strcasecmp(Name,"packtarget")==0) QValue=HTTPUnQuote(QValue,Value); break; case 's': if (strncasecmp(Name,"sprops:",7)==0) { Action=ACT_SAVE_PROPS; Arg1=CopyStr(Arg1,Name+7); } else if (strcasecmp(Name,"selected")==0) QValue=HTTPUnQuote(QValue,Value); break; case 'u': if (strncasecmp(Name,"upload:",7)==0) { Action=ACT_UPLOAD; Arg1=CopyStr(Arg1,Name+7); } break; } //these are secondary arguments in the query string, whereas all the above are the primary //request that defines what action we're taking if (StrLen(QValue)) Arg2=MCatStr(Arg2, Name, "=", QValue, "&",NULL); ptr=GetNameValuePair(ptr,"&","=",&QName,&QValue); } //Most of these actions are handled in 'directory_listing.c' Many of them concern buttons on the 'edit' page for a file //Look in the top of 'directory_listing.c' for an enum that each 'format=' argument will map to switch (Action) { case ACT_NONE: break; case ACT_EDIT: result=TRUE; Value=MCopyStr(Value,Arg1,"?format=edit",NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); result=TRUE; break; case ACT_EDIT_WITH_ACCESSTOKEN: result=TRUE; Value=MCopyStr(Value,Arg1,"?format=editaccesstoken",NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); result=TRUE; break; case ACT_DEL: result=TRUE; Value=MCopyStr(Value,Arg1,"?format=delete",NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); break; case ACT_DEL_SELECTED: result=TRUE; Value=MCopyStr(Value,Arg1,"?format=delete-selected&",Arg2,NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); break; case ACT_RENAME: if (StrLen(Arg2)) { Value=MCopyStr(Value,Arg1,"?format=rename&",Arg2,NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); result=TRUE; } break; case ACT_MKDIR: if (StrLen(Arg2)) { Value=MCopyStr(Value,Arg1,"?format=mkdir&",Arg2,NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); result=TRUE; } break; case ACT_M3U: Value=MCopyStr(Value,Arg1,"?format=m3u&",Arg2,NULL); HTTPServerSendResponse(S, Session, "302", "", Value); result=TRUE; break; case ACT_GET: HTTPServerSendResponse(S, Session, "302", "", Arg1); result=TRUE; break; case ACT_SAVE_PROPS: Value=MCopyStr(Value,Arg1,"?format=saveprops",FileProperties,NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); break; case ACT_PACK: Value=MCopyStr(Value,Arg1,"?format=pack&",Arg2,NULL); Session->LastModified=0; HTTPServerSendResponse(S, Session, "302", "", Value); break; case ACT_UPLOAD: Value=MCopyStr(Value,Arg1,"?format=upload",NULL); HTTPServerSendResponse(S, Session, "302", "", Value); result=TRUE; break; } DestroyString(FileProperties); DestroyString(SelectedFiles); DestroyString(QName); DestroyString(QValue); DestroyString(Name); DestroyString(Value); DestroyString(Arg1); DestroyString(Arg2); return(result); }