static package bf_mysql_close(Var arglist, Byte next, void *vdata, Objid progr) { Var r; Objid oid = arglist.v.list[1].v.obj; r.type = TYPE_INT; free_var(arglist); MYSQL_CONN *wrapper; if (!is_wizard(progr)) return make_error_pack(E_PERM); wrapper = resolve_mysql_connection(oid); if (wrapper == NULL) { r.v.num = 0; return make_var_pack(r); } else { wrapper->active = 0; wrapper->id = 0; wrapper->port = 0; wrapper->connect_time = 0; wrapper->last_query_time = 0; r.v.num = 1; } if (mysql_connection_status(wrapper) != 0) { do_mysql_disconnect(wrapper); wrapper->conn = NULL; r.v.num = 1; } return make_var_pack(r); }
static package bf_mysql_connect(Var arglist, Byte next, void *vdata, Objid progr) { #ifdef OUTBOUND_NETWORK Var r; char error_string[MOOSQL_ERROR_LEN]; MYSQL_CONN *wrapper; if (!is_wizard(progr)) { free_var(arglist); return make_error_pack(E_PERM); } const char *hostname = arglist.v.list[1].v.str; const int port = arglist.v.list[2].v.num; const char *username = arglist.v.list[3].v.str; const char *password = arglist.v.list[4].v.str; const char *dbname = arglist.v.list[5].v.str; free_var(arglist); /* get rid of that now */ /* try to connect to mysql server */ /* check if we have enough connection slots. */ int index=-1; index = connection_array_index(); if (index == -1) return make_error_pack(E_QUOTA); #ifdef MOOSQL_MULTIPLE_STATEMENTS wrapper = do_mysql_connect(hostname, username, password, dbname, port, NULL, CLIENT_MULTI_STATEMENTS, error_string); #else wrapper = do_mysql_connect(hostname, username, password, dbname, port, NULL, 0, error_string); #endif if (wrapper == NULL || wrapper->conn == NULL) { /* an error happened in the connect, return that as a STR */ r.type = TYPE_STR; r.v.str = str_dup(error_string); return make_var_pack(r); } r.type = TYPE_OBJ; r.v.obj = wrapper->id; return make_var_pack(r); #else /* !OUTBOUND_NETWORK */ /* This function is disabled in this server. */ free_var(arglist); return make_error_pack(E_PERM); #endif }
static package bf_mysql_escape( Var arglist, Byte next, void *vdata, Objid progr) { Var r; MYSQL_CONN *wrapper; if (!is_wizard(progr)) { free_var(arglist); return make_error_pack(E_PERM); } Objid oid = arglist.v.list[1].v.obj; wrapper = resolve_mysql_connection(oid); if (wrapper == NULL || wrapper->conn == NULL || wrapper->active == 0) { free_var(arglist); return make_error_pack(E_INVARG); } const char *string = arglist.v.list[2].v.str; free_var(arglist); ulong bytes = strlen(string); char ostring[(2 * bytes)+1]; mysql_real_escape_string(wrapper->conn,ostring,string,bytes); r.type = TYPE_STR; r.v.str = str_dup(ostring); return make_var_pack(r); }
static package bf_verb_code(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, verb-desc [, fully-paren [, indent]]) */ int nargs = arglist.v.list[0].v.num; Objid oid = arglist.v.list[1].v.obj; Var desc = arglist.v.list[2]; int parens = nargs >= 3 && is_true(arglist.v.list[3]); int indent = nargs < 4 || is_true(arglist.v.list[4]); db_verb_handle h; Var code; enum error e; if ((e = validate_verb_descriptor(desc)) != E_NONE || (e = E_INVARG, !valid(oid))) { free_var(arglist); return make_error_pack(e); } h = find_described_verb(oid, desc); free_var(arglist); if (!h.ptr) return make_error_pack(E_VERBNF); else if (!db_verb_allows(h, progr, VF_READ)) return make_error_pack(E_PERM); code = new_list(0); unparse_program(db_verb_program(h), lister, &code, parens, indent, MAIN_VECTOR); return make_var_pack(code); }
static package bf_mysql_status(Var arglist, Byte next, void *vdata, Objid progr) { Var r; Objid oid = arglist.v.list[1].v.obj; free_var(arglist); if (!is_wizard(progr)) return make_error_pack(E_PERM); MYSQL_CONN *wrapper; wrapper = resolve_mysql_connection(oid); if (wrapper == NULL || wrapper->active == 0) return make_error_pack(E_INVARG); r = new_list(7); r.v.list[1].type = TYPE_STR; r.v.list[1].v.str = str_dup(wrapper->server); r.v.list[2].type = TYPE_INT; r.v.list[2].v.num = wrapper->port; r.v.list[3].type = TYPE_STR; r.v.list[3].v.str = str_dup(wrapper->username); r.v.list[4].type = TYPE_STR; r.v.list[4].v.str = str_dup(wrapper->database); r.v.list[5].type = TYPE_INT; r.v.list[5].v.num = wrapper->connect_time; r.v.list[6].type = TYPE_INT; r.v.list[6].v.num = wrapper->last_query_time; r.v.list[7].type = TYPE_INT; r.v.list[7].v.num = mysql_get_server_version(wrapper->conn); return make_var_pack(r); }
static package bf_slice(Var arglist, Byte next, void *vdata, Objid progr) { Var ret, list=arglist.v.list[1]; int n=list.v.list[0].v.num, c, i; if(n < 0) { free_var(arglist); make_error_pack(E_INVARG); } ret = new_list(n); InitListToZero(ret); if(arglist.v.list[0].v.num == 2) c = arglist.v.list[2].v.num; else c = 1; for(i = 1; i <= n; i++) if( list.v.list[i].type != TYPE_LIST || list.v.list[i].v.list[0].v.num < c ) { free_var(ret); free_var(arglist); return make_error_pack(E_INVARG); } else { ret.v.list[i] = var_dup(list.v.list[i].v.list[c]); } free_var(arglist); return make_var_pack(ret); }
static package bf_has_callable_verb(Var arglist, Byte next, void *vdata, Objid progr) { /* (object) */ Objid oid = arglist.v.list[1].v.obj; if (!valid(oid)) { free_var(arglist); return make_error_pack(E_INVARG); } else if (!db_object_allows(oid, progr, FLAG_READ)) { free_var(arglist); return make_error_pack(E_PERM); } else { db_verb_handle vh; Var result; vh = db_find_callable_verb(oid, arglist.v.list[2].v.str); if (vh.ptr) { result = new_list(1); result.v.list[1].type = TYPE_OBJ; result.v.list[1].v.obj = db_verb_definer(vh); } else { result = new_list(0); } free_var(arglist); return make_var_pack(result); } }
static package bf_sort(Var arglist, Byte next, void *vdata, Objid progr) { /* sort(list) => sorts and returns list. sort({1,3,2}) => {1,2,3} */ /* returns E_TYPE is list is not all the same type */ Var sorted = new_list(0), tmp; Var e; int i, l; e.type=TYPE_NONE; for(i = 1; i <= arglist.v.list[1].v.list[0].v.num; i++) { e = var_ref(arglist.v.list[1].v.list[i]); l = find_insert(sorted, e); if(l == -10) { free_var(arglist); free_var(sorted); free_var(e); return make_error_pack(E_TYPE); } tmp = listinsert(var_ref(sorted), var_ref(e), l); free_var(sorted); sorted = var_ref(tmp); free_var(tmp); } free_var(arglist); free_var(e); return make_var_pack(sorted); }
static package bf_make(Var arglist, Byte next, void *vdata, Objid progr) { Var ret, elt; int n=arglist.v.list[1].v.num, i; if(n < 0) { free_var(arglist); make_error_pack(E_INVARG); } ret = new_list(n); InitListToZero(ret); if(arglist.v.list[0].v.num == 2) { elt = var_dup(arglist.v.list[2]); } else { elt.type = TYPE_INT; elt.v.num = 0; } for(i = 1; i <= n; i++) ret.v.list[i] = var_dup(elt); free_var(elt); free_var(arglist); return make_var_pack(ret); }
static package bf_urldecode( Var arglist, Byte next, void *vdata, Objid progr) { Var r; CURL *curl_handle; const char *string = arglist.v.list[1].v.str; free_var(arglist); curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); r.type = TYPE_STR; char *output = curl_easy_unescape(curl_handle,string,0,NULL); if(output == NULL) { curl_free(output); return make_error_pack(E_INVARG); } r.v.str = str_dup(output); curl_free(output); curl_easy_cleanup(curl_handle); curl_global_cleanup(); return make_var_pack(r); }
static package bf_verb_args(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, verb-desc) */ Objid oid = arglist.v.list[1].v.obj; Var desc = arglist.v.list[2]; db_verb_handle h; db_arg_spec dobj, iobj; db_prep_spec prep; Var r; enum error e; if ((e = validate_verb_descriptor(desc)) != E_NONE || (e = E_INVARG, !valid(oid))) { free_var(arglist); return make_error_pack(e); } h = find_described_verb(oid, desc); free_var(arglist); if (!h.ptr) return make_error_pack(E_VERBNF); else if (!db_verb_allows(h, progr, VF_READ)) return make_error_pack(E_PERM); db_verb_arg_specs(h, &dobj, &prep, &iobj); r = new_list(3); r.v.list[1].type = TYPE_STR; r.v.list[1].v.str = unparse_arg_spec(dobj); r.v.list[2].type = TYPE_STR; r.v.list[2].v.str = str_dup(db_unparse_prep(prep)); r.v.list[3].type = TYPE_STR; r.v.list[3].v.str = unparse_arg_spec(iobj); return make_var_pack(r); }
static package bf_is_clear_prop(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, prop-name) */ Objid oid = arglist.v.list[1].v.obj; const char *pname = arglist.v.list[2].v.str; Var r; db_prop_handle h; enum error e; if (!valid(oid)) e = E_INVARG; else { h = db_find_property(oid, pname, 0); if (!h.ptr) e = E_PROPNF; else if (!h.built_in && !db_property_allows(h, progr, PF_READ)) e = E_PERM; else { r.type = TYPE_INT; r.v.num = (!h.built_in && db_property_value(h).type == TYPE_CLEAR); e = E_NONE; } } free_var(arglist); if (e == E_NONE) return make_var_pack(r); else return make_error_pack(e); }
static package bf_eval(Var arglist, Byte next, void *data, Objid progr) { package p; if (next == 1) { if (!is_programmer(progr)) { free_var(arglist); p = make_error_pack(E_PERM); } else { Var errors; Program *program = parse_list_as_program(arglist, &errors); free_var(arglist); if (program) { free_var(errors); if (setup_activ_for_eval(program)) p = make_call_pack(2, 0); else { free_program(program); p = make_error_pack(E_MAXREC); } } else { Var r; r = new_list(2); r.v.list[1].type = TYPE_INT; r.v.list[1].v.num = 0; r.v.list[2] = errors; p = make_var_pack(r); } } } else { /* next == 2 */ Var r; r = new_list(2); r.v.list[1].type = TYPE_INT; r.v.list[1].v.num = 1; r.v.list[2] = arglist; p = make_var_pack(r); } return p; }
/* Remove_Duplicates - from Access_Denied@LambdaMOO. */ static package bf_remove_duplicates(Var arglist, Byte next, void *vdata, Objid progr) { Var r; int i; r = new_list(0); for (i = 1; i <= arglist.v.list[1].v.list[0].v.num; i++) r = setadd(r, var_ref(arglist.v.list[1].v.list[i])); free_var(arglist); return make_var_pack(r); }
static package bf_verb_cache_stats(Var arglist, Byte next, void *vdata, Objid progr) { Var r; free_var(arglist); if (!is_wizard(progr)) { return make_error_pack(E_PERM); } r = db_verb_cache_stats(); return make_var_pack(r); }
static package bf_mysql_ping(Var arglist, Byte next, void *vdata, Objid progr) { /* we will return 1 if the connection is active, 0 if it is not */ Var r; Objid oid = arglist.v.list[1].v.obj; free_var(arglist); if (!is_wizard(progr)) return make_error_pack(E_PERM); MYSQL_CONN *wrapper; wrapper = resolve_mysql_connection(oid); r.type = TYPE_INT; r.v.num = mysql_connection_status(wrapper); return make_var_pack(r); }
static package bf_generate_json(Var arglist, Byte next, void *vdata, Objid progr) { yajl_gen g; yajl_gen_config cfg = { 0, "" }; struct generate_context gctx; gctx.mode = MODE_COMMON_SUBSET; const char *buf; unsigned int len; Var json; package pack; if (1 < arglist.v.list[0].v.num) { if (!mystrcasecmp(arglist.v.list[2].v.str, "common-subset")) { gctx.mode = MODE_COMMON_SUBSET; } else if (!mystrcasecmp(arglist.v.list[2].v.str, "embedded-types")) { gctx.mode = MODE_EMBEDDED_TYPES; } else { free_var(arglist); return make_error_pack(E_INVARG); } } g = yajl_gen_alloc(&cfg, NULL); if (yajl_gen_status_ok == generate(g, arglist.v.list[1], &gctx)) { yajl_gen_get_buf(g, (const unsigned char **)&buf, &len); json.type = TYPE_STR; json.v.str = str_dup(buf); pack = make_var_pack(json); } else { pack = make_error_pack(E_INVARG); } yajl_gen_clear(g); yajl_gen_free(g); free_var(arglist); return pack; }
static package bf_verb_info(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, verb-desc) */ Objid oid = arglist.v.list[1].v.obj; Var desc = arglist.v.list[2]; db_verb_handle h; Var r; unsigned flags; char perms[5], *s; enum error e; if ((e = validate_verb_descriptor(desc)) != E_NONE || (e = E_INVARG, !valid(oid))) { free_var(arglist); return make_error_pack(e); } h = find_described_verb(oid, desc); free_var(arglist); if (!h.ptr) return make_error_pack(E_VERBNF); else if (!db_verb_allows(h, progr, VF_READ)) return make_error_pack(E_PERM); r = new_list(3); r.v.list[1].type = TYPE_OBJ; r.v.list[1].v.obj = db_verb_owner(h); r.v.list[2].type = TYPE_STR; s = perms; flags = db_verb_flags(h); if (flags & VF_READ) *s++ = 'r'; if (flags & VF_WRITE) *s++ = 'w'; if (flags & VF_EXEC) *s++ = 'x'; if (flags & VF_DEBUG) *s++ = 'd'; *s = '\0'; r.v.list[2].v.str = str_dup(perms); r.v.list[3].type = TYPE_STR; r.v.list[3].v.str = str_ref(db_verb_names(h)); return make_var_pack(r); }
static package bf_assoc(Var arglist, Byte next, void *vdata, Objid progr) { /* (ANY, LIST[, INT]) */ Var r; int index = 1; if (arglist.v.list[0].v.num == 3) index = arglist.v.list[3].v.num; if (index < 1) { free_var(arglist); return make_error_pack(E_RANGE); } r = list_assoc(arglist.v.list[1], arglist.v.list[2], index); free_var(arglist); return make_var_pack(r); } /* end bf_listassoc() */
static package bf_verbs(Var arglist, Byte next, void *vdata, Objid progr) { /* (object) */ Objid oid = arglist.v.list[1].v.obj; free_var(arglist); if (!valid(oid)) return make_error_pack(E_INVARG); else if (!db_object_allows(oid, progr, FLAG_READ)) return make_error_pack(E_PERM); else { struct verb_data d; d.r = new_list(db_count_verbs(oid)); d.i = 0; db_for_all_verbs(oid, add_to_list, &d); return make_var_pack(d.r); } }
static package bf_prop_info(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, prop-name) */ Objid oid = arglist.v.list[1].v.obj; const char *pname = arglist.v.list[2].v.str; db_prop_handle h; Var r; unsigned flags; char *s; if (!valid(oid)) { free_var(arglist); return make_error_pack(E_INVARG); } h = db_find_property(oid, pname, 0); free_var(arglist); if (!h.ptr || h.built_in) return make_error_pack(E_PROPNF); else if (!db_property_allows(h, progr, PF_READ)) return make_error_pack(E_PERM); r = new_list(2); r.v.list[1].type = TYPE_OBJ; r.v.list[1].v.obj = db_property_owner(h); r.v.list[2].type = TYPE_STR; r.v.list[2].v.str = s = str_dup("xxx"); flags = db_property_flags(h); if (flags & PF_READ) *s++ = 'r'; if (flags & PF_WRITE) *s++ = 'w'; if (flags & PF_CHOWN) *s++ = 'c'; if (flags & PF_PRIVATE) *s++ = 'p'; *s = '\0'; return make_var_pack(r); }
/** * 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_set_verb_code(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, verb-desc, code) */ Objid oid = arglist.v.list[1].v.obj; Var desc = arglist.v.list[2]; Var code = arglist.v.list[3]; int i; Program *program; db_verb_handle h; Var errors; enum error e; for (i = 1; i <= code.v.list[0].v.num; i++) if (code.v.list[i].type != TYPE_STR) { free_var(arglist); return make_error_pack(E_TYPE); } if ((e = validate_verb_descriptor(desc)) != E_NONE || (e = E_INVARG, !valid(oid))) { free_var(arglist); return make_error_pack(e); } h = find_described_verb(oid, desc); if (!h.ptr) { free_var(arglist); return make_error_pack(E_VERBNF); } else if (!is_programmer(progr) || !db_verb_allows(h, progr, VF_WRITE)) { free_var(arglist); return make_error_pack(E_PERM); } program = parse_list_as_program(code, &errors); if (program) { if (task_timed_out) free_program(program); else db_set_verb_program(h, program); } free_var(arglist); return make_var_pack(errors); }
static package bf_mysql_connections(Var arglist, Byte next, void *vdata, Objid progr) { Var r; free_var(arglist); if (!is_wizard(progr)) return make_error_pack(E_PERM); int count=0; int lcv=0; for (lcv=0;lcv<MOOSQL_MAX_CON;lcv++) if (SQL_CONNECTIONS[lcv].active == 1) count++; r = new_list(count); /* needed to know how many to allocate the list firstly */ count = 0; for (lcv=0;lcv<MOOSQL_MAX_CON;lcv++) { if (SQL_CONNECTIONS[lcv].active == 1) { count++; r.v.list[count].type = TYPE_OBJ; r.v.list[count].v.obj = SQL_CONNECTIONS[lcv].id; } } return make_var_pack(r); }
static package bf_has_property(Var arglist, Byte next, void *vdata, Objid progr) { /* (object) */ Objid oid = arglist.v.list[1].v.obj; if (!valid(oid)) { free_var(arglist); return make_error_pack(E_INVARG); } else if (!db_object_allows(oid, progr, FLAG_READ)) { free_var(arglist); return make_error_pack(E_PERM); } else { Var result; result.type = TYPE_INT; if (db_find_property(oid, arglist.v.list[2].v.str, 0).ptr) { result.v.num = 1; } else { result.v.num = 0; } free_var(arglist); return make_var_pack(result); } }
static package bf_add_verb(Var arglist, Byte next, void *vdata, Objid progr) { /* (object, info, args) */ Objid oid = arglist.v.list[1].v.obj; Var info = arglist.v.list[2]; Var args = arglist.v.list[3]; Var result; Objid owner; unsigned flags; const char *names; db_arg_spec dobj, iobj; db_prep_spec prep; enum error e; if ((e = validate_verb_info(info, &owner, &flags, &names)) != E_NONE) /* Already failed */ ; else if ((e = validate_verb_args(args, &dobj, &prep, &iobj)) != E_NONE) free_str(names); else if (!valid(oid)) { free_str(names); e = E_INVARG; } else if (!db_object_allows(oid, progr, FLAG_WRITE) || (progr != owner && !is_wizard(progr))) { free_str(names); e = E_PERM; } else { result.type = TYPE_INT; result.v.num = db_add_verb(oid, names, owner, flags, dobj, prep, iobj); } free_var(arglist); if (e == E_NONE) return make_var_pack(result); else return make_error_pack(e); }
static package bf_mysql_query( Var arglist, Byte next, void *vdata, Objid progr) { Var r; char error_string[MOOSQL_ERROR_LEN]; MYSQL_CONN *wrapper; MYSQL_RES *res_set; #ifdef MOOSQL_MULTIPLE_STATEMENTS Var tmp; Var end; int len = 0; int continu = 1; #endif if (!is_wizard(progr)) { free_var(arglist); return make_error_pack(E_PERM); } Objid oid = arglist.v.list[1].v.obj; wrapper = resolve_mysql_connection(oid); if (wrapper == NULL || wrapper->conn == NULL || wrapper->active == 0) { free_var(arglist); return make_error_pack(E_INVARG); } const char *query = arglist.v.list[2].v.str; free_var(arglist); /* we do the query now. */ if (mysql_query (wrapper->conn, query) != 0) /* failed */ { /* there is an error, so we will return that string. similar to below which * returns a string for a successful query with no result set which is handled in * process_mysql_query */ snprintf(error_string,MOOSQL_ERROR_LEN,"ERR: %s",mysql_error(wrapper->conn)); r.type = TYPE_STR; r.v.str = str_dup(error_string); return make_var_pack(r); } wrapper->last_query_time = time(0); #ifdef MOOSQL_MULTIPLE_STATEMENTS r = new_list(1); r.v.list[1].type = TYPE_INT; r.v.list[1].v.num = 0; end = new_list(0); while (continu) { len++; res_set = process_mysql_query(wrapper,error_string); if (res_set == NULL) /* there was no result on this query */ { tmp.type = TYPE_STR; tmp.v.str = str_dup(error_string); end = listappend(end,var_dup(tmp)); } else { tmp = process_result_set(wrapper,res_set); end = listappend(end,var_dup(tmp)); } if (mysql_more_results(wrapper->conn)) { mysql_next_result(wrapper->conn); continu = 1; } else continu = 0; } if (len <= 1) /* if there is only one result return it like in previous versions, a list of rows */ return make_var_pack(end.v.list[1]); r.v.list[1].v.num = len; /* if there are more return it in this format {X, Y} where X is the number of results and Y is a list of results */ r = listappend(r,end); return make_var_pack(r); #else res_set = process_mysql_query(wrapper,error_string); if (res_set == NULL) /* there was either an error / no result on this query */ { r.type = TYPE_STR; r.v.str = str_dup(error_string); return make_var_pack(r); } r = process_result_set(wrapper,res_set); return make_var_pack(r); #endif }
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; }
static package bf_parse_json(Var arglist, Byte next, void *vdata, Objid progr) { yajl_handle hand; yajl_parser_config cfg = { 1, 1 }; yajl_status stat; struct parse_context pctx; pctx.top = &pctx.stack; pctx.stack.v.type = TYPE_INT; pctx.stack.v.v.num = 0; pctx.mode = MODE_COMMON_SUBSET; const char *str = arglist.v.list[1].v.str; size_t len = strlen(str); package pack; int done = 0; if (1 < arglist.v.list[0].v.num) { if (!mystrcasecmp(arglist.v.list[2].v.str, "common-subset")) { pctx.mode = MODE_COMMON_SUBSET; } else if (!mystrcasecmp(arglist.v.list[2].v.str, "embedded-types")) { pctx.mode = MODE_EMBEDDED_TYPES; } else { free_var(arglist); return make_error_pack(E_INVARG); } } hand = yajl_alloc(&callbacks, &cfg, NULL, (void *)&pctx); while (!done) { if (len == 0) done = 1; if (done) stat = yajl_parse_complete(hand); else stat = yajl_parse(hand, (const unsigned char *)str, len); len = 0; if (done) { if (stat != yajl_status_ok) { /* clean up the stack */ while (pctx.top != &pctx.stack) { Var v = POP(pctx.top); free_var(v); } pack = make_error_pack(E_INVARG); } else { Var v = POP(pctx.top); pack = make_var_pack(v); } } } yajl_free(hand); free_var(arglist); return pack; }