Exemplo n.º 1
0
bstring uri_normalize(const char *uri)
{
    int st, origSize, normSize;
    char *normal_str, *cleaned_uri;
    bstring normalized;
    UriParserStateA state;
    UriUriA u;
    state.uri = &u;

    cleaned_uri = malloc((sizeof(char) * strlen(uri)) + 1);
    clean_uri(uri, cleaned_uri);

    /* Parse URI */
    if (uriParseUriA(&state, cleaned_uri) != URI_SUCCESS) {
        free(cleaned_uri);
        uriFreeUriMembersA(&u);
        return bfromcstr("");
    }

    free(cleaned_uri);

    /* Normalize URI */
    st = uriNormalizeSyntaxA(&u);
    if (st != URI_SUCCESS) {
        uriFreeUriMembersA(&u);
        return bfromcstr("");
    }

    origSize = strlen(uri);
    normal_str = malloc(sizeof(char) * origSize + 1);
    if (normal_str == NULL) {
        uriFreeUriMembersA(&u);
        return bfromcstr("");
    }

    st = uriToStringA(normal_str, &u, origSize + 1, &normSize);
    if (st != URI_SUCCESS) {
        uriFreeUriMembersA(&u);
        return bfromcstr("");
    }

    normalized = bfromcstr(normal_str);

    free(normal_str);
    uriFreeUriMembersA(&u);

    return normalized;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
UriUriA *create_absolute_uri(const UriUriA *base_uri, const char *url)
{
	UriParserStateA state;
	UriUriA *abs_dest, rel_source;
	char *newurl;

	if (!url || !*url)
		return NULL;

	if ((abs_dest = uri_alloc_1()) == NULL)
		return NULL;

	if (base_uri) {
		state.uri = &rel_source;
		if (uriParseUriA(&state, url) != URI_SUCCESS) {
			uri_free(abs_dest); 
			uriFreeUriMembersA(&rel_source);
			return NULL;
		}

		if (uriAddBaseUriA(abs_dest, &rel_source, base_uri) != URI_SUCCESS) {
			uri_free(abs_dest);
			uriFreeUriMembersA(&rel_source);
			return NULL;
		}

		uriFreeUriMembersA(&rel_source);
	}
	else {
		state.uri = abs_dest;
		if (uriParseUriA(&state, url) != URI_SUCCESS) {
			uri_free(abs_dest); 
			return NULL;
		}
	}

	if (uriNormalizeSyntaxA(abs_dest) != URI_SUCCESS) {
		uri_free(abs_dest);
		return NULL;
	}

	/* http://www.example.com and http://www.example.com/ have to generate the same object */
	if (!base_uri && (!abs_dest->pathHead || !abs_dest->pathHead->text.first)
		&& !abs_dest->query.first) {
		newurl = string_new(url);
		string_cat(&newurl, "/");

		uriFreeUriMembersA(abs_dest);

		state.uri = abs_dest;
		if (uriParseUriA(&state, newurl) != URI_SUCCESS) {
			uri_free(abs_dest);
			string_free(newurl);
			return NULL;
		}

		if (uriNormalizeSyntaxA(abs_dest) != URI_SUCCESS) {
			uri_free(abs_dest);
			string_free(newurl);
			return NULL;
		}
		string_free(newurl);
	}

	return abs_dest;
}