00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <sys/stat.h>
00013 #include <sys/types.h>
00014 #include <unistd.h>
00015 #include <u/libu.h>
00016 #include <klone/supplier.h>
00017 #include <klone/io.h>
00018 #include <klone/ioprv.h>
00019 #include <klone/page.h>
00020 #include <klone/http.h>
00021 #include <klone/emb.h>
00022 #include <klone/codecs.h>
00023 #include <klone/ses_prv.h>
00024 #include <klone/rsfilter.h>
00025 #include "http_s.h"
00026
00027 static int supemb_is_valid_uri(http_t *h, request_t *rq, const char *uri,
00028 size_t len, time_t *mtime)
00029 {
00030 embres_t *e;
00031 char filename[U_FILENAME_MAX] = { 0 };
00032
00033 dbg_err_if (uri == NULL);
00034 dbg_err_if (mtime == NULL);
00035 dbg_err_if (len >= U_FILENAME_MAX);
00036
00037 u_unused_args(h);
00038
00039 strncpy(filename, uri, len);
00040
00041 if(emb_lookup(filename, &e) == 0)
00042 {
00043
00044 if(e->type == ET_FILE)
00045 *mtime = ((embfile_t*)e)->mtime;
00046 else
00047 *mtime = 0;
00048
00049 return 1;
00050 }
00051
00052 err:
00053 return 0;
00054 }
00055
00056 static int supemb_get_cipher_key(request_t *rq, response_t *rs, char *key,
00057 size_t keysz)
00058 {
00059 session_t *ss = NULL;
00060 http_t *http = NULL;
00061 session_opt_t *so;
00062 vars_t *vars;
00063 var_t *v;
00064
00065 dbg_err_if (rq == NULL);
00066 dbg_err_if (rs == NULL);
00067 dbg_err_if (key == NULL);
00068
00069
00070 dbg_err_if((http = request_get_http(rq)) == NULL);
00071 dbg_err_if((so = http_get_session_opt(http)) == NULL);
00072
00073
00074 dbg_err_if(session_create(so, rq, rs, &ss));
00075
00076
00077 vars = session_get_vars(ss);
00078 dbg_err_if(vars == NULL);
00079
00080 v = vars_geti(vars,"KLONE_CIPHER_KEY", 0);
00081 dbg_err_if(v == NULL);
00082
00083 dbg_err_if(var_get_value_size(v) > keysz);
00084
00085
00086 memset(key, 0, keysz);
00087
00088
00089 memcpy(key, var_get_value(v), var_get_value_size(v));
00090
00091 session_free(ss);
00092
00093 return 0;
00094 err:
00095 if(ss)
00096 session_free(ss);
00097 return ~0;
00098 }
00099
00100 static int supemb_static_set_header_fields(request_t *rq, response_t *rs,
00101 embfile_t *e, int *sai)
00102 {
00103 http_t *http;
00104
00105 dbg_err_if (rq == NULL);
00106 dbg_err_if (rs == NULL);
00107 dbg_err_if (e == NULL);
00108 dbg_err_if (sai == NULL);
00109
00110 dbg_err_if((http = request_get_http(rq)) == NULL);
00111
00112
00113
00114
00115 dbg_err_if(response_set_content_type(rs, e->mime_type));
00116 dbg_err_if(response_set_last_modified(rs, e->mtime));
00117 dbg_err_if(response_set_content_length(rs, e->file_size));
00118
00119
00120
00121 if(http->send_enc_deflate)
00122 {
00123 if(e->comp && (*sai = request_is_encoding_accepted(rq, "deflate")) != 0)
00124 {
00125 dbg_err_if(response_set_content_encoding(rs, "deflate"));
00126 dbg_err_if(response_set_content_length(rs, e->size));
00127
00128 }
00129 }
00130
00131 return 0;
00132 err:
00133 return ~0;
00134 }
00135
00136 static int supemb_serve_static(request_t *rq, response_t *rs, embfile_t *e)
00137 {
00138 codec_t *gzip = NULL, *decrypt = NULL;
00139 int sai = 0;
00140 int decrypting = 0;
00141 char key[CODEC_CIPHER_KEY_SIZE];
00142 codec_t *rsf = NULL;
00143
00144 dbg_return_if (rq == NULL, ~0);
00145 dbg_return_if (rs == NULL, ~0);
00146 dbg_return_if (e == NULL, 0);
00147
00148
00149 dbg_err_if(response_filter_create(rq, rs, NULL, &rsf));
00150 dbg_err_if(io_codec_add_tail(response_io(rs), rsf));
00151 rsf = NULL;
00152
00153
00154 dbg_err_if(supemb_static_set_header_fields(rq, rs, e, &sai));
00155
00156
00157 if(request_get_method(rq) == HM_HEAD)
00158 return 0;
00159
00160 #ifdef HAVE_LIBZ
00161
00162 if(e->comp && !sai)
00163 dbg_err_if(codec_gzip_create(GZIP_UNCOMPRESS, &gzip));
00164 #endif
00165
00166 #ifdef HAVE_LIBOPENSSL
00167
00168
00169 if(e->encrypted)
00170 {
00171 if(supemb_get_cipher_key(rq, rs, key, CODEC_CIPHER_KEY_SIZE))
00172 {
00173 dbg_err_if(response_set_status(rs, 401));
00174 dbg_err("cipher key not found, aborting");
00175 }
00176 dbg_err_if(codec_cipher_create(CIPHER_DECRYPT, EVP_aes_256_cbc(),
00177 key, NULL, &decrypt));
00178
00179 memset(key, 0, CODEC_CIPHER_KEY_SIZE);
00180 }
00181 #endif
00182
00183 if(gzip)
00184 {
00185 dbg_err_if(io_codec_add_head(response_io(rs), gzip));
00186 gzip = NULL;
00187 }
00188
00189 if(decrypt)
00190 {
00191 dbg_err_if(io_codec_add_head(response_io(rs), decrypt));
00192 decrypt = NULL;
00193 decrypting = 1;
00194 }
00195
00196
00197
00198 dbg_err_if(!io_write(response_io(rs), (const char*)e->data, e->size));
00199
00200
00201 dbg_err_if(io_codecs_remove(response_io(rs)));
00202
00203 return 0;
00204 err:
00205 if(decrypting)
00206 dbg_if(response_set_status(rs, 401));
00207
00208 dbg_if(io_codecs_remove(response_io(rs)));
00209 if(decrypt)
00210 codec_free(decrypt);
00211 if(gzip)
00212 codec_free(gzip);
00213 return ~0;
00214 }
00215
00216 static int supemb_serve_dynamic(request_t *rq, response_t *rs, embpage_t *e)
00217 {
00218 session_t *ss = NULL;
00219 http_t *http = NULL;
00220 codec_t *filter = NULL;
00221 session_opt_t *so;
00222 io_t *oio;
00223
00224 dbg_return_if (rq == NULL, ~0);
00225 dbg_return_if (rs == NULL, ~0);
00226 dbg_return_if (e == NULL, ~0);
00227
00228
00229 oio = response_io(rs);
00230
00231
00232 dbg_err_if((http = request_get_http(rq)) == NULL);
00233 dbg_err_if((so = http_get_session_opt(http)) == NULL);
00234
00235
00236 dbg_err_if(request_parse_data(rq));
00237
00238
00239 dbg_err_if(session_create(so, rq, rs, &ss));
00240
00241
00242 dbg_err_if(response_set_content_type(rs, "text/html"));
00243
00244
00245 response_disable_caching(rs);
00246
00247
00248
00249 dbg_err_if(response_filter_create(rq, rs, ss, &filter));
00250 io_codec_add_tail(oio, filter);
00251
00252
00253 e->run(rq, rs, ss);
00254
00255
00256 io_flush(oio);
00257
00258
00259
00260
00261 if(oio->wcount == 0)
00262 io_write(oio, "\n", 1);
00263
00264
00265 session_free(ss);
00266
00267 return 0;
00268 err:
00269 io_flush(response_io(rs));
00270 if(ss)
00271 session_free(ss);
00272 return ~0;
00273 }
00274
00275 static int supemb_serve(request_t *rq, response_t *rs)
00276 {
00277 const char *file_name;
00278 embres_t *e;
00279
00280 dbg_err_if (rq == NULL);
00281 dbg_err_if (rs == NULL);
00282
00283 file_name = request_get_resolved_filename(rq);
00284 dbg_ifb(file_name == NULL || emb_lookup(file_name, &e))
00285 {
00286 response_set_status(rs, HTTP_STATUS_NOT_FOUND);
00287 return 0;
00288 }
00289
00290
00291
00292 switch(e->type)
00293 {
00294 case ET_FILE:
00295 dbg_err_if(supemb_serve_static(rq, rs, (embfile_t*)e));
00296 break;
00297 case ET_PAGE:
00298 dbg_err_if(supemb_serve_dynamic(rq, rs, (embpage_t*)e));
00299 break;
00300 default:
00301 dbg_err_if("unknown res type");
00302 }
00303
00304 return 0;
00305 err:
00306 return ~0;
00307 }
00308
00309 static int supemb_init(void)
00310 {
00311 return 0;
00312 }
00313
00314 static void supemb_term(void)
00315 {
00316 return;
00317 }
00318
00319 supplier_t sup_emb = {
00320 "embedded content supplier",
00321 supemb_init,
00322 supemb_term,
00323 supemb_is_valid_uri,
00324 supemb_serve
00325 };
00326