/****************************** handyFcts.c ********************************** Handy C functions (includes the W3C library; see handyFcts.h) ****************************************************************************/ #include "handyFcts.h" char TmpBuff[BUFF_SIZE]; /* temporary buffer used everywhere */ int WithTrace=0; /* if NULL, traces -> stderr, else traces -> stdout */ FILE *FpTrace= NULL; char **TheEnvp; FILE *CommandOutputFile=NULL; /* if !=NULL, it stores scripts results, */ HTList *ResultList=NULL; /* otherwise, ResultList stores them */ /* cf. from WWWLib.h[tml], e.g. in file:/users/phmartin/wkb/utils/w3c-libwww-5.1l/Library/src/WWWLib.html - HTUtils.h: traces, BOOL, PRIVATE, ... HTArray.h, HTAssoc.h, HTList.h, HTAtom.h, HTChunk.h (dynamic string), HTMemory.h HTUU.h (uuencode/decode to/from RFC 1113 printable encoding format) - WWWCore.h: everything related to URLs (parsing, PUT/GET/POST, ...) */ /* ****************************** CHAR ************************************** */ BOOL isIdentChar (char c) { return ( isalnum(c) || (c=='_') || (c=='-') ); } BOOL isIdentFirstChar (char c) { return ( isalpha(c) || (c=='_') || (c=='-') ); } BOOL charInStr (char c,char *s) /* isIn(c,s) */ { while (*s && *s!=c) s++; return (*s==c); } /* int nbOfThisCharIn (char *s,char c) { int n; for (n=0; *s; s++) { if (*s == c) n++; } return n; } */ /* in HTEscape.c, char *HTUnEscape(char *str) returns a HT_MALLOCed string */ char unescapeURLchar (char c1,char c2) { register char c = (c1 >= 'A') ? ((c1 & 0xdf) - 'A')+10 : (c1 - '0'); c *= 16; c+= (c2 >= 'A') ? ((c2 & 0xdf) - 'A')+10 : (c2 - '0'); return c; } char *orderSuffixForDigit (int i) { switch (i) { case 1: return "st"; case 2: return "nd"; case 3: return "rd"; }return "th"; } /* ***************************** STRING ************************************** */ /* ---------------------------- STRING - test -------------------------------- */ BOOL emptyStr (char *s) { return !(s && *s); } BOOL strEqual (char *s1,char *s2) { if (!s1) return (s2==NULL); /* strcmp() does not test this */ return !strcmp(s1,s2); } BOOL strEqualContent (char *s1,char *s2) /* strEqual except that spaces do not count */ { if (!s1) return (s2==NULL); for ( ; ; s1++, s2++) { while (isspace(*s1)) s1++; while (isspace(*s2)) s2++; if (*s1!=*s2) return NO; if (!*s1) break; } return YES; } BOOL strCaseEqual (char *s1,char *s2) { if (!s1) return (s2==NULL); return !strcasecomp(s1,s2); } BOOL escapedNewlineThere (char *s) { return ( (*s=='\\') && (*(s+1)=='\n') ); } BOOL spaceOrEscapedNewlineThere (char *s) { char c=*s; if (isspace(c)) return YES; if (c=='\\') { c= *(++s); return (c=='\n'); } if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) return YES; return NO; } BOOL spaceCommentOrHTMLmarkThere (char *s) { char c=*s; if (isspace(c)) return YES; if (c=='\\') { c= *(++s); return (c=='\n'); } if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) return YES; if (c=='/') { c= *(++s); return ((c=='*') || (c=='/')); } return isHTMLmarkThere(s); } /* ---------------------------- STRING - search ------------------------------ */ /* char *strCaseStr (char *str, char *subStr) //Already in HTString.h { char *s, *ss; for (;*str; str++) { for (ss=subStr,s=str; *ss && *s && (tolower(*ss)==tolower(*s)); ss++,s++); if (!*ss) return str; } return NULL; }*/ #if 0 char *strContentInStr (char *elem, char *str, initP char **pAfterElem) { char *s1, *s2; if (!elem || !*elem || !str) return NULL; /*pr("strContentInStr:\n%s\n\nin\n\n%s.",elem,str);*/ for ( ; *str; str++) { for (s1=elem, s2=str; ; s1++,s2++) { s1=skipSpacesAndHTMLmarksExceptMarks(s1,"img",""); s2=skipSpacesAndHTMLmarksExceptMarks(s2,"img",""); if (!*s1) { *pAfterElem=s2; return str; } if (*s1!=*s2) {/*pr("%c(%c%c) != %c(%c%c).
\n", *s1, *s1?*(s1+1):'\0', (*s1&&*(s1+1))?*(s1+2):'\0', *s2, *s2?*(s2+1):'\0', (*s2&&*(s2+1))?*(s2+2):'\0');*/ break; } /*pr("
%c(%c%c) == %c(%c%c).
\n", *s1, *s1?*(s1+1):'\0', (*s1&&*(s1+1))?*(s1+2):'\0', *s2, *s2?*(s2+1):'\0', (*s2&&*(s2+1))?*(s2+2):'\0');*/ } } return NULL; } #else /* this version seems to have no problem */ char *strContentInStr(char *elem, char *str, initP char **pAfterElem) { char *s1, *s2; *pAfterElem=str; if (!elem || !*elem || !str) return NULL; /*pr("strContentInStr:\n%s\n\nin\n\n%s.",elem,str);*/ str=skipSpacesAndHTMLmarksExceptMarks(str,"img",""); while (*str) { for (s1=elem, s2=str; ; ) { if (!*s1) { *pAfterElem=s2; return str; } if (*s1!=*s2) {/*pr("%c(%c%c) != %c(%c%c).
\n", *s1, *s1?*(s1+1):'\0', (*s1&&*(s1+1))?*(s1+2):'\0', *s2, *s2?*(s2+1):'\0', (*s2&&*(s2+1))?*(s2+2):'\0');*/ break; } /*pr("
%c(%c%c) == %c(%c%c).
\n", *s1, *s1?*(s1+1):'\0', (*s1&&*(s1+1))?*(s1+2):'\0', *s2, *s2?*(s2+1):'\0', (*s2&&*(s2+1))?*(s2+2):'\0');*/ s1=skipSpacesAndHTMLmarksExceptMarks(s1+1,"img",""); s2= (*s1) ? skipSpacesAndHTMLmarksExceptMarks(s2+1,"img","") : s2+1; } str=skipSpacesAndHTMLmarksExceptMarks(str+1,"img",""); } return NULL; } #endif char *strstrOrEndStr (char *str, char *subStr) { char *s= strstr(str,subStr); return (s) ? s : skipToEndOfString(str); } char *skipToEndOfString (char *s) { while (*s) s++; return s; } char *skipAfterEndOfLine(char *s) { char c; for (;(c= *s);s++) { if ((c=='\n') || (c=='\r')) return s+1; } return s; } char *skipSpaces (char *s) { char c; if (!s) return NULL; while ((c= *s)) { if (isspace(c)) s++; else if (c=='\\') { c= *(++s); if (c=='\n') s++; else return s-1; } else if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) s+=6; else return s; } return s; } char *skipSpacesAndComments (char *s) { char c; if (!s) return NULL; while ((c= *s)) { if (isspace(c)) s++; else if (c=='\\') { c= *(++s); if (c=='\n') s++; else return s-1; } else if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) s+=6; else if (c=='/') { c= *(++s); if (c=='*') s=skipComments(s+1); else if (c=='/') s=skipAfterEndOfLine(s+1); else return s-1; } else return s; } return s; } char *skipSep (char *s, char *sep) { if (s) { while (*s && charInStr(*s,sep)) s++; } return s; } /* char *skipAfterThisUnquotedChar (char *s, char stopChar) { char c; if (!s || !*s) return s; if (*s==stopChar) return s+1; s++; while ((c= *s)) { if ((c==stopChar) && (*(s-1)!='\\')) return s+1; else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else s++; } return s; } */ char *skipAfterThisUnquotedChar (char *s, char stopChar, varP BOOL *pHtmlMarkFound) { char c; BOOL htmlMarkFound=*pHtmlMarkFound; if (!s || !*s) return s; if (*s==stopChar) return s+1; s++; while ((c= *s)) { if ((c==stopChar) && (*(s-1)!='\\')) return s+1; else if (c=='\\') { s++; if (*s) s++; } /* (*s && !isspace(*s)) ?? */ else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if ((c=='<') && !htmlMarkFound && isHTMLmarkThere(s)) { htmlMarkFound=YES; s++; } else s++; } *pHtmlMarkFound=htmlMarkFound; return s; } char *skipAfterOneOfTheseUnquotedChars (char *s, char *stopChars) { char c; if (!s || !*s) return s; if (charInStr(*s,stopChars)) return s+1; s++; while ((c= *s)) { if (charInStr(*s,stopChars) && (*(s-1)!='\\')) return s+1; else if (c=='\\') { s++; if (*s) s++; } /* (*s && !isspace(*s)) ?? */ else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else s++; } return s; } /*BOOL ifStringSkipAfter (char **pStr) { char *s= *pStr; if (*s != '"') return NO; s++; while (*s && (*s!='"' || *(s-1)=='\\')) s++; *pStr= s; return YES; }*/ char *skipComments (char *s) /* *(s-1)=='*' */ { char c; for (;(c= *s); s++) { if ((c=='*') && (*(s+1)=='/')) return s+2; } return s; } char *skipQuotedString (char *s) /* *(s-1)=='"' */ { char c; for (;(c= *s); s++) { if ((c=='"') && (*(s-1)!='\\')) return s+1; } return s; } char *skipStringQuotedLikeACharacter (char *s) /* *(s-1)=='\''*/ { char c; if ((*s=='s') && isspace(*(s+1)) && isalpha(*(s+2))) return s; /*ex: Sowa's type*/ for (;(c= *s); s++) { if ((c=='\'') && (*(s-1)!='\\')) return s+1; } return s; } char *skipBackquotedString (char *s) /* *(s-1)=='`' */ { char c; for (;(c= *s); s++) { if ((c=='`') && (*(s-1)!='\\')) return s+1; } return s; } char *skipRecursiveSquareBrackets (char *s) /* *(s-1)=='[' */ { int lev=1; char c; /*for (lev=1;((c= *s)) && lev; s++) { if (c==']') lev--; else if (c=='[') lev++; } */ while ( ((c= *s)) && lev ) { if (c==']') { lev--; s++; } else if (c=='[') { lev++; s++; } else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if (c=='\\') { s++; if (*s) s++; } else s++; } return s; } char *skipRecursiveBraces (char *s) /* *(s-1)=='{' */ { int lev=1; char c; while ( ((c= *s)) && lev ) { if (c=='}') { lev--; s++; } else if (c=='{') { lev++; s++; } else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if (c=='\\') { s++; if (*s) s++; } else s++; } return s; } char *skipRecursiveBracesAndTellIfHTMLmarkFound (char *s, varP BOOL *pHtmlMarkFound) { int lev=1; char c; BOOL htmlMarkFound=*pHtmlMarkFound; while ( ((c= *s)) && lev ) { if (c=='}') { lev--; s++; } else if (c=='{') { lev++; s++; } else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if (c=='\\') { s++; if (*s) s++; } else if ((c=='<') && !htmlMarkFound && isHTMLmarkThere(s)) { htmlMarkFound=YES; s++; } else s++; } *pHtmlMarkFound=htmlMarkFound; return s; } char *skipRecursiveParenthesis (char *s) /* *(s-1)=='(' */ { int lev=1; char c; while ( ((c= *s)) && lev ) { if (c==')') { lev--; s++; } else if (c=='(') { lev++; s++; } else if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if (c=='\\') { s++; if (*s) s++; } else s++; } return s; } char *skipAfterNumber (char *s) /* isdigit(*(s-1)) */ { char c; for (; ((c= *s)); s++) { if (isdigit(c)) { } else if (c=='.') { if (!(c=*(s+1)) || isspace(c)) return s; } else return s; } return s; } char *skipAfterIdent (char *s) /* isalpha(*(s-1)) */ { char c; for (; ((c= *s)); s++) { if (isalnum(c) || (c=='_') || (c=='-') || (c=='/')) { } else if (c=='.') { if (!(c=*(s+1)) || isspace(c)) return s; } else return s; } return s; } char *skipAfterIdentOrURL (char *s) /* isalpha(*(s-1)) */ { char c; for (; ((c= *s)); s++) { if (isalnum(c) || (c=='_') || (c=='-') || (c=='/')) { } else if ((c=='.') || (c==':') || (c=='~') || (c=='#')) { if (!(c=*(s+1)) || isspace(c)) return s; } else if (c=='?') { if (!(c=*(s+1)) || isspace(c)) return s; else { while ( ((c=*(++s))) && !isspace(c) ); break; } } else return s; } return s; } char *skipIdentURLorStrings (char *s) /* no *(s-1) for this function */ { char c=*s; if (!c) return s; else if (isalpha(c)) return skipAfterIdentOrURL(s+1); else if (isdigit(c)) return skipAfterNumber(s+1); else if (c=='"') return skipQuotedString(s+1); else if (c=='\'') return skipStringQuotedLikeACharacter(s+1); else { prErr("Identifier, number or string expected instead at: %s.", displayableLineFrom(s)); return s+1; } } char *nextToken (varP char **ptrStr, char *sep, initP char *pErasedChar) { char *token, *s= *ptrStr; *pErasedChar='\0'; while (*s && charInStr(*s,sep)) s++; if (!*s) { *ptrStr=s; return NULL; } token=s; while (*s && !charInStr(*s,sep)) s++; if (s>token) { *pErasedChar=*s; *s='\0'; *ptrStr=s+1; tr("nextToken:%s.\n",token); return token; } else { tr("nextToken(%s,%s): no token",*ptrStr,sep); *ptrStr=s; return NULL; } } int nbTokenIn (char *str) { char c, *tok; int nb=0; while ((tok= nextToken(&str," \n\r\t",&c))) { nb++; if (c) *(str-1)=c; } return nb; } char *getNextAttributeValueInStr (char *str, initP char **pAttr, initP char **pValue) { char c, *s=str, *end; if (!s) return *pAttr=*pValue=""; *pAttr=s=skipSpacesCommentsAndHTMLmarks(s); if (!*s) return *pValue=s; while (((c=*s)) && (c!=':')) s++; if (!c) { prErr("Format for attribute-value pairs: ATTR_NAME ':' VALUE_STRING ';'"); return *pAttr=*pValue=s; } end=s-1; while ((end>=str) && isspace(*end)) *end-- ='\0'; end++; if (end<=str) { *str='\0'; return *pAttr=*pValue=str; }; *end='\0'; s++; *pValue=s=skipSpaces(s); if (!*s) return s; while (((c=*s)) && (c!=';')) s++; if (!c) return s; end=s-1; while ((end>=str) && isspace(*end)) *end-- ='\0'; end++; if (end<=str) { *str='\0'; return *pAttr=*pValue=str; }; *end='\0'; s++; return s; } /* ---------------------------- STRING - convert ------------------------------ */ char *mkIfNull(char* str) { return (str) ? str : ""; } char *lowerStr (char *str) /* modify and return str */ { char *s = str; if (!s) return ""; while (*s) { *s = tolower(*s); s++; } return str; } char *upperStr (char *str) /* modify and return str */ { char *s = str; if (!s) return ""; while (*s) { *s = toupper(*s); s++; } return str; } char *eraseLastCharIn (char *str) { int i; if (!str) return ""; i=strlen(str); if (i) str[i-1]='\0'; return str; } ErrMess initAssocListFromString (char *str, initP HTAssocList *assocList) { char *s=str, *attr, *value; if (!assocList) return "Internal error: no association list to initialize"; while (*s && ((s= getNextAttributeValueInStr(s,&attr,&value))) && attr) { if (HTAssocList_addObject(assocList,attr,value)==NO) {HTList_free(s); return "No memory space for storing attribute-values.";} } return NULL; } /* ---------------------------- STRING - copy --------------------------------- */ char *copyCatStr (char *buff,char *s1,char *s2) /* return (buff= s1+s2) */ { char *s=buff; if (!s1) return ""; for (;(*s= *s1); s++,s1++); if (!s2) return buff; for (;(*s= *s2); s++,s2++); return buff; } char *addTokenTo (char *buff,char *token) /* return (buff+=' '+token) */ { char *s=buff; while (*s) s++; *s++=' '; for (;(*s= *token); s++,token++); return buff; } char *removeTokenIn (char *buff, char *token) { char c, *tok, *str=buff; #if 1 int l=strlen(token); while ((tok= strstr(str,token))) { if ((tok > buff) && !charInStr(*(tok-1)," \n\r\t")) str=tok+1; else if (((c=tok[l])) && !charInStr(c," \n\r\t")) str=tok+1; else { str=tok; tok+=l; while (*tok && charInStr(*tok," \n\r\t")) tok++; strcpy(str,tok); } } #else while ((tok= nextToken(&str," \n\r\t",&c))) /* not tested */ { if (strEqual(tok,token)) { strcpy(tok,str); return buff; } else if (c) *(str-1)=c; } #endif return buff; } char *removeFirstTokenIn (char *buff) /* not yet called */ { char *s=buff; /* while (*s && charInStr(*s," \n\r\t")) s++; */ while (*s && !charInStr(*s," \n\r\t")) s++; /* skip first token */ while (*s && charInStr(*s," \n\r\t")) s++; strcpy(buff,s); return buff; } char *displayableLineFrom (char *str) { static char LineToDisplay[85]; char c, *s=skipSpaces(str); while (*s && (*s != '\n') && (s-str < 80)) s++; c=*s; *s='\0'; strcpy(LineToDisplay,str); *s=c; return LineToDisplay; } void countInStr (char *str,int *pNbBytes, int *pNbWords, int *pNbLines, int *pNbParagraphs) { int nbWords=0, nbLines=0, nbParagraphs=0; char c, *s=str; while (*s) /* for each paragraph= spaces + words + spacesNotIncluding2NewLines */ { for ( ;((c= *s)) && isspace(c); s++) { if (c=='\n') nbLines++; } if (c) nbParagraphs++; while (*s) /* for each word followed by spaces */ { nbWords++; while ( ((c= *(++s))) && !isspace(c) ); for (;((c= *s)) && isspace(c); s++) if (c=='\n') { nbLines++; s++; break; } for (;((c= *s)) && isspace(c) && (c!='\n'); s++); if (c=='\n') { nbLines++; s++; break; } } } *pNbBytes= s-str; *pNbWords=nbWords; *pNbLines=nbLines; *pNbParagraphs=nbParagraphs; } char *replaceAt (char *buff, char *oldStr, char *newStr) { int lo=strlen(oldStr), ln=strlen(newStr); char *tmp, *s=buff; /* tr("Replace '%s' by '%s' in %s\n",oldStr,newStr,buff); */ if (lnlo) { if (!(tmp= my_strdup(s+lo))) return buff; else { strcpy(s+ln,tmp); MY_FREE(tmp); } } while (*newStr) *s++ = *newStr++; return buff; } char *doOneReplacementUsingAssocList (char *buff, HTAssocList *assocList) { HTAssoc *attrValuePair; char *s, *name; while ((attrValuePair= HTAssocList_nextObject(assocList))) if ( (name=HTAssoc_name(attrValuePair)) && name[0] && (s=strstr(buff,name)) ) replaceAt(s,name,HTAssoc_value(attrValuePair)); return buff; } char *strAllocCopyReplaceVarUsingAssocList (char *s, HTAssocList *varList) /*if no replacement done return NULL, else return an allocated area (or "" if empty result - NOT TO BE FREED)*/ { char c, *var, *value, *sv_s=s; BOOL replacementByEmptyString=NO; HTChunk *chunk=HTChunk_new(1000); tr("strAllocCopyReplaceVarUsingAssocList1:%s.\n",s); while ((c= *s)) { switch (c) { case '\'': s=skipStringQuotedLikeACharacter(s+1); break; case '\\': s++; if (*s) s++; break; case'$': var=++s; while (((c= *s)) && isIdentChar(c)) s++; *s='\0'; if ((s>var) && (value= my_HTAssocList_findObject(varList,var))) { tr("value for %s:'%s'\n",var,value); *(var-1)='\0'; HTChunk_puts(chunk,sv_s); *(var-1)='$'; if (*value) HTChunk_puts(chunk,value); else replacementByEmptyString=YES; *s=c; sv_s=s; /* pr("chunk i:%s.\n",HTChunk_data(chunk)); */ } else *s=c; break; default: s++; } } if (HTChunk_size(chunk) <= 0) { /* pr("Nochunk for %s\n",sv_s); */ HTChunk_delete(chunk); return (replacementByEmptyString) ? "" : NULL; } else { if (s > sv_s) HTChunk_puts(chunk,sv_s); tr("strAllocCopyReplaceVarUsingAssocList2:%s.\n",HTChunk_data(chunk)); s=HTChunk_toCString(chunk); if (s) storeAsAllocated(s); return s; } } char *strAllocCat (char *s1, char *s2) { HTChunk *chunk=HTChunk_new(1000); HTChunk_puts(chunk,s1); HTChunk_puts(chunk,s2); s1=HTChunk_toCString(chunk); if (s1) storeAsAllocated(s1); return s1; } char *strRealloc (char *str, int lng, varP int *pMaxSize) { str[lng]='\0'; *pMaxSize += ALLOC_SIZE; str = (char *) my_realloc (str, sizeof(char) * (*pMaxSize +1) ); /*tr("\n\n\n\n =========== strRealloc: %d %d\n%s\n",lng,*pMaxSize,str);*/ return str; } /* *************************** ALLOCATION *********************************** */ static HTList *AllocatedBuffList=NULL; char *my_strdup(const char *s) { void *ptr; if (!s) { prErr("Internal error: tentative to allocate a NULL buffer"); return NULL; } if ((ptr= strdup(s))) { if (!AllocatedBuffList) AllocatedBuffList=HTList_new(); if (HTList_addObject(AllocatedBuffList,ptr)==YES) return ptr; } prErr("Not enough dynamic memory: could not duplicate the string \"%s\"",s); return NULL; } /* my_malloc = HTMemory_malloc + stores the ptr in AllocatedBuffList */ void *my_malloc (size_t size) { void *ptr= malloc(size); /* or HT_MALLOC */ if (ptr) { if (!AllocatedBuffList) AllocatedBuffList=HTList_new(); if (HTList_addObject(AllocatedBuffList,ptr)==YES) return ptr; } prErr("Not enough dynamic memory: could not allocate %d bytes",size); return NULL; } void *my_calloc (size_t nobj, size_t size) /* not used on HTList/HTAssocList*/ { void *ptr= calloc(nobj,size); /* or HT_CALLOC */ if (ptr) { if (!AllocatedBuffList) AllocatedBuffList=HTList_new(); if (HTList_addObject(AllocatedBuffList,ptr)==YES) return ptr; } prErr("Not enough dynamic memory: could not allocate %d objects of size %d", nobj,size); return NULL; } void *my_realloc (void *p, size_t size) { void *ptr= realloc(p,size); /* or HT_REALLOC */ if (ptr==p) return ptr; if (ptr) { if (!AllocatedBuffList) if (!(AllocatedBuffList=HTList_new())) { prErr("Internal error: cannot create a list"); return ptr; } if (HTList_removeObject(AllocatedBuffList,p)==NO) { prErr("Internal error: cannot find or remove an allocated buffer in the " "list of allocated buffers"); /* if (WithTrace) abort(); //to see the function stack with GDB */ } else if (HTList_addObject(AllocatedBuffList,ptr)==NO) prErr("Internal error: cannot add an object in a list"); return ptr; } prErr("Not enough dynamic memory: could not reallocate %d bytes",size); return NULL; } void storeAsAllocated (void *ptr) { if (!ptr) prErr("Internal error: tentative to store a NULL buffer"); else if (HTList_addObject(AllocatedBuffList,ptr)==NO) prErr("Internal error: cannot add a pointer in a list"); } void my_free (void *ptr) /* not to use on HTList/HTAssocList components */ { if (ptr) { if (HTList_removeObject(AllocatedBuffList,ptr)==YES) free(ptr); else /* if (WithTrace) */ { prErr("Internal error: tentative to free the non-allocated buffer:"); pr("%s\n",(char *)ptr); /* abort(); */ } } else /* if (WithTrace) */ prErr("Internal error: tentative to free a NULL buffer"); } /* in handyFcts.h: #define MY_FREE(pointer) {my_free((pointer));((pointer))=NULL;} */ /* ********************** HTAssocList, HTArray ******************************* */ HTAssoc *HTAssocList_findAssoc (HTAssocList *list, char *name) { if (list && name) { HTAssocList *cur=list; HTAssoc *assoc; while ((assoc= (HTAssoc *) HTList_nextObject(cur))) if (strEqual(assoc->name,name)) return assoc; /* else pr("myAssocfind: '%s' == '%s'.\n",assoc->name,name); */ } return NULL; } char *my_HTAssocList_findObject (HTAssocList *list, char *name) { if (list && name) { HTAssocList *cur=list; HTAssoc *assoc; while ((assoc= (HTAssoc *) HTList_nextObject(cur))) if (strEqual(assoc->name,name)) return assoc->value; /* else pr("myAssocfind: '%s' == '%s'.\n",assoc->name,name); */ } return NULL; } BOOL my_HTAssocList_replaceObject (HTAssocList *list,char *name,char *value) { if (list && name) { HTAssocList *cur= list; HTAssoc *assoc; while ((assoc = (HTAssoc *) HTList_nextObject(cur))) if (strEqual(assoc->name,name)) { StrAllocCopy(assoc->name,name); if (value) StrAllocCopy(assoc->value,value); return YES; } return HTAssocList_addObject(list,name,value); } return NO; } BOOL my_HTAssocList_removeObject (HTAssocList *list, char *name) { BOOL found = NO; if (list && name) { HTAssocList *cur=list; HTAssoc *assoc; while ((assoc= (HTAssoc *) HTList_nextObject(cur))) if (strEqual(assoc->name,name)) { HTList_removeObject(list, assoc); HT_FREE(assoc); found=YES; } } return found; } BOOL HTAssocList_appendObject (HTAssocList *list, char *name, char *value) { if (list && name) { HTAssoc *assoc= (HTAssoc *) HT_CALLOC(1,sizeof(HTAssoc)); if(!assoc) {prErr("No memory for appending objects in a list");return NO;} StrAllocCopy(assoc->name,name); if (value) StrAllocCopy(assoc->value,value); return HTList_appendObject(list,(void *)assoc); } else prErr("Internal error detected in HTAssocList_appendObject()"); return NO; } /* #define my_HTArray_addObject(array, object) \ (HTArray_addObject((array),(object)) ? (array)->size : 0) */ int my_HTArray_addObject (HTArray *array, void *object) { return HTArray_addObject(array,object) ? HTArray_size(array) : 0; } /* #define my_HTArray_getObject(array, pos) \ ((array) ? (((pos)-1 < (array)->size) ? ((array)->data)[(pos)-1] : NULL) : NULL) */ void *my_HTArray_getObject (HTArray *array, int pos) { return (pos-1 < HTArray_size(array)) ? HTArray_data(array)[pos-1] : NULL; } /* ****************************** FILE *************************************** */ /* -------------------------- FILE - test filename --------------------------- */ BOOL isDocName (char *s) { if (!s) return NO; s=skipSpaces(s); return (!strncasecomp(s,"http://",7)); } BOOL isHTMLDocName (char *s) { char *suffix= strrchr(s,'.'); if (suffix && (strEqual(suffix,".html") || strEqual(suffix,".htm"))) return YES; else return NO; } /* -------------------------- FILE - load URL -------------------------------- */ char *WWWdir = NULL; /* Current directory */ HTRequest *W3C_Request=NULL; /* For using the W3C library */ typedef struct { char *uid; char *pw; BOOL retry; BOOL proxy; } myHTBasic; /* copy of the stupidly protected HTBasic type in $(W3C)/Library/src/HTAABrow.c */ void W3CinitForURLRequests() { HTProfile_newPreemptiveClient("IR_App", "1.0"); /*pm:4/1/99: new proxy, if 1 -> if 0 allows (only) local files to be accessed*/ #if 1 if (HTTP_PROXY[0] && !HTProxy_add("http",HTTP_PROXY)) prErr("The proxy %s cannot be set\n",HTTP_PROXY); if (FTP_PROXY[0] && !HTProxy_add("ftp",FTP_PROXY)) prErr("The proxy %s cannot be set\n",FTP_PROXY); if (NEWS_PROXY[0] && !HTProxy_add("news",NEWS_PROXY)) prErr("The proxy %s cannot be set\n",NEWS_PROXY); if (WAIS_PROXY[0] && !HTProxy_add("wais",WAIS_PROXY)) prErr("The proxy %s cannot be set\n",WAIS_PROXY); if (GOPHER_PROXY[0] && !HTProxy_add("gother",GOPHER_PROXY)) prErr("The proxy %s cannot be set\n",GOPHER_PROXY); if (NO_PROXY1[0] && !HTNoProxy_add(NO_PROXY1,NULL,NO_PROXY1_PORT)) fprintf(stderr,"\nCannot invalidate proxy for %s\n",NO_PROXY1); if (NO_PROXY2[0] && !HTNoProxy_add(NO_PROXY2,NULL,NO_PROXY2_PORT)) fprintf(stderr,"\nCannot invalidate proxy for %s\n",NO_PROXY2); #else HTProxy_getEnvVar(); #endif HTCache_flushAll(); /* HTSetTraceMessageMask("h"); i.e. WWWTRACE |= SHOW_ALL_TRACE; */ if (PROXY_PASSWD[0]) { myHTBasic *basic = (myHTBasic *) my_calloc(1, sizeof(myHTBasic)); basic->uid = my_strdup(PROXY_UID); basic->pw = my_strdup(PROXY_PASSWD); basic->retry= NO; basic->proxy = YES; /* HTRequest_setRealm(request,PROXY_REALM); */ HTAA_updateNode(YES,"basic",PROXY_REALM,HTTP_PROXY,basic); /*it calls HTUTree_addNode(AA_PROXY_TREE,PROXY_REALM,HTTP_PROXY,basic)*/ /*Note:HTAA_proxyBeforeFilter() calls&returns HTBasic_generate() via ptr*/ } W3C_Request = HTRequest_new(); if (!HTRequest_setProxy(W3C_Request,HTTP_PROXY)) /* NOT just a test */ fprintf(stderr,"\nThe proxy %s cannot be set\n",HTTP_PROXY); /* else fprintf(stderr,"\nThe proxy %s has been set\n",HTTP_PROXY); */ HTRequest_setOutputFormat(W3C_Request, WWW_SOURCE); HTRequest_addGnHd(W3C_Request,HT_G_PRAGMA_NO_CACHE); /* new files retrieved */ /*WWWdir=HTGetCurrentDirectoryURL();*/ WWWdir= my_strdup(APPLI_URL); /* constant defined in the Makefile */ } void W3CendForURLRequests() { MY_FREE(WWWdir); HTRequest_delete(W3C_Request); HTProfile_delete(); } void changeWWWdirectoryWithDir (char *newDir) { #if 1 int l=strlen(newDir); strcpy(TmpBuff,newDir); if (newDir[l-1]!='/') { TmpBuff[l]='/'; TmpBuff[l+1]='\0'; } newDir= HTParse(TmpBuff,WWWdir, PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION); HTSimplify(&newDir); storeAsAllocated(newDir); MY_FREE(WWWdir); WWWdir=newDir; #else MY_FREE(WWWdir); WWWdir= my_strdup(newDir); /*if (HTURL_isAbsolute(newDir)) { MY_FREE(WWWdir); WWWdir= my_strdup(newDir); else { if (WWWdir[strlen(WWWdir)-1]=='/') sprintf(TmpBuff,"%s%s",WWWdir,newDir); else sprintf(TmpBuff,"%s/%s",WWWdir,newDir); MY_FREE(WWWdir); WWWdir= my_strdup(TmpBuff); }*/ #endif } void changeWWWdirectoryWithFilePath (char *newPath) /* ends by '/' or a filename */ { char *endNewDir, *newDir= HTParse(newPath,WWWdir, PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION); HTSimplify(&newDir); if ((endNewDir= strrchr(newDir,'/'))) *(endNewDir+1)='\0'; MY_FREE(WWWdir); WWWdir=my_strdup(newDir); HT_FREE(newDir); } char *currentWWWdirectory() { return WWWdir; } char *loadURLtoString (char *url) /* Global: HTRequest *W3C_Request, char *WWWdir */ { if (!url || !*url) { prErr("No URL to load"); return NULL; } else { char *absolute_url= HTParse(url, WWWdir, PARSE_ALL); HTChunk *chunk= HTLoadToChunk(absolute_url, W3C_Request); char *str = (chunk) ? HTChunk_toCString(chunk) : NULL; if (str) storeAsAllocated(str); else { if (HTTP_PROXY[0]) prErr("\nCannot load %s to memory via the proxy %s.\nCheck the " "spelling or the access rights\n",absolute_url,HTTP_PROXY); else prErr("\nCannot load %s to memory.\nCheck the " "spelling or the access rights\n",absolute_url); } HT_FREE(absolute_url); return str; } } BOOL loadURLtoFile (char *url, char *fileName) { if (!url || !*url) { prErr("No URL to load"); return NO; } else { struct stat fileStat; BOOL ok=NO; char *absolute_url= HTParse(url, WWWdir, PARSE_ALL); if (!absolute_url) { prErr("\nOut of memory - Cannot load %s to a local file", absolute_url); return NO; } if (!(ok= HTLoadToFile(absolute_url,W3C_Request,fileName))) { if (HTTP_PROXY[0]) prErr("\nCannot load %s to the local file %s via the proxy %s.\n" "Check the spelling or access rights",absolute_url,fileName ,HTTP_PROXY); else prErr("\nCannot load %s to the local file %s.\n" "Check the spelling or access rights",absolute_url,fileName); } else if ((stat(fileName, &fileStat)==-1) || (fileStat.st_size==0)) { ok=NO; if (HTTP_PROXY[0]) prErr("\nCannot load %s to the local file %s via the proxy %s.\n" "Check spelling or access rights",absolute_url,fileName ,HTTP_PROXY); else prErr("\nCannot load %s to the local file %s.\n" "Check spelling or access rights",absolute_url,fileName); } else tr("%s LOADED TO %s via %s\n",absolute_url,fileName,HTTP_PROXY); HT_FREE(absolute_url); chmod(fileName,S_IRWXU | S_IRWXG | S_IRWXO); return ok; } } int loadURLsToTmpfiles (int nbUrls, char *urlArray[], /* load in parallel */ varP HTAssocList *assocUrlsToTmpFileNames) { int i, nbFileLoaded=0; char tmpFileName[L_tmpnam]; struct stat fileStat; char **commandArray= (char **) my_calloc(nbUrls,sizeof(char *)); char ***argvArray= (char ***) my_calloc(nbUrls,sizeof(char **)); char *absolute_url; for (i=0; iname) || (stat(assoc->name, &fileStat)==-1) || (fileStat.st_size==0) ) { prErr("\nParallel_load: could not load %s to a local file. " "Check the spelling or the access rights",assoc->value); assoc->name[0]='\0'; unlink(tmpFileName); } else nbFileLoaded++; } return nbFileLoaded; } /* -------------------------- FILE - read CGI parameters --------------------------- */ /*GET/POST param to CGI script -> paramList*/ ErrMess initListParamWithCGIparam (initP HTAssocList *paramList) { int c,c1,c2, i, allocSize; char *s, *name, *value; /*buff[2049];*/ if (!paramList) return "Server internal error: no parameter list to initialize"; if (strEqual(getenv("REQUEST_METHOD"),"POST")) { int l=atoi(getenv("CONTENT_LENGTH")); if (l==0) return "Server internal error: CONTENT_LENGTH==0."; else if (l>ALLOC_SIZE) allocSize=ALLOC_SIZE; else allocSize=l; /* if (!strEqual(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) { prErr("This script can only be used to decode form results"); return 1; } */ s= (char*) my_calloc(1,sizeof(char)*(allocSize+1)); if (!s) return "Server memory problem: cannot store the parameters"; for (i=0, name=s, value=""; (c=getc(stdin))!=EOF && (l>0); i++,l--) { if (i==allocSize) { allocSize+=ALLOC_SIZE; s[i]='\0'; s=(char*)my_realloc(s,sizeof(char)*(allocSize+1)); } if (c=='+') s[i]=' '; else if (c=='%') { c1=getc(stdin); s[i]=unescapeURLchar(c1,getc(stdin)); l-=2; } else if (c=='=') { s[i]='\0'; value= &s[i+1]; } else if (c=='&') { s[i]='\0'; if (HTAssocList_addObject(paramList,name,value)==NO) { MY_FREE(s); return "Internal error in storing the parameters."; } i= -1; name=s; value=""; } else s[i]=c; } if (i>0) /* => s[i-1]!='&' */ { s[i]='\0'; if (HTAssocList_addObject(paramList,name,value)==NO) { MY_FREE(s); return "Internal error in storing the parameters"; } } } else if (strEqual(getenv("REQUEST_METHOD"),"GET")) /* no CONTENT_LENGTH */ { char *query = getenv("QUERY_STRING"); /* *queryBeginning=query */ if (!query || !*query) return "No query information to process."; allocSize=ALLOC_SIZE; s=(char*) my_calloc(1,sizeof(char)*(allocSize+1)); if (!s) return "Server memory problem: cannot store the parameters"; for (i=0, name=s, value=""; ((c = *query)); i++, query++) { if (i==allocSize) { allocSize+=ALLOC_SIZE; s[i]='\0'; s=(char*)my_realloc(s,sizeof(char)*(allocSize+1)); } if (c=='+') s[i]=' '; else if (c=='%') { c1= *(++query); c2= *(++query); s[i]=unescapeURLchar(c1,c2); } else if (c=='=') { s[i]='\0'; value= &s[i+1]; } else if (c=='&') { s[i]='\0'; /* pr("name:%s\n",name); pr("value:%s\n",value); */ if (HTAssocList_addObject(paramList,name,value)==NO) return "Internal error in storing the parameters"; i=-1; name=s; value=""; } else s[i]=c; } if (i>0) /* && s[i-1]!='&' */ { s[i]='\0'; /* pr("name2:%s\n",name); pr("value:%s\n",value); */ if (HTAssocList_addObject(paramList,name,value)==NO) return "Internal error in storing the parameters"; } } else return "This script should be referenced with a METHOD of GET or POST.\n" "If you don't understand this, see this forms overview"; MY_FREE(s); return NULL; } /* ------------------------ FILE - read string from file ----------------------- */ void ungetsInBuffer (char *str, varP char *buff) { char *s=str; while (*s) s++; while (*buff) buff++; while (s > str) *(buff++)= *(--s); *buff='\0'; } char readCharInBufferOrFd (varP char buff[], int fd) { char c, *s=buff; while (*s) s++; /*fpr(stderr,"readCharIn%s (%d): ",(s > buff)?"buffer":"Fd", fd);*/ if (s > buff) { c=*(--s); *s='\0'; } else if (!read(fd,&c,1)) c='\0'; /*fpr(stderr,"%c_",c);*/ return c; } /* because of the realloc, the return of this function should not be ignored: str=dynamicReadUntil(stopMark, fd, initP char *str, pPosToWrite, pMaxSize)*/ char *dynamicReadUntil (char *stopMark, int fd, initP char *str, varP int *pPosToWrite, varP int *pMaxSize) { static char alreadyReadChars[50]=""; int i= *pPosToWrite, j=1, allocSize= *pMaxSize; char c, stopMarkFirstChar, buff[50]; if (!*stopMark) stopMark= "\n"; stopMarkFirstChar= *stopMark; for (i=0; ((c= readCharInBufferOrFd(alreadyReadChars,fd))); str[i++]=c) { if (i == allocSize) { str[i]='\0'; *pMaxSize += ALLOC_SIZE; allocSize= *pMaxSize; str = (char *) my_realloc (str, sizeof(char)*(allocSize+1)); if (!str) return NULL; } if (c==stopMarkFirstChar) { while (stopMark[j] && ((c= readCharInBufferOrFd(alreadyReadChars,fd))) && (c==stopMark[j])) buff[j++]=c; if (!stopMark[j]) { str[i]='\0'; *pPosToWrite = i; return str; } else { buff[j]='\0'; ungetsInBuffer(buff+1,alreadyReadChars); j=1; } } } if (!i) return NULL; else { str[i]='\0'; *pPosToWrite = i; return str; } } BOOL ungets (char *str, FILE *fp) { char *s=str; while (*s) s++; for (s--; s >= str; s--) if (ungetc(*s,fp)==EOF) return NO; /* else pr("ungetc %c\n",*s); */ return YES; } /* because of the realloc, the return of this function should not be ignored: str=dynamicFgetsUntil(stopMark, fp, initP char *str, includeStopMark, varP pPosToWrite, varP pMaxSize); */ char *dynamicFgetsUntil (char *stopMark /* in lowercase */, FILE *fp, initP char *str, BOOL includeStopMark, varP int *pPosToWrite, varP int *pMaxSize) { int c, i= *pPosToWrite, j, allocSize= *pMaxSize; int iRealloc=0; char stopMarkFirstChar, buff[50]; if (!*stopMark) stopMark= "\n"; stopMarkFirstChar= *stopMark; while ((c=getc(fp))!=EOF) { str[i++]=c; str[i]='\0';/* '\0' ok but useless */ /* if (i == iRealloc+10) { tr("\n\n\n\n\n@@@@@@@@@@@@@@@@@@@@@@@ %d <- '%d%c'\n\n",i,c,c); if (i-20 > 0) tr("!!!%s!!!\n",str+(i-20)); } if ( (iRealloc==30000) && (c=='}') ) { tr("<<<<<<<<<%s>>>>>>>>>>>\n",str+(iRealloc-10)); } */ /* pr("str[%d]='%c', str:'%s'\n",i,c,str); */ if (i==allocSize) { if ((str=strRealloc(str,i,varP pMaxSize))) { allocSize=*pMaxSize; iRealloc=i; /* tr("\n\n\n\n\n\n########### iRealloc %d\n",i); */ } else return NULL; } if (c==stopMarkFirstChar) /* 1st c. ok => j=1 below */ { for (j=1; stopMark[j] && ((c=getc(fp))!=EOF) && (tolower(c)==stopMark[j]); j++) { buff[j]=c; /* tr("buff[%d]=%c\n",j,c); */ } if (stopMark[j]) { buff[j]='\0'; ungetc(c,fp); ungets(buff+1,fp); } else /* stopMark found */ { if (!includeStopMark) i--; else for (j=1; (c= stopMark[j]); j++) { if ((i==allocSize) && !(str=strRealloc(str,i,varP pMaxSize))) return NULL; str[i++]=c; } str[i]='\0'; *pPosToWrite = i; /* tr("222:%d %d%s......\n",i,j,str+(iRealloc-10)); */ return str; } } } if (!i) { tr("end file or empty file"); return NULL; } else { str[i]='\0'; *pPosToWrite = i; tr("333"); return str; } } /* if (fgets(line,499,fp) && (line[0]=='$') && (line[1]=='(')) markForEndOfCommand=")$"; do { if (lastLineOfCommand(varP line, markForEndOfCommand)) { strcat(command,line); line[0]='\0'; break; } if (*line) strcat(command,line); }while (fgets(line,499,fp)); BOOL lastLineOfCommand (varP char *line, char *markForEndOfCommand) { char c, *pc, *end; if (!*line) return YES; if (!strEqual(markForEndOfCommand,".")) { if ((end= strstr(line,markForEndOfCommand))) { *(end+strlen(markForEndOfCommand))='\0'; return YES; } else return NO; } for (end=line; *end; end++) { if (*end == '.') { for (pc=end+1; ((c= *pc)) && isspace(c); pc++) { if (charInStr(c,"\n\r")) { *end='\0'; return YES; } } if (!c) { *end='\0'; return YES; } } } return NO; } char *endOfCommand (char *command, char *markForEndOfCommand) { char c, *pc, *end; if (!strEqual(markForEndOfCommand,".")) { if (!(end= strstr(command,markForEndOfCommand))) { end=command; while (*end) end++; } } else { for (end=command; *end; end++) if (*end == '.') { for (pc=end+1; ((c= *pc)) && isspace(c); pc++) { if (charInStr(c,"\n\r")) return end; } if (!c) return end; } } return end; } */ /* ------------------- FILE - print string to file (stderr/stdout) ------------------ */ int tr (const char *format, ...) /* print traces */ { va_list pArgs; if (!format || !*format) return 0; va_start(pArgs,format); if (!WithTrace) return 0;/*(FpTrace) ? vfprintf(FpTrace,format,pArgs) : 0*/ if (CommandOutputFile) return vfprintf(CommandOutputFile,format,pArgs); else return vfprintf(stdout,format,pArgs); /* if (!WithTrace) return vfprintf(stderr,format,pArgs); */ } #if 1 int prErr (const char *format, ...) /* print error messages */ { FILE *fp=CommandOutputFile; char buff[1000]; int res; va_list pArgs; if (!format || !*format) return 0; if (!fp) fp=stdout; /* stdout instead of stderr for a CGI program */ va_start(pArgs, format); sprintf(buff,"
%s
\n\n",format); res= vfprintf(fp, buff, pArgs); /* not with return since buff is local */ return res; } /* the error message may include __FILE__ and __LINE__ */ #else char *prErr (char *str, ...) /*prErr() version nearly ok; bug for str + two arguments*/ { va_list ap; char c,cv, *s=str, *svStr=str; FILE *fp=stdout; if (!s || !*s) return s; va_start(ap,str); while ((c= *s)) { if (c!='%') s++; else if (!(c= *(++s))) break; else if (c=='%') s++; else { while ( ((c= *(++s))) && (c!=' ') ); cv= *(s-1); switch (cv) { case 'd': case 'i': case 'c': *s='\0'; fpr(fp,str,va_arg(ap,int)); *s=c; str=s; break; case 'o': case 'u': case 'x': case 'X': *s='\0'; fpr(fp,str,va_arg(ap,unsigned int)); *s=c; str=s; break; case 'f': case 'e': case 'g': case 'E': case 'G': *s='\0'; fpr(fp,str,va_arg(ap,double)); *s=c; str=s; break; case 'p': *s='\0'; fpr(fp,str,va_arg(ap,void *)); *s=c; str=s; break; case 'n': *s='\0'; fpr(fp,str,va_arg(ap,int *)); *s=c; str=s; break; case 's': *s='\0'; fpr(fp,str,va_arg(ap,char *)); *s=c; str=s; break; case 'S': *s='\0'; fpr(fp,str,va_arg(ap,wchar_t *)); *s=c; str=s; break; case 'C': *s='\0'; fpr(fp,str,va_arg(ap,intptr_t)); *s=c; str=s; break; } } } if (*str) fpr(fp,str); va_end(ap); return svStr; } #endif /* prErr() version not ok: args should be of char *, int, double, ... at the same time #define MAXARGS 15 char *prErr (char *str, ...) { va_list ap; int i; char c, *s=str; FILE *fp=stdout; char *args[MAXARGS]= {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL}; if (!str || !*str) return str; va_start(ap,str); for (i=0; (c= *s); s++) { if (c=='%') { if (i>=MAXARGS) break; if ( ((c= *(++s))) && (c!='%') ) { while ( ((c= *(++s))) && (c!=' ') ); c= *(s--); switch (c) { case 'd': case 'i': case 'c': args[i++]= va_arg(ap,int); break; case 'o': case 'u': case 'x': case 'X': args[i++]= va_arg(ap,unsigned int); break; case 'f': case 'e': case 'g': case 'E': case 'G': args[i++]= va_arg(ap,double); break; case 'p': args[i++]= va_arg(ap,void *); break; case 'n': args[i++]= va_arg(ap,int *); break; case 's': args[i++]= va_arg(ap,char *); break; case 'S': args[i++]= va_arg(ap,wchar_t *); break; case 'C': args[i++]= va_arg(ap,intptr_t); break; } } } } va_end(ap); fpr(fp,str,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7], args[8],args[9],args[10],args[11],args[12],args[13],args[14]); return str; } */ void prErrDoc (const char *format, ...) { va_list pArgs; va_start(pArgs,format); pr("\nError message\n"); pr("\n

"); vfprintf(stdout,format,pArgs); pr("\n\n\n"); } #if 0 /* useless now that prErr() behaves similarly */ void mkTextError (char *s) { if (!s || !*s) return; if (CommandOutputFile) { char c= s[strlen(s)-1]; if ((c=='\n') || (c=='\r')) fpr(CommandOutputFile,"%s\n",s); else fpr(CommandOutputFile,"%s\n\n",s); }else prErr("%s\n",s); } void addTextError (char *s) { if (!s || !*s) return; if (CommandOutputFile) { char c= s[strlen(s)-1]; if ((c=='\n') || (c=='\r')) fpr(CommandOutputFile,"%s",s); else fpr(CommandOutputFile,"%s\n",s); }else prErr("%s\n",s); } void addTextToError (char *s) { if (!s || !*s) return; if (CommandOutputFile) { char c= s[strlen(s)-1]; if ((c=='\n') || (c=='\r')) fpr(CommandOutputFile,"%s",s); else fpr(CommandOutputFile,"%s\n",s); }else prErr("%s\n",s); } #endif void prAnswer (char *s) { if (!s || !*s) return; if (CommandOutputFile) fpr(CommandOutputFile,s); else if (ResultList && HTList_appendObject(ResultList,my_strdup(s))==NO) prErr("Cannot put results in memory"); } void putsAnswer (char *s, BOOL printCommand) { if (!s) return; if (CommandOutputFile) {if(printCommand) fpr(CommandOutputFile,"%s\n\n",s);} else if (*s && ResultList && HTList_appendObject(ResultList,my_strdup(s))==NO) prErr("Cannot put a result in memory"); } void mkTextAnswer (char *s) /* create the first "Answer" in "answers" */ { if (!s || !*s) return; if (CommandOutputFile) { char c= s[strlen(s)-1]; if ((c!='\n') && (c!='\r')) fpr(CommandOutputFile,"%s\n",s); else fpr(CommandOutputFile,"%s",s); } else if (ResultList && HTList_appendObject(ResultList,my_strdup(s))==NO) prErr("Cannot add results in memory"); } void addTextAnswer (char *s) /* create a new "Answer" in "answers" */ { if (!s || !*s) return; if (CommandOutputFile) { int l=strlen(s)-1; if ((s[l]=='\n') || (s[l]=='\r')) fpr(CommandOutputFile,"%s",s); else fpr(CommandOutputFile,"%s\n",s); } else if (ResultList && HTList_appendObject(ResultList,my_strdup(s))==NO) prErr("Cannot add a result in memory"); } void addTextToAnswer (char *s) /* complete the existing "Answer" */ { if (!s || !*s) return; if (CommandOutputFile) { int l=strlen(s)-1; if ((s[l]=='\n') || (s[l]=='\r')) fpr(CommandOutputFile,"%s",s); else fpr(CommandOutputFile,"%s\n",s); } else if (ResultList && HTList_appendObject(ResultList,my_strdup(s))==NO) prErr("Cannot add to the list of results in memory"); } void mkTextAnswerN (int nbString, char *s) { int i; if (!nbString) return; mkTextAnswer(s); s += strlen(s)+1; for (i=1; i after the '<' or end str */ { char c; for (;((c= *s)); s++) { if ((c=='<') && isHTMLmarkThere(s)) return s+1; } return s; } #if 1 char *skipAfterThisHTMLmark (char *s) /* in: *(s-1) == '<' */ { char c; while ((c= *s)) { if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if (c=='>') return s+1; else s++; } return s; } #else char *skipAfterThisHTMLmark (char *s) /* in: *(s-1) == '<' */ { char c, *sv_s; if ((*s=='!') && (*(s+1)=='-') && (*(s+2)=='-')) { if ((s= strstr(sv_s=s+3,"-->"))) s+=3; else { prErr("Error after: %s\n \"-->\" unfound",displayableLineFrom(s)); for (s=sv_s; *s; s++); } } else while ((c= *s)) { if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else if (c=='>') return s+1; else s++; } return s; } #endif char *skipSpacesCommentsAndHTMLmarks (char *s) { char c; /* static BOOL isInHTMLcomment=NO; to do, with care, in the future */ while ((c= *s)) { if (isspace(c)) s++; else if (c=='\\') { c= *(++s); if (c=='\n') s++; else return s-1; } else if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) s+=6; else { if ((c=='<') && isHTMLmarkThere(s)) s=skipAfterThisHTMLmark(s+1); else if (c=='/') { c= *(s+1); if (c=='*') s=skipComments(s+2); else if (c=='/') s=skipAfterEndOfLine(s+2); else return s; } else return s; } } return s; } char *skipSpacesCommentsAndHTMLmarksAndTellIfHTMLmarkFound(char *s, varP BOOL *pHtmlMarkFound) { char c; BOOL htmlMarkFound=*pHtmlMarkFound; while ((c= *s)) { if (isspace(c)) s++; else if (c=='\\') { c= *(++s); if (c=='\n') s++; else return s-1; } else if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) s+=6; else { if ((c=='<')&&isHTMLmarkThere(s)) {htmlMarkFound=YES; s=skipAfterThisHTMLmark(s+1);} else if (c=='/') { c= *(s+1); if (c=='*') s=skipComments(s+2); else if (c=='/') s=skipAfterEndOfLine(s+2); else return s; } else return s; } } *pHtmlMarkFound=htmlMarkFound; return s; } char *skipSpacesCommentsAndHTMLmarksExceptChar (char *s, char stop) { char c; while ((c= *s)) { if (c==stop) return s; else if (isspace(c)) s++; else if (c=='\\') { c= *(++s); if (c=='\n') s++; else return s-1; } else if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) s+=6; else { if ((c=='<') && isHTMLmarkThere(s)) s=skipAfterThisHTMLmark(s+1); else if (c=='/') { c= *(s+1); if (c=='*') s=skipComments(s+2); else if (c=='/') s=skipAfterEndOfLine(s+2); else return s; } else return s; } } return s; } BOOL onlySpacesCommentsOrHTMLmarksIn (char *s) { char c; while ((c= *s)) { if (isspace(c)) s++; else if (c=='\\') { c= *(++s); if (c=='\n') s++; else return NO; } else if ((c=='&') && (*(s+1)=='n') && (*(s+2)=='b') && (*(s+3)=='s') && (*(s+4)=='p') && (*(s+5)==';')) s+=6; else { if ((c=='<') && isHTMLmarkThere(s)) s= skipAfterThisHTMLmark(s+1); else if (c=='/') { c= *(++s); if (c=='*') s=skipComments(s+1); else if (c=='/') s= skipAfterEndOfLine(s+1); else return NO; } else return NO; } } return YES; } char *removeHTMLmarksFrom (char *s) { char c, *dest=s, *svDest=s; while ((c= *s)) { if ((c=='<') && isHTMLmarkThere(s)) s= skipAfterThisHTMLmark(s+1); else *dest++ = *s++; } *dest = '\0'; return svDest; } char *skipUntilTheseHTMLmarks (char *s, char *stopMark1,char *stopMark2) { char c, *token; /* return: next plain text || & "')) { s+=3; inHTMLcomment=NO; } else return s; } return s; } #else char *skipHTMLmarksExceptMark (char *s, char *stopMark)/* s: HTML area */ { char c, *token, *sv_s; /* return: next plain text || & ""))) s+=3; else { prErr("Error after: %s\n \"-->\" unfound",displayableLineFrom(s)); for (s=sv_s; *s; s++); } } else if ((c=='/') || isalpha(c)) { if (*stopMark) { for (token=s; ((c= *s)) && !isspace(c) && (c!='>'); s++); if (!c) return s; *s='\0'; if (strCaseEqual(token,stopMark)) { *s=c; return token-1; } *s= c; } else { while (((c= *s)) && !isspace(c) && (c!='>')) s++; if (!c) return s; } while ( ((c= *s)) && (c!='>') ) { if (c=='"') s=skipQuotedString(s+1); else if (c=='\'') s=skipStringQuotedLikeACharacter(s+1); else s++; } if (c) s++; } else return s-1; } } return s; } #endif /* for (j=0; ((c=getc(fp))!=EOF) && isspace(c); j++) { if (charInStr(c,"\n\r")) { while (j--) ungetc(c,fp); break; } } if (!c) { command[i]='\0'; */ char *skipAfterAttributeAndGetItsValue (char *s, char *attr, char *defaultValue, /*s:before attrs*/ char **pValue, char *pErasedChar) { char c, *token; BOOL attrFound; while (*s && (*s!='>')) { token=s=skipSpaces(s); while ( ((c= *s)) && !isspace(c) && (c!='=') && (c!='>') ) s++; *s='\0'; attrFound= strCaseEqual(token,attr); *s= c; s=skipSpaces(s); if (c == '=') { s=skipSpaces(s+1); c= *s; if (c == '"') { s++; token=s; while ( ((c= *s)) && (c!='"' || *(s-1)=='\\')) s++; if (attrFound) { if (c) { *s='\0'; *pValue=token; *pErasedChar= c; return s+1; } else break; } } else if (c=='\'') { s++; token=s; while ( ((c= *s)) && (c!='\'' || *(s-1)=='\\')) s++; if (attrFound) { if (c) { *s='\0'; *pValue=token; *pErasedChar= c; return s+1; } else break; } } else if (c!='>') { token=s; while ( ((c= *s)) && !isspace(c) ) s++; if (attrFound) { if (c) { *s='\0'; *pValue=token; *pErasedChar= c; return s+1; } else break; } } }/*else this attr. is supposed to have no associated value */ } *pValue=defaultValue; *pErasedChar='\0'; return s; } void hideTrailingHTMLmarksIn (char *s, char *end_s) { if (*end_s) return; #if 0 while ((--end_s>s) && (*end_s=='>')) /* hide non white_separated trailing marks */ { while (--end_s && (*end_s != '<')) if ((end_s<=s) || (*end_s == '"')) return; *end_s= '\0'; } while ((end_s>s) && isspace(*s)) *s-- = '\0'; #else for (;;) /* hide possibly white_separated trailing marks except */ { while (--end_s && isspace(*end_s)) if (end_s<=s) return; else *end_s='\0'; if (*end_s != '>') return; while (--end_s && (*end_s != '<')) if ((end_s<=s) || (*end_s == '"')) return; if ((*(end_s+1)=='/') && (toupper(*(end_s+2))=='A') && (*(end_s+3)=='>')) return; *end_s= '\0'; } #endif } /* -------------- HTML FILE/STRING - transform and print HTML file ----------------- */ void prWithoutHTMLmarksIn (char *str) { while (*str) { char c, *s=skipToNextHTMLmark(str); if (!*s) { fputs(str,stdout); break; } s--; /* *s=='<' */ c= *s; *s='\0'; if (*str) fputs(str,stdout); *s= c; str=skipAfterThisHTMLmark(s+1); } } void prWithVisibleURLs (char *str) { char c, erasedChar, *url=NULL, *tmpUrl, *s=str; while (*s) { s=skipToNextHTMLmark(s); if (!*s) break; if ((tolower(*s)=='a') && isspace(*(s+1))) /* "') ) { s+=3; c= *s; *s='\0'; fputs(str,stdout); *s= c; pr(" [%s] ",url); str=s; MY_FREE(url); url=NULL; break; } } } } puts(str); if (url) MY_FREE(url); } void prAccessibleDocFrom (char *url, int level, int maxLevel, BOOL htmlOnly) { int i; char erasedChar, *str, *s, *referedUrl, *allocatedNewDir=NULL, *svCurrentDir=WWWdir; /* to do: skip comments, transform relatives URLs into absolutes. Done ?? */ if (level>maxLevel) return; if (!url || !*url) return; if (!(str= loadURLtoString(url))) return; s=str; if (strchr(url,'/')) { char *absoluteNewDir= HTParse(url, WWWdir, PARSE_ALL); char *endNewCurrentDir= strrchr(absoluteNewDir,'/')+1; char c=*endNewCurrentDir; *endNewCurrentDir='\0'; if (!(allocatedNewDir= my_strdup(absoluteNewDir))) return; *endNewCurrentDir=c; HT_FREE(absoluteNewDir); WWWdir= allocatedNewDir; /* tr("tmp dir from %s: %s.\n",url,WWWdir); */ } while (*s) { s=skipToNextHTMLmark(s); if (!*s) break; if ((tolower(*s)=='a') && isspace(*(s+1))) /* "') && (strThe section of title \"%s\" has not been found in %s
\n", elem, absolute_url); return; } } else { for (s=str; ((elemInDoc= strContentInStr(elem,s,initP &afterElem))); s=afterElem) { if (occurrence==wantedOccurrence) break; occurrence++; sv_elemInDoc=elemInDoc; } if (!elemInDoc) { if (!sv_elemInDoc) { prErrDoc("The following document element has not been found in %s:" "
\n%s", absolute_url, elem); return; }else elemInDoc=sv_elemInDoc; } } /*if (!(elemInDoc= strContentInStr(elem, str, initP &afterElem))) { prErrDoc("The following document element has not been found in %s:
\n%s", absolute_url, elem); return; }*/ if ((mark= strcasestr(str,""); isAnHTMLDoc=NO; } if (strchr(document,'/')) { char *absoluteNewDir= HTParse(document, WWWdir, PARSE_ALL); char *endNewCurrentDir= strrchr(absoluteNewDir,'/')+1; c=*endNewCurrentDir; *endNewCurrentDir='\0'; pr("\n\n",absoluteNewDir); HT_FREE(absoluteNewDir); } else pr("\n\n",WWWdir); c=*elemInDoc; *elemInDoc='\0'; fputs(str,stdout); *elemInDoc=c; if (sv_elemInDoc) pr("[the %d%s occurrence of the desired element has not been " "found\nbut the %d%s occurrence is here highlighted]\n", wantedOccurrence, orderSuffixForDigit(wantedOccurrence), occurrence, orderSuffixForDigit(occurrence)); pr("
\n"); if (!elemIsSection && strcasestr(elem,"

Destination of the clicked relation:

\n"); } c=*afterElem; *afterElem='\0'; pr("%s\n",elemInDoc); *afterElem=c; str=afterElem; if (imageInDest) { pr("

----- End of the destination of the " "clicked relation -----

\n"); } fputs(str,stdout); if (!isAnHTMLDoc) pr(""); MY_FREE(fileContent); } #if 0 void displayCGsUsingBCGapplet (char *cgs) { pr("\nCG graphical display\n"); pr("\n

"); if (!cgs || !*cgs) pr("No CG to display\n"); else { int fdPipeToCG2BCG[2],fdPipeFromCG2BCG[2]; tr("CG to display: %s\n",cgs); if(pipe(FdPipeToProcessor) == -1) return "Cannot create FdPipeToProcessor !"; if(pipe(FdPipeFromProcessor) == -1)return "Cannot create FdPipeFromProcessor !"; /*fcntl(FdPipeInCommand[0], F_SETFL, O_NDELAY);*/ /*fcntl(FdPipeOutCommand[0],F_SETFL, O_NDELAY);*/ ProcessorPID= startProcess(SANTIAGO_BIN,argv,envp, FdPipeToProcessor[0],FdPipeFromProcessor[1]); if (ProcessorPID == -1) return "Cannot start the processor"; tr("Santiago PID:%d\n",ProcessorPID); /*write(FdPipeToProcessor[1],"test",4); TmpBuff[0]='\0';TmpBuff[1]='\0'; read(FdPipeFromProcessor[0],TmpBuff,2); TmpBuff[2]='\0'; pr("***%s***\n",TmpBuff);*/ FdToProcessor=FdPipeToProcessor[1]; /* no FILE*fp: fdopen() doesn't work */ FdFromProcessor=FdPipeFromProcessor[0]; for (i=0; ((tok= argv[i])) && *tok; i++) { write(FdToProcessor,tok,strlen(tok)); write(FdToProcessor," ",1); } write(FdToProcessor,";\n",2); /* the '\n' is very important */ } pr("\n\n\n"); } #endif /* ***************************** PROCESS ************************************** */ /* call the next function on a string before giving it to popen */ char searchNonEscapedShellCharactersIn (char *s) { while (*s) { s=skipSpaces(s); switch (*s) { case '\0': return '\0'; case '"' : s=skipQuotedString(s+1); break; case '\'': s=skipStringQuotedLikeACharacter(s+1); break; case '\\': s++; if (*s) s++; break; case';': case '|': case '&': case '(': case ')': case '{': case '}': case'$': case '*': case '?': case '<': case '>': case '[': case ']': case'^': return *s; default: s++; } } return '\0'; } void runCommandWithWWWfiles (int nbFirstArgNotOption, int nbFirstFile, char *argv[], int argc, FILE *OutputFp, BOOL withXMP) { int i=nbFirstFile, j, nbLoaded=0; HTAssocList *tmpAssocList, *assocList=HTAssocList_new(); /*Assoc copy name to orig. file name*/ HTAssoc *attrValuePair; FILE *fp; HTChunk *chunk=HTChunk_new(1000); char *str; /* chunk/str store the call */ if (!chunk || !assocList) { prErr("Out of memory"); return; } HTChunk_puts(chunk,argv[0]); HTChunk_putc(chunk,' '); /* command name */ for (j=1; j=19) { argc=19; prErr("Only the %d first files will be processed.\n",19-j); } #if 1 if ((nbLoaded= loadURLsToTmpfiles(argc-i,&argv[i],varP assocList))) { tmpAssocList=assocList; while ((attrValuePair= (HTAssoc *) HTList_nextObject(tmpAssocList))) if (attrValuePair->name && attrValuePair->name[0]) /*if file copied*/ { HTChunk_puts(chunk,attrValuePair->name); HTChunk_putc(chunk,' '); } } #else for (; i&1"); str=HTChunk_data(chunk); /* pr("\n%s\n",str); */ if (!(fp= popen(str,"r"))) prErr("Internal problem: cannot call %s.\n",argv[0]); else if (OutputFp) { if (withXMP) fputs("

\n",OutputFp); /* or plaintext (!listing) */ while (fgets(str,999,fp)) fputs(doOneReplacementUsingAssocList(str,assocList),OutputFp); if (withXMP) fputs("\n",OutputFp); pclose(fp); } for (tmpAssocList=assocList; (attrValuePair= HTAssocList_nextObject(tmpAssocList)); unlink(HTAssoc_name(attrValuePair)) ); } HTChunk_delete(chunk); HTAssocList_delete(assocList); } int execCommand (char *command, char *argv[], char *envp[], int input, int output, int errput) { int pid, pidChild, status; if ((pidChild= fork()) == -1) { prErr("Cannot fork!!!"); return 1; } if (!pidChild) /* code for the child process */ { tr("I am the child process\n"); if (input>=0) if (dup2(input,0)==-1) prErr("Failed to duplicate %d as an input",input); if (output>=0) if (dup2(output,1)==-1) prErr("Failed to duplicate %d as an output",output); if (errput>=0) if (dup2(errput,2)==-1) prErr("Failed to duplicate %d as an error output",errput); execve(command,argv,envp); prErr("%s cannot be executed",command); exit(1); /* the child must exit now */ } tr("child %d created\n",pidChild); while (((pid= wait(&status))) && (pid>0) && (pid!=pidChild)); if (WIFEXITED(status)) return WEXITSTATUS(status); else return -1; } int execCommands (int nbCommands, char *commandArray[], char **argvArray[], char *envp[], int input, int output, int errput) { int i, pidChild, status; /* *pidChildArray= (int *) my_calloc(nbCommands,sizeof(int)); */ for (i=0; i=0) if (dup2(input,0)==-1) prErr("Failed to duplicate %d as an input",input); if (output>=0) if (dup2(output,1)==-1) prErr("Failed to duplicate %d as an output",output); if (errput>=0) if (dup2(errput,2)==-1) prErr("Failed to duplicate %d as an error output",errput); execve(commandArray[i],argvArray[i],envp); prErr("'%s %s %s ' cannot be executed: %s'", commandArray[i], argvArray[i][1],argvArray[i][2],strerror(errno)); exit(1); /* the child must exit now */ } } tr("childs created. I wait them to end\n"); while (((pidChild= wait(&status))) && (pidChild>0)); tr("All childs have just ended. I go on\n"); if (WIFEXITED(status)) return WEXITSTATUS(status); else return -1; } int startProcess (char *command,char *argv[],char *envp[],int input,int output) { int pidChild; /* if (pidChild) kill(pidChild, SIGKILL); */ if ((pidChild= fork()) == -1) { prErr("Cannot fork!!!"); return -1; } if (!pidChild) /* code for the child process */ { if (input>=0) if (dup2(input,0)==-1) prErr("Failed to duplicate %d as an input",input); if (output>=0) if (dup2(output,1)==-1) prErr("Failed to duplicate %d as an output",output); execve(command,argv,envp); prErr("%s cannot be executed",command); exit(1); /* the child must exit now */ } tr("%s is running with input:%d output:%d\n",command,input,output); return pidChild; }