00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00030 #ifndef DISABLE_CGI
00031
00032 #ifdef ENABLE_FASTCGI
00033 #include "fcgi_stdio.h"
00034 #else
00035 #include <stdio.h>
00036 #endif
00037 #include <stdlib.h>
00038 #include <stdbool.h>
00039 #include <stdarg.h>
00040 #include <string.h>
00041 #include <fcntl.h>
00042 #include <unistd.h>
00043 #include <libgen.h>
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046 #include "qDecoder.h"
00047 #include "qInternal.h"
00048
00075 bool qCgiResponseSetCookie(Q_ENTRY *request, const char *name, const char *value, int expire, const char *path, const char *domain, bool secure) {
00076
00077 if (qCgiResponseGetContentType(request) != NULL) {
00078 DEBUG("Should be called before qCgiResponseSetContentType().");
00079 return false;
00080 }
00081
00082
00083 char *encname = qEncodeUrl(name);
00084 char *encvalue = qEncodeUrl(value);
00085 char cookie[(4 * 1024) + 256];
00086 snprintf(cookie, sizeof(cookie), "%s=%s", encname, encvalue);
00087 free(encname), free(encvalue);
00088
00089 if (expire != 0) {
00090 char *gmtstr = qTimeGetGmtStr(time(NULL) + expire);
00091 strcat(cookie, "; expires=");
00092 strcat(cookie, gmtstr);
00093 free(gmtstr);
00094 }
00095
00096 if (path != NULL) {
00097 if (path[0] != '/') {
00098 DEBUG("Path string(%s) must start with '/' character.", path);
00099 return false;
00100 }
00101 strcat(cookie, "; path=");
00102 strcat(cookie, path);
00103 }
00104
00105 if (domain != NULL) {
00106 if (strstr(domain, "/") != NULL || strstr(domain, ".") == NULL) {
00107 DEBUG("Invalid domain name(%s).", domain);
00108 return false;
00109 }
00110 strcat(cookie, "; domain=");
00111 strcat(cookie, domain);
00112 }
00113
00114 if (secure == true) {
00115 strcat(cookie, "; secure");
00116 }
00117
00118 printf("Set-Cookie: %s\n", cookie);
00119
00120 return true;
00121 }
00122
00142 bool qCgiResponseRemoveCookie(Q_ENTRY *request, const char *name, const char *path, const char *domain, bool secure) {
00143 return qCgiResponseSetCookie(request, name, "", -1, path, domain, secure);
00144 }
00145
00158 bool qCgiResponseSetContentType(Q_ENTRY *request, const char *mimetype) {
00159 if(qEntryGetStr(request, "_Q_CONTENTTYPE") != NULL) {
00160 DEBUG("alreay set.");
00161 return false;
00162 }
00163
00164 printf("Content-Type: %s\n\n", mimetype);
00165
00166 qEntryPutStr(request, "_Q_CONTENTTYPE", mimetype, true);
00167 return true;
00168 }
00169
00181 const char *qCgiResponseGetContentType(Q_ENTRY *request) {
00182 return qEntryGetStr(request, "_Q_CONTENTTYPE");
00183 }
00184
00197 bool qCgiResponseRedirect(Q_ENTRY *request, const char *uri) {
00198 if(qCgiResponseGetContentType(request) != NULL) {
00199 DEBUG("Should be called before qCgiResponseSetContentType().");
00200 return false;
00201 }
00202
00203 printf("Location: %s\n\n", uri);
00204 return true;
00205 }
00206
00224 int qCgiResponseDownload(Q_ENTRY *request, const char *filepath, const char *mimetype) {
00225 if (qCgiResponseGetContentType(request) != NULL) {
00226 DEBUG("Should be called before qCgiResponseSetContentType().");
00227 return -1;
00228 }
00229
00230 int fd;
00231 if (filepath == NULL || (fd = open(filepath, O_RDONLY, 0)) < 0) {
00232 DEBUG("Can't open file.");
00233 return -1;
00234 }
00235
00236 const char *mime;
00237 if(mimetype == NULL) mime = "application/octet-stream";
00238 else mime = mimetype;
00239
00240 char *disposition;
00241 if (!strcmp(mime, "application/octet-stream")) disposition = "attachment";
00242 else disposition = "inline";
00243
00244 char *filename = qFileGetName(filepath);
00245
00246 printf("Content-Disposition: %s;filename=\"%s\"\n", disposition, filename);
00247 printf("Content-Transfer-Encoding: binary\n");
00248 printf("Accept-Ranges: bytes\n");
00249 printf("Content-Length: %zu\n", (size_t)qFileGetSize(filepath));
00250 printf("Connection: close\n");
00251 qCgiResponseSetContentType(request, mime);
00252
00253 free(filename);
00254
00255 fflush(stdout);
00256 int sent = qFileSend(fileno(stdout), fd, qFileGetSize(filepath));
00257
00258 close(fd);
00259 return sent;
00260 }
00273 void qCgiResponseError(Q_ENTRY *request, char *format, ...) {
00274 char buf[MAX_LINEBUF];
00275 va_list arglist;
00276
00277 va_start(arglist, format);
00278 vsnprintf(buf, sizeof(buf), format, arglist);
00279 va_end(arglist);
00280
00281 if (getenv("REMOTE_ADDR") == NULL) {
00282 printf("Error: %s\n", buf);
00283 } else {
00284 qCgiResponseSetContentType(request, "text/html");
00285
00286 printf("<html>\n");
00287 printf("<head>\n");
00288 printf("<title>Error: %s</title>\n", buf);
00289 printf("<script language='JavaScript'>\n");
00290 printf(" alert(\"%s\");\n", buf);
00291 printf(" history.back();\n");
00292 printf("</script>\n");
00293 printf("</head>\n");
00294 printf("</html>\n");
00295 }
00296
00297 qEntryFree(request);
00298 exit(EXIT_FAILURE);
00299 }
00300
00301 #endif