📄 http.c
字号:
httpGets(char *line, /* I - Line to read into */ int length, /* I - Max length of buffer */ http_t *http) /* I - HTTP data */{ char *lineptr, /* Pointer into line */ *bufptr, /* Pointer into input buffer */ *bufend; /* Pointer to end of buffer */ int bytes; /* Number of bytes read */ DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http)); if (http == NULL || line == NULL) return (NULL); /* * Pre-scan the buffer and see if there is a newline in there... */#ifdef WIN32 WSASetLastError(0);#else errno = 0;#endif /* WIN32 */ do { bufptr = http->buffer; bufend = http->buffer + http->used; while (bufptr < bufend) if (*bufptr == 0x0a) break; else bufptr ++; if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER) { /* * No newline; see if there is more data to be read... */ if (!http->blocking && !http_wait(http, 1000)) return (NULL);#ifdef HAVE_SSL if (http->tls) bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used); else#endif /* HAVE_SSL */ bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0); DEBUG_printf(("httpGets: read %d bytes...\n", bytes)); if (bytes < 0) { /* * Nope, can't get a line this time... */#ifdef WIN32 if (WSAGetLastError() != http->error) { http->error = WSAGetLastError(); continue; } DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));#else DEBUG_printf(("httpGets: recv() error %d!\n", errno)); if (errno == EINTR) continue; else if (errno != http->error) { http->error = errno; continue; }#endif /* WIN32 */ return (NULL); } else if (bytes == 0) { http->error = EPIPE; return (NULL); } /* * Yup, update the amount used and the end pointer... */ http->used += bytes; bufend += bytes; bufptr = bufend; } } while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER); http->activity = time(NULL); /* * Read a line from the buffer... */ lineptr = line; bufptr = http->buffer; bytes = 0; length --; while (bufptr < bufend && bytes < length) { bytes ++; if (*bufptr == 0x0a) { bufptr ++; break; } else if (*bufptr == 0x0d) bufptr ++; else *lineptr++ = *bufptr++; } if (bytes > 0) { *lineptr = '\0'; http->used -= bytes; if (http->used > 0) memmove(http->buffer, bufptr, http->used); DEBUG_printf(("httpGets: Returning \"%s\"\n", line)); return (line); } DEBUG_puts("httpGets: No new line available!"); return (NULL);}/* * 'httpPrintf()' - Print a formatted string to a HTTP connection. */int /* O - Number of bytes written */httpPrintf(http_t *http, /* I - HTTP data */ const char *format, /* I - printf-style format string */ ...) /* I - Additional args as needed */{ int bytes, /* Number of bytes to write */ nbytes, /* Number of bytes written */ tbytes; /* Number of bytes all together */ char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */ *bufptr; /* Pointer into buffer */ va_list ap; /* Variable argument pointer */ DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format)); va_start(ap, format); bytes = vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); DEBUG_printf(("httpPrintf: %s", buf)); for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes) {#ifdef HAVE_SSL if (http->tls) nbytes = http_write_ssl(http, bufptr, bytes - tbytes); else#endif /* HAVE_SSL */ nbytes = send(http->fd, bufptr, bytes - tbytes, 0); if (nbytes < 0) { nbytes = 0;#ifdef WIN32 if (WSAGetLastError() != http->error) { http->error = WSAGetLastError(); continue; }#else if (errno == EINTR) continue; else if (errno != http->error) { http->error = errno; continue; }#endif /* WIN32 */ return (-1); } } return (bytes);}/* * 'httpGetDateString()' - Get a formatted date/time string from a time value. */const char * /* O - Date/time string */httpGetDateString(time_t t) /* I - UNIX time */{ struct tm *tdate; static char datetime[256]; tdate = gmtime(&t); snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT", days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon], tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec); return (datetime);}/* * 'httpGetDateTime()' - Get a time value from a formatted date/time string. */time_t /* O - UNIX time */httpGetDateTime(const char *s) /* I - Date/time string */{ int i; /* Looping var */ struct tm tdate; /* Time/date structure */ char mon[16]; /* Abbreviated month name */ int day, year; /* Day of month and year */ int hour, min, sec; /* Time */ if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6) return (0); for (i = 0; i < 12; i ++) if (strcasecmp(mon, months[i]) == 0) break; if (i >= 12) return (0); tdate.tm_mon = i; tdate.tm_mday = day; tdate.tm_year = year - 1900; tdate.tm_hour = hour; tdate.tm_min = min; tdate.tm_sec = sec; tdate.tm_isdst = 0; return (mktime(&tdate));}/* * 'httpUpdate()' - Update the current HTTP state for incoming data. */http_status_t /* O - HTTP status */httpUpdate(http_t *http) /* I - HTTP data */{ char line[1024], /* Line from connection... */ *value; /* Pointer to value on line */ http_field_t field; /* Field index */ int major, minor, /* HTTP version numbers */ status; /* Request status */ DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state)); /* * If we haven't issued any commands, then there is nothing to "update"... */ if (http->state == HTTP_WAITING) return (HTTP_CONTINUE); /* * Grab all of the lines we can from the connection... */ while (httpGets(line, sizeof(line), http) != NULL) { DEBUG_printf(("httpUpdate: Got \"%s\"\n", line)); if (line[0] == '\0') { /* * Blank line means the start of the data section (if any). Return * the result code, too... * * If we get status 100 (HTTP_CONTINUE), then we *don't* change states. * Instead, we just return HTTP_CONTINUE to the caller and keep on * tryin'... */ if (http->status == HTTP_CONTINUE) return (http->status); if (http->status < HTTP_BAD_REQUEST) http->digest_tries = 0;#ifdef HAVE_SSL if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls) { if (http_setup_ssl(http) != 0) {# ifdef WIN32 closesocket(http->fd);# else close(http->fd);# endif /* WIN32 */ return (HTTP_ERROR); } return (HTTP_CONTINUE); }#endif /* HAVE_SSL */ httpGetLength(http); switch (http->state) { case HTTP_GET : case HTTP_POST : case HTTP_POST_RECV : case HTTP_PUT : http->state ++; case HTTP_POST_SEND : break; default : http->state = HTTP_WAITING; break; } return (http->status); } else if (strncmp(line, "HTTP/", 5) == 0) { /* * Got the beginning of a response... */ if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3) return (HTTP_ERROR); http->version = (http_version_t)(major * 100 + minor); http->status = (http_status_t)status; } else if ((value = strchr(line, ':')) != NULL) { /* * Got a value... */ *value++ = '\0'; while (isspace(*value & 255)) value ++; /* * Be tolerants of servers that send unknown attribute fields... */ if (!strcasecmp(line, "expect")) { /* * "Expect: 100-continue" or similar... */ http->expect = (http_status_t)atoi(value); } else if (!strcasecmp(line, "cookie")) { /* * "Cookie: name=value[; name=value ...]" - replaces previous cookies... */ httpSetCookie(http, value); } else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN) { DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line)); continue; } else httpSetField(http, field, value); } else { http->status = HTTP_ERROR; return (HTTP_ERROR); } } /* * See if there was an error... */ if (http->error == EPIPE && http->status > HTTP_CONTINUE) return (http->status); if (http->error) { DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error, strerror(http->error))); http->status = HTTP_ERROR; return (HTTP_ERROR); } /* * If we haven't already returned, then there is nothing new... */ return (HTTP_CONTINUE);}/* * 'httpDecode64()' - Base64-decode a string. */char * /* O - Decoded string */httpDecode64(char *out, /* I - String to write to */ const char *in) /* I - String to read from */{ int outlen; /* Output buffer length */ /* * Use the old maximum buffer size for binary compatibility... */ outlen = 512; return (httpDecode64_2(out, &outlen, in));}/* * 'httpDecode64_2()' - Base64-decode a string. */char * /* O - Decoded string */httpDecode64_2(char *out, /* I - String to write to */ int *outlen, /* IO - Size of output string */ const char *in) /* I - String to read from */{ int pos, /* Bit position */ base64; /* Value of this character */ char *outptr, /* Output pointer */ *outend; /* End of output buffer */ /* * Range check input... */ if (!out || !outlen || *outlen < 1 || !in || !*in) return (NULL); /* * Convert from base-64 to bytes... */ for (outptr = out, outend = out + *outlen - 1, pos = 0; *in != '\0'; in ++) { /* * Decode this character into a number from 0 to 63... */ if (*in >= 'A' && *in <= 'Z') base64 = *in - 'A'; else if (*in >= 'a' && *in <= 'z') base64 = *in - 'a' + 26; else if (*in >= '0' && *in <= '9') base64 = *in - '0' + 52; else if (*in == '+') base64 = 62; else if (*in == '/') base64 = 63; else if (*in == '=') break; else continue; /* * Store the result in the appropriate chars... */ switch (pos) { case 0 : if (outptr < outend) *outptr = base64 << 2; pos ++; break; case 1 : if (outptr < outend) *outptr++ |= (base64 >> 4) & 3; if (outptr < outend) *outptr = (base64 << 4) & 255; pos ++; break; case 2 : if (outptr < outend) *outptr++ |= (base64 >> 2) & 15; if (outptr < outend) *outptr = (base64 << 6) & 255; pos ++; break; case 3 : if (outptr < outend) *outptr++ |= base64; pos = 0; break; } } *outptr = '\0'; /* * Return the decoded string and size... */ *outlen = (int)(outptr - out); return (out);}/* * 'httpEncode64()' - Base64-encode a string. */char * /* O - Encoded string */httpEncode64(char *out, /* I - String to write to */ const char *in) /* I - String to read from */{ return (httpEncode64_2(out, 512, in, strlen(in)));}/* * 'httpEncode64_2()' - Base64-encode a string. */char * /* O - Encoded string */httpEncode64_2(char *out, /* I - String to write to */ int outlen, /* I - Size of output string */ const char *in, /* I - String to read from */ int inlen) /* I - Size of input string */{ char *outptr, /* Output pointer */ *outend; /* End of output buffer */ static const char base64[] = /* Base64 characters... */ { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "+/" }; /* * Range check input... */ if (!out || outlen < 1 || !in || inlen < 1) return (NULL); /* * Convert bytes to base-64... */ for (outptr = out, outend = out + outlen - 1; inlen > 0; in ++, inlen --) { /* * Encode the up to 3 characters as 4 Base64 numbers... */ if (outptr < outend) *outptr ++ = base64[(in[0] & 255) >> 2]; if (outptr < outend) *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63]; in ++; inlen --; if (inlen <= 0) { if (outptr < outend) *outptr ++ = '='; if (outptr < outend) *outptr ++ = '='; break; } if (outptr < outend) *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63]; in ++; inlen --; if (inlen <= 0) { if (outptr < outend) *outptr ++ = '='; break; } if (outptr < outend) *outptr ++ = base64[in[0] & 63]; } *outptr = '\0'; /* * Return the encoded string... */ return (out);}/* * 'httpGetLength()' - Get the amount of data remaining from the * content-length or transfer-encoding fields. */int /* O - Content length */httpGetLength(http_t *http) /* I - HTTP data */{ DEBUG_printf(("httpGetLength(http=%p), state=%d\n", http, http->state));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -