#include "parse_url.h" #include "string.h" int main(void){ //uint8_t header[]="HTTP/1.1 200 OK\r\nFoo: bar\r\nCookies: Yes Please\r\n\r\n"; uint8_t url[]="http://www.google.com:80/foobar"; struct domain out = {.port=80}; get_protocol(url,&out,url+strlen((char*)url)-1); //printf("%s,%s,%d,%s,%d",out.protocol,out.domain,out.port,out.path,out.success); return 0; } ERL_NIF_TERM parse_url(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary block; ERL_NIF_TERM path, output; struct domain out = {.port=80,.success=false}; if (enif_is_binary(env,argv[0])==false) return enif_make_atom(env, "error"); enif_inspect_binary(env, argv[0], &block); if (block.size<4) return enif_make_atom(env, "error"); get_protocol(block.data,&out,block.data+block.size-1); if (out.success==false) return enif_make_atom(env, "error"); //fprintf(stderr,"%d %d -- //",(int)(block.size-out.path-1),(int)out.path); if (out.path==0){ unsigned char dat[1]={'/'}; ErlNifBinary bin={.size=1,.data=dat}; path=enif_make_binary(env,&bin); } else{ path=enif_make_sub_binary(env, argv[0], block.size-out.path , out.path); } output=enif_make_tuple4(env , enif_make_binary(env, &out.protocol) , enif_make_binary(env, &out.domain) , enif_make_int(env,out.port) , path ); free(out.protocol.data); free(out.domain.data); return output; } inline void get_protocol(uint8_t* s, struct domain* out, uint8_t* len){ uint8_t* i, *protocol; if ((i=memchr(s,':',len-s+1)) != NULL){ protocol = malloc(i-s); memcpy(protocol,s,i-s); //strncpy((char*)protocol,(char *)s,i-s); lower(protocol,protocol+(i-s)+1); out->protocol.size=i-s; out->protocol.data=protocol; // printf("%s\n",out->protocol); return get_domain(i+3,out,len); } else{ protocol=malloc(4); strncpy((char*)protocol,"http",4); out->protocol.size=4; out->protocol.data=protocol; return get_domain(s,out,len); } } inline void get_domain(uint8_t* s, struct domain* out, uint8_t* len){ uint8_t* i=s, *domain; while(*i != ':' && *i !='/' && idomain.size=i-s; out->domain.data=domain; // printf("%s\n",out->domain); if (*i == '/'){ return get_path(i,out,len); } else if(*i==':'){ return get_port(i+1,out,len); } else if(i>len-1){ out->success=true; return; } else return; //badarg } inline void get_port(uint8_t* s, struct domain* out, uint8_t* len){ uint8_t* i=s, *port; i=memchr(s,'/',len-s+1); if (i==s || i-s>5) return; //badarg if (i==NULL){ out->success=true; return; } else { port=malloc(6); strncpy((char*)port,(char *)s,i-s); port[5]='\0'; out->port=atoi((char*)port); free(port); return get_path(i,out,len); } } inline void get_path(uint8_t* s, struct domain* out, uint8_t* len){ out->path=len-s+1; /* uint8_t *path; */ /* out->success=true; */ /* if (len-s==-1) return; */ /* path = malloc(len-s+1); */ /* strncpy((char*)path,(char *)s,len-s+1); */ out->success=true; /* out->path.size=len-s+1; */ /* out->path.data=path; */ // printf("%s\n",out->path); } inline void lower(uint8_t* s,uint8_t* end){ while(s++'A'-1 && *s<'Z'+1) *s+=32; }