// // TO AUTOMATE: // // instead of inserting default values into input tags in processLoop24() // generate an HTTP reply and send it back. we have to use //
to support the uploading of images // so that each input tag will be it's own Content-Type:... along with // a boundary delimeter. make a fake form in the tag in here // with that enctype and you can see the multipart formatting. // #include "gb-include.h" #include "XmlDoc.h" #include "HttpServer.h" #include "Msg1.h" #include "Msg20.h" void processLoop24 ( void *state ); bool printFilledOutForm ( class State24 *st , char *coll ); void gotSearchResults ( void *state ) ; // from PageEvents.cpp: bool printEventTitle ( SafeBuf &sb , Msg20Reply *mr , class State7 *st ) ; bool printEventSummary ( SafeBuf &sb , class Msg20Reply *mr , long width , long minusFlags , long requiredFlags , class State7 *st , ExpandedResult *er , long maxChars ); // from PageEvents.cpp: extern bool sendPageEvents2 ( TcpSocket *s , HttpRequest *hr , SafeBuf *resultsBuf, SafeBuf *emailLikedbListBuf, void *state , void (* emailCallback)(void *state) , SafeBuf *providedBuf , void *providedState , void (* providedCallback)(void *state) ); enum InputType { IT_EVENT_TITLE = 1, IT_EVENT_DESC = 2, IT_EVENT_URL = 3, IT_EVENT_START_DATE1 = 4, IT_EVENT_END_DATE1 = 5 }; class State24 { public: // . put this junk in top left frame // . this is the url of the form we have selected Url m_formUrl; // . for querying the form urls themselves // . we treat them as events but index the gbeventform:1 term // . TODO: do this later. for now just use a simple input box // to set m_formUrl directly //Query m_formQuery; TagRec m_tagRec; Msg8a m_msg8a; // . print the form itself in the bottom left frame from m_formUrl XmlDoc m_formDoc; // . this describes the form for m_formUrl // . it maps tag hashes to input types, like IT_EVENT_TITLE // or IT_EVENT_DESC or IT_EVENT_URL etc. // . its is stored in tagdb for the form url // . it is a string whose format is like "1:12abef;2:34cd01;..." // which is InputType:32bitValue;... // . we use these values to make a dropdown menu that popups up // over each visible form element when you right-click on it // and the default value is the one in m_inputMap. SafeBuf m_formInputMap; collnum_t m_collnum; // . put this junk in top right frame. the query PLUS search results. // we select the event from the search results to put into the form. // . query #1 is for querying events to fill in the forms Query m_eventQuery; // the location SafeBuf m_eventWhere; // radius from location in miles long m_eventRadius; // then put the event search result pageget.cpp into the // bottom right frame. long long m_formDocId; long m_formEventId; long m_formClockSet; TcpSocket *m_socket; HttpRequest m_hr; SafeBuf m_sb; SafeBuf m_tbuf; Msg1 m_msg1; RdbList m_tagList; Msg20 m_msg20; Msg20Request m_msg20Request; }; static bool sendErrorReply ( void *state , long err ) { // ensure this is set if ( ! err ) { char *xx=NULL;*xx=0; } // get it State24 *st = (State24 *)state; // get the tcp socket from the state TcpSocket *s = st->m_socket; char tmp [ 1024*32 ] ; sprintf ( tmp , "had server-side error: %s
", mstrerror(g_errno)); // nuke state8 mdelete ( st , sizeof(State24) , "pagesubmit" ); delete (st); // erase g_errno for sending //g_errno = 0; return g_httpServer.sendErrorReply ( s, err, mstrerror(err) ); } static bool sendReply ( void *state ) { // get it State24 *st = (State24 *)state; SafeBuf *sb = &st->m_sb; // now encapsulate it in html head/tail and send it off g_httpServer.sendDynamicPage( st->m_socket , sb->getBufStart(), sb->length() , -1, //cachtime false ,//postreply? NULL, //ctype -1 , //httpstatus NULL,//cookie "utf-8"); // nuke state8 mdelete ( st , sizeof(State24) , "pagesubmit" ); delete (st); return true; } //static void gotTagRec24 ( void *state ) ; // . returns false if blocked, true otherwise // . sets g_errno on error // . the event submission tool bool sendPageSubmit ( TcpSocket *s , HttpRequest *hr ) { // make a state State24 *st = NULL; try { st = new (State24); } catch ( ... ) { g_errno = ENOMEM; log("PageParser: new(%i): %s", sizeof(State24),mstrerror(g_errno)); return g_httpServer.sendErrorReply(s,500, mstrerror(g_errno));} mnew ( st , sizeof(State24) , "PageParser" ); // save socket ptr st->m_socket = s; st->m_hr.copy ( hr ); // must be local if ( ! hr->isLocal() ) return sendErrorReply(st,ENOTLOCAL); // get the collection long collLen; char *coll = hr->getString ( "c" , &collLen ,NULL ); if ( ! coll ) coll = g_conf.m_defaultColl; st->m_collnum = g_collectiondb.getCollnum ( coll ); // set query long eqlen; char *eq = hr->getString("q",&eqlen,NULL); if ( eq ) st->m_eventQuery.set ( eq , 2 ); // form url long fulen; char *fu = hr->getString("formurl",&fulen,NULL); if ( fu ) st->m_formUrl.set(fu); st->m_formDocId = hr->getLongLong("formdocid",0LL); st->m_formEventId = hr->getLong("formeventid",0); st->m_formClockSet = hr->getLong("formclockset",0); // use now if its 0 if ( st->m_formClockSet == 0 ) st->m_formClockSet = getTimeGlobal(); // if we are the form iframe if ( hr->getLong("showform",0) ) // return false if blocked return printFilledOutForm ( st , coll ); // header SafeBuf *sb = &st->m_sb; sb->safePrintf("\n"); /* SafeBuf cubuf; st->m_hr.getCurrentUrl ( cubuf ); char *cu = cubuf.getBufStart(); // . when this page loads, save the url to tagdb if we should // . i took this out since i am tring to do this without mappings if ( strstr (cu,"&save=1") ) { // make a tagrec SafeBuf *tbuf = &st->m_tbuf; tbuf->addTag3 ( fu , // mysite "eventformurl", // tagname getTimeGlobal(), // now "bridge", 0, // ip cu ,// data is the url RDB_TAGDB ); // use the list we got RdbList *list = &st->m_tagList; key128_t startKey; key128_t endKey; startKey.setMin(); endKey.setMax(); // set it from safe buf list->set ( tbuf->getBufStart() , tbuf->length() , NULL , 0 , (char *)&startKey , (char *)&endKey , -1 , false , false , sizeof(key128_t) ); // . just use TagRec::m_msg1 now // . no, can't use that because tags are added using // SafeBuf::addTag() which first pushes the rdbid, so we // gotta use msg4 if ( ! st->m_msg1.addList ( list , RDB_TAGDB , coll , st , gotTagRec24 , false , 0 ) ) // st->m_niceness ) ) return false; // . if addTagRecs() doesn't block then sendReply right away // . this returns false if blocks, true otherwise gotTagRec24 ( st ); return true; } // just get the tag rec otherwise TagRec *gr = &st->m_tagRec; // lookup tag rec for form url if ( ! st->m_msg8a.getTagRec ( &st->m_formUrl , coll, true, 0, // niceness st , gotTagRec24 , gr ) ) return false; gotTagRec24 ( st ); return true; } void gotTagRec24 ( void *state ) { State24 *st = (State24 *)state; SafeBuf *sb = &st->m_sb; TagRec *gr = &st->m_tagRec; SafeBuf cubuf; st->m_hr.getCurrentUrl ( cubuf ); char *cu = cubuf.getBufStart(); // if we were fetching a tag rec for a form url, let's reload the // page then!! if ( strstr ( cu,"&reload=1") ) { // use the tag rec char *newurl = gr->getString( "eventformurl",NULL); if ( newurl ) { // send a page redirect sb->safePrintf("", newurl); sendReply(st); return; } } */ sb->safePrintf(//"" "" "" "" "
" //"" //"
" //"" "
" //"" , st->m_formUrl.getUrl() ); // parse these out of the url! char *query = ""; char *location = ""; long radius = 30; // put in a div that scrolls like an iframe sb->safePrintf(""); // put in a div that scrolls like an iframe sb->safePrintf(""); // now encapsulate it in html head/tail and send it off sendReply ( st ); return true; } static bool gotMsg20Result ( void *state ) ; // . assume we are an event submission form // . print ourselves out into "sb" // . detect event form inputs and put a dropdown that shows up on a right // click that allows the admin to change the type of input form from // what we've detected it to be. i.e. startdate|title|description|... bool printFilledOutForm ( State24 *st , char *coll ) { char *fu = st->m_formUrl.getUrl(); if ( ! fu || ! fu[0] ) { g_errno = EBADURL; return sendErrorReply ( st , g_errno ); } // // get the event we are putting into the form // Msg20Request *rr = &st->m_msg20Request; rr->reset(); rr->m_docId = st->m_formDocId; rr->m_eventId = st->m_formEventId; //rr->ptr_coll = coll; //rr->size_coll = gbstrlen(coll)+1; // now we are going to gk144, use "main" rr->ptr_coll = "main\0"; rr->size_coll = 5; rr->m_callback = gotMsg20Result; rr->m_state = st; rr->m_getEventSummary = 1; rr->m_clockSet = st->m_formClockSet; // HACK: send to gk144!!! it has all the events, not titan! //rr->m_hostIP = atoip("10.5.54.154"); //rr->m_hostUDPPort = 9000; // send to gk144 cluster rr->m_hostdb = &g_hostdb2; // also get the search result we are using to populate this form if ( st->m_formDocId > 0 && ! st->m_msg20.getSummary ( rr ) ) return false; // we got it return gotMsg20Result ( st ); } bool gotMsg20Result ( void *state ) { State24 *st = (State24 *)state; // set this up for passing to XmlDoc::set4() SpiderRequest sreq; sreq.reset(); strcpy(sreq.m_url,st->m_formUrl.getUrl()); long firstIp = hash32n(sreq.m_url); sreq.setKey( firstIp, 0LL, false ); sreq.m_isPageParser = 0; // was 1 sreq.m_isPageSubmit = 1; sreq.m_hopCount = 0;//st->m_hopCount; sreq.m_hopCountValid = 1; sreq.m_fakeFirstIp = 0;//1; sreq.m_firstIp = 0;//firstIp; sreq.m_domHash32 = st->m_formUrl.getDomainHash32(); sreq.m_siteHash32 = st->m_formUrl.getHostHash32(); XmlDoc *fd = &st->m_formDoc; //Msg20Request *rr = &st->m_msg20Request; char *coll = g_collectiondb.getColl(st->m_collnum); // . use the enormous power of our new XmlDoc class // . this returns false if blocked // . also gets XmlDoc::m_tagRec which contains the input mapping if ( ! fd->set4 ( &sreq , NULL , coll , NULL , // pbuf 1 , // niceness NULL , // content false , // deletefromindex 0 , // forced ip CT_HTML )) // contentType // return error reply if g_errno is set return sendErrorReply ( st , g_errno ); // make this our callback in case something blocks fd->setCallback ( st , processLoop24 ); processLoop24 ( st ); // this should always block return false; } #define FI_VENUE 1 #define FI_TITLE 2 #define FI_DESC 3 #define FI_DATE_START 4 #define FI_DATE_END 5 #define FI_DOW 6 #define FI_URL 7 #define FI_EMAIL 8 #define FI_PHONE 9 #define FI_STREET 10 #define FI_CITY 11 #define FI_STATE 12 #define FI_ZIP 13 #define FI_COUNTRY 14 #define FI_TIME_START 15 #define FI_TIME_END 16 #define FI_PRICE 17 #define FI_MY_NAME 18 #define FI_MY_PHONE 19 #define FI_MY_EMAIL 20 #define FI_IMAGE 21 void processLoop24 ( void *state ) { // cast it State24 *st = (State24 *)state; // get the xmldoc XmlDoc *fd = &st->m_formDoc; Words *w = fd->getWords(); // blocked? if ( w == (void *)-1 ) return; // error? if ( ! w ) { sendErrorReply ( st , g_errno ); return; } Sections *sx = fd->getSections(); if ( sx == (void *)-1 ) return; if ( ! sx ) { sendErrorReply ( st , g_errno ); return; } SafeBuf *sb = &st->m_sb; sb->safePrintf("", fd->getFirstUrl()->getUrl() ); // is this basically in PageEvents.cpp? Msg20Reply *mr = st->m_msg20.getReply(); if ( ! mr ) { sb->safeMemcpy ( fd->ptr_utf8Content, fd->size_utf8Content - 1 ); sendReply ( st ); return; } // this logic taken from Msg40.cpp!! long ni = mr->size_eventDateIntervals/sizeof(Interval); Interval *ii = (Interval *)mr->ptr_eventDateIntervals; long timeStart = 0; long timeEnd = 0; for ( long j = 0 ; j < ni ; j++ ) { if ( mr->m_prevStart >= 0 & (unsigned long)ii[j].m_a < (unsigned long)mr->m_prevStart ) continue; if ( ii[j].m_a < st->m_formClockSet ) continue; timeStart = ii[j].m_a; timeEnd = ii[j].m_b; break; } long start1 = timeStart; bool isDST1 = getIsDST (start1,mr->m_timeZoneOffset); start1 += mr->m_timeZoneOffset * 3600; if ( mr->m_useDST && isDST1 ) start1 += 3600; struct tm *timeStruct = gmtime ( &start1 ); ExpandedResult er; er.m_mapi = 0; er.m_timeStart = timeStart; er.m_timeEnd = timeEnd; er.m_dayNum1 = timeStruct->tm_mday; er.m_month1 = timeStruct->tm_mon; er.m_year1 = timeStruct->tm_year+1900; er.m_hour1 = timeStruct->tm_hour; er.m_min1 = timeStruct->tm_min; er.m_dow1 = timeStruct->tm_wday; time_t start2 = timeEnd; bool isDST2 = getIsDST (start2,mr->m_timeZoneOffset); start2 += mr->m_timeZoneOffset * 3600; if ( mr->m_useDST && isDST2 ) start2 += 3600; timeStruct = gmtime ( &start2 ); er.m_dayNum2 = timeStruct->tm_mday; er.m_month2 = timeStruct->tm_mon; er.m_year2 = timeStruct->tm_year+1900; er.m_hour2 = timeStruct->tm_hour; er.m_min2 = timeStruct->tm_min; er.m_dow2 = timeStruct->tm_wday; // parse out address (from PageEvents.cpp::printEventAddress) char *addr = mr->ptr_eventAddr; char *name1 ; char *name2 ; char *suite ; char *street ; char *city ; char *adm1 ; char *zip ; char *country; double lat,lon; // this now makes "city" etc point into a static buffer, beware! setFromStr2 ( addr, &name1 , &name2, &suite, &street, &city, &adm1, &zip, &country,&lat , &lon ); // override with this name1 = mr->ptr_eventBestPlaceName; // get the event display for this event id //EventDisplay *ed = fd->getEventDisplay ( st->m_eventId ); // use the msg20reply now //TagRec *gr = &fd->m_tagRec; // print out each word long nw = w->getNumWords(); char **wptrs = w->getWords(); long *wlens = w->getWordLens(); long long *wids = w->getWordIds(); nodeid_t *tids = w->getTagIds(); for ( long i = 0 ; i < nw ; i++ ) { // if no event selected, skip all this! //if ( ! mr ) { // sb->safeMemcpy ( wptrs[i], wlens[i] ); // continue; //} // // . if its the
tag then make sure it goes // back to the gbhom/gk144 host and does not use // the tag. that way gk144 can insert the // event image into the http reply from the browser before // passing it on to the external event form server. // we should insert a "formproxy=http://..." // input into the form so we know to forward the form reply // to that url. and also to substitute in the picture. // . we detect "formproxy=..." in pageevents.cpp like we // look for "form". see top of sendPageEvents2() which // calls sendPageFormProxy() when it sees that. // . don't nuke the "url" in this tag, but rather // include it as a text input named "formproxy". // // if ( ! strncasecmp(wptrs[i] ,"safeMemcpy ( wptrs[i] , leftLen ); // insert our url so form is submitted to us sb->safePrintf("http://10.5.1.203:8000/"); // end the rest of the form tag sb->safeMemcpy ( end , wend - end ); // put a hidden input tag for us to use sb->safePrintf ("m_hr.getString("formurl",NULL); Url uu; uu.set ( fu ); char *us = uu.getUrl(); long uslen = uu.getUrlLen(); // hack off filename, if there uslen -= uu.getFilenameLen(); // then prepend to form url sb->safeMemcpy(us,uslen); } // print original url into the submission url as // a cgi parm sb->safeMemcpy ( origUrl , origUrlLen ); sb->safePrintf ( "\">"); // and put the url of the image so we can download // it and insert it before returning the final // reply to the external event submission server sb->safePrintf("" , mr->ptr_imgUrl ); // make the facebook thumb into a larger image if ( mr->m_eventFlags & EV_FACEBOOK ) { char *end = sb->getBuf() - 7; if ( *end == 'q' ) *end = 'n'; } // that's it! continue; } bool isTextArea = false; if ( ! strncasecmp(wptrs[i] ,"safeMemcpy ( wptrs[i], wlens[i] ); continue; } // if its hidden skip as well if ( strncasestr(wptrs[i] , wlens[i], " type=hidden" ) ) { sb->safeMemcpy ( wptrs[i], wlens[i] ); continue; } if ( strncasestr(wptrs[i] , wlens[i], " type=\"hidden" ) ) { sb->safeMemcpy ( wptrs[i], wlens[i] ); continue; } // now get the sentence previous to this input tag Section *ss = sx->m_sectionPtrs[i-1]; // hit prev unti we got a sentence for ( ; ss ; ss = ss->m_prev ) if ( ss->m_flags & SEC_SENTENCE ) break; // if not sentence forget it! if ( ! ss ) { sb->safeMemcpy ( wptrs[i], wlens[i] ); continue; } // ok, now scan the words sentence and normalize them // into a string SafeBuf nb; bool lastWasSpace = true; for ( long j = ss->m_a ; j < ss->m_b ; j++ ) { // punct? if ( ! wids[j] ) { if ( lastWasSpace ) continue; nb.pushChar(' '); lastWasSpace = true; continue; } // skip isolated s like "Day(s) of week" if ( wlens[j] == 1 && to_lower_a(wptrs[j][0])=='s' ) continue; // ignore this ("content photo") if ( !strncasecmp(wptrs[j],"content",wlens[j]) ) continue; if ( !strncasecmp(wptrs[j],"event",wlens[j]) ) continue; // word? nb.safeMemcpy ( wptrs[j], wlens[j] ); lastWasSpace = false; } // convert to lower case //sb.toLowerUtf8(); // now get that buf char *s = nb.getBufStart(); if ( nb.length() <= 0 ) s = NULL; // if no words before it we can't idenfity it, so just // print the input tag here and continue if ( ! s ) { sb->safeMemcpy ( wptrs[i],wlens[i]); continue; } long flags = 0; // look for indicative phrases if ( ! strcasecmp(s,"venue name") ) flags = FI_VENUE; if ( ! strcasecmp(s,"location") ) flags = FI_VENUE; if ( ! strcasecmp(s,"name") ) flags = FI_TITLE; if ( ! strcasecmp(s,"title") ) flags = FI_TITLE; if ( ! strcasecmp(s,"short description") ) flags = FI_DESC; // mm/dd/yy if ( ! strcasecmp(s,"start date") ) flags = FI_DATE_START; // mm/dd/yy if ( ! strcasecmp(s,"end date") ) flags = FI_DATE_END; // day of week if ( ! strcasecmp(s,"day of week") ) flags = FI_DOW; if ( ! strcasecmp(s,"website") ) flags = FI_URL; if ( ! strcasecmp(s,"website or map") ) flags = FI_URL; if ( ! strcasecmp(s,"url") ) flags = FI_URL; if ( ! strcasecmp(s,"email") ) flags = FI_EMAIL; if ( ! strcasecmp(s,"main phone number") ) flags = FI_PHONE; if ( ! strcasecmp(s,"main phone") ) flags = FI_PHONE; if ( ! strcasecmp(s,"phone") ) flags = FI_PHONE; if ( ! strcasecmp(s,"address") ) flags = FI_STREET; if ( ! strcasecmp(s,"city") ) flags = FI_CITY; if ( ! strcasecmp(s,"town") ) flags = FI_CITY; if ( ! strcasecmp(s,"city town") ) flags = FI_CITY; if ( ! strcasecmp(s,"town city") ) flags = FI_CITY; if ( ! strcasecmp(s,"state") ) flags = FI_STATE; if ( ! strcasecmp(s,"zip") ) flags = FI_ZIP; if ( ! strcasecmp(s,"country") ) flags = FI_COUNTRY; if ( ! strcasecmp(s,"time") ) flags = FI_TIME_START; if ( ! strcasecmp(s,"admission") ) flags = FI_PRICE; if ( ! strcasecmp(s,"price") ) flags = FI_PRICE; if ( ! strcasecmp(s,"ticket admission") ) flags = FI_PRICE; if ( ! strcasecmp(s,"ticket price") ) flags = FI_PRICE; if ( ! strcasecmp(s,"ticket cost") ) flags = FI_PRICE; if ( ! strcasecmp(s,"your name") ) flags = FI_MY_NAME; if ( ! strcasecmp(s,"organized by") ) flags = FI_MY_NAME; if ( ! strcasecmp(s,"your phone number") ) flags = FI_MY_PHONE; if ( ! strcasecmp(s,"your email address") ) flags =FI_MY_EMAIL; if ( ! strcasecmp(s,"your email") ) flags = FI_MY_EMAIL; if ( ! strcasecmp(s,"image") ) flags = FI_IMAGE; if ( ! strcasecmp(s,"photo") ) flags = FI_IMAGE; if ( ! strcasecmp(s,"picture") ) flags = FI_IMAGE; SafeBuf vbuf; // ok, now determine value of the input box if ( flags == FI_TITLE ) { printEventTitle ( vbuf , mr , NULL ); } if ( flags == FI_DESC ) { printEventSummary ( vbuf , mr , 99999 , // width EDF_SUBEVENTBROTHER , // donotprint 0 , NULL , // state NULL , // expanded result 200 ); // maxchars } if ( flags == FI_DATE_START ) { vbuf.safePrintf("%s %li" , getMonthName(er.m_month1) , (long)er.m_dayNum1 ); } if ( flags == FI_DATE_END ) { vbuf.safePrintf("%s %li" , getMonthName(er.m_month2) , (long)er.m_dayNum2 ); } if ( flags == FI_TIME_START ) { char *ampm = "am"; long h = er.m_hour1; if ( h == 12 ) ampm = "pm"; if ( h > 12 ) { ampm = "pm"; h -= 12; } vbuf.safePrintf("%li:%02li %s" , (long)h , (long)er.m_min1 , ampm ); } if ( flags == FI_TIME_END ) { char *ampm = "am"; long h = er.m_hour2; if ( h == 12 ) ampm = "pm"; if ( h > 12 ) { ampm = "pm"; h -= 12; } vbuf.safePrintf("%li:%02li %s" , (long)h , (long)er.m_min2 , ampm ); } if ( flags == FI_URL ) { // make event guru url vbuf.safePrintf("http://www.eventguru.com/?id=%llu." "%llu" , mr->m_docId , mr->m_eventHash64 ); } if ( flags == FI_EMAIL ) { // make event guru url vbuf.safePrintf("guru@eventguru.com"); } if ( flags == FI_STREET && street ) { vbuf.safePrintf("%s",street); } if ( flags == FI_CITY && city) { vbuf.safePrintf("%s",city); } if ( flags == FI_STATE && adm1 ) { vbuf.safePrintf("%s",adm1); } if ( flags == FI_ZIP && zip ) { vbuf.safePrintf("%s",zip); } if ( flags == FI_COUNTRY && country ) { vbuf.safePrintf("%s",country); } if ( flags == FI_VENUE && name1 ) { vbuf.safePrintf("%s",name1); } if ( flags == FI_MY_NAME ) { vbuf.safePrintf("Matt Wells"); } if ( flags == FI_MY_PHONE ) { vbuf.safePrintf("505 450 3518"); } if ( flags == FI_MY_EMAIL ) { vbuf.safePrintf("guru@eventguru.com"); } char *val = vbuf.getBufStart(); long vlen = vbuf.length(); if ( vlen <= 0 ) val = NULL; // if no value, just print the input tag with no value if ( ! val ) { sb->safeMemcpy ( wptrs[i],wlens[i]); continue; } // // TEXTAREA logic // if ( isTextArea ) { // finish text area tag sb->safeMemcpy ( wptrs[i],wlens[i]); // then insert our value sb->safeMemcpy ( val , vlen ); // scan for next for ( ; i+1 < nw ; i++ ) { // stop if it follows next if ( tids[i+1] == TAG_TEXTAREA|BACKBIT ) break; } continue; } // // . print input box, but not "value=" // . substitute our own value here // char *x = wptrs[i]; char *xend = x + wlens[i]; bool didIt = false; for ( ; x < xend ; x++ ) { if ( strncasecmp(x," value=",7) && *x != '>' ) { sb->pushChar(*x); continue; } // substitue sb->safePrintf(" value=\""); sb->safeMemcpy(val,vlen); sb->safePrintf("\""); didIt = true; // end? if ( *x == '>' ) { sb->pushChar('>'); break; } // skip over original val x += 6; // quote? bool inQuote = false; if ( *x == '\"' ) { inQuote = true; x++; } // skip till space, or quote if in quotes for ( ; x < xend ; x++ ) { if ( is_wspace_a (*x) && ! inQuote){x--;break;} if ( *x == '\"' ) break; if ( *x == '>' && ! inQuote ) {x--;break;} } // ok, its pointing to a space or quote, do not // print out that space or quote continue; } } sendReply ( st ); } static void gotImage ( void *state , TcpSocket *s ) ; ///////////// // // TAKE THE HTTP REQUEST from the browser meant as an event submission // and proxy it to the external event submission server. // // We do this so we can insert the event image into the supplied HTTP REQUEST. // // The tag typically has a "filename=\"" string in the // POSTed form data. so we just have to insert the image file contents // after that. // ///////////// class State27 { public: TcpSocket *m_socket; SafeBuf m_replyBuf; SafeBuf m_relayBuf; HttpRequest m_hr; }; static void relayReply ( void *state , TcpSocket *subsock ) ; // . returns false if blocked, true otherwise // . sets g_errno on error bool sendPageFormProxy ( TcpSocket *s , HttpRequest *hr ) { // must be local if ( ! hr->isLocal() ) return sendErrorReply(NULL,ENOTLOCAL); // get the image url char *imgUrl = hr->getString ( "egimgurl" , NULL ); // the original form submission url, a page on the external // event submission server char *formUrl = hr->getString ("formproxyto",NULL); // fake it //formUrl = "http://www.itsatrip.org/events/submit.aspx"; char *req = s->m_readBuf; long reqSize = s->m_readOffset; long allocSize = s->m_readBufSize; // make a state State27 *st = NULL; try { st = new (State27); } catch ( ... ) { g_errno = ENOMEM; log("PageParser: new(%i): %s", sizeof(State27),mstrerror(g_errno)); return g_httpServer.sendErrorReply(s,500, mstrerror(g_errno));} mnew ( st , sizeof(State27) , "PageParser" ); // save socket ptr st->m_socket = s; st->m_hr.copy ( hr ); // copy the original reply we need to forward st->m_replyBuf.safeMemcpy ( s->m_readBuf ,s->m_readOffset ); // if not there, just proxy it now as it is if ( ! imgUrl ) { // assume we got one gotImage ( st , NULL ); return false; } log("formprox: downloading image %s",imgUrl); g_errno = 0; // re-write it //if ( strncasecmp(imgUrl,"https://",8) == 0 ) imgUrl += 8; // otherwise, get the image, scale it and insert it into the // post request... look for "filename=\"" as a form element. if ( ! g_httpServer.getDoc ( imgUrl , 0 , // ip - look it up 0 , // ofset -1 , // size 0 , // if modified since st , gotImage , 60000 , // timeout 0 , // proxyip 0 , // proxyport 9999999 , // maxtextdoclen 9999999 // maxotherdoclen )) return false; // must be error log("formprox: error downloading image url %s : %s", imgUrl,mstrerror(g_errno)); // delete state then mdelete ( st , sizeof(State27) , "pageprox" ); delete (st); // prevent it from being freed when we return here s->m_readBuf = NULL; // use this directly since we are just forwarding the request TcpServer *tcp = &g_httpServer.m_tcp; // because buffer is now owned by this socket if ( ! tcp->sendMsg ( formUrl , // host/port req , reqSize , allocSize , reqSize , NULL, // st , NULL,//callback 60 , // timeout 999999999 ,// maxtextdoclen 999999999 // maxotherdoclen ) ) return false; // it did not block return true; } static void removeLine ( SafeBuf *rb , char *lineStart ) ; static void removeDisposition ( SafeBuf *rb , char *name ) ; static void adjustContentLength ( SafeBuf *rb ) ; void gotImage ( void *state , TcpSocket *socket ) { // cast it State27 *st = (State27 *)state; // if image failed! if ( g_errno ) { hadError: log("submit: image download failed: %s",mstrerror(g_errno)); TcpSocket *s = st->m_socket; mdelete ( st , sizeof(State27) , "pageprox" ); delete (st); g_httpServer.sendErrorReply(s,500,mstrerror(g_errno)); return; } // shortcut SafeBuf *rb = &st->m_replyBuf; HttpMime hm; if ( socket ) { hm.set ( socket->m_readBuf , socket->m_readOffset , NULL ); if ( hm.getHttpStatus() != 200 ) { g_errno = EBADREPLY; goto hadError;} // save it SafeBuf imgBuf; imgBuf.safeMemcpy ( hm.getContent() , hm.getContentLen() ); char fn[128]; sprintf(fn,"/tmp/tmpimg%lu",getTimeLocal()); imgBuf.save ( "" , fn ); // convert it char cmd[512]; sprintf ( cmd , "anytopnm %s > %s-2", fn , fn ); system ( cmd ); // scale it sprintf ( cmd , "pnmscale -xysize 128 128 %s-2 > %s-3",fn,fn); system ( cmd ); // convert it to png sprintf ( cmd , "pnmtopng %s-3 > %s-4.png", fn , fn ); system ( cmd ); // load it (tmp/tmpimgxxxxxx4.png) imgBuf.purge(); char fn2[128]; sprintf(fn2,"/tmp/tmpimg%lu-4.png",getTimeLocal()); imgBuf.load ( "" , fn2 ); // now insert that into the http reply char *insertionPoint = strstr(rb->getBufStart(),"filename=\""); // skip if can't find it if ( ! insertionPoint ) return; // skip over filename=\" insertionPoint += 10; // put our junk there long insertPos = insertionPoint - rb->getBufStart(); rb->insert("img.png", insertPos ); // find the \r\n\r\n after that point char *imgData = strstr(rb->getBufStart()+insertPos,"\r\n\r\n"); imgData += 4; long dataPos = imgData - rb->getBufStart(); // note it log("submit: inserting image of %li bytes",imgBuf.length()); // then the image content rb->insert2 ( imgBuf.getBufStart() , imgBuf.length(),dataPos ); } // the original form submission url, a page on the external // event submission server char *formUrl = st->m_hr.getString ("formproxyto",NULL); // now get formurl from the file //SafeBuf info; //info.loadFromFile2("/tmp/tmpfile",formUrlHash32); //char *formUrl = info.getBufStart(); // fake it //formUrl = "http://www.itsatrip.org/events/submit.aspx"; // now the request buf will be like "POST / HTTP/1.1\r\n...." // so we have to replace "/" with "formUrl" which is the original // url being submitted to because we had made it our own server ip // on the path of "/". so formUrl's path needs to go there. char *ourPath = strstr(rb->getBufStart()," / "); if ( ! ourPath ) { g_errno = EBADREPLY; goto hadError; } ourPath += 1; Url ff; ff.set(formUrl); char *path = ff.getPath(); long plen = ff.getPathLen(); rb->safeReplace ( path , plen , ourPath - rb->getBufStart() , 1 ); // replace "Host: 10.5.1.203:8000\r\n" with the right host char *host = ff.getHost(); long hlen = ff.getHostLen(); char *hostLine = strstr(rb->getBufStart(),"Host: "); hostLine += 6; char *hostLineEnd = strstr(hostLine,"\r\n"); if ( ! hostLine || ! hostLineEnd){g_errno = EBADREPLY; goto hadError; } long hostLinePos = hostLine - rb->getBufStart(); long hostLineLen = hostLineEnd - hostLine; rb->safeReplace ( host, hlen , hostLinePos, hostLineLen ); // remove stuff. otherwise we pass them in cookie from eventguru! // and referer is like 10.5.1.203/... removeLine ( rb , "Referer: "); removeLine ( rb , "Cookie: "); // take out the gzip encoding removeLine ( rb , "Accept-Encoding:"); // we added these hidden form variables for proxying purposes // so we have to remove them now removeDisposition ( rb , "formproxyto" ); removeDisposition ( rb , "egimgurl" ); // . now we must adjust the content-length // . YEAH, because inserting the image screws this up!!! adjustContentLength ( rb ); char *req = rb->getBufStart(); long allocated = rb->getCapacity(); long reqSize = rb->length(); rb->detachBuf(); // use this directly since we are just forwarding the request TcpServer *tcp = &g_httpServer.m_tcp; // . because buffer is now owned by this socket // . we should relay the reply from the submission server back to // our st->m_socket when it comes in!!! // . so set the callback to do that if ( ! tcp->sendMsg ( formUrl , // host/port req, allocated, reqSize, reqSize, st , relayReply,//callback 60 , // timeout 999999999 ,// maxtextdoclen 999999999 // maxotherdoclen ) ) return; // did not block, must have been an error relayReply ( st , NULL ); } void relayReply ( void *state , TcpSocket *subsock ) { // cast it State27 *st = (State27 *)state; // if failed to submit the event if ( g_errno || ! subsock ) { log("submit: failed to send to submission server: %s", mstrerror(g_errno)); TcpSocket *s = st->m_socket; mdelete ( st , sizeof(State27) , "pageprox" ); delete (st); g_httpServer.sendErrorReply(s,500,mstrerror(g_errno)); return; } // return reply back as it is char *reply = subsock->m_readBuf; long replySize = subsock->m_readOffset; //long allocSize = subsock->m_readBufSize; // do not double free //subsock->m_readBuf = NULL; // copy over st->m_relayBuf.safeMemcpy ( reply , replySize ); char *formUrl = st->m_hr.getString ("formproxyto",NULL); char ttt[128+MAX_URL_LEN]; sprintf(ttt,"\n",formUrl); char *cstart = strstr(st->m_relayBuf.getBufStart(),"\r\n\r\n"); long cpos; if ( cstart ) cstart += 4; if ( cstart ) cpos = cstart - st->m_relayBuf.getBufStart(); // insert the base href tag! st->m_relayBuf.insert2 ( ttt,gbstrlen(ttt),cpos ); // re-set Content-Length adjustContentLength ( &st->m_relayBuf ); // shortcuts char *relay = st->m_relayBuf.getBufStart(); long relaySize = st->m_relayBuf.length(); long relayAllocSize = st->m_relayBuf.getCapacity(); // . let tcpserver free it when done transmitting it // . detach after setting "relay" because it sets m_buf to null st->m_relayBuf.detachBuf(); // . relay the submission server's reply back to the admin // . crap this is including the http mime! /* g_httpServer.sendDynamicPage( st->m_socket , reply , replySize , -1, //cachtime false ,//postreply? NULL, //ctype -1 , //httpstatus NULL,//cookie "utf-8"); */ // use this directly since we are just forwarding the request TcpServer *tcp = &g_httpServer.m_tcp; // . because buffer is now owned by this socket // . we should relay the reply from the submission server back to // our st->m_socket when it comes in!!! // . so set the callback to do that tcp->sendMsg ( st->m_socket , relay, // st->m_relayBuf.getBufStart(), // reply, relayAllocSize, relaySize, // replySize, relaySize, // replySize, NULL , // state NULL//callback ); // nuke it after sendMsg() call so formUrl is valid for it mdelete ( st , sizeof(State27) , "pageprox" ); delete (st); } void removeLine ( SafeBuf *rb , char *lineStart ) { char *s = rb->getBufStart(); char *line = strstr(s , lineStart ); if ( ! line ) return; // find end of line char *end = line; for ( ; *end ; end++ ) if ( *end == '\r' && end[1] == '\n' ) break; // no end? if ( ! end ) return; end += 2; rb->safeReplace ( "" , 0 , line - s , end - line ); } // name = "formproxyto" etc. // \r\n\r\n", '-' , "148434662416964166751880432549\r\nContent-Disposition: form-data; name=\"formproxyto\"\r\n\r\nhttp://www.itsatrip.org/events/submit.aspx\r\n", '-' , "148434662416964166751880432549 void removeDisposition ( SafeBuf *rb , char *name ) { char *start = rb->getBufStart(); char *f = strstr(start,name); if ( ! f ) return; // back up to start of "Content-Disposition:" line char *b = f; for ( ; b > start ; b-- ) if ( !strncasecmp(b,"Content-Disposition:",20)) break; if ( b == start ) return; // now go forward until next Content-Disposition: line char *next = f; for ( ; *next ; next++ ) if ( !strncasecmp(next,"Content-Disposition:",20)) break; if ( ! *next ) return; // nuke that rb->safeReplace ( "" , 0 , b - start , next - b ); } void adjustContentLength ( SafeBuf *rb ) { char *start = rb->getBufStart(); char *f = strstr(start,"Content-Length:"); if ( ! f ) return; // skip to number for ( ; *f ; f++ ) { if ( is_digit(*f) ) break; } // find start of content char *cs = strstr(start,"\r\n\r\n"); if ( ! cs ) return; cs += 4; long headerLen = cs - start; //long clen = gbstrlen(cs); long clen = rb->length() - headerLen; // find length of number, nd = # of digits long nd = 0; char *fe = f; for ( ; *fe ; fe++ ) { if ( ! is_digit(*fe) ) break; nd++; } // write that out char format[64]; sprintf(format,"%%0%lili",nd); char ttt[32]; long toPrint = sprintf(ttt,format,clen); // just copy it over, padded with zeroes memcpy ( f , ttt , toPrint ); }