/** * Parse an XML string into a nested list. * The second parameter indicates if body text (text within XML tags) * should show up among the children of the tag or in its own * section. * * See documentation (ext-xml.README) for examples. */ static package parse_xml(const char *data, int bool_stream) { /* * FIXME: Feed expat smaller chunks of the string and * check for task timeout between chunks * */ int decoded_length; const char *decoded; package result; XML_Parser parser = XML_ParserCreate(NULL); XMLdata *root = new_node(NULL, ""); XMLdata *child = root; decoded_length = strlen(data); decoded = data; XML_SetUserData(parser, &child); XML_SetElementHandler(parser, xml_startElement, xml_endElement); if(bool_stream) { XML_SetCharacterDataHandler(parser, xml_streamCharacterDataHandler); } else { XML_SetCharacterDataHandler(parser, xml_characterDataHandler); } if (!XML_Parse(parser, decoded, decoded_length, 1)) { Var r; r.type = TYPE_INT; r.v.num = XML_GetCurrentByteIndex(parser); flush_nodes(child); result = make_raise_pack(E_INVARG, XML_ErrorString(XML_GetErrorCode(parser)), r); } else { finish_node(root); result = make_var_pack(var_ref(root->element.v.list[4].v.list[1])); free_node(root); } XML_ParserFree(parser); return result; }
static package bf_http_request( Var arglist, Byte next, void *vdata, Objid progr) { CURL *curl_handle; CURLcode ok; package result; if (!is_wizard(progr)) { free_var(arglist); return make_error_pack(E_PERM); } int nargs = arglist.v.list[0].v.num; const char *address = arglist.v.list[1].v.str; const char *agent="",*postfields="",*cookies=""; int headers = 0; switch(nargs) { case 5: cookies = arglist.v.list[5].v.str; case 4: postfields = arglist.v.list[4].v.str; case 3: agent = arglist.v.list[3].v.str; case 2: headers = arglist.v.list[2].v.num; } if(!strlen(agent)) agent = "MOO-http/1.0"; const char delimiters[] = "\n"; free_var(arglist); struct MemoryStruct chunk; chunk.memory = malloc(1); chunk.size = 0; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, address); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, agent); curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 5); curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl_handle, CURLOPT_FTP_RESPONSE_TIMEOUT, 3); curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 5); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl_handle, CURLOPT_MAXFILESIZE, 1048576); if(strlen(postfields)) curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, postfields); if(strlen(cookies)) curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookies); if(headers) curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1); ok = curl_easy_perform(curl_handle); curl_easy_cleanup(curl_handle); if(ok == CURLE_OK && strlen(chunk.memory) != chunk.size) ok = CURLE_BAD_CONTENT_ENCODING; // binary !!! if(ok == CURLE_OK) { char *token,*p=chunk.memory; Var r; r.type = TYPE_LIST; r = new_list(0); token = strsep(&p, delimiters); while( token != NULL ) { Var line; line.type = TYPE_STR; if(token[strlen(token)-1] == '\r') token[strlen(token)-1] = '\0'; //run it through utf8_substr to get rid of invalid utf8 line.v.str = (char *)utf8_substr(token,1,utf8_strlen(token)); r = listappend(r, var_dup(line)); token = strsep(&p, delimiters); free_var(line); } result = make_var_pack(r); } else { Var r; r.type = TYPE_INT; r.v.num = ok; result = make_raise_pack(E_INVARG, curl_easy_strerror(ok), r); } if(chunk.memory) free(chunk.memory); curl_global_cleanup(); return result; }