📄 minihttp.c
字号:
other than a canned HTML page, there are convenience routines that you'll use to send Unicode strings down the socket, as well as canned generic headers. You'll see that in the NLS Hello World example below. */ PR_snprintf(outbuf, 256, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); sent = PR_Send(req->sock, outbuf, strlen(outbuf), 0, PR_INTERVAL_NO_TIMEOUT); /* Now, send some content down the same socket. */ PR_snprintf(outbuf, 256, "<HTML><HEAD><TITLE>Hello World</TITLE></HEAD>" "<BODY><h1>Hello, world!</h1>" "<p>This is a static string within Personal Security Manager." "</p><br><br><hr>" "</BODY></HTML>"); sent = PR_Send(req->sock, outbuf, strlen(outbuf), 0, PR_INTERVAL_NO_TIMEOUT); /* This next line tells the HTTP dispatcher that we've already sent a response back to the user, so no default response is needed. */ req->sentResponse = PR_TRUE; /* That's it. */ return SSM_SUCCESS;}/* NLS Hello World example. This is about as complex as the "simple" Hello World example shown above. However, this example grabs string resources from the properties file and sends them back to the user.*/SSMStatusSSM_HTTPHelloWorldWithNLS(HTTPRequest *req){ char *type = NULL, *content = NULL; SSMTextGenContext *cx = NULL; SSMStatus rv; /* Grab the "hello_type" string from the properties file. We'll use this when sending the canned HTTP header. The first parameter is a resource object which (when non-NULL) provides parameters for formatting the text. However, we can pass NULL if we know that the text we're extracting doesn't have any NLS formatting parameters inside (numeric params such as {0}, {1}, etc). See psm.properties.in for the definition of the "hello_type" and "hello_content" strings. */ SSM_DEBUG("Getting type string.\n"); rv = SSMTextGen_NewTopLevelContext(req, &cx); if (rv != SSM_SUCCESS) goto loser; rv = SSM_GetUTF8Text(cx, "hello_type", &type); if (rv != SSM_SUCCESS) goto loser; /* Grab the property string containing the content we want ("hello_content"). */ SSM_DEBUG("Getting content string.\n"); rv = SSM_GetUTF8Text(cx, "hello_content", &content); if (rv != SSM_SUCCESS) goto loser; /* Send HTTP headers, using a standard template that I've already hacked up. You pass in the HTTPRequest object, along with the content type and any additional headers you may want to embed. You can pass NULL for the content type or the header parameter. If you pass a NULL content type, "text/html" will be used. */ SSM_DEBUG("Sending OK header.\n"); rv = SSM_HTTPSendOKHeader(req, NULL, type); /* no addt'l headers */ if (rv != SSM_SUCCESS) goto loser; /* Send the content string. I wrote a convenience routine called SSM_SendUTF8String which, given an HTTPRequest and a Unicode string, sends the string in the requested locale. */ SSM_DEBUG("Sending actual content text.\n"); rv = SSM_HTTPSendUTF8String(req, content); /* As in the first example, tell the HTTP dispatcher that we've already sent a response back to the user, so no default response is needed. */ req->sentResponse = PR_TRUE; /* That's it. */ loser: /* Clean up after ourselves. */ PR_FREEIF(type); PR_FREEIF(content); if (cx) SSMTextGen_DestroyContext(cx); SSM_DEBUG("return value is %ld.\n", (long) rv); return rv;}SSMStatusSSM_HTTPGetGenericLump(HTTPRequest *req, PRBool binary){ SSMResource *target; SSMStatus rv = SSM_SUCCESS; char *baseRef; char name[256], *type_ch = NULL; char *type = NULL, *hdrs = NULL, *content = NULL; SSMTextGenContext *cx = NULL; ATOBContext *atobcx = NULL; rv = SSMTextGen_NewTopLevelContext(req, &cx); if (rv != SSM_SUCCESS) { SSM_HTTPReportSpecificError(req, "HTTPGetGenericLump: Error %d attempting to create textgen context.", rv); goto loser; } /* Get target object. */ target = SSMTextGen_GetTargetObject(cx); rv = SSM_HTTPParamValue(req, "baseRef", &baseRef); if (rv != SSM_SUCCESS) { req->httprv = HTTP_BAD_REQUEST; goto loser; } /* Use the baseRef parameter to grab two strings from the property files. */ PR_snprintf(name, 256, "%s_type", baseRef); rv = SSM_GetUTF8Text(cx, name, &type); if (rv != SSM_SUCCESS) goto loser; /* If the content type of this lump is not "text / *", set binary flag true. */ type_ch = type; if (type_ch && strncmp(type_ch, "text", 4)) binary = PR_TRUE; PR_snprintf(name, 256, "%s_hdrs", baseRef); rv = SSM_GetUTF8Text(cx, name, &hdrs); if (rv != SSM_SUCCESS) hdrs = NULL; PR_snprintf(name, 256, "%s_content", baseRef); rv = SSM_GetUTF8Text(cx, name, &content); if (rv != SSM_SUCCESS) goto loser; /* Send headers, followed by content. */ rv = SSM_HTTPSendOKHeader(req, hdrs, type); if (rv != SSM_SUCCESS) goto loser; if (binary) { char *srcbuf, *dstbuf, *o, *i; unsigned int len = PL_strlen(content); unsigned int maxoutlen, outlen; unsigned int inlen, numSent; /* Decode base64 content from the unicode string, then send the binary bits. */ srcbuf = content; dstbuf = (char*) PR_CALLOC(sizeof(char) * len); if (!dstbuf) goto loser; /* decode (srcbuf) into (dstbuf). */ /* REMOVED CALL */; if (!atobcx) goto loser; maxoutlen = inlen = len; o = dstbuf; i = srcbuf; /* REMOVED CALL */; maxoutlen -= outlen; o += outlen; /* REMOVED CALL */; /* after the next line, outlen contains the number of bytes of binary data to be sent out on the connection */ outlen += (len - maxoutlen); numSent = PR_Send(req->sock, dstbuf, outlen, 0, PR_INTERVAL_NO_TIMEOUT); PR_Free(dstbuf); if (numSent != outlen) /* error of some sort */ goto loser; } else { rv = SSM_HTTPSendUTF8String(req, content); if (rv != SSM_SUCCESS) goto loser; } req->sentResponse = PR_TRUE; goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done: PR_FREEIF(type); PR_FREEIF(hdrs); PR_FREEIF(content); if (cx != NULL) { SSMTextGen_DestroyContext(cx); } if (atobcx != NULL) { /* REMOVED CALL */; } return rv;}SSMStatusSSM_HTTPGetBinaryHandler(HTTPRequest *req){ return SSM_HTTPGetGenericLump(req, PR_TRUE);}SSMStatusSSM_HTTPDefaultCommandHandler(HTTPRequest *req){ return SSM_HTTPGetGenericLump(req, PR_FALSE);}SSMStatus SSM_HTTPCloseAndSleep(HTTPRequest* req){ SSMStatus rv = SSM_HTTPGetGenericLump(req, PR_FALSE); /* ### sjlee: this unfortunate hack is due to the fact that bad things * happen if we do not finish closing the window before * another window pops up: this will be supplanted by a * more complete fix later */ PR_Sleep(PR_TicksPerSecond()*1); return rv;}/* Command handler for monitoring resources. This is used by the keygen dialog, where one of the frames causes this handler to run, then after the keygen context is finished processing keygen requests, the dialog is closed by javascript content sent back by this handler.*/SSMStatus SSM_HTTPMonitorResourceHandler(HTTPRequest *req){ SSMResource *target = NULL; SSMStatus rv; /* Get the target resource. */ target = (req->target ? req->target : (SSMResource *) req->ctrlconn); if (target) { /* Get a reference on the target object so that it doesn't get deleted from underneath us. */ SSM_LockResource(target); SSM_GetResourceReference(target); SSM_UnlockResource(target); /* if this is a keygen context, post an urgent open message. */ /* ### mwelch Very hacky. Should make a more specific handler for this. */ if (SSM_IsAKindOf(target, SSM_RESTYPE_KEYGEN_CONTEXT)) { SSMKeyGenContext *ct = (SSMKeyGenContext *) target; if (ct->m_ctxtype == SSM_CRMF_KEYGEN) { SSM_DEBUG("Posting open message on keygen queue.\n"); SSM_SendQMessage(ct->m_incomingQ, SSM_PRIORITY_SHUTDOWN, SSM_DATA_PROVIDER_OPEN, 0, NULL, PR_TRUE); } } /* Now, wait for something/someone to shut down the target object's threads. */ SSM_WaitForResourceShutdown(target); } /* Call the default HTTP handler to send out the requested page. */ rv = SSM_HTTPDefaultCommandHandler(req); /* All done. */ return rv;}/* Handler which shuts down a resource. */SSMStatus SSM_HTTPShutdownResourceHandler(HTTPRequest *req){ SSMResource *target; SSMStatus rv; target = (req->target ? req->target : (SSMResource *) req->ctrlconn); if (target) { /* Get a reference on the object so that it doesn't get deleted from underneath us. */ SSM_LockResource(target); SSM_GetResourceReference(target); SSM_UnlockResource(target); /* if this is a keygen context, post an urgent open message */ /* ### mwelch Very hacky. Should make a specific handler for this. */ if (SSM_IsAKindOf(target, SSM_RESTYPE_KEYGEN_CONTEXT)) { SSM_DEBUG("Closing down key gen.\n"); SSMKeyGenContext_CancelKeyGen((SSMKeyGenContext *)target); } } /* Call the default handler to send out the requested page. */ rv = SSM_HTTPDefaultCommandHandler(req); return rv;}/* Find a command handler by name. */SSMStatusSSM_HTTPFindCommandHandler(const char *name, SSMCommandHandlerFunc *func){ CommandHandlerEntry *e, *found = NULL; PRIntn i; PRIntn numEntries = SSM_Count(http_handlers); *func = NULL; /* in case we fail */ if (name) { for(i=0;i<numEntries;i++) { e = (CommandHandlerEntry *) SSM_At(http_handlers, i); if (!PL_strcmp(e->key, name)) { found = e; break; } } } if (found) *func = found->func; return (*func ? SSM_SUCCESS : SSM_FAILURE);}/* Register a command handler. */SSMStatus SSM_HTTPRegisterCommandHandler(const char *name, SSMCommandHandlerFunc func){ SSMStatus rv = SSM_SUCCESS; CommandHandlerEntry *ent = NULL; ent = (CommandHandlerEntry *) PR_CALLOC(sizeof(CommandHandlerEntry)); if (!ent) goto loser; ent->key = name; ent->func = func; SSM_Enqueue(http_handlers, SSM_PRIORITY_NORMAL, ent); goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; PR_FREEIF(ent); done: return rv;}SSMStatushttp_init_handlers(void){ SSMStatus rv = SSM_SUCCESS; http_handlers = SSM_NewCollection(); if (!http_handlers) { PR_ASSERT(!"Could not create HTTP handler registry."); goto loser; } rv = http_register_handlers(); if (rv != SSM_SUCCESS) goto loser; goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; done: return rv;}SSMStatus SSM_InitHTTP(void){ PRFileDesc *httpListenSocket = NULL; SSMStatus rv = SSM_SUCCESS; PRNetAddr httpAddr;#ifdef ALLOW_STANDALONE char *saEnv = NULL; /* Determine if we're in standalone mode. */ saEnv = PR_GetEnv(SSM_ENV_STANDALONE); if (saEnv) standalone = 1;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -