complete update of utilities: ncbyte, nclist, ncuri, nclog

This commit is contained in:
Dennis Heimbigner 2012-08-08 23:15:18 +00:00
parent 9969af8aa5
commit 499f8d3a1c
40 changed files with 1669 additions and 1065 deletions

View File

@ -11,7 +11,7 @@ include_HEADERS += netcdf_par.h
endif
noinst_HEADERS = nc_logging.h nc_tests.h fbits.h nc.h \
nclist.h nc_uri.h utf8proc.h ncdispatch.h ncdimscale.h \
nclist.h ncuri.h utf8proc.h ncdispatch.h ncdimscale.h \
netcdf_f.h err_macros.h ncbytes.h nchashmap.h ceconstraints.h rnd.h \
nclog.h ncconfigure.h nc4internal.h nctime.h nc3dispatch.h

View File

@ -1,50 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef NC_URI_H
#define NC_URI_H
/*! This is an open structure meaning
it is ok to directly access its fields*/
typedef struct NC_URI {
char* uri; /* as passed by the caller */
char* protocol;
char* user; /* from user:password@ */
char* password; /* from user:password@ */
char* host; /*!< host*/
char* port; /*!< host */
char* file; /*!< file */
char* constraint; /*!< projection+selection */
char* projection; /*!< without leading '?'*/
char* selection; /*!< with leading '&'*/
char* params; /* all params */
char** paramlist; /*!<null terminated list */
} NC_URI;
extern int nc_uriparse(const char* s, NC_URI** nc_uri);
extern void nc_urifree(NC_URI* nc_uri);
/* Replace the constraints */
extern void nc_urisetconstraints(NC_URI*,const char* constraints);
/* Construct a complete NC_ URI; caller frees returned string */
/* Define flags to control what is included */
#define NC_URICONSTRAINTS 1
#define NC_URIUSERPWD 2
#define NC_URIPARAMS 4
#define NC_URIALL (NC_URICONSTRAINTS|NC_URIUSERPWD|NC_URIPARAMS)
extern char* nc_uribuild(NC_URI*,const char* prefix, const char* suffix, int flags);
/* Param Management */
extern int nc_uridecodeparams(NC_URI* nc_uri);
extern int nc_urisetparams(NC_URI* nc_uri,const char*);
/*! 0 result => entry not found; 1=>found; result holds value (may be null).
In any case, the result is imutable and should not be free'd.
*/
extern int nc_urilookup(NC_URI*, const char* param, const char** result);
#endif /*NC_URI_H*/

View File

@ -36,7 +36,7 @@ EXTERNC int ncbytesset(NCbytes*,unsigned int,char);
/* Append one byte */
EXTERNC int ncbytesappend(NCbytes*,char); /* Add at Tail */
/* Append n bytes */
EXTERNC int ncbytesappendn(NCbytes*,void*,unsigned int); /* Add at Tail */
EXTERNC int ncbytesappendn(NCbytes*,const void*,unsigned int); /* Add at Tail */
/* Null terminate the byte string without extending its length (for debugging) */
EXTERNC int ncbytesnull(NCbytes*);
@ -48,11 +48,11 @@ EXTERNC int ncbytescat(NCbytes*,const char*);
EXTERNC int ncbytessetcontents(NCbytes*, char*, unsigned int);
/* Following are always "in-lined"*/
#define ncbyteslength(bb) ((bb)?(bb)->length:0U)
#define ncbytesalloc(bb) ((bb)?(bb)->alloc:0U)
#define ncbytescontents(bb) ((bb && bb->content)?(bb)->content:(char*)"")
#define ncbyteslength(bb) ((bb)!=NULL?(bb)->length:0U)
#define ncbytesalloc(bb) ((bb)!=NULL?(bb)->alloc:0U)
#define ncbytescontents(bb) (((bb)!=NULL && (bb)->content!=NULL)?(bb)->content:(char*)"")
#define ncbytesextend(bb,len) ncbytessetalloc((bb),(len)+(bb->alloc))
#define ncbytesclear(bb) ((bb)?(bb)->length=0:0U)
#define ncbytesavail(bb,n) ((bb)?((bb)->alloc - (bb)->length) >= (n):0U)
#define ncbytesclear(bb) ((bb)!=NULL?(bb)->length=0:0U)
#define ncbytesavail(bb,n) ((bb)!=NULL?((bb)->alloc - (bb)->length) >= (n):0U)
#endif /*NCBYTES_H*/

View File

@ -19,7 +19,7 @@
#endif
#include "netcdf.h"
#include "nc.h"
#include "nc_uri.h"
#include "ncuri.h"
#define longtype ((sizeof(long) == sizeof(int) ? NC_INT : NC_INT64))

View File

@ -58,9 +58,7 @@ EXTERNC NClist* nclistclone(NClist*);
/* Following are always "in-lined"*/
#define nclistclear(l) nclistsetlength((l),0U)
#define nclistextend(l,len) nclistsetalloc((l),(len)+(l->alloc))
#define nclistcontents(l) ((l)->content)
#define nclistlength(l) ((l)?(l)->length:0U)
#define nclistcontents(l) ((l)==NULL?NULL:(l)->content)
#define nclistlength(l) ((l)==NULL?0U:(l)->length)
#endif /*NCLIST_H*/

View File

@ -7,7 +7,7 @@
#ifndef NCLOG_H
#define NCLOG_H
#define ENVFLAG "NCLOGFILE"
#define NCENVFLAG "NCLOGFILE"
/* Suggested tag values */
#define NCLOGNOTE 0
@ -16,7 +16,7 @@
#define NCLOGDBG 3
extern void ncloginit(void);
extern void ncsetlogging(int tf);
extern int ncsetlogging(int tf);
extern int nclogopen(const char* file);
extern void nclogclose(void);

59
include/ncuri.h Normal file
View File

@ -0,0 +1,59 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef NCURI_H
#define NCURI_H
/*! This is an open structure meaning
it is ok to directly access its fields*/
typedef struct NCURI {
char* uri; /* as passed by the caller */
char* params; /* all params */
char** paramlist; /*!<null terminated list */
char* constraint; /*!< projection+selection */
char* projection; /*!< without leading '?'*/
char* selection; /*!< with leading '&'*/
char* strings; /* first char of strings is always '\0' */
/* Following all point into the strings field */
char* protocol;
char* user; /* from user:password@ */
char* password; /* from user:password@ */
char* host; /*!< host*/
char* port; /*!< host */
char* file; /*!< file */
} NCURI;
extern int ncuriparse(const char* s, NCURI** ncuri);
extern void ncurifree(NCURI* ncuri);
/* Replace the constraints */
extern void ncurisetconstraints(NCURI*,const char* constraints);
/* Construct a complete NC URI; caller frees returned string */
/* Define flags to control what is included */
#define NCURICONSTRAINTS 1
#define NCURIUSERPWD 2
#define NCURIPREFIXPARAMS 4
#define NCURISUFFIXPARAMS 8
#define NCURIPARAMS NCURIPREFIXPARAMS
#define NCURIENCODE 16 /* If output should be encoded */
#define NCURISTD (NCURICONSTRAINTS|NCURIUSERPWD)
extern char* ncuribuild(NCURI*,const char* prefix, const char* suffix, int flags);
/* Param Management */
extern int ncuridecodeparams(NCURI* ncuri);
extern int ncurisetparams(NCURI* ncuri,const char*);
/*! 0 result => entry not found; 1=>found; result holds value (may be null).
In any case, the result is imutable and should not be free'd.
*/
extern int ncurilookup(NCURI*, const char* param, const char** result);
extern char* ncuriencode(char* s, char* allowable);
extern char* ncuridecode(char* s);
extern char* ncuridecodeonly(char* s, char*);
#endif /*NCURI_H*/

View File

@ -364,7 +364,7 @@ makegetvar34(NCDAPCOMMON* nccomm, CDFnode* var, void* data, nc_type dsttype, Get
}
int
constrainable34(NC_URI* durl)
constrainable34(NCURI* durl)
{
char** protocol = constrainableprotocols;
for(;*protocol;protocol++) {

View File

@ -29,8 +29,8 @@ extern int oc_dumpnode(OClink, OCddsnode);
int
nc__testurl(const char* path, char** basenamep)
{
NC_URI* uri;
int ok = nc_uriparse(path,&uri);
NCURI* uri;
int ok = ncuriparse(path,&uri);
if(ok) {
char* slash = strrchr(uri->file, '/');
char* dot;
@ -39,7 +39,7 @@ nc__testurl(const char* path, char** basenamep)
dot = strrchr(slash, '.');
if(dot != NULL && dot != slash) *dot = '\0';
if(basenamep) *basenamep=slash ; else free(slash);
nc_urifree(uri);
ncurifree(uri);
}
return ok;
}
@ -259,7 +259,7 @@ paramvalue34(NCDAPCOMMON* nccomm, const char* key)
const char* value;
if(nccomm == NULL || key == NULL) return 0;
if(!nc_urilookup(nccomm->oc.url,key,&value))
if(!ncurilookup(nccomm->oc.url,key,&value))
return NULL;
return value;
}
@ -276,7 +276,7 @@ paramcheck34(NCDAPCOMMON* nccomm, const char* key, const char* subkey)
char* p;
if(nccomm == NULL || key == NULL) return 0;
if(!nc_urilookup(nccomm->oc.url,key,&value))
if(!ncurilookup(nccomm->oc.url,key,&value))
return 0;
if(subkey == NULL) return 1;
p = strstr(value,subkey);
@ -711,7 +711,7 @@ dap_fetch(NCDAPCOMMON* nccomm, OClink conn, const char* ce,
if(SHOWFETCH) {
/* Build uri string minus the constraint */
char* baseurl = nc_uribuild(nccomm->oc.url,NULL,ext,0);
char* baseurl = ncuribuild(nccomm->oc.url,NULL,ext,0);
if(ce == NULL)
LOG1(NCLOGNOTE,"fetch: %s",baseurl);
else

View File

@ -8,19 +8,20 @@ PROG=./ncd
P=`pwd`
T="synth4"
T="test.01"
F="file://$TOP/ncdap_test/testdata3/$T"
#F="http://motherlode.ucar.edu:8081/dts/$T"
F="http://motherlode.ucar.edu:8080/thredds/dodsC/testdods/coads_climatology.nc"
F="http://motherlode.ucar.edu:8081/dts/$T?f64"
#F="http://motherlode.ucar.edu:8080/thredds/dodsC/testdods/coads_climatology.nc"
#F="http://nomads.ncep.noaa.gov:9090/dods/gfs_hd/gfs_hd20120801/gfs_hd_00z"
VAR=lat
VAR=f64
PARMS="[log]"
#PARMS="${PARMS}[netcdf3]"
PARMS="${PARMS}[fetch=disk]"
#PARMS="${PARMS}[cache]"
#PARMS="${PARMS}[prefetch]"
#PARMS="${PARMS}[fetch=disk]"
PARMS="${PARMS}[cache]"
PARMS="${PARMS}[prefetch]"
#PARMS="${PARMS}[nocache]"
#PARMS="${PARMS}[noprefetch]"
#PARMS="${PARMS}[wholevar]"

View File

@ -118,7 +118,7 @@ typedef struct NCOC {
OClink conn;
char* rawurltext; /* as given to nc3d_open */
char* urltext; /* as modified by nc3d_open */
NC_URI* url; /* parse of rawuritext */
NCURI* url; /* parse of rawuritext */
OCdasnode ocdasroot;
DCEconstraint* dapconstraint; /* from url */
int inmemory; /* store fetched data in memory? */
@ -303,7 +303,7 @@ extern void unattach34(CDFnode*);
extern int nodematch34(CDFnode* node1, CDFnode* node2);
extern int simplenodematch34(CDFnode* node1, CDFnode* node2);
extern CDFnode* findxnode34(CDFnode* target, CDFnode* xroot);
extern int constrainable34(NC_URI*);
extern int constrainable34(NCURI*);
extern char* makeconstraintstring34(DCEconstraint*);
extern size_t estimatedataddssize34(CDFnode* datadds);
extern void canonicalprojection34(NClist*, NClist*);

View File

@ -15,6 +15,8 @@
# endif
#endif
#include "oclog.h"
#include "nc3dispatch.h"
#include "ncd3dispatch.h"
#include "dapalign.h"
@ -122,10 +124,10 @@ NCD3_open(const char * path, int mode,
dapcomm->oc.rawurltext = strdup(path);
#endif
nc_uriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url);
ncuriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url);
/* parse the client parameters */
nc_uridecodeparams(dapcomm->oc.url);
ncuridecodeparams(dapcomm->oc.url);
if(!constrainable34(dapcomm->oc.url))
SETFLAG(dapcomm->controls,NCF_UNCONSTRAINABLE);
@ -164,9 +166,9 @@ NCD3_open(const char * path, int mode,
} else
dapcomm->oc.dapconstraint = NULL;
/* Construct a url for oc minus any constraint */
dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,
(NC_URIALL ^ NC_URICONSTRAINTS));
/* Construct a url for oc minus any constraint and params*/
dapcomm->oc.urltext = ncuribuild(dapcomm->oc.url,NULL,NULL,
(NCURISTD ^ NCURICONSTRAINTS));
/* Pass to OC */
ocstat = oc_open(dapcomm->oc.urltext,&dapcomm->oc.conn);
@ -183,9 +185,9 @@ NCD3_open(const char * path, int mode,
ncloginit();
if(nclogopen(value))
ncsetlogging(1);
oc_loginit();
if(oc_logopen(value))
oc_setlogging(1);
ocloginit();
if(oclogopen(value))
ocsetlogging(1);
}
/* fetch and build the unconstrained DDS for use as
@ -286,12 +288,12 @@ fprintf(stderr,"constrained dds: %s\n",dumptree(dapcomm->cdf.ddsroot));
/* using the modified constraint, rebuild the constraint string */
if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) {
/* ignore all constraints */
dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,0);
dapcomm->oc.urltext = ncuribuild(dapcomm->oc.url,NULL,NULL,0);
} else {
char* constraintstring = buildconstraintstring3(dapcomm->oc.dapconstraint);
nc_urisetconstraints(dapcomm->oc.url,constraintstring);
ncurisetconstraints(dapcomm->oc.url,constraintstring);
nullfree(constraintstring);
dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,NC_URICONSTRAINTS);
dapcomm->oc.urltext = ncuribuild(dapcomm->oc.url,NULL,NULL,NCURICONSTRAINTS);
}
#ifdef DEBUG

View File

@ -18,7 +18,7 @@
#include "nclist.h"
#include "nchashmap.h"
#include "nclog.h"
#include "nc_uri.h"
#include "ncuri.h"
#include "fbits.h"
#include "dceconstraints.h"

View File

@ -50,7 +50,7 @@ freeNCDAPCOMMON(NCDAPCOMMON* dapcomm)
oc_root_free(dapcomm->oc.conn,dapcomm->oc.ocdasroot);
dapcomm->oc.ocdasroot = NULL;
oc_close(dapcomm->oc.conn); /* also reclaims remaining OC trees */
nc_urifree(dapcomm->oc.url);
ncurifree(dapcomm->oc.url);
nullfree(dapcomm->oc.urltext);
nullfree(dapcomm->oc.rawurltext);

View File

@ -18,8 +18,8 @@ libdispatch_la_CPPFLAGS = ${AM_CPPFLAGS}
libdispatch_la_SOURCES = dparallel.c dcopy.c dfile.c ddim.c datt.c \
dattinq.c dattput.c dattget.c derror.c dvar.c dvarget.c dvarput.c \
dvarinq.c ddispatch.c \
dnclog.c dstring.c dutf8proc.c utf8proc_data.h \
nc_uri.c nclist.c ncbytes.c nchashmap.c nctime.c \
nclog.c dstring.c dutf8proc.c utf8proc_data.h \
ncuri.c nclist.c ncbytes.c nchashmap.c nctime.c \
dsubstrate.c
# Add functions only found in netCDF-4.

View File

@ -1,5 +1,5 @@
#include "ncdispatch.h"
#include "nc_uri.h"
#include "ncuri.h"
extern int NCSUBSTRATE_intialize(void);
@ -92,7 +92,7 @@ int
NC_testurl(const char* path)
{
int isurl = 0;
NC_URI* tmpurl = NULL;
NCURI* tmpurl = NULL;
char* p;
if(path == NULL) return 0;
@ -104,7 +104,7 @@ NC_testurl(const char* path)
if(*p == '/') return 0; /* probably an absolute file path */
/* Ok, try to parse as a url */
if(nc_uriparse(path,&tmpurl)) {
if(ncuriparse(path,&tmpurl)) {
/* Do some extra testing to make sure this really is a url */
/* Look for a knownprotocol */
struct NCPROTOCOLLIST* protolist;
@ -114,7 +114,7 @@ NC_testurl(const char* path)
break;
}
}
nc_urifree(tmpurl);
ncurifree(tmpurl);
return isurl;
}
return 0;
@ -129,20 +129,20 @@ int
NC_urlmodel(const char* path)
{
int model = 0;
NC_URI* tmpurl = NULL;
NCURI* tmpurl = NULL;
struct NCPROTOCOLLIST* protolist;
if(!nc_uriparse(path,&tmpurl)) goto done;
if(!ncuriparse(path,&tmpurl)) goto done;
/* Look at any prefixed parameters */
if(nc_urilookup(tmpurl,"netcdf4",NULL)
|| nc_urilookup(tmpurl,"netcdf-4",NULL)) {
if(ncurilookup(tmpurl,"netcdf4",NULL)
|| ncurilookup(tmpurl,"netcdf-4",NULL)) {
model = (NC_DISPATCH_NC4|NC_DISPATCH_NCD);
} else if(nc_urilookup(tmpurl,"netcdf3",NULL)
|| nc_urilookup(tmpurl,"netcdf-3",NULL)) {
} else if(ncurilookup(tmpurl,"netcdf3",NULL)
|| ncurilookup(tmpurl,"netcdf-3",NULL)) {
model = (NC_DISPATCH_NC3|NC_DISPATCH_NCD);
} else if(nc_urilookup(tmpurl,"cdmremote",NULL)
|| nc_urilookup(tmpurl,"cdmr",NULL)) {
} else if(ncurilookup(tmpurl,"cdmremote",NULL)
|| ncurilookup(tmpurl,"cdmr",NULL)) {
model = (NC_DISPATCH_NCR|NC_DISPATCH_NC4);
}
@ -165,7 +165,7 @@ NC_urlmodel(const char* path)
model |= (NC_DISPATCH_NC3 | NC_DISPATCH_NCD);
done:
nc_urifree(tmpurl);
ncurifree(tmpurl);
return model;
}

View File

@ -1,466 +0,0 @@
/*********************************************************************
* Copyright 2010, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header$
*********************************************************************/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "nc_uri.h"
#define NC_URIDEBUG
#define LBRACKET '['
#define RBRACKET ']'
#ifndef FIX
#define FIX(s) ((s)==NULL?"":(s))
#endif
#ifndef NILLEN
#define NILLEN(s) ((s)==NULL?0:strlen(s))
#endif
static char* legalprotocols[] = {
"file:",
"http:",
"https:",
"ftp:",
NULL /* NULL terminate*/
};
static void nc_paramfree(char** params);
static int nc_find(char** params, const char* key);
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
int
nc_uriparse(const char* uri0, NC_URI** nc_urip)
{
NC_URI* nc_uri = NULL;
char* uri;
char** pp;
char* p;
char* p1;
int c;
/* accumulate parse points*/
char* protocol = NULL;
char* params = NULL;
char* host = NULL;
char* port = NULL;
char* constraint = NULL;
char* user = NULL;
char* pwd = NULL;
char* file = NULL;
nc_uri = (NC_URI*)calloc(1,sizeof(NC_URI));
if(nc_uri == NULL) return 0;
/* Temporary hack to remove escape characters inserted by Windows or MinGW */
if(strchr(uri0,'\\') != NULL) {
char* u = strdup(uri0);
if(u == NULL) return 0;
p = u;
p1 = u;
while((c=*p1++)) {if(c != '\\') *p++ = c;}
uri0 = (const char*)u;
}
/* make local copy of uri */
uri = strdup(uri0);
/* remove all whitespace*/
p = uri;
p1 = uri;
while((c=*p1++)) {if(c != ' ' && c != '\t') *p++ = c;}
p = uri;
/* break up the uri string into pieces*/
/* 1. leading bracketed parameters */
if(*p == LBRACKET) {
params = p+1;
/* find end of the clientparams*/
for(;*p;p++) {if(p[0] == RBRACKET && p[1] != LBRACKET) break;}
if(*p == 0) goto fail; /* malformed client params*/
*p = '\0'; /* leave off the trailing rbracket for now */
p++; /* move past the params*/
}
/* verify that the uri starts with an acceptable protocol*/
for(pp=legalprotocols;*pp;pp++) {
if(strncmp(p,*pp,strlen(*pp))==0) break;
}
if(*pp == NULL) goto fail; /* illegal protocol*/
/* save the protocol */
protocol = *pp;
/* 4. skip protocol */
p += strlen(protocol);
/* 5. skip // */
if(*p != '/' && *(p+1) != '/')
goto fail;
p += 2;
/* 6. Mark the end of the host section */
file = strchr(p,'/');
if(file) {
*file++ = '\0'; /* warning: we just overwrote the leading / */
} else
goto fail; /* url only has host part, no path */
/* 7. extract any user:pwd */
p1 = strchr(p,'@');
if(p1) {/* Assume we have user:pwd@ */
*p1 = '\0';
user = p;
pwd = strchr(p,':');
if(!pwd) goto fail; /* malformed */
*pwd++ = '\0';
p = pwd+strlen(pwd)+1;
}
/* 8. extract host and port */
host = p;
port = strchr(p,':');
if(port) {
*port++ = '\0';
}
/* 9. Look for '?' */
constraint = strchr(file,'?');
if(constraint) {
*constraint++ = '\0';
}
/* assemble the component pieces*/
if(uri0 && strlen(uri0) > 0)
nc_uri->uri = strdup(uri0);
if(protocol && strlen(protocol) > 0) {
nc_uri->protocol = strdup(protocol);
/* remove trailing ':' */
nc_uri->protocol[strlen(protocol)-1] = '\0';
}
if(user && strlen(user) > 0)
nc_uri->user = strdup(user);
if(pwd && strlen(pwd) > 0)
nc_uri->password = strdup(pwd);
if(host && strlen(host) > 0)
nc_uri->host = strdup(host);
if(port && strlen(port) > 0)
nc_uri->port = strdup(port);
if(file && strlen(file) > 0) {
/* Add back the leading / */
nc_uri->file = malloc(strlen(file)+2);
strcpy(nc_uri->file,"/");
strcat(nc_uri->file,file);
}
if(constraint && strlen(constraint) > 0)
nc_uri->constraint = strdup(constraint);
nc_urisetconstraints(nc_uri,constraint);
if(params != NULL && strlen(params) > 0) {
nc_uri->params = (char*)malloc(1+2+strlen(params));
strcpy(nc_uri->params,"[");
strcat(nc_uri->params,params);
strcat(nc_uri->params,"]");
}
#ifdef NC_XDEBUG
{
fprintf(stderr,"nc_uri:");
fprintf(stderr," params=|%s|",FIX(nc_uri->params));
fprintf(stderr," protocol=|%s|",FIX(nc_uri->protocol));
fprintf(stderr," host=|%s|",FIX(nc_uri->host));
fprintf(stderr," port=|%s|",FIX(nc_uri->port));
fprintf(stderr," file=|%s|",FIX(nc_uri->file));
fprintf(stderr," constraint=|%s|",FIX(nc_uri->constraint));
fprintf(stderr,"\n");
}
#endif
free(uri);
if(nc_urip != NULL) *nc_urip = nc_uri;
return 1;
fail:
if(nc_uri) nc_urifree(nc_uri);
if(uri != NULL) free(uri);
return 0;
}
void
nc_urifree(NC_URI* nc_uri)
{
if(nc_uri == NULL) return;
if(nc_uri->uri != NULL) {free(nc_uri->uri);}
if(nc_uri->protocol != NULL) {free(nc_uri->protocol);}
if(nc_uri->user != NULL) {free(nc_uri->user);}
if(nc_uri->password != NULL) {free(nc_uri->password);}
if(nc_uri->host != NULL) {free(nc_uri->host);}
if(nc_uri->port != NULL) {free(nc_uri->port);}
if(nc_uri->file != NULL) {free(nc_uri->file);}
if(nc_uri->constraint != NULL) {free(nc_uri->constraint);}
if(nc_uri->projection != NULL) {free(nc_uri->projection);}
if(nc_uri->selection != NULL) {free(nc_uri->selection);}
if(nc_uri->params != NULL) {free(nc_uri->params);}
if(nc_uri->paramlist != NULL) nc_paramfree(nc_uri->paramlist);
free(nc_uri);
}
/* Replace the constraints */
void
nc_urisetconstraints(NC_URI* 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;
duri->constraint = strdup(constraints);
if(*duri->constraint == '?')
strcpy(duri->constraint,duri->constraint+1);
p = duri->constraint;
proj = (char*) p;
select = strchr(proj,'&');
if(select != NULL) {
size_t plen = (select - proj);
if(plen == 0) {
proj = NULL;
} else {
proj = (char*)malloc(plen+1);
memcpy((void*)proj,p,plen);
proj[plen] = '\0';
}
select = nulldup(select);
} else {
proj = nulldup(proj);
select = NULL;
}
duri->projection = proj;
duri->selection = select;
}
/* Construct a complete NC_ URI without the client params
and optionally with the constraints;
caller frees returned string
*/
char*
nc_uribuild(NC_URI* duri, const char* prefix, const char* suffix, int pieces)
{
size_t len = 0;
char* newuri;
int withparams = ((pieces&NC_URIPARAMS)
&& duri->params != NULL);
int withuserpwd = ((pieces&NC_URIUSERPWD)
&& duri->user != NULL && duri->password != NULL);
int withconstraints = ((pieces&NC_URICONSTRAINTS)
&& duri->constraint != NULL);
if(prefix != NULL) len += NILLEN(prefix);
if(withparams) {
len += NILLEN(duri->params);
}
len += (NILLEN(duri->protocol)+NILLEN("://"));
if(withuserpwd) {
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
}
len += (NILLEN(duri->host));
if(duri->port != NULL) {
len += (NILLEN(":")+NILLEN(duri->port));
}
len += (NILLEN(duri->file));
if(suffix != NULL) len += NILLEN(suffix);
if(withconstraints) {
len += (NILLEN("?")+NILLEN(duri->constraint));
}
len += 1; /* null terminator */
newuri = (char*)malloc(len);
if(!newuri) return NULL;
newuri[0] = '\0';
if(prefix != NULL) strcat(newuri,prefix);
if(withparams) {
strcat(newuri,duri->params);
}
strcat(newuri,duri->protocol);
strcat(newuri,"://");
if(withuserpwd) {
strcat(newuri,duri->user);
strcat(newuri,":");
strcat(newuri,duri->password);
strcat(newuri,"@");
}
if(duri->host != NULL) { /* may be null if using file: protocol */
strcat(newuri,duri->host);
}
if(duri->port != NULL) {
strcat(newuri,":");
strcat(newuri,duri->port);
}
strcat(newuri,duri->file);
if(suffix != NULL) strcat(newuri,suffix);
if(withconstraints) {
strcat(newuri,"?");
strcat(newuri,duri->constraint);
}
return newuri;
}
/**************************************************/
/* Parameter support */
/*
Client parameters are assumed to be
one or more instances of bracketed pairs:
e.g "[...][...]...".
The bracket content in turn is assumed to be a
comma separated list of <name>=<value> pairs.
e.g. x=y,z=,a=b.
If the same parameter is specifed more than once,
then the first occurrence is used; this is so that
is possible to forcibly override user specified
parameters by prefixing.
IMPORTANT: client parameter string is assumed to
have blanks compress out.
Returns 1 if parse suceeded, 0 otherwise;
*/
int
nc_uridecodeparams(NC_URI* nc_uri)
{
char* cp;
char* cq;
int c;
int i;
int nparams;
char* params0;
char* params;
char* params1;
char** plist;
if(nc_uri == NULL) return 0;
if(nc_uri->params == NULL) return 1;
params0 = nc_uri->params;
/* Pass 1 to replace beginning '[' and ending ']' */
if(params0[0] == '[')
params = strdup(params0+1);
else
params = strdup(params0);
if(params[strlen(params)-1] == ']')
params[strlen(params)-1] = '\0';
/* Pass 2 to replace "][" pairs with ','*/
params1 = strdup(params);
cp=params; cq = params1;
while((c=*cp++)) {
if(c == RBRACKET && *cp == LBRACKET) {cp++; c = ',';}
*cq++ = c;
}
*cq = '\0';
free(params);
params = params1;
/* Pass 3 to break string into pieces and count # of pairs */
nparams=0;
for(cp=params;(c=*cp);cp++) {
if(c == ',') {*cp = '\0'; nparams++;}
}
nparams++; /* for last one */
/* plist is an env style list */
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
/* Pass 4 to break up each pass into a (name,value) pair*/
/* and insert into the param list */
/* parameters of the form name name= are converted to name=""*/
cp = params;
for(i=0;i<nparams;i++) {
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
char* vp;
/*break up the ith param*/
vp = strchr(cp,'=');
if(vp != NULL) {*vp = '\0'; vp++;} else {vp = "";}
plist[2*i] = strdup(cp);
plist[2*i+1] = strdup(vp);
cp = next;
}
plist[2*nparams] = NULL;
free(params);
if(nc_uri->paramlist != NULL)
nc_paramfree(nc_uri->paramlist);
nc_uri->paramlist = plist;
return 1;
}
int
nc_urilookup(NC_URI* uri, const char* key, const char** resultp)
{
int i;
char* value = NULL;
if(uri == NULL || key == NULL || uri->params == NULL) return 0;
if(uri->paramlist == NULL) {
i = nc_uridecodeparams(uri);
if(!i) return 0;
}
i = nc_find(uri->paramlist,key);
if(i < 0) return 0;
value = uri->paramlist[(2*i)+1];
if(resultp) *resultp = value;
return 1;
}
int
nc_urisetparams(NC_URI* uri, const char* newparams)
{
if(uri == NULL) return 0;
if(uri->paramlist != NULL) nc_paramfree(uri->paramlist);
uri->paramlist = NULL;
if(uri->params != NULL) free(uri->params);
uri->params = nulldup(newparams);
return 1;
}
/* Internal version of lookup; returns the paired index of the key */
static int
nc_find(char** params, const char* key)
{
int i;
char** p;
for(i=0,p=params;*p;p+=2,i++) {
if(strcmp(key,*p)==0) return i;
}
return -1;
}
static void
nc_paramfree(char** params)
{
char** p;
if(params == NULL) return;
for(p=params;*p;p+=2) {
free(*p);
if(p[1] != NULL) free(p[1]);
}
free(params);
}

View File

@ -50,6 +50,7 @@ ncbytessetalloc(NCbytes* bb, unsigned int sz)
if(bb->alloc >= sz) return TRUE;
if(bb->nonextendible) return ncbytesfail();
newcontent=(char*)calloc(sz,sizeof(char));
if(newcontent == NULL) return FALSE;
if(bb->alloc > 0 && bb->length > 0 && bb->content != NULL) {
memcpy((void*)newcontent,(void*)bb->content,sizeof(char)*bb->length);
}
@ -106,9 +107,13 @@ int
ncbytesappend(NCbytes* bb, char elem)
{
if(bb == NULL) return ncbytesfail();
if(bb->length >= bb->alloc) if(!ncbytessetalloc(bb,0)) return ncbytesfail();
/* We need space for the char + null */
while(bb->length+1 >= bb->alloc) {
if(!ncbytessetalloc(bb,0)) return ncbytesfail();
}
bb->content[bb->length] = elem;
bb->length++;
bb->content[bb->length] = '\0';
return TRUE;
}
@ -124,13 +129,16 @@ ncbytescat(NCbytes* bb, const char* s)
}
int
ncbytesappendn(NCbytes* bb, void* elem, unsigned int n)
ncbytesappendn(NCbytes* bb, const void* elem, unsigned int n)
{
if(bb == NULL || elem == NULL) return ncbytesfail();
if(n == 0) {n = strlen((char*)elem);}
while(!ncbytesavail(bb,n)) {if(!ncbytessetalloc(bb,0)) return ncbytesfail();}
while(!ncbytesavail(bb,n+1)) {
if(!ncbytessetalloc(bb,0)) return ncbytesfail();
}
memcpy((void*)&bb->content[bb->length],(void*)elem,n);
bb->length += n;
bb->content[bb->length] = '\0';
return TRUE;
}

View File

@ -4,8 +4,6 @@
* $Header$
*********************************************************************/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
@ -18,9 +16,9 @@
#define MAXTAGS 256
#define NCTAGDFALT "Log";
static int ncinitlog = 0;
static int nclogginginitialized = 0;
static int nclogging = 0;
static int ncsystemfile = 0;
static int ncsystemfile = 0; /* 1 => we are logging to file we did not open */
static char* nclogfile = NULL;
static FILE* nclogstream = NULL;
@ -30,11 +28,17 @@ static char* nctagdfalt = NULL;
static char* nctagsetdfalt[] = {"Warning","Error","Note","Debug"};
static char* nctagname(int tag);
/*!\defgroup NClog NClog Management
@{*/
/*!\internal
*/
void
ncloginit(void)
{
const char* file = getenv(ENVFLAG);
ncinitlog = 1;
const char* file = getenv(NCENVFLAG);
nclogginginitialized = 1;
ncsetlogging(0);
nclogfile = NULL;
nclogstream = NULL;
@ -49,17 +53,38 @@ ncloginit(void)
nctagset = nctagsetdfalt;
}
void
/*!
Enable/Disable logging.
\param[in] tf If 1, then turn on logging, if 0, then turn off logging.
\return The previous value of the logging flag.
*/
int
ncsetlogging(int tf)
{
if(!ncinitlog) ncloginit();
int was;
if(!nclogginginitialized) ncloginit();
was = nclogging;
nclogging = tf;
return was;
}
/*!
Specify a file into which to place logging output.
\param[in] file The name of the file into which to place logging output.
If the file has the value NULL, then send logging output to
stderr.
\return zero if the open failed, one otherwise.
*/
int
nclogopen(const char* file)
{
if(!ncinitlog) ncloginit();
if(!nclogginginitialized) ncloginit();
nclogclose();
if(file == NULL || strlen(file) == 0) {
/* use stderr*/
@ -100,6 +125,7 @@ nclogopen(const char* file)
void
nclogclose(void)
{
if(!nclogginginitialized) ncloginit();
if(nclogstream != NULL && !ncsystemfile) {
fclose(nclogstream);
}
@ -109,11 +135,23 @@ nclogclose(void)
ncsystemfile = 0;
}
/*!
Send logging messages. This uses a variable
number of arguments and operates like the stdio
printf function.
\param[in] tag Indicate the kind of this log message.
\param[in] format Format specification as with printf.
*/
void
nclog(int tag, const char* fmt, ...)
{
va_list args;
char* prefix;
if(!nclogginginitialized) ncloginit();
if(!nclogging || nclogstream == NULL) return;
prefix = nctagname(tag);
@ -134,6 +172,13 @@ nclogtext(int tag, const char* text)
nclogtextn(tag,text,strlen(text));
}
/*!
Send arbitrarily long text as a logging message.
Each line will be sent using nclog with the specified tag.
\param[in] tag Indicate the kind of this log message.
\param[in] text Arbitrary text to send as a logging message.
*/
void
nclogtextn(int tag, const char* text, size_t count)
{
@ -167,3 +212,5 @@ nctagname(int tag)
return nctagset[tag];
}
}
/**@}*/

831
libdispatch/ncuri.c Normal file
View File

@ -0,0 +1,831 @@
/*********************************************************************
* Copyright 2010, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header$
*********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "ncuri.h"
#define NCURIDEBUG
#ifdef NCURIDEBUG
static int failpoint = 0;
#define THROW(n) {failpoint=(n); goto fail;}
#else
#define THROW(n)
#endif
#define PADDING 8
#define LBRACKET '['
#define RBRACKET ']'
#define EOFCHAR '\0'
#ifndef FIX
#define FIX(s) ((s)==NULL?"NULL":(s))
#endif
#ifndef NILLEN
#define NILLEN(s) ((s)==NULL?0:strlen(s))
#endif
#ifndef nulldup
#define nulldup(s) ((s)==NULL?NULL:strdup(s))
#endif
#define terminate(p) {*(p) = EOFCHAR;}
#define endof(p) ((p)+strlen(p))
static struct NC_ProtocolInfo {
char* name;
int filelike; /* 1=>this protocol has no host, user+pwd, or port */
} legalprotocols[] = {
{"file",1},
{"http",0},
{"https",0},
{"ftp",0},
};
/* Allowable character sets for encode */
static char* fileallow =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
static char* queryallow =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
/* Forward */
static void ncparamfree(char** params);
static int ncfind(char** params, const char* key);
static void nclshift1(char* p);
static void ncrshift1(char* p);
static char* nclocate(char* p, const char* charlist);
static void ncappendparams(char* newuri, char** p);
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
int
ncuriparse(const char* uri0, NCURI** ncurip)
{
NCURI* ncuri = 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;}
ncuri = (NCURI*)calloc(1,sizeof(NCURI));
if(ncuri == NULL)
{THROW(2); goto fail;}
/* save original uri */
ncuri->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' */
ncuri->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 */
p = suffixparams;
/* There must be brackets */
if(*p != LBRACKET)
{THROW(14); goto fail;}
suffixparams++; /* skip leading LBRACKET */
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 */
ncuri->protocol = protocol;
ncuri->user = user;
ncuri->password = pwd;
ncuri->host = host;
ncuri->port = port;
ncuri->file = file;
ncurisetconstraints(ncuri,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 comma if both are defined */
space++;
ncuri->params = (char*)malloc(space);
ncuri->params[0] = EOFCHAR; /* so we can use strcat */
if(plen > 0) {
strcat(ncuri->params,prefixparams);
if(slen > 0)
strcat(ncuri->params,";");
}
if(slen > 0)
strcat(ncuri->params,suffixparams);
}
#ifdef NCXDEBUG
{
fprintf(stderr,"ncuri:");
fprintf(stderr," params=|%s|",FIX(ncuri->params));
fprintf(stderr," protocol=|%s|",FIX(ncuri->protocol));
fprintf(stderr," host=|%s|",FIX(ncuri->host));
fprintf(stderr," port=|%s|",FIX(ncuri->port));
fprintf(stderr," file=|%s|",FIX(ncuri->file));
fprintf(stderr," constraint=|%s|",FIX(ncuri->constraint));
fprintf(stderr,"\n");
}
#endif
if(ncurip != NULL) *ncurip = ncuri;
return 1;
fail:
if(ncuri != NULL) {
ncurifree(ncuri);
}
return 0;
}
void
ncurifree(NCURI* ncuri)
{
if(ncuri == NULL) return;
if(ncuri->uri != NULL) {free(ncuri->uri);}
if(ncuri->params != NULL) {free(ncuri->params);}
if(ncuri->paramlist != NULL) ncparamfree(ncuri->paramlist);
if(ncuri->strings != NULL) {free(ncuri->strings);}
if(ncuri->constraint != NULL) {free(ncuri->constraint);}
if(ncuri->projection != NULL) {free(ncuri->projection);}
if(ncuri->selection != NULL) {free(ncuri->selection);}
free(ncuri);
}
/* Replace the constraints */
void
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;
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 = (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;
}
/* Construct a complete NC URI.
Optionally with the constraints.
Optionally with the user parameters.
Caller frees returned string.
Optionally encode the pieces.
*/
char*
ncuribuild(NCURI* duri, const char* prefix, const char* suffix, int flags)
{
size_t len = 0;
char* newuri;
char* tmpfile;
char* tmpsuffix;
char* tmpquery;
int nparams = 0;
int paramslen = 0;
/* if both are specified, prefix has priority */
int withsuffixparams = ((flags&NCURISUFFIXPARAMS)!=0
&& duri->params != NULL);
int withprefixparams = ((flags&NCURIPREFIXPARAMS)!=0
&& duri->params != NULL);
int withuserpwd = ((flags&NCURIUSERPWD)!=0
&& duri->user != NULL && duri->password != NULL);
int withconstraints = ((flags&NCURICONSTRAINTS)!=0
&& duri->constraint != NULL);
#ifdef NEWESCAPE
int encode = (flags&NCURIENCODE);
#else
int encode = 0;
#endif
if(prefix != NULL) len += NILLEN(prefix);
len += (NILLEN(duri->protocol)+NILLEN("://"));
if(withuserpwd) {
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
}
len += (NILLEN(duri->host));
if(duri->port != NULL) {
len += (NILLEN(":")+NILLEN(duri->port));
}
tmpfile = duri->file;
if(encode)
tmpfile = ncuriencode(tmpfile,fileallow);
len += (NILLEN(tmpfile));
if(suffix != NULL) {
tmpsuffix = (char*)suffix;
if(encode)
tmpsuffix = ncuriencode(tmpsuffix,fileallow);
len += (NILLEN(tmpsuffix));
}
if(withconstraints) {
tmpquery = duri->constraint;
if(encode)
tmpquery = ncuriencode(tmpquery,queryallow);
len += (NILLEN("?")+NILLEN(tmpquery));
}
if(withprefixparams || withsuffixparams) {
char** p;
if(duri->paramlist == NULL)
if(!ncuridecodeparams(duri))
return NULL;
for(paramslen=0,nparams=0,p=duri->paramlist;*p;p++) {
nparams++;
paramslen += NILLEN(*p);
}
if(nparams % 2 == 1)
return NULL; /* malformed */
nparams = (nparams / 2);
len += paramslen;
len += 3*nparams; /* for brackets for every param plus possible = */
if(withsuffixparams)
len += strlen("#");
}
len += 1; /* null terminator */
newuri = (char*)malloc(len);
if(newuri == NULL) return NULL;
newuri[0] = EOFCHAR;
if(prefix != NULL) strcat(newuri,prefix);
if(withprefixparams) {
ncappendparams(newuri,duri->paramlist);
}
if(duri->protocol != NULL)
strcat(newuri,duri->protocol);
strcat(newuri,"://");
if(withuserpwd) {
strcat(newuri,duri->user);
strcat(newuri,":");
strcat(newuri,duri->password);
strcat(newuri,"@");
}
if(duri->host != NULL) { /* may be null if using file: protocol */
strcat(newuri,duri->host);
}
if(duri->port != NULL) {
strcat(newuri,":");
strcat(newuri,duri->port);
}
if(tmpfile != NULL) {
strcat(newuri,tmpfile);
if(suffix != NULL) strcat(newuri,tmpsuffix);
}
if(withconstraints) {
strcat(newuri,"?");
strcat(newuri,tmpquery);
}
if(withsuffixparams & !withprefixparams) {
strcat(newuri,"#");
ncappendparams(newuri,duri->paramlist);
}
return newuri;
}
static void
ncappendparams(char* newuri, char** p)
{
while(*p) {
strcat(newuri,"[");
strcat(newuri,*p++);
if(strlen(*p) > 0) {
strcat(newuri,"=");
strcat(newuri,*p);
}
p++;
strcat(newuri,"]");
}
}
/**************************************************/
/* Parameter support */
/*
In the original url, client parameters are assumed to be one
or more instances of bracketed pairs: e.g "[...][...]...".
They may occur either at the front, or suffixed after
a trailing # character After processing, the list is
converted to a semicolon separated list of the combination
of prefix and suffix parameters.
After the url is parsed, the parameter list
is converted to a semicolon separated list with all
whitespace removed.
In any case, each parameter in turn is assumed to be a
of the form <name>=<value> or [<name>].
e.g. [x=y][z][a=b][w]. If the same parameter is specified more
than once, then the first occurrence is used; this is so
that is possible to forcibly override user specified
parameters by prefixing. IMPORTANT: client parameter string
is assumed to have blanks compressed out. Returns 1 if parse
suceeded, 0 otherwise; */
int
ncuridecodeparams(NCURI* ncuri)
{
char* cp;
int i,c;
int nparams;
char* params;
char** plist;
if(ncuri == NULL) return 0;
if(ncuri->params == NULL) return 1;
params = strdup(ncuri->params); /* so we can modify */
/* Pass 1 to break string into pieces at the semicolons
and count # of pairs */
nparams=0;
for(cp=params;(c=*cp);cp++) {
if(c == ';') {*cp = EOFCHAR; nparams++;}
}
nparams++; /* for last one */
/* plist is an env style list */
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
/* Break up each param into a (name,value) pair*/
/* and insert into the param list */
/* parameters of the form name name= are converted to name=""*/
for(cp=params,i=0;i<nparams;i++) {
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
char* vp;
/*break up the ith param*/
vp = strchr(cp,'=');
if(vp != NULL) {*vp = EOFCHAR; vp++;} else {vp = "";}
plist[2*i] = nulldup(cp);
plist[2*i+1] = nulldup(vp);
cp = next;
}
plist[2*nparams] = NULL;
free(params);
if(ncuri->paramlist != NULL)
ncparamfree(ncuri->paramlist);
ncuri->paramlist = plist;
return 1;
}
int
ncurilookup(NCURI* uri, const char* key, const char** resultp)
{
int i;
char* value = NULL;
if(uri == NULL || key == NULL || uri->params == NULL) return 0;
if(uri->paramlist == NULL) {
i = ncuridecodeparams(uri);
if(!i) return 0;
}
i = ncfind(uri->paramlist,key);
if(i < 0)
return 0;
value = uri->paramlist[(2*i)+1];
if(resultp) *resultp = value;
return 1;
}
int
ncurisetparams(NCURI* uri, const char* newparams)
{
if(uri == NULL) return 0;
if(uri->paramlist != NULL) ncparamfree(uri->paramlist);
uri->paramlist = NULL;
if(uri->params != NULL) free(uri->params);
uri->params = nulldup(newparams);
return 1;
}
/* Internal version of lookup; returns the paired index of the key */
static int
ncfind(char** params, const char* key)
{
int i;
char** p;
for(i=0,p=params;*p;p+=2,i++) {
if(strcmp(key,*p)==0) return i;
}
return -1;
}
static void
ncparamfree(char** params)
{
char** p;
if(params == NULL) return;
for(p=params;*p;p+=2) {
free(*p);
if(p[1] != NULL) free(p[1]);
}
free(params);
}
/* Return the ptr to the first occurrence of
any char in the list. Return NULL if no
occurrences
*/
static char*
nclocate(char* p, const char* charlist)
{
for(;*p;p++) {
if(strchr(charlist,*p) != NULL)
return p;
}
return NULL;
}
/* Shift every char starting at p 1 place to the left */
static void
nclshift1(char* p)
{
if(p != NULL && *p != EOFCHAR) {
char* q = p++;
while((*q++=*p++));
}
}
/* Shift every char starting at p 1 place to the right */
static void
ncrshift1(char* p)
{
char cur;
cur = 0;
do {
char next = *p;
*p++ = cur;
cur = next;
} while(cur != 0);
*p = 0; /* make sure we are still null terminated */
}
/* Provide % encoders and decoders */
static char* hexchars = "0123456789abcdefABCDEF";
static void
toHex(unsigned int b, char hex[2])
{
hex[0] = hexchars[(b >> 4) & 0xff];
hex[1] = hexchars[(b) & 0xff];
}
static unsigned int
fromHex(int c)
{
if(c >= '0' && c <= '9') return (c - '0');
if(c >= 'a' && c <= 'f') return (10 + (c - 'a'));
if(c >= 'A' && c <= 'F') return (10 + (c - 'A'));
return -1;
}
/* Return a string representing encoding of input; caller must free;
watch out: will encode whole string, so watch what you give it.
Allowable argument specifies characters that do not need escaping.
*/
char*
ncuriencode(char* s, char* allowable)
{
size_t slen;
char* encoded;
char* inptr;
char* outptr;
if(s == NULL) return NULL;
slen = strlen(s);
encoded = (char*)malloc((3*slen) + 1); /* max possible size */
for(inptr=s,outptr=encoded;*inptr;) {
int c = *inptr++;
if(c == ' ') {
*outptr++ = '+';
} else {
/* search allowable */
int c2;
char* a = allowable;
while((c2=*a++)) {
if(c == c2) break;
}
if(c2) {*outptr++ = c;}
else {
char hex[2];
toHex(c,hex);
*outptr++ = '%';
*outptr++ = hex[0];
*outptr++ = hex[1];
}
}
}
*outptr = EOFCHAR;
return encoded;
}
/* Return a string representing decoding of input; caller must free;*/
char*
ncuridecode(char* s)
{
return ncuridecodeonly(s,NULL);
}
/* Return a string representing decoding of input only for specified
characters; caller must free
*/
char*
ncuridecodeonly(char* s, char* only)
{
size_t slen;
char* decoded;
char* outptr;
char* inptr;
unsigned int c;
if (s == NULL) return NULL;
if(only == NULL) only = "";
slen = strlen(s);
decoded = (char*)malloc(slen+1); /* Should be max we need */
outptr = decoded;
inptr = s;
while((c = *inptr++)) {
if(c == '+' && strchr(only,'+') != NULL)
*outptr++ = ' ';
else if(c == '%') {
/* try to pull two hex more characters */
if(inptr[0] != EOFCHAR && inptr[1] != EOFCHAR
&& strchr(hexchars,inptr[0]) != NULL
&& strchr(hexchars,inptr[1]) != NULL) {
/* test conversion */
int xc = (fromHex(inptr[0]) << 4) | (fromHex(inptr[1]));
if(strchr(only,xc) != NULL) {
inptr += 2; /* decode it */
c = xc;
}
}
}
*outptr++ = c;
}
*outptr = EOFCHAR;
return decoded;
}

View File

@ -1,8 +1,6 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -145,7 +143,7 @@ ocbytesappendn(OCbytes* bb, const void* elem, unsigned int n)
}
int
ocbytesprepend(OCbytes* bb, const char elem)
ocbytesprepend(OCbytes* bb, char elem)
{
int i; /* do not make unsigned */
if(bb == NULL) return ocbytesfail();
@ -188,3 +186,14 @@ ocbytessetcontents(OCbytes* bb, char* contents, unsigned int alloc)
bb->nonextendible = 1;
return 1;
}
/* Null terminate the byte string without extending its length */
/* For debugging */
int
ocbytesnull(OCbytes* bb)
{
ocbytesappend(bb,'\0');
bb->length--;
return 1;
}

View File

@ -34,19 +34,23 @@ EXTERNC int ocbytesget(OCbytes*,unsigned int);
EXTERNC int ocbytesset(OCbytes*,unsigned int,char);
/* Append one byte */
EXTERNC int ocbytesappend(OCbytes*,const char); /* Add at Tail */
EXTERNC int ocbytesappend(OCbytes*,char); /* Add at Tail */
/* Append n bytes */
EXTERNC int ocbytesappendn(OCbytes*,const void*,unsigned int); /* Add at Tail */
/* Null terminate the byte string without extending its length (for debugging) */
EXTERNC int ocbytesnull(OCbytes*);
/* Concatenate a null-terminated string to the end of the buffer */
EXTERNC int ocbytescat(OCbytes*,const char*);
/* Set the contents of the buffer; mark the buffer as non-extendible */
EXTERNC int ocbytessetcontents(OCbytes*, char*, unsigned int);
/* Following are always "in-lined"*/
#define ocbyteslength(bb) ((bb)!=NULL?(bb)->length:0U)
#define ocbytesalloc(bb) ((bb)!=NULL?(bb)->alloc:0U)
#define ocbytescontents(bb) (((bb) !=NULL && (bb)->content != NULL)?(bb)->content:(char*)"")
#define ocbytescontents(bb) (((bb)!=NULL && (bb)->content!=NULL)?(bb)->content:(char*)"")
#define ocbytesextend(bb,len) ocbytessetalloc((bb),(len)+(bb->alloc))
#define ocbytesclear(bb) ((bb)!=NULL?(bb)->length=0:0U)
#define ocbytesavail(bb,n) ((bb)!=NULL?((bb)->alloc - (bb)->length) >= (n):0U)

View File

@ -37,8 +37,11 @@ ocparamdecode(OCstate* state)
const char*
ocparamlookup(OCstate* state, const char* key)
{
const char* value = NULL;
if(state == NULL || key == NULL || state->uri == NULL) return NULL;
return ocurilookup(state->uri,key);
if(!ocurilookup(state->uri,key,&value))
value = NULL;
return value;
}
int

View File

@ -151,7 +151,7 @@ occompile1(OCstate* state, OCnode* xnode, XXDR* xxdrs, OCdata** datap)
} else if(tmp[0] == EndOfSequence) {
break; /* we are done with the this sequence instance*/
} else {
oc_log(LOGERR,"missing/invalid begin/end record marker\n");
oclog(OCLOGERR,"missing/invalid begin/end record marker\n");
ocstat = OC_EINVALCOORDS;
goto fail;
}
@ -408,7 +408,7 @@ ocerrorstring(XXDR* xdrs)
if(ocstrncmp(data,tag,sizeof(tag))==0) {
char* p;
if((p=strchr(data,'}')) != NULL) *(++p)='\0';
oc_log(LOGERR,"Server error: %s",data);
oclog(OCLOGERR,"Server error: %s",data);
/* Since important, report to stderr as well */
fprintf(stderr,"Server error: %s",data);
return 1;

View File

@ -42,8 +42,8 @@ oc_curl_protocols(struct OCGLOBALSTATE* state)
if(strcmp("http",*proto)==0) {state->curl.proto_https=1;break;}
}
if(ocdebug > 0) {
oc_log(LOGNOTE,"Curl file:// support = %d",state->curl.proto_file);
oc_log(LOGNOTE,"Curl https:// support = %d",state->curl.proto_https);
oclog(OCLOGNOTE,"Curl file:// support = %d",state->curl.proto_file);
oclog(OCLOGNOTE,"Curl https:// support = %d",state->curl.proto_https);
}
}
@ -226,7 +226,7 @@ combinecredentials(const char* user, const char* pwd)
int userPassSize = strlen(user) + strlen(pwd) + 2;
char *userPassword = malloc(sizeof(char) * userPassSize);
if (!userPassword) {
oc_log(LOGERR,"Out of Memory\n");
oclog(OCLOGERR,"Out of Memory\n");
return NULL;
}
strcpy(userPassword, user);

View File

@ -404,7 +404,7 @@ ocread(OCdata* data, XXDR* xdrs, char* memory, size_t memsize, size_t start, siz
return OC_NOERR;
xdrfail:
oc_log(LOGERR,"DAP DATADDS packet is apparently too short");
oclog(OCLOGERR,"DAP DATADDS packet is apparently too short");
return OCTHROW(OC_EDATADDS);
}

View File

@ -24,7 +24,7 @@ octhrow(int err)
int
xdrerror(void)
{
oc_log(LOGERR,"xdr failure");
oclog(OCLOGERR,"xdr failure");
return OCTHROW(OC_EDATADDS);
}
@ -39,7 +39,7 @@ void*
ocmalloc(size_t size)
{
void* memory = calloc(size,1); /* use calloc to zero memory*/
if(memory == NULL) oc_log(LOGERR,"ocmalloc: out of memory");
if(memory == NULL) oclog(OCLOGERR,"ocmalloc: out of memory");
return memory;
}

View File

@ -32,10 +32,10 @@
/* Need some syntactic trickery to make these macros work*/
#ifdef OCDEBUG
#define OCDBG(l,msg) {oc_log(LOGDBG,msg);}
#define OCDBG1(l,msg,arg) {oc_log(LOGDBG,msg,arg);}
#define OCDBG2(l,msg,arg1,arg2) {oc_log(LOGDBG,msg,arg1,arg2);}
#define OCDBGTEXT(l,text) {oc_logtext(LOGNOTE,text);} else {}
#define OCDBG(l,msg) {oclog(OCLOGDBG,msg);}
#define OCDBG1(l,msg,arg) {oclog(OCLOGDBG,msg,arg);}
#define OCDBG2(l,msg,arg1,arg2) {oclog(OCLOGDBG,msg,arg1,arg2);}
#define OCDBGTEXT(l,text) {oclogtext(OCLOGNOTE,text);} else {}
#define OCDBGCODE(l,code) {code;}
#else

View File

@ -68,7 +68,7 @@ ocfetchurl_file(CURL* curl, const char* url, FILE* stream,
if (stat == OC_NOERR) {
/* return the file size*/
#ifdef OCDEBUG
oc_log(LOGNOTE,"filesize: %lu bytes",fetchdata.size);
oclog(OCLOGNOTE,"filesize: %lu bytes",fetchdata.size);
#endif
if (sizep != NULL)
*sizep = fetchdata.size;
@ -80,7 +80,7 @@ ocfetchurl_file(CURL* curl, const char* url, FILE* stream,
return OCTHROW(stat);
fail:
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
return OCTHROW(OC_ECURL);
}
@ -112,7 +112,7 @@ ocfetchurl(CURL* curl, const char* url, OCbytes* buf, long* filetime)
cstat = curl_easy_perform(curl);
if(cstat == CURLE_PARTIAL_FILE) {
/* Log it but otherwise ignore */
oc_log(LOGWARN, "curl error: %s; ignored",
oclog(OCLOGWARN, "curl error: %s; ignored",
curl_easy_strerror(cstat));
cstat = CURLE_OK;
}
@ -128,13 +128,13 @@ ocfetchurl(CURL* curl, const char* url, OCbytes* buf, long* filetime)
ocbytesappend(buf, '\0');
ocbytessetlength(buf, len); /* dont count null in buffer size*/
#ifdef OCDEBUG
oc_log(LOGNOTE,"buffersize: %lu bytes",(off_t)ocbyteslength(buf));
oclog(OCLOGNOTE,"buffersize: %lu bytes",(off_t)ocbyteslength(buf));
#endif
return OCTHROW(stat);
fail:
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
return OCTHROW(OC_ECURL);
}
@ -146,15 +146,15 @@ WriteFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
struct Fetchdata* fetchdata;
fetchdata = (struct Fetchdata*) data;
if(realsize == 0)
oc_log(LOGWARN,"WriteFileCallback: zero sized chunk");
oclog(OCLOGWARN,"WriteFileCallback: zero sized chunk");
count = fwrite(ptr, size, nmemb, fetchdata->stream);
if (count > 0) {
fetchdata->size += (count * size);
} else {
oc_log(LOGWARN,"WriteFileCallback: zero sized write");
oclog(OCLOGWARN,"WriteFileCallback: zero sized write");
}
#ifdef OCPROGRESS
oc_log(LOGNOTE,"callback: %lu bytes",(off_t)realsize);
oclog(OCLOGNOTE,"callback: %lu bytes",(off_t)realsize);
#endif
return count;
}
@ -165,7 +165,7 @@ WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
size_t realsize = size * nmemb;
OCbytes* buf = (OCbytes*) data;
if(realsize == 0)
oc_log(LOGWARN,"WriteMemoryCallback: zero sized chunk");
oclog(OCLOGWARN,"WriteMemoryCallback: zero sized chunk");
/* Optimize for reading potentially large dods datasets */
if(!ocbytesavail(buf,realsize)) {
/* double the size of the packet */
@ -173,7 +173,7 @@ WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
}
ocbytesappendn(buf, ptr, realsize);
#ifdef OCPROGRESS
oc_log(LOGNOTE,"callback: %lu bytes",(off_t)realsize);
oclog(OCLOGNOTE,"callback: %lu bytes",(off_t)realsize);
#endif
return realsize;
}
@ -283,7 +283,7 @@ ocfetchlastmodified(CURL* curl, char* url, long* filetime)
return OCTHROW(stat);
fail:
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
return OCTHROW(OC_ECURL);
}
@ -329,7 +329,7 @@ done:
ocbytesfree(buf);
occurlclose(curl);
if(cstat != CURLE_OK) {
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
stat = OC_EDAPSVC;
}
return OCTHROW(stat);

View File

@ -68,7 +68,7 @@ ocinternalinitialize(void)
/* Compute some xdr related flags */
xxdr_init();
oc_loginit();
ocloginit();
oc_curl_protocols(&ocglobalstate); /* see what protocols are supported */
@ -106,14 +106,14 @@ ocinternalinitialize(void)
}
}
if(f == NULL) {
oc_log(LOGDBG,"Cannot find runtime configuration file");
oclog(OCLOGDBG,"Cannot find runtime configuration file");
} else {
OCASSERT(path != NULL);
fclose(f);
if(ocdebug > 1)
fprintf(stderr, "DODS RC file: %s\n", path);
if(ocdodsrc_read(*alias,path) == 0)
oc_log(LOGERR, "Error parsing %s\n",path);
oclog(OCLOGERR, "Error parsing %s\n",path);
}
if(path != NULL) free(path);
}
@ -144,7 +144,7 @@ ocopen(OCstate** statep, const char* url)
state->trees = oclistnew();
state->uri = tmpurl;
if(!ocuridecodeparams(state->uri)) {
oc_log(LOGWARN,"Could not parse client parameters");
oclog(OCLOGWARN,"Could not parse client parameters");
}
state->packet = ocbytesnew();
ocbytessetalloc(state->packet,DFALTPACKETSIZE); /*initial reasonable size*/
@ -231,9 +231,9 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
/* Obtain any http code */
state->error.httpcode = ocfetchhttpcode(state->curl);
if(state->error.httpcode >= 400) {
oc_log(LOGWARN,"oc_open: Could not read url; http error = %l",state->error.httpcode);
oclog(OCLOGWARN,"oc_open: Could not read url; http error = %l",state->error.httpcode);
} else {
oc_log(LOGWARN,"oc_open: Could not read url");
oclog(OCLOGWARN,"oc_open: Could not read url");
}
goto fail;
}
@ -242,7 +242,7 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
stat = DAPparse(state,tree,tree->text);
/* Check and report on an error return from the server */
if(stat == OC_EDAPSVC && state->error.code != NULL) {
oc_log(LOGERR,"oc_open: server error retrieving url: code=%s message=\"%s\"",
oclog(OCLOGERR,"oc_open: server error retrieving url: code=%s message=\"%s\"",
state->error.code,
(state->error.message?state->error.message:""));
}
@ -319,11 +319,11 @@ createtempfile(OCstate* state, OCtree* tree)
if(fd < 0)
fd = createtempfile1(TMPPATH2,&name);
if(fd < 0) {
oc_log(LOGERR,"oc_open: attempt to open tmp file failed: %s",name);
oclog(OCLOGERR,"oc_open: attempt to open tmp file failed: %s",name);
return errno;
}
#ifdef OCDEBUG
oc_log(LOGNOTE,"oc_open: using tmp file: %s",name);
oclog(OCLOGNOTE,"oc_open: using tmp file: %s",name);
#endif
tree->data.filename = name; /* remember our tmp file name */
tree->data.file = fdopen(fd,"w+");
@ -532,7 +532,7 @@ ocsetcurlproperties(OCstate* state)
/* process the triple store wrt to this state */
if(ocdodsrc_process(state) != OC_NOERR) {
oc_log(LOGERR,"Malformed .opendaprc configuration file");
oclog(OCLOGERR,"Malformed .opendaprc configuration file");
goto fail;
}
if(state->creds.username == NULL && state->creds.password == NULL) {
@ -548,6 +548,6 @@ ocsetcurlproperties(OCstate* state)
fail:
if(cstat != CURLE_OK)
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
oclog(OCLOGERR, "curl error: %s", curl_easy_strerror(cstat));
return;
}

View File

@ -1,8 +1,5 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -24,7 +21,7 @@ int oclistnull(ocelem e) {return e == ocDATANULL;}
#define DEFAULTALLOC 16
#define ALLOCINCR 16
OClist* oclistnewn(int prealloc)
OClist* oclistnew(void)
{
OClist* l;
/*
@ -33,13 +30,11 @@ OClist* oclistnewn(int prealloc)
ocinitialized = 1;
}
*/
if(prealloc < 0) prealloc = 0;
l = (OClist*)malloc(sizeof(OClist));
if(l) {
l->alloc=prealloc;
l->length=prealloc;
l->content=(prealloc==0?NULL:(ocelem*)calloc(prealloc,sizeof(ocelem)));
if(l == NULL) {free(l);return 0;}
l->alloc=0;
l->length=0;
l->content=NULL;
}
return l;
}
@ -65,8 +60,8 @@ oclistsetalloc(OClist* l, unsigned int sz)
newcontent=(ocelem*)calloc(sz,sizeof(ocelem));
if(l->alloc > 0 && l->length > 0 && l->content != NULL) {
memcpy((void*)newcontent,(void*)l->content,sizeof(ocelem)*l->length);
free(l->content);
}
if(l->content != NULL) free(l->content);
l->content=newcontent;
l->alloc=sz;
return TRUE;
@ -102,11 +97,11 @@ oclistset(OClist* l, unsigned int index, ocelem elem)
int
oclistinsert(OClist* l, unsigned int index, ocelem elem)
{
unsigned int i;
int i; /* do not make unsigned */
if(l == NULL) return FALSE;
if(index > l->length) return FALSE;
oclistsetalloc(l,0);
for(i=l->length;i>index;i--) l->content[i] = l->content[i-1];
for(i=(int)l->length;i>index;i--) l->content[i] = l->content[i-1];
l->content[index] = elem;
l->length++;
return TRUE;
@ -145,7 +140,7 @@ oclistremove(OClist* l, unsigned int i)
if(l == NULL || (len=l->length) == 0) return ocDATANULL;
if(i >= len) return ocDATANULL;
elem = l->content[i];
for(i++;i<len;i++) l->content[i-1] = l->content[i];
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
l->length--;
return elem;
}
@ -169,3 +164,61 @@ oclistcontains(OClist* list, ocelem elem)
}
return 0;
}
/* Remove element by value; only removes first encountered */
int
oclistelemremove(OClist* l, ocelem elem)
{
unsigned int len;
unsigned int i;
int found = 0;
if(l == NULL || (len=l->length) == 0) return ocDATANULL;
for(i=0;i<oclistlength(l);i++) {
ocelem candidate = l->content[i];
if(elem == candidate) {
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
l->length--;
found = 1;
break;
}
}
return found;
}
/* Extends oclist to include a unique operator
which remove duplicate values; NULL values removed
return value is always 1.
*/
int
oclistunique(OClist* list)
{
unsigned int i,j,k,len;
ocelem* content;
if(list == NULL || list->length == 0) return 1;
len = list->length;
content = list->content;
for(i=0;i<len;i++) {
for(j=i+1;j<len;j++) {
if(content[i] == content[j]) {
/* compress out jth element */
for(k=j+1;k<len;k++) content[k-1] = content[k];
len--;
}
}
}
list->length = len;
return 1;
}
OClist*
oclistclone(OClist* list)
{
OClist* clone = oclistnew();
*clone = *list;
clone->content = oclistdup(list);
return clone;
}

View File

@ -21,7 +21,7 @@ typedef struct OClist {
ocelem* content;
} OClist;
EXTERNC OClist* oclistnewn(int);
EXTERNC OClist* oclistnew(void);
EXTERNC int oclistfree(OClist*);
EXTERNC int oclistsetalloc(OClist*,unsigned int);
EXTERNC int oclistsetlength(OClist*,unsigned int);
@ -46,12 +46,19 @@ EXTERNC ocelem* oclistdup(OClist*);
/* Look for value match */
EXTERNC int oclistcontains(OClist*, ocelem);
/* Remove element by value; only removes first encountered */
EXTERNC int oclistelemremove(OClist* l, ocelem elem);
/* remove duplicates */
EXTERNC int oclistunique(OClist*);
/* Create a clone of a list */
EXTERNC OClist* oclistclone(OClist*);
/* Following are always "in-lined"*/
#define oclistnew() oclistnewn(0)
#define oclistclear(l) oclistsetlength((l),0U)
#define oclistextend(l,len) oclistsetalloc((l),(len)+(l->alloc))
#define oclistcontents(l) ((l)->content)
#define oclistlength(l) ((l!=NULL)?(l)->length:0U)
#define oclistcontents(l) ((l)==NULL?NULL:(l)->content)
#define oclistlength(l) ((l)==NULL?0U:(l)->length)
#endif /*OCLIST_H*/

View File

@ -1,22 +1,33 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
/*********************************************************************
* Copyright 2010, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header$
*********************************************************************/
#include "config.h"
#include "ocinternal.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include "oclog.h"
#define PREFIXLEN 8
#define MAXTAGS 256
#define OCTAGDFALT "Log";
#define ENVFLAG "OCLOGFILE"
static int ocloginit = 0;
static int oclogginginitialized = 0;
static int oclogging = 0;
static int ocsystemfile = 0; /* 1 => we are logging something we did not open */
static int ocsystemfile = 0; /* 1 => we are logging to file we did not open */
static char* oclogfile = NULL;
static FILE* oclogstream = NULL;
static int octagsize = 0;
static char** octagset = NULL;
static char* octagdfalt = NULL;
static char* octagsetdfalt[] = {"Warning","Error","Note","Debug"};
static char* octagname(int tag);
/*!\defgroup OClog OClog Management
@{*/
@ -24,19 +35,22 @@ static FILE* oclogstream = NULL;
*/
void
oc_loginit(void)
ocloginit(void)
{
const char* file = getenv(ENVFLAG); /* I hope this is portable*/
ocloginit = 1;
oc_setlogging(0);
const char* file = getenv(OCENVFLAG);
oclogginginitialized = 1;
ocsetlogging(0);
oclogfile = NULL;
oclogstream = NULL;
/* Use environment variables to preset oclogging state*/
/* I hope this is portable*/
if(file != NULL && strlen(file) > 0) {
if(oc_logopen(file)) {
oc_setlogging(1);
if(oclogopen(file)) {
ocsetlogging(1);
}
}
octagdfalt = OCTAGDFALT;
octagset = octagsetdfalt;
}
/*!
@ -48,10 +62,10 @@ Enable/Disable logging.
*/
int
oc_setlogging(int tf)
ocsetlogging(int tf)
{
int was;
if(!ocloginit) oc_loginit();
if(!oclogginginitialized) ocloginit();
was = oclogging;
oclogging = tf;
return was;
@ -68,10 +82,10 @@ stderr.
*/
int
oc_logopen(const char* file)
oclogopen(const char* file)
{
if(!ocloginit) oc_loginit();
oc_logclose();
if(!oclogginginitialized) ocloginit();
oclogclose();
if(file == NULL || strlen(file) == 0) {
/* use stderr*/
oclogstream = stderr;
@ -89,8 +103,7 @@ oc_logopen(const char* file)
ocsystemfile = 1;
} else {
int fd;
oclogfile = (char*)malloc(strlen(file)+1);
strcpy(oclogfile,file);
oclogfile = strdup(file);
oclogstream = NULL;
/* We need to deal with this file carefully
to avoid unauthorized access*/
@ -100,24 +113,20 @@ oc_logopen(const char* file)
} else {
free(oclogfile);
oclogfile = NULL;
oc_setlogging(0);
oclogstream = NULL;
ocsetlogging(0);
return 0;
}
ocsystemfile = 0;
}
return 1;
}
/*!
Close the logging output file (unless it is stderr).
Logging is still enabled.
*/
void
oc_logclose(void)
oclogclose(void)
{
if(!ocloginit) oc_loginit();
if(!oclogginginitialized) ocloginit();
if(oclogstream != NULL && !ocsystemfile) {
assert(oclogfile != NULL && oclogstream != NULL);
fclose(oclogstream);
}
if(oclogfile != NULL) free(oclogfile);
@ -136,63 +145,71 @@ printf function.
*/
void
oc_log(int tag, const char* format, ...)
oclog(int tag, const char* fmt, ...)
{
va_list args;
char* prefix;
if(!ocloginit) oc_loginit();
if(!oclogginginitialized) ocloginit();
if(!oclogging || oclogstream == NULL) return;
switch (tag) {
case LOGWARN: prefix = "Warning:"; break;
case LOGERR: prefix = "Error: "; break;
case LOGNOTE: prefix = "Note: "; break;
case LOGDBG: prefix = "Debug: "; break;
default:
fprintf(oclogstream,"Error: Bad log prefix: %d\n",tag);
prefix = "Error: ";
break;
}
prefix = octagname(tag);
fprintf(oclogstream,"%s:",prefix);
if(format != NULL) {
va_start(args, format);
vfprintf(oclogstream, format, args);
if(fmt != NULL) {
va_start(args, fmt);
vfprintf(oclogstream, fmt, args);
va_end( args );
}
fprintf(oclogstream, "\n" );
fflush(oclogstream);
}
void
oclogtext(int tag, const char* text)
{
oclogtextn(tag,text,strlen(text));
}
/*!
Send arbitrarily long text as a logging message.
Each line will be sent using oc_log with the specified tag.
Each line will be sent using oclog with the specified tag.
\param[in] tag Indicate the kind of this log message.
\param[in] text Arbitrary text to send as a logging message.
*/
void
oc_logtext(int tag, const char* text)
oclogtextn(int tag, const char* text, size_t count)
{
char line[1024];
size_t delta = 0;
const char* eol = text;
if(!ocloginit) oc_loginit();
if(!oclogging || oclogstream == NULL) return;
fwrite(text,1,count,oclogstream);
fflush(oclogstream);
}
while(*text) {
eol = strchr(text,'\n');
if(eol == NULL)
delta = strlen(text);
else
delta = (eol - text);
if(delta > 0) memcpy(line,text,delta);
line[delta] = '\0';
fprintf(oclogstream," %s\n",line);
text = eol+1;
/* The tagset is null terminated */
void
oclogsettags(char** tagset, char* dfalt)
{
octagdfalt = dfalt;
if(tagset == NULL) {
octagsize = 0;
} else {
int i;
/* Find end of the tagset */
for(i=0;i<MAXTAGS;i++) {if(tagset[i]==NULL) break;}
octagsize = i;
}
octagset = tagset;
}
static char*
octagname(int tag)
{
if(tag < 0 || tag >= octagsize) {
return octagdfalt;
} else {
return octagset[tag];
}
}

View File

@ -1,20 +1,31 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
/*********************************************************************
* Copyright 2010, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header$
*********************************************************************/
#ifndef OCLOG_H
#define OCLOG_H
#define LOGNOTE 0
#define LOGWARN 1
#define LOGERR 2
#define LOGDBG 3
#define OCENVFLAG "OCLOGFILE"
extern void oc_loginit(void);
extern int oc_setlogging(int tf);
extern int oc_logopen(const char* file);
extern void oc_logclose(void);
/* Suggested tag values */
#define OCLOGNOTE 0
#define OCLOGWARN 1
#define OCLOGERR 2
#define OCLOGDBG 3
extern void oc_log(int tag, const char* fmt, ...);
extern void oc_logtext(int tag, const char* text);
extern void ocloginit(void);
extern int ocsetlogging(int tf);
extern int oclogopen(const char* file);
extern void oclogclose(void);
/* The tag value is an arbitrary integer */
extern void oclog(int tag, const char* fmt, ...);
extern void oclogtext(int tag, const char* text);
extern void oclogtextn(int tag, const char* text, size_t count);
/* Provide printable names for tags */
extern void oclogsettags(char** tagset, char* dfalt);
#endif /*OCLOG_H*/

View File

@ -143,7 +143,7 @@ makeattribute(char* name, OCtype ptype, OClist* values)
static void
marklostattribute(OCnode* att)
{
oc_log(LOGNOTE,"Lost attribute: %s",att->name);
oclog(OCLOGNOTE,"Lost attribute: %s",att->name);
}
void
@ -288,7 +288,7 @@ ocddsdasmerge(OCstate* state, OCnode* dasroot, OCnode* ddsroot)
OCnode* das2 = (OCnode*)oclistget(dasnodes,j);
if(das->name == NULL || das2->name == NULL) continue;
if(strcmp(das->name,das2->name)==0) {
oc_log(LOGWARN,"oc_mergedas: potentially ambiguous DAS name: %s",das->name);
oclog(OCLOGWARN,"oc_mergedas: potentially ambiguous DAS name: %s",das->name);
}
}
oclistpush(dasnodes,(ocelem)das);

View File

@ -208,12 +208,12 @@ parseproxy(OCstate* state, char* v)
state->proxy.password[p_len] = '\0';
#endif /*0*/
if (ocdebug > 1) {
oc_log(LOGNOTE,"host name: %s", state->proxy.host);
oc_log(LOGNOTE,"user name: %s", state->creds.username);
oclog(OCLOGNOTE,"host name: %s", state->proxy.host);
oclog(OCLOGNOTE,"user name: %s", state->creds.username);
#ifdef INSECURE
oc_log(LOGNOTE,"password: %s", state->creds.password);
oclog(OCLOGNOTE,"password: %s", state->creds.password);
#endif
oc_log(LOGNOTE,"port number: %d", state->proxy.port);
oclog(OCLOGNOTE,"port number: %d", state->proxy.port);
}
if(v) free(v);
return OC_NOERR;
@ -234,7 +234,7 @@ sorttriplestore(void)
sorted = (struct OCTriple*)malloc(sizeof(struct OCTriple)*ocdodsrc->ntriples);
if(sorted == NULL) {
oc_log(LOGERR,"sorttriplestore: out of memory");
oclog(OCLOGERR,"sorttriplestore: out of memory");
return;
}
@ -285,7 +285,7 @@ ocdodsrc_read(char* basename, char* path)
if(ocdodsrc == NULL) {
ocdodsrc = (struct OCTriplestore*)malloc(sizeof(struct OCTriplestore));
if(ocdodsrc == NULL) {
oc_log(LOGERR,"ocdodsrc_read: out of memory");
oclog(OCLOGERR,"ocdodsrc_read: out of memory");
return 0;
}
ocglobalstate.ocdodsrc = ocdodsrc;
@ -294,7 +294,7 @@ ocdodsrc_read(char* basename, char* path)
in_file = fopen(path, "r"); /* Open the file to read it */
if (in_file == NULL) {
oc_log(LOGERR, "Could not open configuration file: %s",basename);
oclog(OCLOGERR, "Could not open configuration file: %s",basename);
return OC_EPERM;
}
@ -303,7 +303,7 @@ ocdodsrc_read(char* basename, char* path)
if(!rcreadline(in_file,line0,sizeof(line0))) break;
linecount++;
if(linecount >= MAXRCLINES) {
oc_log(LOGERR, ".dodsrc has too many lines");
oclog(OCLOGERR, ".dodsrc has too many lines");
return 0;
}
line = line0;
@ -312,7 +312,7 @@ ocdodsrc_read(char* basename, char* path)
/* trim leading blanks */
line = rctrimleft(line,TRIMCHARS);
if(strlen(line) >= MAXRCLINESIZE) {
oc_log(LOGERR, "%s line too long: %s",basename,line0);
oclog(OCLOGERR, "%s line too long: %s",basename,line0);
return 0;
}
/* parse the line */
@ -321,7 +321,7 @@ ocdodsrc_read(char* basename, char* path)
char* url = ++line;
char* rtag = strchr(line,RTAG);
if(rtag == NULL) {
oc_log(LOGERR, "Malformed [url] in %s entry: %s",basename,line);
oclog(OCLOGERR, "Malformed [url] in %s entry: %s",basename,line);
continue;
}
line = rtag + 1;
@ -338,7 +338,7 @@ ocdodsrc_read(char* basename, char* path)
if(value == NULL) {
/* add fake '=1' */
if(strlen(line) + strlen("=1") >= MAXRCLINESIZE) {
oc_log(LOGERR, "%s entry too long: %s",basename,line);
oclog(OCLOGERR, "%s entry too long: %s",basename,line);
continue;
}
strcat(line,"=1");
@ -369,31 +369,31 @@ ocdodsrc_process(OCstate* state)
if(value != NULL) {
if(atoi(value)) state->curlflags.compress = 1;
if(ocdebug > 0)
oc_log(LOGNOTE,"Compression: %ld", state->curlflags.compress);
oclog(OCLOGNOTE,"Compression: %ld", state->curlflags.compress);
}
if((value = curllookup("VERBOSE",url)) != NULL) {
if(atoi(value)) state->curlflags.verbose = 1;
if(ocdebug > 0)
oc_log(LOGNOTE,"curl.verbose: %ld", state->curlflags.verbose);
oclog(OCLOGNOTE,"curl.verbose: %ld", state->curlflags.verbose);
}
if((value = curllookup("TIMEOUT",url)) != NULL) {
if(atoi(value)) state->curlflags.timeout = atoi(value);
if(ocdebug > 0)
oc_log(LOGNOTE,"curl.timeout: %ld", state->curlflags.timeout);
oclog(OCLOGNOTE,"curl.timeout: %ld", state->curlflags.timeout);
}
if((value = curllookup("COOKIEFILE",url)) != NULL) {
state->curlflags.cookiefile = strdup(TRIM(value));
if(!state->curlflags.cookiefile) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"COOKIEFILE: %s", state->curlflags.cookiefile);
oclog(OCLOGNOTE,"COOKIEFILE: %s", state->curlflags.cookiefile);
}
if((value = curllookup("COOKIEJAR",url))
|| (value = curllookup("COOKIE_JAR",url))) {
state->curlflags.cookiejar = strdup(TRIM(value));
if(!state->curlflags.cookiejar) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"COOKIEJAR: %s", state->curlflags.cookiejar);
oclog(OCLOGNOTE,"COOKIEJAR: %s", state->curlflags.cookiejar);
}
/* Some servers (e.g. thredds) appear to require a place
@ -412,21 +412,21 @@ ocdodsrc_process(OCstate* state)
if((value = curllookup("SSL.VALIDATE",url)) != NULL) {
if(atoi(value)) state->ssl.validate = 1;
if(ocdebug > 0)
oc_log(LOGNOTE,"CURL.SSL.VALIDATE: %ld", state->ssl.validate);
oclog(OCLOGNOTE,"CURL.SSL.VALIDATE: %ld", state->ssl.validate);
}
if((value = curllookup("SSL.CERTIFICATE",url)) != NULL) {
state->ssl.certificate = strdup(TRIM(value));
if(!state->ssl.certificate) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.SSL.CERTIFICATE: %s", state->ssl.certificate);
oclog(OCLOGNOTE,"CREDENTIALS.SSL.CERTIFICATE: %s", state->ssl.certificate);
}
if((value = curllookup("SSL.KEY",url)) != NULL) {
state->ssl.key = strdup(TRIM(value));
if(!state->ssl.key) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.SSL.KEY: %s", state->ssl.key);
oclog(OCLOGNOTE,"CREDENTIALS.SSL.KEY: %s", state->ssl.key);
}
if((value = curllookup("SSL.KEYPASSWORD",url)) != NULL) {
@ -434,7 +434,7 @@ ocdodsrc_process(OCstate* state)
if(!state->ssl.keypasswd) {stat = OC_ENOMEM; goto done;}
#ifdef INSECURE
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
oclog(OCLOGNOTE,"CREDENTIALS.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
#endif
}
@ -442,14 +442,14 @@ ocdodsrc_process(OCstate* state)
state->ssl.cainfo = strdup(TRIM(value));
if(!state->ssl.cainfo) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"SSL.CAINFO: %s", state->ssl.cainfo);
oclog(OCLOGNOTE,"SSL.CAINFO: %s", state->ssl.cainfo);
}
if((value = curllookup("SSL.CAPATH",url)) != NULL) {
state->ssl.capath = strdup(TRIM(value));
if(!state->ssl.capath) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"SSL.CAPATH: %s", state->ssl.capath);
oclog(OCLOGNOTE,"SSL.CAPATH: %s", state->ssl.capath);
}
if((value = curllookup("SSL.VERIFYPEER",url)) != NULL) {
@ -463,14 +463,14 @@ ocdodsrc_process(OCstate* state)
tf = 1; /* default if not null */
state->ssl.verifypeer = tf;
if(ocdebug > 0)
oc_log(LOGNOTE,"SSL.VERIFYPEER: %d", state->ssl.verifypeer);
oclog(OCLOGNOTE,"SSL.VERIFYPEER: %d", state->ssl.verifypeer);
}
if((value = curllookup("CREDENTIALS.USER",url)) != NULL) {
state->creds.username = strdup(TRIM(value));
if(!state->creds.username) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.USER: %s", state->creds.username);
oclog(OCLOGNOTE,"CREDENTIALS.USER: %s", state->creds.username);
}
if((value = curllookup("CREDENTIALS.PASSWORD",url)) != NULL) {

View File

@ -186,7 +186,7 @@ readfile(const char* path, const char* suffix, OCbytes* packet)
if(suffix != NULL) strcat(filename,suffix);
fd = open(filename,O_RDONLY);
if(fd < 0) {
oc_log(LOGERR,"open failed:%s",filename);
oclog(OCLOGERR,"open failed:%s",filename);
return OCTHROW(OC_EOPEN);
}
size=0;
@ -197,7 +197,7 @@ readfile(const char* path, const char* suffix, OCbytes* packet)
break;
else if(count < 0) {
stat = OC_EIO;
oc_log(LOGERR,"read failed: %s",filename);
oclog(OCLOGERR,"read failed: %s",filename);
break;
}
ocbytesappendn(packet,buf,count);

View File

@ -4,87 +4,53 @@
* $Header$
*********************************************************************/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "oc.h"
#include "ocuri.h"
#define OCURIDEBUG
#ifdef OCURIDEBUG
static int failpoint = 0;
#define THROW(n) {failpoint=(n); goto fail;}
#else
#define THROW(n)
#endif
#define PADDING 8
#define LBRACKET '['
#define RBRACKET ']'
#define EOFCHAR '\0'
#ifndef FIX
#define FIX(s) ((s)==NULL?"":(s))
#define FIX(s) ((s)==NULL?"NULL":(s))
#endif
#ifndef NILLEN
#define NILLEN(s) ((s)==NULL?0:strlen(s))
#endif
#ifdef HAVE_STRDUP
# ifndef nulldup
# define nulldup(s) ((s)==NULL?NULL:strdup(s))
# endif
#ifndef nulldup
#define nulldup(s) ((s)==NULL?NULL:strdup(s))
#endif
#ifndef HAVE_STRDUP
static char* nulldup(char* s)
{
char* dup = NULL;
if(s != NULL) {
dup = (char*)malloc(strlen(s)+1);
if(dup != NULL)
strcpy(dup,s);
}
return dup;
}
#endif
#define terminate(p) {*(p) = EOFCHAR;}
#ifdef OCIGNORE
/* Not all systems have strndup, so provide one*/
static char*
ocstrndup(const char* s, size_t len)
{
char* dup;
if(s == NULL) return NULL;
dup = (char*)ocmalloc(len+1);
MEMCHECK(dup,NULL);
memcpy((void*)dup,s,len);
dup[len] = '\0';
return dup;
}
#endif
#define endof(p) ((p)+strlen(p))
#if 0
/* Do not trust strncmp */
static int
ocuristrncmp(const char* s1, const char* s2, size_t len)
{
const char *p,*q;
if(s1 == s2) return 0;
if(s1 == NULL) return -1;
if(s2 == NULL) return +1;
for(p=s1,q=s2;len > 0;p++,q++,len--) {
if(*p != *q)
return (*p - *q);
if(*p == 0) return 0; /* *p == *q == 0 */
}
/* 1st len chars are same */
return 0;
}
#endif
static char* legalprotocols[] = {
"file",
"http",
"https",
"ftp",
NULL /* NULL terminate*/
static struct OC_ProtocolInfo {
char* name;
int filelike; /* 1=>this protocol has no host, user+pwd, or port */
} legalprotocols[] = {
{"file",1},
{"http",0},
{"https",0},
{"ftp",0},
};
/* Allowable character sets for encode */
@ -94,8 +60,13 @@ static char* fileallow =
static char* queryallow =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
/* Forward */
static void ocparamfree(char** params);
static int ocfind(char** params, const char* key);
static void oclshift1(char* p);
static void ocrshift1(char* p);
static char* oclocate(char* p, const char* charlist);
static void ocappendparams(char* newuri, char** p);
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
int
@ -103,10 +74,9 @@ ocuriparse(const char* uri0, OCURI** ocurip)
{
OCURI* ocuri = NULL;
char* uri = NULL;
char** pp;
char* p;
char* p1;
int c;
struct OC_ProtocolInfo* proto;
int i,nprotos;
/* accumulate parse points*/
char* protocol = NULL;
@ -119,139 +89,250 @@ ocuriparse(const char* uri0, OCURI** ocurip)
char* prefixparams = NULL;
char* suffixparams = NULL;
if(uri0 == NULL || strlen(uri0) == 0)
goto fail;
{THROW(1); goto fail;}
ocuri = (OCURI*)calloc(1,sizeof(OCURI));
if(ocuri == NULL)
goto fail;
{THROW(2); goto fail;}
/* save original uri */
ocuri->uri = nulldup(uri0);
/* make local copy of uri */
uri = (char*)malloc(strlen(uri0)+2); /* +1 for trailing null, +1 if we
need to append a char */
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' */
ocuri->strings = uri;
uri++;
/* dup the incoming url */
strcpy(uri,uri0);
/* remove all whitespace*/
p = uri;
p1 = uri;
while((c=*p1++)) {if(c != ' ' && c != '\t') *p++ = c;}
/* 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 < ' ')
oclshift1(p); /* compress out */
}
p = uri;
/* break up the uri string into pieces*/
/* break up the uri string into big chunks: prefixparams, protocol,
host section, and the file section (i.e. remainder)
*/
/* leading bracketed parameters */
/* collect any prefix bracketed parameters */
if(*p == LBRACKET) {
prefixparams = p+1;
/* find end of the clientparams*/
for(;*p;p++) {if(p[0] == RBRACKET && p[1] != LBRACKET) break;}
if(*p == 0) goto fail; /* malformed client params*/
*p = '\0'; /* wipe out the last rbracket */
p++; /* move past the params*/
/* find end of the clientparams; convert LB,RB to ';' */
for(;*p;p++) {
if(p[0] == RBRACKET && p[1] == LBRACKET) {
p[0] = ';';
oclshift1(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;
p1 = strchr(p,':');
if(!p1)
goto fail;
*p1 = '\0';
p = p1+1;
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*/
for(pp=legalprotocols;*pp;pp++) {
if(strcmp(protocol,*pp)==0) break;
nprotos = (sizeof(legalprotocols)/sizeof(struct OC_ProtocolInfo));
proto = NULL;
for(i=0;i<nprotos;i++) {
if(strcmp(protocol,legalprotocols[i].name)==0) {
proto = &legalprotocols[i];
break;
}
}
if(*pp == NULL) goto fail; /* illegal protocol*/
if(proto == NULL)
{THROW(6); goto fail; /* illegal protocol*/}
/* skip // */
if(*p != '/' && *(p+1) != '/')
goto fail;
if(p[0] != '/' && p[1] != '/')
{THROW(7); goto fail;}
p += 2;
/* locate the end of the host section */
file = strchr(p,'/');
/* Temporarily overwrite the '/' */
if(file != NULL)
*file = '\0';
/* 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 = oclocate(p,"/?#");
if(p == NULL) {
file = endof(host); /* there is no file section */
} else {
ocrshift1(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;}
/* extract any user:pwd */
host = p;
p1 = strchr(p,'@');
if(p1) {/* Assume we have user:pwd@ */
*p1 = '\0';
user = p;
pwd = strchr(p,':');
if(!pwd) goto fail; /* malformed */
*pwd++ = '\0';
}
/* extract host and port */
p = host;
port = strchr(p,':');
if(port!=NULL)
*port++ = '\0';
assert(file != NULL);
p = file;
/* Locate end of the file */
constraint = strchr(file,'?');
if(constraint!=NULL)
suffixparams = strchr(constraint,'#');
else
suffixparams = strchr(file,'#');
if(constraint != NULL) {
*constraint++ = '\0';
p = constraint;
/* find the end of the file section and the start of the
constraints and/or suffixparams
*/
p = oclocate(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 oclocate 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) {
*suffixparams++ = '\0';
/* there really are suffix params; so rebuild the suffix params */
p = suffixparams;
/* There must be brackets */
if(*p != LBRACKET)
{THROW(14); goto fail;}
suffixparams++; /* skip leading LBRACKET */
p = suffixparams;
/* convert RBRACKET LBRACKET to ';' */
for(;*p;p++) {
if(p[0] == RBRACKET && p[1] == LBRACKET) {
p[0] = ';';
oclshift1(p+1);
} else if(p[0] == RBRACKET && p[1] != LBRACKET) {
/* terminate suffixparams */
*p = EOFCHAR;
break;
}
}
if(*suffixparams == EOFCHAR)
suffixparams = NULL; /* suffixparams are empty */
}
/* assemble the component pieces*/
if(uri0 && strlen(uri0) > 0)
ocuri->uri = nulldup(uri0);
if(protocol && strlen(protocol) > 0) {
ocuri->protocol = nulldup(protocol);
}
if(user && strlen(user) > 0)
ocuri->user = nulldup(user);
if(pwd && strlen(pwd) > 0)
ocuri->password = nulldup(pwd);
if(host && strlen(host) > 0)
ocuri->host = nulldup(host);
if(port && strlen(port) > 0)
ocuri->port = nulldup(port);
if(file) {
/* Add back the leading / */
if(file) *file = '/';
if(strlen(file) > 0)
ocuri->file = nulldup(file);
else
file = NULL;
}
if(constraint && strlen(constraint) == 0)
constraint = NULL;
if(constraint && strlen(constraint) > 0)
ocuri->constraint = nulldup(constraint);
/* 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 */
ocuri->protocol = protocol;
ocuri->user = user;
ocuri->password = pwd;
ocuri->host = host;
ocuri->port = port;
ocuri->file = file;
ocurisetconstraints(ocuri,constraint);
/* concat suffix and prefix params */
if(prefixparams != NULL || suffixparams != NULL) {
int space = prefixparams ? strlen(prefixparams) : 0;
space += suffixparams ? strlen(suffixparams) : 0;
space += (2 + 1);
int plen = prefixparams ? strlen(prefixparams) : 0;
int slen = suffixparams ? strlen(suffixparams) : 0;
int space = plen + slen + 1;
/* add 1 for an extra comma if both are defined */
space++;
ocuri->params = (char*)malloc(space);
if(prefixparams && strlen(prefixparams) > 0) {
strcpy(ocuri->params,"[");
ocuri->params[0] = EOFCHAR; /* so we can use strcat */
if(plen > 0) {
strcat(ocuri->params,prefixparams);
strcat(ocuri->params,"]");
if(slen > 0)
strcat(ocuri->params,";");
}
if(suffixparams && strlen(suffixparams) > 0) {
strcat(ocuri->params,"[");
if(slen > 0)
strcat(ocuri->params,suffixparams);
strcat(ocuri->params,"]");
}
}
#ifdef OCXDEBUG
@ -266,13 +347,13 @@ ocuriparse(const char* uri0, OCURI** ocurip)
fprintf(stderr,"\n");
}
#endif
free(uri);
if(ocurip != NULL) *ocurip = ocuri;
return 1;
fail:
if(ocuri) ocurifree(ocuri);
if(uri != NULL) free(uri);
if(ocuri != NULL) {
ocurifree(ocuri);
}
return 0;
}
@ -281,17 +362,12 @@ ocurifree(OCURI* ocuri)
{
if(ocuri == NULL) return;
if(ocuri->uri != NULL) {free(ocuri->uri);}
if(ocuri->protocol != NULL) {free(ocuri->protocol);}
if(ocuri->user != NULL) {free(ocuri->user);}
if(ocuri->password != NULL) {free(ocuri->password);}
if(ocuri->host != NULL) {free(ocuri->host);}
if(ocuri->port != NULL) {free(ocuri->port);}
if(ocuri->file != NULL) {free(ocuri->file);}
if(ocuri->params != NULL) {free(ocuri->params);}
if(ocuri->paramlist != NULL) ocparamfree(ocuri->paramlist);
if(ocuri->strings != NULL) {free(ocuri->strings);}
if(ocuri->constraint != NULL) {free(ocuri->constraint);}
if(ocuri->projection != NULL) {free(ocuri->projection);}
if(ocuri->selection != NULL) {free(ocuri->selection);}
if(ocuri->params != NULL) {free(ocuri->params);}
if(ocuri->paramlist != NULL) ocparamfree(ocuri->paramlist);
free(ocuri);
}
@ -314,7 +390,7 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
duri->constraint = nulldup(constraints);
if(*duri->constraint == '?')
strcpy(duri->constraint,duri->constraint+1);
oclshift1(duri->constraint);
p = duri->constraint;
proj = (char*) p;
@ -326,7 +402,7 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
} else {
proj = (char*)malloc(plen+1);
memcpy((void*)proj,p,plen);
proj[plen] = '\0';
proj[plen] = EOFCHAR;
}
select = nulldup(select);
} else {
@ -338,9 +414,10 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
}
/* Construct a complete OC URI without the client params
and optionally with the constraints;
caller frees returned string.
/* Construct a complete OC URI.
Optionally with the constraints.
Optionally with the user parameters.
Caller frees returned string.
Optionally encode the pieces.
*/
@ -352,12 +429,17 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
char* tmpfile;
char* tmpsuffix;
char* tmpquery;
int nparams = 0;
int paramslen = 0;
int withparams = ((flags&OCURIPARAMS)
&& duri->params != NULL);
int withuserpwd = ((flags&OCURIUSERPWD)
/* if both are specified, prefix has priority */
int withsuffixparams = ((flags&OCURISUFFIXPARAMS)!=0
&& duri->params != NULL);
int withprefixparams = ((flags&OCURIPREFIXPARAMS)!=0
&& duri->params != NULL);
int withuserpwd = ((flags&OCURIUSERPWD)!=0
&& duri->user != NULL && duri->password != NULL);
int withconstraints = ((flags&OCURICONSTRAINTS)
int withconstraints = ((flags&OCURICONSTRAINTS)!=0
&& duri->constraint != NULL);
#ifdef NEWESCAPE
int encode = (flags&OCURIENCODE);
@ -366,10 +448,6 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
#endif
if(prefix != NULL) len += NILLEN(prefix);
if(withparams) {
len += NILLEN("[]");
len += NILLEN(duri->params);
}
len += (NILLEN(duri->protocol)+NILLEN("://"));
if(withuserpwd) {
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
@ -398,17 +476,33 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
len += (NILLEN("?")+NILLEN(tmpquery));
}
if(withprefixparams || withsuffixparams) {
char** p;
if(duri->paramlist == NULL)
if(!ocuridecodeparams(duri))
return NULL;
for(paramslen=0,nparams=0,p=duri->paramlist;*p;p++) {
nparams++;
paramslen += NILLEN(*p);
}
if(nparams % 2 == 1)
return NULL; /* malformed */
nparams = (nparams / 2);
len += paramslen;
len += 3*nparams; /* for brackets for every param plus possible = */
if(withsuffixparams)
len += strlen("#");
}
len += 1; /* null terminator */
newuri = (char*)malloc(len);
if(newuri == NULL) return NULL;
newuri[0] = '\0';
newuri[0] = EOFCHAR;
if(prefix != NULL) strcat(newuri,prefix);
if(withparams) {
strcat(newuri,"[");
strcat(newuri,duri->params);
strcat(newuri,"]");
if(withprefixparams) {
ocappendparams(newuri,duri->paramlist);
}
if(duri->protocol != NULL)
strcat(newuri,duri->protocol);
@ -427,92 +521,93 @@ ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
strcat(newuri,duri->port);
}
strcat(newuri,tmpfile);
if(suffix != NULL) strcat(newuri,tmpsuffix);
if(tmpfile != NULL) {
strcat(newuri,tmpfile);
if(suffix != NULL) strcat(newuri,tmpsuffix);
}
if(withconstraints) {
strcat(newuri,"?");
strcat(newuri,tmpquery);
}
if(withsuffixparams & !withprefixparams) {
strcat(newuri,"#");
ocappendparams(newuri,duri->paramlist);
}
return newuri;
}
static void
ocappendparams(char* newuri, char** p)
{
while(*p) {
strcat(newuri,"[");
strcat(newuri,*p++);
if(strlen(*p) > 0) {
strcat(newuri,"=");
strcat(newuri,*p);
}
p++;
strcat(newuri,"]");
}
}
/**************************************************/
/* Parameter support */
/*
Client parameters are assumed to be
one or more instances of bracketed pairs:
e.g "[...][...]...".
The bracket content in turn is assumed to be a
comma separated list of <name>=<value> pairs.
e.g. x=y,z=,a=b.
If the same parameter is specifed more than once,
then the first occurrence is used; this is so that
is possible to forcibly override user specified
parameters by prefixing.
IMPORTANT: client parameter string is assumed to
have blanks compress out.
Returns 1 if parse suceeded, 0 otherwise;
*/
In the original url, client parameters are assumed to be one
or more instances of bracketed pairs: e.g "[...][...]...".
They may occur either at the front, or suffixed after
a trailing # character After processing, the list is
converted to a semicolon separated list of the combination
of prefix and suffix parameters.
After the url is parsed, the parameter list
is converted to a semicolon separated list with all
whitespace removed.
In any case, each parameter in turn is assumed to be a
of the form <name>=<value> or [<name>].
e.g. [x=y][z][a=b][w]. If the same parameter is specified more
than once, then the first occurrence is used; this is so
that is possible to forcibly override user specified
parameters by prefixing. IMPORTANT: client parameter string
is assumed to have blanks compressed out. Returns 1 if parse
suceeded, 0 otherwise; */
int
ocuridecodeparams(OCURI* ocuri)
{
char* cp;
char* cq;
int c;
int i;
int i,c;
int nparams;
char* params0;
char* params;
char* params1;
char** plist;
if(ocuri == NULL) return 0;
if(ocuri->params == NULL) return 1;
params0 = ocuri->params;
params = strdup(ocuri->params); /* so we can modify */
/* Pass 1 to replace beginning '[' and ending ']' */
if(params0[0] == '[')
params = nulldup(params0+1);
else
params = nulldup(params0);
if(params[strlen(params)-1] == ']')
params[strlen(params)-1] = '\0';
/* Pass 2 to replace "][" pairs with ','*/
params1 = nulldup(params);
cp=params; cq = params1;
while((c=*cp++)) {
if(c == RBRACKET && *cp == LBRACKET) {cp++; c = ',';}
*cq++ = c;
}
*cq = '\0';
free(params);
params = params1;
/* Pass 3 to break string into pieces and count # of pairs */
/* Pass 1 to break string into pieces at the semicolons
and count # of pairs */
nparams=0;
for(cp=params;(c=*cp);cp++) {
if(c == ',') {*cp = '\0'; nparams++;}
if(c == ';') {*cp = EOFCHAR; nparams++;}
}
nparams++; /* for last one */
/* plist is an env style list */
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
/* Pass 4 to break up each pass into a (name,value) pair*/
/* Break up each param into a (name,value) pair*/
/* and insert into the param list */
/* parameters of the form name name= are converted to name=""*/
cp = params;
for(i=0;i<nparams;i++) {
for(cp=params,i=0;i<nparams;i++) {
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
char* vp;
/*break up the ith param*/
vp = strchr(cp,'=');
if(vp != NULL) {*vp = '\0'; vp++;} else {vp = "";}
if(vp != NULL) {*vp = EOFCHAR; vp++;} else {vp = "";}
plist[2*i] = nulldup(cp);
plist[2*i+1] = nulldup(vp);
cp = next;
@ -525,19 +620,22 @@ ocuridecodeparams(OCURI* ocuri)
return 1;
}
const char*
ocurilookup(OCURI* uri, const char* key)
int
ocurilookup(OCURI* uri, const char* key, const char** resultp)
{
int i;
if(uri == NULL || key == NULL || uri->params == NULL) return NULL;
char* value = NULL;
if(uri == NULL || key == NULL || uri->params == NULL) return 0;
if(uri->paramlist == NULL) {
i = ocuridecodeparams(uri);
if(!i) return 0;
}
i = ocfind(uri->paramlist,key);
if(i >= 0)
return uri->paramlist[(2*i)+1];
return NULL;
if(i < 0)
return 0;
value = uri->paramlist[(2*i)+1];
if(resultp) *resultp = value;
return 1;
}
int
@ -575,81 +673,46 @@ ocparamfree(char** params)
free(params);
}
#ifdef OCIGNORE
/*
Delete the entry.
return value = 1 => found and deleted;
0 => param not found
/* Return the ptr to the first occurrence of
any char in the list. Return NULL if no
occurrences
*/
int
ocparamdelete(char** params, const char* key)
static char*
oclocate(char* p, const char* charlist)
{
int i;
char** p;
char** q;
if(params == NULL || key == NULL) return 0;
i = ocfind(params,key);
if(i < 0) return 0;
p = params+(2*i);
for(q=p+2;*q;) {
*p++ = *q++;
for(;*p;p++) {
if(strchr(charlist,*p) != NULL)
return p;
}
*p = NULL;
return 1;
return NULL;
}
static int
oclength(char** params)
/* Shift every char starting at p 1 place to the left */
static void
oclshift1(char* p)
{
int i = 0;
if(params != NULL) {
while(*params) {params+=2; i++;}
if(p != NULL && *p != EOFCHAR) {
char* q = p++;
while((*q++=*p++));
}
return i;
}
/*
Insert new client param (name,value);
return value = 1 => not already defined
0 => param already defined (no change)
*/
char**
ocparaminsert(char** params, const char* key, const char* value)
/* Shift every char starting at p 1 place to the right */
static void
ocrshift1(char* p)
{
int i;
char** newp;
size_t len;
if(params == NULL || key == NULL) return 0;
i = ocfind(params,key);
if(i >= 0) return 0;
/* not found, append */
i = oclength(params);
len = sizeof(char*)*((2*i)+1);
newp = realloc(params,len+2*sizeof(char*));
memcpy(newp,params,len);
newp[2*i] = nulldup(key);
newp[2*i+1] = (value==NULL?NULL:nulldup(value));
return newp;
char cur;
cur = 0;
do {
char next = *p;
*p++ = cur;
cur = next;
} while(cur != 0);
*p = 0; /* make sure we are still null terminated */
}
/*
Replace new client param (name,value);
return value = 1 => replacement performed
0 => key not found (no change)
*/
int
ocparamreplace(char** params, const char* key, const char* value)
{
int i;
if(params == NULL || key == NULL) return 0;
i = ocfind(params,key);
if(i < 0) return 0;
if(params[2*i+1] != NULL) free(params[2*i+1]);
params[2*i+1] = nulldup(value);
return 1;
}
#endif
/* Provide % encoders and decoders */
@ -713,7 +776,7 @@ ocuriencode(char* s, char* allowable)
}
}
}
*outptr = '\0';
*outptr = EOFCHAR;
return encoded;
}
@ -749,7 +812,7 @@ ocuridecodeonly(char* s, char* only)
*outptr++ = ' ';
else if(c == '%') {
/* try to pull two hex more characters */
if(inptr[0] != '\0' && inptr[1] != '\0'
if(inptr[0] != EOFCHAR && inptr[1] != EOFCHAR
&& strchr(hexchars,inptr[0]) != NULL
&& strchr(hexchars,inptr[1]) != NULL) {
/* test conversion */
@ -762,7 +825,7 @@ ocuridecodeonly(char* s, char* only)
}
*outptr++ = c;
}
*outptr = '\0';
*outptr = EOFCHAR;
return decoded;
}

View File

@ -8,17 +8,19 @@
it is ok to directly access its fields*/
typedef struct OCURI {
char* uri; /* as passed by the caller */
char* params; /* all params */
char** paramlist; /*!<null terminated list */
char* constraint; /*!< projection+selection */
char* projection; /*!< without leading '?'*/
char* selection; /*!< with leading '&'*/
char* strings; /* first char of strings is always '\0' */
/* Following all point into the strings field */
char* protocol;
char* user; /* from user:password@ */
char* password; /* from user:password@ */
char* host; /*!< host*/
char* port; /*!< host */
char* file; /*!< file */
char* constraint; /*!< projection+selection */
char* projection; /*!< without leading '?'*/
char* selection; /*!< with leading '&'*/
char* params; /* all params */
char** paramlist; /*!<null terminated list */
} OCURI;
extern int ocuriparse(const char* s, OCURI** ocuri);
@ -30,20 +32,25 @@ extern void ocurisetconstraints(OCURI*,const char* constraints);
/* Construct a complete OC URI; caller frees returned string */
/* Define flags to control what is included */
#define OCURICONSTRAINTS 1
#define OCURIUSERPWD 2
#define OCURIPARAMS 4
#define OCURIENCODE 8 /* If output should be encoded */
#define OCURICONSTRAINTS 1
#define OCURIUSERPWD 2
#define OCURIPREFIXPARAMS 4
#define OCURISUFFIXPARAMS 8
#define OCURIPARAMS OCURIPREFIXPARAMS
#define OCURIENCODE 16 /* If output should be encoded */
#define OCURISTD (OCURICONSTRAINTS|OCURIUSERPWD)
extern char* ocuribuild(OCURI*,const char* prefix, const char* suffix, int flags);
/* Param Management */
extern int ocuridecodeparams(OCURI* ocuri);
extern int ocurisetparams(OCURI* ocuri,const char*);
/*! NULL result => entry not found.
Empty value should be represented as a zero length string */
extern const char* ocurilookup(OCURI*, const char* param);
/*! 0 result => entry not found; 1=>found; result holds value (may be null).
In any case, the result is imutable and should not be free'd.
*/
extern int ocurilookup(OCURI*, const char* param, const char** result);
extern char* ocuriencode(char* s, char* allowable);
extern char* ocuridecode(char* s);

View File

@ -433,7 +433,7 @@ ocdataddsmsg(OCstate* state, OCtree* tree)
if(c > 0 && (c < ' ' || c >= '\177'))
contents[i+j] = ERRFILL;
}
oc_log(LOGERR,"DATADDS failure, possible message: '%s'\n",
oclog(OCLOGERR,"DATADDS failure, possible message: '%s'\n",
contents+i);
goto done;
}