Initial nsreturnz import
| 1 | /* |
| 2 | * The contents of this file are subject to the AOLserver Public License |
| 3 | * Version 1.1 (the "License"); you may not use this file except in |
| 4 | * compliance with the License. You may obtain a copy of the License at |
| 5 | * http://aolserver.com/. |
| 6 | * |
| 7 | * Software distributed under the License is distributed on an "AS IS" |
| 8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See |
| 9 | * the License for the specific language governing rights and limitations |
| 10 | * under the License. |
| 11 | * |
| 12 | * The Original Code is AOLserver Code and related documentation |
| 13 | * distributed by AOL. |
| 14 | * |
| 15 | * The Initial Developer of the Original Code is America Online, |
| 16 | * Inc. Portions created by AOL are Copyright (C) 1999 America Online, |
| 17 | * Inc. All Rights Reserved. |
| 18 | * |
| 19 | * Alternatively, the contents of this file may be used under the terms |
| 20 | * of the GNU General Public License (the "GPL"), in which case the |
| 21 | * provisions of GPL are applicable instead of those above. If you wish |
| 22 | * to allow use of your version of this file only under the terms of the |
| 23 | * GPL and not to allow others to use your version of this file under the |
| 24 | * License, indicate your decision by deleting the provisions above and |
| 25 | * replace them with the notice and other provisions required by the GPL. |
| 26 | * If you do not delete the provisions above, a recipient may use your |
| 27 | * version of this file under either the License or the GPL. |
| 28 | */ |
| 29 | |
| 30 | /* |
| 31 | * nsreturnz.c |
| 32 | * |
| 33 | * AOLserver gzip compression module. |
| 34 | */ |
| 35 | |
| 36 | |
| 37 | static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/nsreturnz/nsreturnz.c,v 1.1.1.1 2003/03/10 17:57:37 rmadilo Exp $, compiled: " __DATE__ " " __TIME__; |
| 38 | |
| 39 | |
| 40 | #include "ns.h" |
| 41 | |
| 42 | /* |
| 43 | * This code adds a new TCL command named "ns_returnz" to AOLserver. |
| 44 | * To test this module, add the following to the |
| 45 | * [ns\server\server-name\modules] section of your nsd.ini file: |
| 46 | * rubylane.so on Unix platforms |
| 47 | * |
| 48 | * You can then run your "ns_returnz" command from the /NS/EvalTcl |
| 49 | * interface provided by AOLserver. |
| 50 | */ |
| 51 | |
| 52 | DllExport int Ns_ModuleVersion = 1; |
| 53 | static Tcl_CmdProc <a href="/cvs/aolserver/nsreturnz/nsreturnz.c#A_NsreturnzCmd">NsreturnzCmd</a>; |
| 54 | |
| 55 | #define GZIP_FILE_HEADER \ |
| 56 | "\037\213" /* GZIP magic number */ \ |
| 57 | "\010" /* Z_DEFLATED */ \ |
| 58 | "\000" /* flags */ \ |
| 59 | "\000\000\000\000" /* timestamp */ \ |
| 60 | "\000" /* xflags */ \ |
| 61 | "\003" /* Unix OS_CODE */ |
| 62 | |
| 63 | static int |
| 64 | <a href="/cvs/aolserver/nsreturnz/nsreturnz.c#A_NsreturnzCmd">NsreturnzCmd</a>(ClientData buf, Tcl_Interp *interp, int argc, char **argv) |
| 65 | { |
| 66 | int len, do_gzip, rc, outlen, crc; |
| 67 | unsigned char *accept, *agent, *outbuf; |
| 68 | Ns_Conn *conn; |
| 69 | Ns_Set *headers; |
| 70 | |
| 71 | if (argc < 4) { |
| 72 | Tcl_AppendResult(interp, "wrong # args: should be \"", |
| 73 | argv[0], " status mime string\"", NULL); |
| 74 | return TCL_ERROR; |
| 75 | } |
| 76 | |
| 77 | /* get connection structure */ |
| 78 | conn = <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclGetConn">Ns_TclGetConn</a>(interp); |
| 79 | if (conn == NULL) { |
| 80 | Tcl_AppendResult(interp, "NULL conn??", NULL); |
| 81 | return TCL_ERROR; |
| 82 | } |
| 83 | |
| 84 | /* get headers, see if browser supports compression */ |
| 85 | do_gzip = 0; |
| 86 | headers = <a href="/cvs/aolserver/aolserver/nsd/conn.c#A_Ns_ConnHeaders">Ns_ConnHeaders</a>(conn); |
| 87 | if (headers != NULL) { |
| 88 | accept = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(headers, "Accept-Encoding"); |
| 89 | agent = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(headers, "User-Agent"); |
| 90 | if (accept != NULL && strstr(accept, "gzip") != NULL && (agent == NULL || strstr(agent, "MSIE 5.0; Mac") == NULL)) { |
| 91 | do_gzip = 1; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | len = strlen(argv[3]); |
| 96 | if (!do_gzip) { |
| 97 | <a href="/cvs/aolserver/aolserver/nsd/return.c#A_Ns_ConnReturnData">Ns_ConnReturnData</a>(conn, atoi(argv[1]), argv[3], len, argv[2]); |
| 98 | return TCL_OK; |
| 99 | } |
| 100 | |
| 101 | /* going to gzip! Man says: |
| 102 | |
| 103 | "Compresses the source buffer into the destination buffer. The level |
| 104 | parameter has the same meaning as in deflateInit. sourceLen is the |
| 105 | byte length of the source buffer. Upon entry, destLen is the total |
| 106 | size of the destination buffer, which must be at least 0.1% larger |
| 107 | than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of |
| 108 | the compressed buffer. |
| 109 | |
| 110 | In my tests, level 3 compression is almost twice as fast as level 4, |
| 111 | so I picked that. In tests with a 330K HTML file, the result is |
| 112 | 21K - 27K for levels 1-9, so I picked 3 for speed. (No difference |
| 113 | in timing tests between levels 1/2/3 for this data.) |
| 114 | |
| 115 | To make a gzip file, 10 bytes are added at the beginning, the |
| 116 | first 2 and last 4 bytes of compress2 result are ignored (dunno why), |
| 117 | and a CRC of the orig string and len of orig string are added in |
| 118 | little-endian byte order. Messy, messy... |
| 119 | |
| 120 | */ |
| 121 | |
| 122 | outlen = len*1.002+12+sizeof(GZIP_FILE_HEADER)+8; |
| 123 | outbuf = Ns_Malloc(outlen); /* AOLServer crashes if this fails */ |
| 124 | outlen = outlen-16; /* don't let compress2 use the whole thing */ |
| 125 | rc = compress2(outbuf+8, &outlen, argv[3], len, 3); |
| 126 | #define Z_OK 0 |
| 127 | if (rc != Z_OK) { |
| 128 | Ns_Free(outbuf); |
| 129 | <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Notice, "ns_returnz: compress2 failed, status=%d", rc); |
| 130 | <a href="/cvs/aolserver/aolserver/nsd/return.c#A_Ns_ConnReturnData">Ns_ConnReturnData</a>(conn, atoi(argv[1]), argv[3], len, argv[2]); |
| 131 | return TCL_OK; |
| 132 | } |
| 133 | |
| 134 | <a href="/cvs/aolserver/aolserver/nsd/return.c#A_Ns_ConnSetHeaders">Ns_ConnSetHeaders</a>(conn, "Content-Encoding", "gzip"); |
| 135 | #define Z_NULL 0 |
| 136 | crc = crc32(0, Z_NULL, 0); |
| 137 | crc = crc32(crc, argv[3], len); |
| 138 | |
| 139 | /* copy the gzip header into the first 10 bytes, wiping out the |
| 140 | first 2 bytes from compress2. Add 8 to outlen for the gzip |
| 141 | header (10-2), subtract 4 because we're ignoring the last 4 |
| 142 | bytes of compress2 */ |
| 143 | |
| 144 | memcpy(outbuf, GZIP_FILE_HEADER, 10); |
| 145 | outlen = outlen+10-2-4; |
| 146 | |
| 147 | /* append the crc and length, 4 bytes each in LE order */ |
| 148 | |
| 149 | *(unsigned char *)(outbuf+outlen+0) = (crc & 0x000000ff); |
| 150 | *(unsigned char *)(outbuf+outlen+1) = (crc & 0x0000ff00) >> 8; |
| 151 | *(unsigned char *)(outbuf+outlen+2) = (crc & 0x00ff0000) >> 16; |
| 152 | *(unsigned char *)(outbuf+outlen+3) = (crc & 0xff000000) >> 24; |
| 153 | |
| 154 | *(unsigned char *)(outbuf+outlen+4) = (len & 0x000000ff); |
| 155 | *(unsigned char *)(outbuf+outlen+5) = (len & 0x0000ff00) >> 8; |
| 156 | *(unsigned char *)(outbuf+outlen+6) = (len & 0x00ff0000) >> 16; |
| 157 | *(unsigned char *)(outbuf+outlen+7) = (len & 0xff000000) >> 24; |
| 158 | |
| 159 | outlen += 8; |
| 160 | |
| 161 | <a href="/cvs/aolserver/aolserver/nsd/return.c#A_Ns_ConnReturnData">Ns_ConnReturnData</a>(conn, atoi(argv[1]), outbuf, outlen, argv[2]); |
| 162 | Ns_Free(outbuf); |
| 163 | return TCL_OK; |
| 164 | |
| 165 | } |
| 166 | |
| 167 | static int |
| 168 | <a href="/cvs/aolserver/nsreturnz/nsreturnz.c#A_NsreturnzInterpInit">NsreturnzInterpInit</a>(Tcl_Interp *interp, void *context) |
| 169 | { |
| 170 | Tcl_CreateCommand(interp, "ns_returnz", <a href="/cvs/aolserver/nsreturnz/nsreturnz.c#A_NsreturnzCmd">NsreturnzCmd</a>, NULL, NULL); |
| 171 | return NS_OK; |
| 172 | } |
| 173 | |
| 174 | DllExport int |
| 175 | Ns_ModuleInit(char *hServer, char *hModule) |
| 176 | { |
| 177 | return (<a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclInitInterps">Ns_TclInitInterps</a>(hServer, <a href="/cvs/aolserver/nsreturnz/nsreturnz.c#A_NsreturnzInterpInit">NsreturnzInterpInit</a>, NULL)); |
| 178 | } |
| 179 | |
| 180 |
Copyright © 2010 Geeknet, Inc. All rights reserved. Terms of Use