std::map<std::string,std::string> uri_parse_query(const std::string& query) { UriParserStateA state; UriUriA uri; state.uri=&uri; UriQueryListA* list; if(uriParseUriA(&state,query.c_str())!=0|| uriDissectQueryMallocA(&list,nullptr,uri.query.first,uri.query.afterLast)!=0) { uriFreeUriMembersA(&uri); return {{"error","Bad string."}}; } std::map<std::string,std::string> queries; auto head=list; while(head!=nullptr) { if(head->key!=nullptr) { if(head->value!=nullptr) queries[std::string(head->key)]=std::string(head->value); else queries[std::string(head->key)]="true"; } head=head->next; } uriFreeQueryListA(list); uriFreeUriMembersA(&uri); return queries; }
int httpd_query_iterate(const char *uri_str, query_iterate_func f, void *userdata) { UriParserStateA state; UriUriA uri; UriQueryListA *queryList, *p; int itemCount; state.uri = &uri; if (uriParseUriA(&state, uri_str) != URI_SUCCESS) { uriFreeUriMembersA(&uri); return 1; } if (uriDissectQueryMallocA(&queryList, &itemCount, uri.query.first, uri.query.afterLast) != URI_SUCCESS) { uriFreeUriMembersA(&uri); return 1; } p = queryList; while(NULL != p) { if (0 == f(p->key, p->value, userdata)) break; p = p->next; } uriFreeQueryListA(queryList); uriFreeUriMembersA(&uri); return 0; }
void HttpHandler::parseURL(const char* request_uri) { this->parameter = new std::unordered_map<std::string, std::string>(); UriParserStateA state; UriUriA uri; state.uri = &uri; if (request_uri == nullptr) { return; } if (uriParseUriA(&state, request_uri) != URI_SUCCESS) { uriFreeUriMembersA(&uri); return; } UriQueryListA* queryList; int itemCount; if (uriDissectQueryMallocA(&queryList, &itemCount, uri.query.first, uri.query.afterLast) == URI_SUCCESS) { auto& current = queryList; do { if (queryList->value != nullptr) { auto buffer = new char[std::strlen(queryList->value) + 1]; std::strcpy(buffer, (char*) queryList->value); uriUnescapeInPlaceExA(buffer, false, URI_BR_DONT_TOUCH); (*this->parameter)[queryList->key] = buffer; delete[] buffer; } else { (*this->parameter)[queryList->key] = std::string(""); } current = queryList->next; } while (current != nullptr); uriFreeQueryListA(queryList); uriFreeUriMembersA(&uri); return; } }
Datum parse_uri(PG_FUNCTION_ARGS) { TupleDesc tupledesc; AttInMetadata *attinmeta; text* input=PG_GETARG_TEXT_P(0); /* Function is defined STRICT in SQL, so no NULL check is needed. */ bool normalize=PG_GETARG_BOOL(1); bool parse_query=PG_GETARG_BOOL(2); char* inp=palloc((1+VARSIZE(input)-VARHDRSZ)*sizeof(char)); if (!inp) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpy(inp,VARDATA(input),VARSIZE(input)-VARHDRSZ); inp[VARSIZE(input)-VARHDRSZ]='\0'; /* Function internals start here */ int i; int memctr; UriPathSegmentA* pathseg; int quit; char* writehere; UriParserStateA state; UriUriA uri; state.uri = &uri; if (uriParseUriA(&state, inp) != URI_SUCCESS) { uriFreeUriMembersA(&uri); /* ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Unable to parse URI."))); */ PG_RETURN_NULL(); } if (normalize) { if (uriNormalizeSyntaxA(&uri) != URI_SUCCESS) { uriFreeUriMembersA(&uri); PG_RETURN_NULL(); } } UriQueryListA* queryList=NULL; int itemCount; if (parse_query&&(uri.query.afterLast!=uri.query.first)) { if (uriDissectQueryMallocA(&queryList, &itemCount, uri.query.first, uri.query.afterLast) != URI_SUCCESS) { uriFreeUriMembersA(&uri); uriFreeQueryListA(queryList); PG_RETURN_NULL(); } } /* Function internals finish here */ if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); PG_RETURN_NULL(); } /* This error should never happen, because the SQL function is defined as returning a uri_type. */ attinmeta = TupleDescGetAttInMetadata(tupledesc); char** retval=(char**) palloc(13*sizeof(char*)); if (!retval) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } if (uri.scheme.afterLast==uri.scheme.first) { retval[0]=NULL; } else { retval[0]=(char*) palloc((1+(uri.scheme.afterLast-uri.scheme.first))*sizeof(char)); /* scheme, e.g. "http" */ if (!retval[0]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[0],uri.scheme.first,uri.scheme.afterLast-uri.scheme.first); } if (uri.userInfo.afterLast==uri.userInfo.first) { retval[1]=NULL; } else { retval[1]=(char*) palloc((1+(uri.userInfo.afterLast-uri.userInfo.first))*sizeof(char)); /* userInfo, e.g. "gpadmin" */ if (!retval[1]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[1],uri.userInfo.first,uri.userInfo.afterLast-uri.userInfo.first); } if (uri.hostText.afterLast==uri.hostText.first) { retval[2]=NULL; } else { retval[2]=(char*) palloc((1+(uri.hostText.afterLast-uri.hostText.first))*sizeof(char)); /* hostText, e.g. "192.165.0.0" */ if (!retval[2]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[2],uri.hostText.first,uri.hostText.afterLast-uri.hostText.first); } if (uri.hostData.ip4==NULL) { retval[3]=NULL; } else { retval[3]=(char*) palloc(17*sizeof(char)); /* IPv4 */ if (!retval[3]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpy(retval[3],"\\000\\000\\000\\000",17); for(i=0;i<4;++i) { retval[3][1+4*i]+=uri.hostData.ip4->data[i]>> 6; retval[3][2+4*i]+=(uri.hostData.ip4->data[i]>> 3)&7; retval[3][3+4*i]+=uri.hostData.ip4->data[i]&7; } } if (uri.hostData.ip6==NULL) { retval[4]=NULL; } else { retval[4]=(char*) palloc(65*sizeof(char)); /* IPv6 */ if (!retval[4]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpy(retval[4],"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000",65); for(i=0;i<16;++i) { retval[4][1+4*i]+=uri.hostData.ip6->data[i]>> 6; retval[4][2+4*i]+=(uri.hostData.ip6->data[i]>> 3)&7; retval[4][3+4*i]+=uri.hostData.ip6->data[i]&7; } } if (uri.hostData.ipFuture.afterLast==uri.hostData.ipFuture.first) { retval[5]=NULL; } else { retval[5]=(char*) palloc((1+(uri.hostData.ipFuture.afterLast-uri.hostData.ipFuture.first))*sizeof(char)); /* ipFuture, text field */ if (!retval[5]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[5],uri.hostData.ipFuture.first,uri.hostData.ipFuture.afterLast-uri.hostData.ipFuture.first); } if (uri.portText.afterLast==uri.portText.first) { retval[6]=NULL; } else { retval[6]=(char*) palloc((1+(uri.portText.afterLast-uri.portText.first))*sizeof(char)); /* portText, e.g. "80" */ if (!retval[6]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[6],uri.portText.first,uri.portText.afterLast-uri.portText.first); } if (uri.pathHead==NULL) { retval[7]=NULL; } else { memctr=2; pathseg=uri.pathHead; do { quit=((pathseg==uri.pathTail)||(pathseg->next==NULL)); memctr+=3+2*(pathseg->text.afterLast-pathseg->text.first); pathseg=pathseg->next; } while (!quit); if (memctr==2) { ++memctr; } retval[7]=(char*) palloc(memctr*sizeof(char)); /* path */ /* e.g. "{usr,local,lib}" */ if (!retval[7]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } writehere=retval[7]; *writehere='{'; ++writehere; pathseg=uri.pathHead; do { quit=((pathseg==uri.pathTail)||(pathseg->next==NULL)); writehere=memenc(writehere,pathseg->text.first,pathseg->text.afterLast-pathseg->text.first); *writehere=','; ++writehere; pathseg=pathseg->next; } while (!quit); if (memctr!=3) { --writehere; } memcpy(writehere,"}",2); } if (uri.query.afterLast==uri.query.first) { retval[8]=NULL; } else { retval[8]=(char*) palloc((1+(uri.query.afterLast-uri.query.first))*sizeof(char)); /* query without leading "?" */ if (!retval[8]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[8],uri.query.first,uri.query.afterLast-uri.query.first); } if (uri.fragment.afterLast==uri.fragment.first) { retval[9]=NULL; } else { retval[9]=(char*) palloc((1+(uri.fragment.afterLast-uri.fragment.first))*sizeof(char)); /* fragment without leading "#" */ if (!retval[9]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpz(retval[9],uri.fragment.first,uri.fragment.afterLast-uri.fragment.first); } if (uri.absolutePath) { retval[10]=(char*) palloc(5*sizeof(char)); /* absolutePath */ if (!retval[10]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpy(retval[10],"true",5); } else { retval[10]=(char*) palloc(6*sizeof(char)); /* absolutePath */ if (!retval[10]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } memcpy(retval[10],"false",6); } if (parse_query) { int key_counter=2; int val_counter=2; int counter=0; for(UriQueryListA* it=queryList;(counter!=itemCount)&&(it!=NULL); it=it->next,++counter) { if (it->key==NULL) { key_counter+=3; /* should never reach here. */ } else { key_counter+=3+2*strlen(it->key); } if (it->value==NULL) { val_counter+=3; /* currently no way to distinguish empty string value (?a=) from null value (?a). This is a GPDB limitation. */ } else { val_counter+=3+2*strlen(it->value); } } if (key_counter==2) { ++key_counter; } if (val_counter==2) { ++val_counter; } retval[11]=palloc(key_counter*sizeof(char)); if (!retval[11]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } retval[12]=palloc(val_counter*sizeof(char)); if (!retval[12]) { ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Memory allocation failed."))); PG_RETURN_NULL(); } retval[11][0]='{'; retval[12][0]='{'; char* key_ptr=retval[11]+1; char* val_ptr=retval[12]+1; counter=0; for(UriQueryListA* it=queryList;(counter!=itemCount)&&(it!=NULL); it=it->next,++counter) { if (it->key==NULL) { *key_ptr='"'; ++key_ptr; *key_ptr='"'; ++key_ptr; *key_ptr=','; ++key_ptr; /* should never reach here. */ } else { key_ptr=strenc(key_ptr,it->key); *key_ptr=','; ++key_ptr; } if (it->value==NULL) { *val_ptr='"'; ++val_ptr; *val_ptr='"'; ++val_ptr; *val_ptr=','; ++val_ptr; /* currently no way to distinguish empty string value (?a=) from null value (?a). This is a GPDB limitation. */ } else { val_ptr=strenc(val_ptr,it->value); *val_ptr=','; ++val_ptr; } } if (key_counter!=3) { --key_ptr; } memcpy(key_ptr,"}",2); if (val_counter!=3) { --val_ptr; } memcpy(val_ptr,"}",2); uriFreeQueryListA(queryList); } else { retval[11]=NULL; retval[12]=NULL; } /* There is no need to call pfree. It's called automatically. */ HeapTuple tuple; Datum result; tuple=BuildTupleFromCStrings(attinmeta,retval); result=HeapTupleGetDatum(tuple); /* Free memory start */ uriFreeUriMembersA(&uri); /* Free memory finish */ PG_RETURN_DATUM(result); }