📄 minihttp.c
字号:
{ SSMStatus rv = SSM_SUCCESS; char *c, d, *start; PRInt32 numParams, i; numParams = httpparse_count_params(req); req->paramNames = (char **) PR_Calloc(numParams+1, sizeof(char *)); if (!req->paramNames) goto loser; req->paramValues = (char **) PR_Calloc(numParams+1, sizeof(char *)); if (!req->paramValues) goto loser; httpparse_unescape_param(req->params); /* Put the params in their place. */ for(i=0, c = start = req->params; i < numParams; i++) { /* Get the parameter name. */ while((*c) && (*c != '=') && (*c != '&')) c++; req->paramNames[i] = start; /* name goes here */ if (*c == '\0') { /* reached end of params while looking for a name. leave the value null, end. */ break; } /* save off the delimiter so that we can decide how to proceed */ d = *c; /* null out the delimiter so that the param name is usable */ *c++ = '\0'; start = c; if (d == '&') /* found a name but no value. leave value null, loop back. */ continue; /* Now, copy the value. */ req->paramValues[i] = start; /* If we have more params to process, tie off the end of this parameter value. */ if (i != (numParams-1)) { while((*c) && (*c != '&')) /* (*c) check just to be safe */ { if (*c == '~') *c = '&'; c++; } *c++ = '\0'; start = c; /* get ready to mark off next parameter */ } } goto done; loser: PR_FREEIF(req->paramNames); PR_FREEIF(req->paramValues); done: return rv;}/* Parse an incoming request. */static SSMStatushttp_parse_request(HTTPRequest *req){ char *line, *chunk = req->reqbuf; char *b, *e; /* beginning and end of something we want */ char *p; /* beginning of params */ SECItem tmpItem = {siBuffer, NULL, 0}; while ((line = nextLine(&chunk)) != NULL) { /* Is it a request we're interested in? */ if (!STRNCASECMP(line, "GET ", 4)) { SSM_DEBUG("Parsing GET request: `%s'\n", line); /* Parse the GET request. */ b = strchr(line, ' '); e = strrchr(line, ' '); if (!b) SSM_DEBUG("Couldn't find beginning of file!"); if (!e) SSM_DEBUG("Couldn't find end of file!"); if ((!b) || (!e)) continue; while ((IS_WHITESPACE(*b)) && (b < e)) b++; while ((IS_WHITESPACE(*e)) && (b < e)) e--; e++; *e = '\0'; if (*b == '/') b++; /* move past the first slash */ req->handlerName = b; /* this is the command handler */ SSM_DEBUG("Base ref: `%s'.\n", req->handlerName); p = strchr(b, '?'); if (p) { *p++ = '\0'; req->params = p; SSM_DEBUG("Params: `%s'.\n", req->params ? req->params : "(none)"); httpparse_parse_params(req); } continue; } /* If we get here, then we assume we have a header with a colon in it (i.e. a header line other than the GET). We're interested in anything after the colon. */ b = strchr(line, ':'); if (!b) /* Dunno what to do, ignore this line */ continue; do { b++; } while (IS_WHITESPACE(*b)); if (!STRNCASECMP(line, "User-Agent", 10)) { SSM_DEBUG("Found User-Agent: `%s'.\n", b); req->agent = b; } else if (!STRNCASECMP(line, "Accept-Language", 15)) { SSM_DEBUG("Found Accept-Language: `%s'.\n", b); req->language = b; /* REMOVED CALL */; } else if (!STRNCASECMP(line, "Accept-Charset", 14)) { SSM_DEBUG("Found Accept-Charset: `%s'.\n", b); req->charset = b; /* REMOVED CALL */; } else if (!STRNCASECMP(line, "Referer", 7)) { /* Make the new request inherit the same target as * its referer */ req->referer = b; } else if (!STRNCASECMP(line, "Authorization", 13)) { SECStatus srv; SSM_DEBUG("Found Authorization: `%s'.\n", b); /* If the auth type is basic, process the auth info. */ if (!STRNCASECMP(b, "Basic", 5)) { PRIntn len; /* move to the auth info itself */ while ((*b) && (!IS_WHITESPACE(*b))) b++; while ((*b) && (IS_WHITESPACE(*b))) b++; /* decode base-64. */ srv = ATOB_ConvertAsciiToItem(&tmpItem, b); if (srv == SECSuccess) { /* We need to copy the ascii over and NULL * terminate it correctly becuase the * Base64 decoder doesn't guarantee that. */ char *w = (char *) PR_Malloc(tmpItem.len+1); PL_strncpy(w, (char *) tmpItem.data, tmpItem.len); w[tmpItem.len] = '\0'; SSM_DEBUG("Decoded auth: '%s'.\n", w); PR_Free(tmpItem.data); tmpItem.data = (unsigned char *) w; len = tmpItem.len; /* divide control RID (username) and nonce (password). ### mwelch - I walk manually through this because the string isn't null-terminated. */ while((len > 0) && (*w != ':')) { w++; len--; } if (len > 0) { PRIntn ridLen = tmpItem.len-len; req->ctrlrid = (char *) PR_CALLOC(ridLen+1); req->password = (char *) PR_CALLOC(len+1); if (req->ctrlrid) { strncpy(req->ctrlrid, (char *) tmpItem.data, (unsigned long) ridLen); SSM_DEBUG("ctrlrid: %s\n", req->ctrlrid); } else SSM_DEBUG("Couldn't allocate a ctrlrid.\n"); if (req->password) { /* Skip over the colon separating rid and nonce. */ strncpy(req->password, ++w, --len); SSM_DEBUG("password: %s\n", req->password); } else SSM_DEBUG("Couldn't allocate a password.\n"); } else SSM_DEBUG("Couldn't find ':' in between ctrlrid and password.\n"); SECITEM_FreeItem(&tmpItem, PR_FALSE); } else SSM_DEBUG("srv %ld decoding basic auth info.\n", (long) srv); } else SSM_HTTPReportError(req, HTTP_UNAUTHORIZED); } } return SSM_SUCCESS;}/* Read an HTTP request. */SSMStatushttp_read_request(PRFileDesc *sock, HTTPRequest **returnReq){ PRIntn read; PRBool detectEOR = PR_FALSE; /* Have we detected the end of the request? */ char buf[LINESIZE]; SSMStatus rv = SSM_SUCCESS; PRUint32 tail; HTTPRequest *req = NULL; if (!sock || !returnReq) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } /* Set up the request object. */ req = http_request_create(sock); if (!req) goto loser; /* Get the request in chunks. */ while(!detectEOR) { PR_SetError(0, 0); /* reset so that error detect below works */ read = PR_Recv(sock, buf, LINESIZE, 0, PR_INTERVAL_NO_TIMEOUT); if (read <= 0) { rv = PR_GetError(); if (rv == PR_SUCCESS) rv = PR_GetOSError(); goto loser; } /* Add the latest bits onto the end of the request */ rv = http_request_add_chunk(req, buf, read); if (rv != SSM_SUCCESS) goto loser; /* Look for LF+LF, CR+CR, CR+LF+CR+LF, or (heh) LF+CR+LF+CR. If we find any of these, it means that we have the end of request. */ (void) memcpy((char *) &tail, &(req->reqbuf[req->slen-4]), 4); /* Do the four-byte comparisons first, they're easier and more common */ if ((tail == 0x0d0a0d0a) || (tail == 0x0a0d0a0d)) detectEOR = PR_TRUE; else { /* Look for CR+CR or LF+LF. */ tail &= 0x0000FFFF; if ((tail == 0x00000d0d) || (tail == 0x00000a0a)) detectEOR = PR_TRUE; } } /* duplicate the buffer, use one copy for parsing */ req->rawreqbuf = (char *) PR_CALLOC(req->slen+1); if (!req->rawreqbuf) goto loser; (void) memcpy(req->rawreqbuf, req->reqbuf, req->slen+1); goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done: if (returnReq) *returnReq = req; return rv;}SSMStatusSSM_HTTPParamValue(HTTPRequest *req, const char *key, char **value){ PRUint32 i; SSMStatus rv = SSM_FAILURE; if (!value) return rv; *value = NULL; /* in case we fail */ for(i=0; i < req->numParams; i++) { if (req->paramNames[i] && (!PL_strcmp(req->paramNames[i], key))) { *value = req->paramValues[i]; rv = SSM_SUCCESS; break; } } if (rv != SSM_SUCCESS) SSM_DEBUG("HTTPParamValue: Error %d attempting to get parameter '%s'.\n" , rv, key); return rv;}static SSMStatushttp_authenticate(HTTPRequest *req){ SSMStatus rv = SSM_FAILURE; SSMResource *res; SSMControlConnection *ctrlconn = NULL;#ifdef ALLOW_STANDALONE if (standalone) { PR_ASSERT(standalone_conn); req->ctrlconn = standalone_conn; SSM_DEBUG("authenticate: Standalone mode, passing through.\n"); return SSM_SUCCESS; }#endif /* do we have auth information? */ if ((req->ctrlrid) && (req->password)) { /* Get the control connection object. */ rv = SSM_RIDTextToResource(req, req->ctrlrid, &res); if (rv == SSM_SUCCESS) { ctrlconn = (SSMControlConnection *) res; req->ctrlconn = ctrlconn; /* Verify restype and nonce. */ if ((!SSM_IsAKindOf(res, SSM_RESTYPE_CONTROL_CONNECTION)) || (PL_strcmp(req->password, ctrlconn->m_nonce))) { SSM_DEBUG("------------------------------\n"); SSM_DEBUG("Password doesn't match nonce.\n"); SSM_DEBUG("Nonce: %s\n", ctrlconn->m_nonce); SSM_DEBUG("Submitted password: %s\n", req->password); SSM_DEBUG("------------------------------\n"); PR_ASSERT(!"Couldn't authenticate this connection\n"); rv = SSM_FAILURE; } } else SSM_DEBUG("authenticate: Couldn't find a control connection.\n"); } else { if (!req->ctrlrid) SSM_DEBUG("authenticate: No ctrlrid available.\n"); else if (!req->password) SSM_DEBUG("authenticate: No password available.\n"); } if (rv != SSM_SUCCESS) req->httprv = HTTP_UNAUTHORIZED; else req->ctrlconn = ctrlconn; /* type must check out */ return rv;}/* Returns the suffix of the filename, if it exists. */char *http_find_suffix(HTTPRequest *req){ char *result = NULL; char *c; c = req->filename; if (!c) return result; while(*c && (*c != '.')) c++; if (*c) result = ++c; else result = NULL; return result;}static SSMStatushttp_spool_file(HTTPRequest *req){ SSMStatus rv = SSM_FAILURE; char *path = NULL; PRFileDesc *fl = NULL; char *type; char buf[256]; PRInt32 numbytes; path = PR_smprintf("%s%s", PSM_DOC_DIR, req->handlerName); if (!path) { rv = PR_GetError(); goto done; } fl = PR_Open(path, PR_RDONLY, 0); if (!fl) { rv = PR_GetError(); goto done; } /* We have the file open. Send the file type. */ if (PL_strstr(path, ".gif") || PL_strstr(path, ".GIF")) type = "image/gif"; else type = "text/html"; rv = SSM_HTTPSendOKHeader(req, "", type); /* Send its contents back to the user. */ while(1) { PRInt32 frv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -