⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minihttp.c

📁 安全开发库。含客户端建立ssl连接、签名、证书验证、证书发布和撤销等。编译用到nss
💻 C
📖 第 1 页 / 共 5 页
字号:
        numbytes = PR_Read(fl, buf, 256);        if (numbytes <= 0)            break; /* done reading */        frv = PR_Write(req->sock, buf, numbytes);        PR_ASSERT(numbytes == frv);    }    if (numbytes == 0)        rv = SSM_SUCCESS; done:    if (fl)        PR_Close(fl);    if (path)        PR_Free(path);    return rv;}/* Based on the file requested, do some function within PSM.   ### mwelch This NEEDS to be changed to use a string-keyed hash table,              so that people adding code can add their own functionality              independently of this module. */static SSMStatushttp_dispatch(HTTPRequest *req){    SSMStatus rv = SSM_SUCCESS;    SSMCommandHandlerFunc handlerFunc = NULL;    /* Look up the command handler in the registry. */    rv = SSM_HTTPFindCommandHandler(req->handlerName, &handlerFunc);    if (rv != SSM_SUCCESS)    {        SSM_HTTPReportSpecificError(req, "Could not find handler for command '%s' (error %d).", req->handlerName, rv);    }    if (!handlerFunc)    {        /* Attempt to fetch a file from the doc directory. */        rv = http_spool_file(req);        if (rv != SSM_SUCCESS)            handlerFunc = SSM_HTTPDefaultCommandHandler; /* fallback */        else            req->sentResponse = PR_TRUE;    }    if (handlerFunc)        rv = (*handlerFunc)(req);    return rv;}static voidhttp_find_target(HTTPRequest *req){    SSMResource *target = NULL;    char *targetID = NULL;    SSMStatus rv;    /* Attempt to find a target resource. If one is not available, use       the authenticated control connection. */    rv = SSM_HTTPParamValue(req, "target", &targetID);    if (rv == SSM_SUCCESS){        rv = SSM_RIDTextToResource(req, targetID, &target);    } else if (req->referer != NULL){        /* See if the referer had a target.  If it did, then use it's         * target as this request's target.         */        char *refTarget = strstr(req->referer, "target");        if (refTarget != NULL) {            refTarget = strchr(refTarget, '=');            if (refTarget != NULL) {                char ridText[20];                char *nextParam;                                refTarget++;                nextParam = strchr(refTarget, '&');                if (nextParam != NULL) {                    memcpy(ridText, refTarget, nextParam-refTarget);                    ridText[nextParam-refTarget] = '\0';                } else {                    memcpy(ridText, refTarget, strlen(refTarget)+1);                }                SSM_RIDTextToResource(req, ridText, &target);            }        }    }    /*     * SSM_RIDTextToResource gets a reference for us, so there's no     * need to get another one here.     */    req->target = target;}/* Take care of an incoming request. */static voidhttp_handle_request(void *arg){    SSMStatus rv = SSM_SUCCESS;    HTTPRequest *req;    PRFileDesc *sock = (PRFileDesc *) arg;    char *name = NULL;    SSM_RegisterThread("http server", NULL);    SSM_DEBUG("Responding to request.\n");    /* Read in the request. */    if ((rv = http_read_request(sock, &req)) != SSM_SUCCESS)         goto loser;#ifdef DEBUG    name = PR_smprintf("http server %lx", (long) req);    if (name)        SSM_RegisterThread(name, NULL);#endif    /* Parse the buffer, get interesting bits */    if ((rv = http_parse_request(req)) != SSM_SUCCESS)         goto loser;    /* Attempt to authenticate the connection. */    if ((rv = http_authenticate(req)) != SSM_SUCCESS)         goto loser;    /* Find the target object, if one has been explicitly specified. */    http_find_target(req);#ifdef XP_MAC	/* Test pattern for now. */	rv = SSM_HTTPSendUTF8String(req, "Hi, I got all of your request.\r\n");	rv = SSM_HTTPSendUTF8String(req, req->rawreqbuf);	goto done;#endif    /* Do the right thing depending on what has been requested. */    if ((rv = http_dispatch(req)) != SSM_SUCCESS)         goto loser;    goto done; loser:    if (rv == SSM_SUCCESS) rv = SSM_FAILURE;done:    if (req && !req->sentResponse)    {        /* An error occurred along the way. Send the appropriate           error response, or an internal server error if nothing           was set along the way. */        if (req->httprv <= HTTP_OK)            req->httprv = HTTP_NOT_IMPLEMENTED;        SSM_HTTPReportError(req, req->httprv);    }    if (req)         http_request_destroy(req);    else        SSM_DEBUG("Would destroy request, but it doesn't exist!\n");    SSM_DEBUG("Closing, status %ld.\n", rv);#ifdef DEBUG    PR_Free(name);#endif    }/* SSM_HTTPThread listens to the HTTP socket for connections from   one or more clients. (arg) should be an open socket (PRFileDesc*),   therefore the port needs to have been created before being passed    to this thread. */void SSM_HTTPThread(void *arg){    PRFileDesc *listenSock = (PRFileDesc *) arg;    PRFileDesc *acceptSock = NULL;    PRNetAddr clientaddr;    PRBool alive = PR_TRUE;    SSMStatus rv = SSM_SUCCESS;        SSM_RegisterThread("http listener", NULL);    /* Wait for connections. */    while(alive)    {        SSM_DEBUG("Ready for connection on port %ld.\n", (long) httpListenPort);        acceptSock = PR_Accept(listenSock, &clientaddr,                                PR_INTERVAL_NO_TIMEOUT);        if (acceptSock)        {            PRThread *handler;            handler = PR_CreateThread(PR_USER_THREAD,                                      http_handle_request,                                      (void *)acceptSock,                                      PR_PRIORITY_NORMAL,                                      PR_LOCAL_THREAD,                                      PR_UNJOINABLE_THREAD, 0);            if (!handler)            {                SSM_DEBUG("Couldn't create handler for new socket %p.",                          acceptSock);                alive = PR_FALSE;            }        }        else            alive = PR_FALSE;    }    rv = PR_GetError();    /* Close down in an orderly fashion. */#ifdef DEBUG    SSM_DEBUG("http: ** Closing, status = %d **\n", rv);#endif    }SSMStatusSSM_HTTPSendUTF8String(HTTPRequest *req, char *str){    PRInt32 len;    PRInt32 numSent;    SSMStatus rv = SSM_FAILURE;    /* Extract the text from the Unicode string and send it. */    if (str)    {        len = (PRInt32)PL_strlen(str);                numSent = PR_Send(req->sock, str, len, 0,                           PR_INTERVAL_NO_TIMEOUT);        if (numSent == len)            rv = SSM_SUCCESS;        else {            SSM_DEBUG("Error %d trying to send unicode string.\n",                       PR_GetError());        }    }    return rv;}SSMStatusSSM_RIDTextToResource(HTTPRequest *req, const char *ridText,                      SSMResource **res){    SSMResourceID rid = 0;    SSMStatus rv = PR_FAILURE;    *res = NULL; /* in case we fail */    /* scan the text for a number. */    PR_sscanf(ridText, "%ld", &rid);    /* search for the resource in the authenticated control connection. */    if (req->ctrlconn) {        rv = SSMControlConnection_GetResource(req->ctrlconn, rid, res);    } else {        SSMControlConnection *ctrl;        rv = SSM_GetControlConnection(rid, &ctrl);        *res = &ctrl->super.super;    }    return ((SSMStatus) rv);}SSMStatusSSM_HTTPReportError(HTTPRequest *req, HTTPErrorCode statusCode){    char key[256];    char *name = NULL, *hdrs = NULL, *desc = NULL;    char *tmpl = NULL, *out = NULL;    char *errmsg = req->errormsg;    char *noSpecificErr = NULL;    SSMStatus rv = SSM_SUCCESS;    SSMTextGenContext *cx=NULL;    if (statusCode == HTTP_OK)        goto done;    rv = SSMTextGen_NewTopLevelContext(req, &cx);    if (rv != SSM_SUCCESS)        goto loser;    /* Grab "http_error_%d_name", "http_error_%d_hdrs", and       "http_error_%d_desc" for the specific text. */    PR_snprintf(key, 256, "http_error_%d_name", statusCode);    rv = SSM_GetAndExpandText(cx, key, &name);    if (rv != SSM_SUCCESS)        goto loser;    if (statusCode != HTTP_NO_CONTENT) {        PR_snprintf(key, 256, "http_error_%d_hdrs", statusCode);        rv = SSM_GetAndExpandText(cx, key, &hdrs);        if (rv != SSM_SUCCESS)            goto loser;        PR_snprintf(key, 256, "http_error_%d_desc", statusCode);        rv = SSM_GetAndExpandText(cx, key, &desc);        if (rv != SSM_SUCCESS)            goto loser;    } else {        desc = "";        hdrs = "";    }    /* Now that we have the strings to insert, get the header template. */    rv = SSM_GetAndExpandText(cx, "http_error_header_template", &tmpl);    if (rv != SSM_SUCCESS)        goto loser;        /* If no specific error message was reported, report generically. */    if (!errmsg)    {        rv = SSM_GetAndExpandText(cx, "http_error_no_spec_err",                                   &noSpecificErr);        if (rv != SSM_SUCCESS) {            errmsg = "";        } else {            errmsg = noSpecificErr;        }    }    out = PR_smprintf(tmpl, (long)statusCode, name, hdrs, desc, errmsg);    /* Send the result string. */    rv = SSM_HTTPSendUTF8String(req, out);    PR_Free(tmpl);    tmpl = NULL; /* So we don't free it twice. */    if (rv != SSM_SUCCESS)        goto loser;    /* Empty the string in preparation for the next part of the page */    SSMTextGen_UTF8StringClear(&out);    if (statusCode != HTTP_NO_CONTENT)    {		        /* Get and send the appropriate description. */        /* Format with the same arguments as before. */        rv = SSM_GetAndExpandText(cx, "http_error_content", &tmpl);        if (rv != SSM_SUCCESS)            goto loser;        out = PR_smprintf(tmpl, statusCode, name, hdrs, desc, errmsg);        rv = SSM_HTTPSendUTF8String(req, out);        if (rv != SSM_SUCCESS)            goto loser;    }    req->sentResponse = PR_TRUE;     goto done; loser:    if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done:    PR_FREEIF(name);    if (statusCode != HTTP_NO_CONTENT) {        PR_FREEIF(desc);        PR_FREEIF(hdrs);    }    PR_FREEIF(tmpl);    PR_FREEIF(noSpecificErr);    PR_FREEIF(out);    if (cx != NULL) {        SSMTextGen_DestroyContext(cx);    }    return rv;}SSMStatusSSM_HTTPSendOKHeader(HTTPRequest *req,                      char *addtlHeaders,                     char *contentType){    char *tmpl = NULL, *out = NULL;    char *hdrs = addtlHeaders, *type = contentType;    SSMStatus rv = SSM_SUCCESS;    SSMTextGenContext *cx;    req->httprv = HTTP_OK;    /* Create a textgen context so that we can process the templates. */    rv = SSMTextGen_NewTopLevelContext(req, &cx);    if (rv != SSM_SUCCESS)        goto loser;    /* Get the header template. */    rv = SSM_GetAndExpandText(cx, "http_header_template", &tmpl);    if (rv != SSM_SUCCESS)        goto loser;    /* prevent null headers from interfering with content-type header */    if (hdrs == NULL)        hdrs = "";    if (type == NULL)        type = "text/html";    out = PR_smprintf(tmpl, hdrs, type);    /* Send the result string. */    rv = SSM_HTTPSendUTF8String(req, out);    goto done; loser:    if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done:    if (tmpl)        PR_Free(tmpl);    if (out)        PR_Free(out);    if (cx)        SSMTextGen_DestroyContext(cx);    return rv;}/*      Simple Hello World command handler. I've deliberately left Unicode    out of this example, in order to illustrate the use of command    handlers in isolation.        Most of the time, you will not even need to explicitly send anything    out on the HTTP connection. Most of the time, you will probably     want to write simple handlers that perform specific actions inside     PSM (such as making changes to the cert/key db, performing     some operation such as form signing, etc), then sending back a     generic response by calling SSM_HTTPDefaultCommandHandler. This should    even be true for special content that you construct programmatically,    such as cert lists; this is because you will want to write keyword    handlers (see nlsutil.[ch]) to perform such processing inline.        See SSM_HTTPMonitorResourceHandler for an example of the kind of    handler you will typically want to write. (I've tried to comment    that routine extensively so that you will get an idea of what    it is doing.)  */SSMStatusSSM_HTTPHelloWorld(HTTPRequest *req){    size_t sent;    char outbuf[256];    /*        Send HTTP headers first. req->sock is an NSPR socket on which       we send back the response. Note: Normally you would not send       things back down the raw socket. If you want to send something

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -