/* Replace the constraints */ int ncurisetconstraints(NCURI* duri,const char* constraints) { char* proj = NULL; char* select = NULL; const char* p; if(duri->constraint != NULL) free(duri->constraint); if(duri->projection != NULL) free(duri->projection); if(duri->selection != NULL) free(duri->selection); duri->constraint = NULL; duri->projection = NULL; duri->selection = NULL; if(constraints == NULL || strlen(constraints)==0) return (NCU_ECONSTRAINTS); duri->constraint = nulldup(constraints); if(*duri->constraint == '?') nclshift1(duri->constraint); p = duri->constraint; proj = (char*) p; select = strchr(proj,'&'); if(select != NULL) { size_t plen = (size_t)(select - proj); if(plen == 0) { proj = NULL; } else { proj = (char*)malloc(plen+1); memcpy((void*)proj,p,plen); proj[plen] = EOFCHAR; } select = nulldup(select); } else { proj = nulldup(proj); select = NULL; } duri->projection = proj; duri->selection = select; return NCU_OK; }
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/ int ncuriparse(const char* uri0, NCURI** durip) { NCURI* duri = NULL; char* uri = NULL; char* p; struct NC_ProtocolInfo* proto; int i,nprotos; /* accumulate parse points*/ char* protocol = NULL; char* host = NULL; char* port = NULL; char* constraint = NULL; char* user = NULL; char* pwd = NULL; char* file = NULL; char* prefixparams = NULL; char* suffixparams = NULL; if(uri0 == NULL || strlen(uri0) == 0) {THROW(1); goto fail;} duri = (NCURI*)calloc(1,sizeof(NCURI)); if(duri == NULL) {THROW(2); goto fail;} /* save original uri */ duri->uri = nulldup(uri0); /* make local copy of uri */ uri = (char*)malloc(strlen(uri0)+1+PADDING); /* +1 for trailing null, +PADDING for shifting */ if(uri == NULL) {THROW(3); goto fail;} /* strings will be broken into pieces with intermixed '\0; characters; first char is guaranteed to be '\0' */ duri->strings = uri; uri++; /* dup the incoming url */ strcpy(uri,uri0); /* Walk the uri and do the following: 1. remove all whitespace 2. remove all '\\' (Temp hack to remove escape characters inserted by Windows or MinGW) */ for(p=uri;*p;p++) { if(*p == '\\' || *p < ' ') nclshift1(p); /* compress out */ } p = uri; /* break up the uri string into big chunks: prefixparams, protocol, host section, and the file section (i.e. remainder) */ /* collect any prefix bracketed parameters */ if(*p == LBRACKET) { prefixparams = p+1; /* find end of the clientparams; convert LB,RB to '&' */ for(;*p;p++) { if(p[0] == RBRACKET && p[1] == LBRACKET) { p[0] = '&'; nclshift1(p+1); } else if(p[0] == RBRACKET && p[1] != LBRACKET) break; } if(*p == 0) {THROW(4); goto fail; /* malformed client params*/} terminate(p); /* nul term the prefixparams (overwrites the final RBRACKET) */ p++; /* move past the final RBRACKET */ } /* Tag the protocol */ protocol = p; p = strchr(p,':'); if(!p) {THROW(5); goto fail;} terminate(p); /*overwrite colon*/ p++; /* skip the colon */ /* verify that the uri starts with an acceptable protocol*/ nprotos = (sizeof(legalprotocols)/sizeof(struct NC_ProtocolInfo)); proto = NULL; for(i=0;i<nprotos;i++) { if(strcmp(protocol,legalprotocols[i].name)==0) { proto = &legalprotocols[i]; break; } } if(proto == NULL) {THROW(6); goto fail; /* illegal protocol*/} /* skip // */ if(p[0] != '/' && p[1] != '/') {THROW(7); goto fail;} p += 2; /* If this is all we have (proto://) then fail */ if(*p == EOFCHAR) {THROW(8); goto fail;} /* establish the start of the file section */ if(proto->filelike) {/* everything after proto:// */ file = p; host = NULL; /* and no host section */ } else { /*!proto->filelike => This means there should be a host section */ /* locate the end of the host section and therefore the start of the file section */ host = p; p = nclocate(p,"/?#"); if(p == NULL) { file = endof(host); /* there is no file section */ } else { ncrshift1(p); /* make room to terminate the host section without overwriting the leading character */ terminate(p); /* terminate the host section */ file = p+1; /* +1 becauseof the shift */ } } /* If you shift in the code below, you must reset file beginning */ if(host != NULL) {/* Parse the host section */ /* Check for leading user:pwd@ */ p = strchr(host,'@'); if(p) { if(p == host) {THROW(9); goto fail; /* we have proto://@ */} user = host; terminate(p); /* overwrite '@' */ host = p+1; /* start of host ip name */ p = strchr(user,':'); if(p == NULL) {THROW(10); goto fail; /* malformed */} terminate(p); /*overwrite colon */ pwd = p+1; } /* extract host and port */ p = host; p = strchr(p,':'); if(p != NULL) { terminate(p); p++; port = p; if(*port == EOFCHAR) {THROW(11); goto fail; /* we have proto://...:/ */} /* The port must look something like a number */ for(;*p;p++) { if(strchr("0123456789-",*p) == NULL) {THROW(12); goto fail; /* probably not a real port, fail */} } } /* else *p == NULL */ /* check for empty host section */ if(*host == EOFCHAR) {THROW(13); goto fail;} } assert(file != NULL); p = file; /* find the end of the file section and the start of the constraints and/or suffixparams */ p = nclocate(p,"?#"); if(p != NULL) { /* we have constraint and/or suffixparams */ char* fileend = p; /* save the end of the file section */ char* constraintend = NULL; if(*p == '?') constraint = p+1; else constraint = NULL; p = strchr(p,'#'); /* may repeat effect of nclocate above */ if(p != NULL) { constraintend = p; suffixparams = p+1; } else suffixparams = NULL; /* Ok, terminate the pieces */ terminate(fileend); /* terminate file section */ if(constraint != NULL && constraintend != NULL) terminate(constraintend); /* Suffix params are already terminated since they should be the last section of the original url */ } /* check for empty sections */ if(file != NULL && *file == EOFCHAR) file = NULL; /* empty file section */ if(constraint != NULL && *constraint == EOFCHAR) constraint = NULL; /* empty constraint section */ if(suffixparams != NULL && *suffixparams == EOFCHAR) suffixparams = NULL; /* empty suffixparams section */ if(suffixparams != NULL) { /* there really are suffix params; so rebuild the suffix params */ if(*suffixparams == LBRACKET) suffixparams++; p = suffixparams; /* convert RBRACKET LBRACKET to '&' */ for(;*p;p++) { if(p[0] == RBRACKET && p[1] == LBRACKET) { p[0] = '&'; nclshift1(p+1); } else if(p[0] == RBRACKET && p[1] != LBRACKET) { /* terminate suffixparams */ *p = EOFCHAR; break; } } if(*suffixparams == EOFCHAR) suffixparams = NULL; /* suffixparams are empty */ } /* do last minute empty check */ if(protocol != NULL && *protocol == EOFCHAR) protocol = NULL; if(user != NULL && *user == EOFCHAR) user = NULL; if(pwd != NULL && *pwd == EOFCHAR) pwd = NULL; if(host != NULL && *host == EOFCHAR) host = NULL; if(port != NULL && *port == EOFCHAR) port = NULL; if(file != NULL && *file == EOFCHAR) file = NULL; if(constraint != NULL && *constraint == EOFCHAR) constraint = NULL; /* assemble the component pieces */ duri->protocol = protocol; duri->user = user; duri->password = pwd; duri->host = host; duri->port = port; duri->file = file; ncurisetconstraints(duri,constraint); /* concat suffix and prefix params */ if(prefixparams != NULL || suffixparams != NULL) { int plen = prefixparams ? strlen(prefixparams) : 0; int slen = suffixparams ? strlen(suffixparams) : 0; int space = plen + slen + 1; /* add 1 for an extra ampersand if both are defined */ space++; duri->params = (char*)malloc(space); duri->params[0] = EOFCHAR; /* so we can use strcat */ if(plen > 0) { strcat(duri->params,prefixparams); if(slen > 0) strcat(duri->params,"&"); } if(slen > 0) strcat(duri->params,suffixparams); } #ifdef NCXDEBUG { fprintf(stderr,"duri:"); fprintf(stderr," params=|%s|",FIX(duri->params)); fprintf(stderr," protocol=|%s|",FIX(duri->protocol)); fprintf(stderr," host=|%s|",FIX(duri->host)); fprintf(stderr," port=|%s|",FIX(duri->port)); fprintf(stderr," file=|%s|",FIX(duri->file)); fprintf(stderr," constraint=|%s|",FIX(duri->constraint)); fprintf(stderr,"\n"); } #endif if(durip != NULL) *durip = duri; else ncurifree(duri); return 1; fail: if(duri != NULL) { ncurifree(duri); } return 0; }