📄 htwwwstr.c
字号:
/* HTWWWStr.c** WWW RELATED STRING UTILITIES**** (c) COPYRIGHT MIT 1995.** Please first read the full copyright statement in the file COPYRIGH.** @(#) $Id: HTWWWStr.c,v 2.34 1999/02/22 22:10:12 frystyk Exp $**** Now 13 95 Spwaned from HTString.c*//* Library include files */#include "wwwsys.h"#include "WWWUtil.h"#include "HTParse.h"#include "HTInet.h"#include "HTUser.h"#include "HTWWWStr.h" /* Implemented here */PRIVATE char * months[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};#ifndef HAVE_STRFTIMEPRIVATE char * wkdays[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat"};#endif/* ------------------------------------------------------------------------- *//* Find next Field** ---------------** Finds the next RFC822 token in a string** On entry,** *pstr points to a string containing a word separated** by white white space "," ";" or "=". The word** can optionally be quoted using <"> or "<" ">"** Comments surrrounded by '(' ')' are filtered out**** On exit,** *pstr has been moved to the first delimiter past the** field** THE STRING HAS BEEN MUTILATED by a 0 terminator**** Returns a pointer to the first word or NULL on error*/PUBLIC char * HTNextField (char ** pstr){ char * p = *pstr; char * start = NULL; if (!pstr || !*pstr) return NULL; while (1) { /* Strip white space and other delimiters */ while (*p && (isspace((int) *p) || *p==',' || *p==';' || *p=='=')) p++; if (!*p) { *pstr = p; return NULL; /* No field */ } if (*p == '"') { /* quoted field */ start = ++p; for(;*p && *p!='"'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ break; /* kr95-10-9: needs to stop here */ } else if (*p == '<') { /* quoted field */ start = ++p; for(;*p && *p!='>'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ break; /* kr95-10-9: needs to stop here */ } else if (*p == '(') { /* Comment */ for(;*p && *p!=')'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ p++; } else { /* Spool field */ start = p; while(*p && !isspace((int) *p) && *p!=',' && *p!=';' && *p!='=') p++; break; /* Got it */ } } if (*p) *p++ = '\0'; *pstr = p; return start;}/* Find next LWS delimited token** -----------------------------** On entry,** *pstr points to a string containing a word separated** by white white space "," ";" or "=". The word** can optionally be quoted using <"> or "<" ">"** Comments surrrounded by '(' ')' are filtered out**** On exit,** *pstr has been moved to the first delimiter past the** field** THE STRING HAS BEEN MUTILATED by a 0 terminator**** Returns a pointer to the first word or NULL on error*/PUBLIC char * HTNextLWSToken (char ** pstr){ char * p = *pstr; char * start = NULL; if (!pstr || !*pstr) return NULL; /* Strip initial white space */ while (*p && (isspace((int) *p))) p++; if (!*p) { *pstr = p; return NULL; /* No field */ } /* Now search for the next white space */ start = p; while(*p && !isspace((int) *p)) p++; if (*p) *p++ = '\0'; *pstr = p; return start;}/* Find next Name-value pair** -------------------------** This is the same as HTNextField but it does not look for '=' as a** separator so if there is a name-value pair then both parts are** returned.** Returns a pointer to the first word or NULL on error*/PUBLIC char * HTNextPair (char ** pstr){ char * p = *pstr; char * start = NULL; if (!pstr || !*pstr) return NULL; while (1) { /* Strip white space and other delimiters */ while (*p && (*p==',' || *p==';')) p++; if (!*p) { *pstr = p; return NULL; /* No field */ } if (*p == '"') { /* quoted field */ start = ++p; for(;*p && *p!='"'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ break; /* kr95-10-9: needs to stop here */ } else if (*p == '<') { /* quoted field */ start = ++p; for(;*p && *p!='>'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ break; /* kr95-10-9: needs to stop here */ } else if (*p == '(') { /* Comment */ for(;*p && *p!=')'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ p++; } else { /* Spool field */ start = p; while(*p && *p!=',' && *p!=';') p++; break; /* Got it */ } } if (*p) *p++ = '\0'; *pstr = p; return start;}/* Find next element in a comma separated string** ---------------------------------------------** This is the same as HTNextPair but it does not look for anything** else than ',' as separator** Returns a pointer to the first word or NULL on error*/PUBLIC char * HTNextElement (char ** pstr){ char * p = *pstr; char * start = NULL; if (!pstr || !*pstr) return NULL; /* Strip white space and other delimiters */ while (*p && ((isspace((int) *p)) || *p==',')) p++; if (!*p) { *pstr = p; return NULL; /* No field */ } start = p; while (1) { if (*p == '"') { /* quoted field */ for(;*p && *p!='"'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ p++; } else if (*p == '<') { /* quoted field */ for(;*p && *p!='>'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ p++; } else if (*p == '(') { /* Comment */ for(;*p && *p!=')'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ p++; } else { /* Spool field */ while (*p && *p!=',') p++; break; /* Got it */ } } if (*p) *p++ = '\0'; *pstr = p; return start;}/* Find next "/" delimied segment** ------------------------------** This is the same as HTNextField but it includes "/" as a delimiter.** Returns a pointer to the first segment or NULL on error*/PUBLIC char * HTNextSegment (char ** pstr){ char * p = *pstr; char * start = NULL; if (!pstr || !*pstr) return NULL; while (1) { /* Strip white space and other delimiters */ while (*p && (isspace((int) *p) || *p==',' || *p==';' || *p=='=' || *p=='/')) p++; if (!*p) { *pstr = p; return NULL; /* No field */ } if (*p == '"') { /* quoted field */ start = ++p; for(;*p && *p!='"'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ break; /* kr95-10-9: needs to stop here */ } else if (*p == '<') { /* quoted field */ start = ++p; for(;*p && *p!='>'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ break; /* kr95-10-9: needs to stop here */ } else if (*p == '(') { /* Comment */ for(;*p && *p!=')'; p++) if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */ p++; } else { /* Spool field */ start = p; while(*p && !isspace((int) *p) && *p!=',' && *p!=';' && *p!='=' && *p!='/') p++; break; /* Got it */ } } if (*p) *p++ = '\0'; *pstr = p; return start;}/*** Find the next s-expression token from a string of characters.** We return the name of this expression and the param points to the** parameters. **** NOTE: The string has been mutilated by '/0's*/PUBLIC char * HTNextSExp (char ** exp, char ** param){ char * p = *exp; char * name = NULL; if (!exp || !*exp) return NULL; while (*p && isspace((int) *p)) p++; /* Strip leading white space */ if (!*p) { *exp = p; return NULL; /* No field */ } if (*p == '{') { /* Open bracket */ int cnt = 1; /* ** Look for name of this expression. If we find a token then search ** for the rest of the expression and remove the end '}' */ p++; if ((name = HTNextField(&p)) == NULL) return NULL; while (*p && isspace((int) *p)) p++; *param = p; while (*p) { if (*p == '{') cnt++; if (*p == '}') cnt--; if (!cnt) { *p = '\0'; break; } p++; } } return name;}/*** Returns a Message-ID string including the open '<' and the closing '>'.** The format of the string is:**** "<" time-in-sec "Z" process-id "@" FQDN ">"**** or on systems that doesn't have process-id:**** "<" time-in-sec "Z" user "@" FQDN ">"**** Returns a pointer to the MessageID*/PUBLIC const char * HTMessageIdStr (HTUserProfile * up){ static char buf[80]; time_t sectime = time(NULL);#ifdef HAVE_GETPID const char * address = HTUserProfile_fqdn(up);#else const char * address = HTUserProfile_email(up);#endif /* HAVE_GETPID */ if (!address) address = tmpnam(NULL); if ((!address || !*address) && sectime < 0) { HTTRACE(CORE_TRACE, "MessageID... Can't make a unique MessageID\n"); return ""; }#ifdef HAVE_GETPID sprintf(buf, "<%ldZ%ld@%s>", (long)sectime, (long)getpid(), address ? address : "@@@");#else sprintf(buf, "<%ldZ%s>", sectime, address ? address : "@@@");#endif /* HAVE_GETPID */ *(buf+79) = '\0'; return buf;}/* Date and Time Parser** --------------------** These functions are taken from the server written by Ari Luotonen*/#if 0PRIVATE int make_num (const char * s){ if (*s >= '0' && *s <= '9') return 10 * (*s - '0') + *(s+1) - '0'; else return *(s+1) - '0';}#endifPRIVATE int make_month (char * s, char ** ends){ char * ptr = s; while (!isalpha((int) *ptr)) ptr++; if (*ptr) { int i; *ends = ptr+3; for (i=0; i<12; i++) if (!strncasecomp(months[i], ptr, 3)) return i; } return 0;}/*** Parse a str in GMT format to a local time time_t representation** Four formats are accepted:**** Wkd, 00 Mon 0000 00:00:00 GMT (rfc1123)** Weekday, 00-Mon-00 00:00:00 GMT (rfc850)** Wkd Mon 00 00:00:00 0000 GMT (ctime)** 1*DIGIT (delta-seconds)*/PUBLIC time_t HTParseTime (const char * str, HTUserProfile * up, BOOL expand){ char * s; struct tm tm; time_t t; if (!str) return 0; if ((s = strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */ s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */ while (*s && *s==' ') s++; if (strchr(s,'-')) { /* First format */ HTTRACE(CORE_TRACE, "Format...... Weekday, 00-Mon-00 00:00:00 GMT\n"); if ((int)strlen(s) < 18) { HTTRACE(CORE_TRACE, "ERROR....... Not a valid time format \"%s\"\n" _ s); return 0; } tm.tm_mday = strtol(s, &s, 10); tm.tm_mon = make_month(s, &s); tm.tm_year = strtol(++s, &s, 10); tm.tm_hour = strtol(s, &s, 10); tm.tm_min = strtol(++s, &s, 10); tm.tm_sec = strtol(++s, &s, 10); } else { /* Second format */ HTTRACE(CORE_TRACE, "Format...... Wkd, 00 Mon 0000 00:00:00 GMT\n"); if ((int)strlen(s) < 20) { HTTRACE(CORE_TRACE, "ERROR....... Not a valid time format \"%s\"\n" _ s); return 0; } tm.tm_mday = strtol(s, &s, 10); tm.tm_mon = make_month(s, &s); tm.tm_year = strtol(s, &s, 10) - 1900; tm.tm_hour = strtol(s, &s, 10); tm.tm_min = strtol(++s, &s, 10); tm.tm_sec = strtol(++s, &s, 10); } } else if (isdigit((int) *str)) { if (strchr(str, 'T')) { /* ISO (limited format) date string */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -