📄 http.c
字号:
read->last = chunk; if (read->first == NULL) read->first = chunk; read->len = 0; } readLen = readFileOs(info->sockId, &read->last->data[read->len], CHUNK_SIZE - read->len); if (readLen < 0) { error("cannot read from network connection\n"); return -1; } debug(DEBUG_CONNECTION, "read %d bytes from connection\n", readLen); if (readLen == 0) return 0; read->len += readLen; read->cont += readLen; }}void writeBuff(struct inOutBuff *write, const unsigned char *data, int dataLen){ int writeLen; struct chunk *chunk; while (dataLen > 0) { if (write->last == NULL || write->len == CHUNK_SIZE) { chunk = allocMem(sizeof (struct chunk)); chunk->next = NULL; if (write->last != NULL) write->last->next = chunk; write->last = chunk; if (write->first == NULL) write->first = chunk; write->len = 0; } writeLen = CHUNK_SIZE - write->len; if (dataLen < writeLen) writeLen = dataLen; memcpy(&write->last->data[write->len], data, writeLen); write->len += writeLen; write->cont += writeLen; dataLen -= writeLen; data += writeLen; }}static int lineLength(const struct inOutBuff *read){ struct chunk *chunk; int idx, len, off; int count; count = 0; for (chunk = read->first; chunk != NULL; chunk = chunk->next) { len = (chunk == read->last) ? read->len : CHUNK_SIZE; off = (chunk == read->first) ? read->off : 0; for (idx = off; idx < len; idx++) { count++; if (chunk->data[idx] == 10) return count; } } return -1;}static int readBuff(struct inOutBuff *read, unsigned char *data, int dataLen){ int readLen; struct chunk *chunk; int len; while (dataLen > 0) { if (read->first == NULL) return -1; len = (read->first == read->last) ? read->len : CHUNK_SIZE; readLen = len - read->off; if (dataLen < readLen) readLen = dataLen; memcpy(data, &read->first->data[read->off], readLen); read->off += readLen; read->cont -= readLen; dataLen -= readLen; data += readLen; if (read->off == len) { chunk = read->first; read->first = chunk->next; if (read->first == NULL) read->last = NULL; freeMem(chunk); read->off = 0; } } return 0;}static int writeConn(struct connInfo *info){ struct inOutBuff *write = &info->write[info->which]; int writeLen; struct chunk *chunk; int len; for (;;) { if (write->first == NULL) return 0; len = (write->first == write->last) ? write->len : CHUNK_SIZE; writeLen = writeFileOs(info->sockId, &write->first->data[write->off], len - write->off); if (writeLen < 0) { error("cannot write to network connection\n"); return -1; } debug(DEBUG_CONNECTION, "wrote %d bytes to connection\n", writeLen); if (writeLen == 0) return 0; write->off += writeLen; write->cont -= writeLen; if (write->off == len) { chunk = write->first; write->first = chunk->next; if (write->first == NULL) write->last = NULL; freeMem(chunk); write->off = 0; } }}static char *getToken(char **point){ char *localPoint = *point; char *start; while (*localPoint == 9 || *localPoint == 32) localPoint++; start = localPoint; while (*localPoint != 9 && *localPoint != 32 && *localPoint != 0) localPoint++; if (localPoint == start) return NULL; if (*localPoint != 0) *localPoint++ = 0; *point = localPoint; return start;}static void writeBuffString(struct inOutBuff *write, const char *string){ writeBuff(write, (unsigned char *)string, strlen(string));}static int cookieToSession(unsigned int *sessId, char *cookie){ unsigned char mac1[16]; unsigned char mac2[16]; debug(DEBUG_SESSION, "cookie = %s\n", cookie); if (decHexString((unsigned char *)&cookieStruct.sessId, cookie, 4) < 0) { debug(DEBUG_SESSION, "cannot decode session id\n"); return -1; } if (decHexString(mac1, cookie + 8, 16) < 0) { debug(DEBUG_SESSION, "cannot decode authenticator\n"); return -1; } memset(mac2, 0, 16); rc4(mac2, 16, (unsigned char *)&cookieStruct, sizeof (cookieStruct)); if (memcmp(mac1, mac2, 16) != 0) { debug(DEBUG_SESSION, "invalid authenticator\n"); return -1; } *sessId = cookieStruct.sessId; debug(DEBUG_SESSION, "session id = %u\n", *sessId); return 0;}static char *sessionToCookie(unsigned int sessId){ unsigned char mac[16]; static char buff[41]; debug(DEBUG_SESSION, "session id = %u\n", sessId); cookieStruct.sessId = sessId; memset(mac, 0, 16); rc4(mac, 16, (unsigned char *)&cookieStruct, sizeof (cookieStruct)); encHexString(buff, (unsigned char *)&cookieStruct.sessId, 4); encHexString(buff + 8, mac, 16); debug(DEBUG_SESSION, "cookie = %s\n", buff); return buff;}static void writeBuffInt(struct inOutBuff *write, unsigned int val){ char buff[10]; writeBuffString(write, intToString(buff, val));}static void printBuff(struct inOutBuff *buff, const char *form, ...){ int i = 0; int start = 0; char *strVal; int intVal; va_list args; va_start(args, form); for (;;) { start = i; while (form[i] != '%' && form[i] != 0) i++; if (i > start) writeBuff(buff, (unsigned char *)(form + start), i - start); if (form[i] == 0) break; if (form[i + 1] == '%') writeBuff(buff, (unsigned char *)"%", 1); else if (form[i + 1] == 's') { strVal = va_arg(args, char *); writeBuffString(buff, strVal); } else if (form[i + 1] == 'd') { intVal = va_arg(args, int); writeBuffInt(buff, intVal); } i += 2; } va_end(args);}static char *errNoToErrStr(int errNo){ switch (errNo) { case 200: return "OK"; case 400: return "Bad Request"; case 401: return "Unauthorized"; case 404: return "Not Found"; case 500: return "Internal Server Error"; case 501: return "Not Implemented"; case 505: return "HTTP Version Not Supported"; default: return "For No Reason"; }}static int writeHeaders(struct connInfo *info, int errNo){ printBuff(&info->write[0], "HTTP/1.1 %d %s\r\n", errNo, errNoToErrStr(errNo)); printBuff(&info->write[0], "Server: TAS/0.1\r\n"); if (info->contType != NULL) printBuff(&info->write[0], "Content-Type: %s\r\n", info->contType); if (info->contLen >= 0) printBuff(&info->write[0], "Content-Length: %d\r\n", info->contLen); if (info->newSess != NULL) printBuff(&info->write[0], "Set-Cookie: %s\r\n", sessionToCookie(info->newSess->id)); if (errNo == 401) printBuff(&info->write[0], "WWW-Authenticate: Basic realm=\"TAS\"\r\n"); printBuff(&info->write[0], "Accept-Ranges: none\r\n"); printBuff(&info->write[0], "Connection: close\r\n"); printBuff(&info->write[0], "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n"); printBuff(&info->write[0], "Cache-Control: no-cache\r\n"); printBuff(&info->write[0], "Pragma: No-cache\r\n"); printBuff(&info->write[1], "\r\n"); return 0;}static void writeErrorMsg(struct connInfo *info, int errNo, char *errMsg){ if (info->verb == NULL || strcmp(info->verb, "HEAD") != 0) { printBuff(&info->write[2], "<html>\r\n"); printBuff(&info->write[2], "<head><title>Error %d: %s</title></head>\r\n", errNo, errNoToErrStr(errNo)); printBuff(&info->write[2], "<body>Error %d: %s (%s)</body>\r\n", errNo, errNoToErrStr(errNo), (errMsg == NULL) ? "Unknown Reason" : errMsg); printBuff(&info->write[2], "</html>\r\n"); info->contLen = info->write[2].cont; } writeHeaders(info, errNo); info->state = STATE_DRAIN;}static void writeError(struct connInfo *info, int errNo){ writeErrorMsg(info, errNo, NULL);}static void toLower(char *string){ while (*string != 0) { if (*string >= 'A' && *string <= 'Z') *string += 32; string++; }}static void unescape(char *string){ int i, k, val; debug(DEBUG_REQUEST | DEBUG_LUA, "unescaped string = %s\n", string); k = 0; for (i = 0; string[i] != 0; i++) { if (string[i] == '%' && string[i + 1] != 0 && string[i + 2] != 0) { val = 0; if (addHexDigit(&val, string[i + 1]) >= 0 && addHexDigit(&val, string[i + 2]) >= 0) { string[k++] = (char)val; i += 2; continue; } } string[k++] = string[i]; } string[k] = 0; debug(DEBUG_REQUEST | DEBUG_LUA, "escaped string = %s\n", string);}static int serviceConn(struct connInfo *info){ int i, k, len, len2; char *line, *tmp, *tmp2; struct httpHeader *head; unsigned char fileBuff[8192]; char **argList; char *errMsg; unsigned int sessId; struct sessInfo *currSess; int pub; switch (info->state) { case STATE_REQUEST: debug(DEBUG_CONNECTION, "connection state is STATE_REQUEST\n"); len = lineLength(&info->read); if (len <= 0) return 0; line = allocBuff(info, len); readBuff(&info->read, (unsigned char *)line, len); chomp(line, len); debug(DEBUG_REQUEST, "request line is '%s'\n", line); info->verb = getToken(&line); tmp = getToken(&line); info->proto = getToken(&line); debug(DEBUG_REQUEST, "verb = %s, uri = %s, protocol = %s\n", (info->verb == NULL) ? "none" : info->verb, (tmp == NULL) ? "none" : tmp, (info->proto == NULL) ? "none" : info->proto); if (info->verb == NULL || tmp == NULL || info->proto == NULL) { error("request without verb (%s), URI (%s), or protocol (%s)\n", (info->verb == NULL) ? "none" : info->verb, (tmp == NULL) ? "none" : tmp, (info->proto == NULL) ? "none" : info->proto); writeError(info, 400); return 0; } if (strcmp(info->verb, "GET") != 0 && strcmp(info->verb, "HEAD") != 0) { error("unsupported verb: %s\n", info->verb); writeError(info, 501); return 0; } if (strcmp(info->proto, "HTTP/1.1") != 0) { error("unsupported protocol version: %s\n", info->proto); writeError(info, 505); return 0; } if (strncmp(tmp, "http://", 7) == 0) { tmp += 7; info->host = tmp; while (*tmp != ':' && *tmp != '/' && *tmp != 0) tmp++; if (*tmp == 0) { error("URI host part does not end in ':' or '/'\n"); writeError(info, 400); return 0; } if (*tmp == ':') { *tmp++ = 0; while (*tmp != '/' && *tmp != 0) tmp++; if (*tmp == 0) { error("URI port part does not end in '/'\n"); writeError(info, 400); return 0; } tmp++; } else *tmp++ = 0; debug(DEBUG_REQUEST, "host = %s\n", info->host); info->path = tmp; } else if (tmp[0] == '/') info->path = ++tmp; else { error("URI path part is not an absolute path\n"); writeError(info, 400); return 0; } while (*tmp != '?' && *tmp != 0) { if (tmp[0] == '.' && tmp[1] == '.') { error("URI path part contains '..'\n"); writeError(info, 400); return 0; } tmp++; } if (*tmp == '?') { *tmp++ = 0; info->para = tmp; } debug(DEBUG_REQUEST, "path = %s, parameters = %s\n", info->path, (info->para == NULL) ? "none" : info->para); info->state = STATE_HEADERS; return 0; case STATE_HEADERS: debug(DEBUG_CONNECTION, "connection state is STATE_HEADERS\n"); len = lineLength(&info->read); if (len <= 0) return 0; line = allocBuff(info, len); readBuff(&info->read, (unsigned char *)line, len); chomp(line, len); debug(DEBUG_REQUEST, "header line is '%s'\n", line); if (*line == 0) { if (info->host == NULL) for (head = info->firstHead; head != NULL; head = head->next) if (strcmp(head->name, "host") == 0) info->host = head->value; debug(DEBUG_REQUEST, "last header line, host = %s\n", (info->host == NULL) ? "none" : info->host); info->state = STATE_RESPONSE; return 0; } if (*line == 9 || *line == 32) { debug(DEBUG_REQUEST, "continued header line\n"); if (info->lastHead == NULL) { error("no previous header to continue\n"); writeError(info, 400); return 0; } len2 = strlen(info->lastHead->value); tmp = allocBuff(info, len2 + len); memcpy(tmp, info->lastHead->value, len2); memcpy(tmp + len2, line, len); info->lastHead->value = tmp; debug(DEBUG_REQUEST, "updated header, name = %s, value = '%s'\n", info->lastHead->name, info->lastHead->value); } else { tmp = getToken(&line); if (tmp == NULL) { error("header without name\n"); writeError(info, 400); return 0; } for (i = 0; tmp[i] != ':' && tmp[i] != 0; i++); if (tmp[i] != ':' || tmp[i + 1] != 0) { error("header name does not end in ':'\n"); writeError(info, 400); return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -