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
00026
00027
00028
00029
00030
00031 #include "libts.h"
00032 #include "HttpBodyFactory.h"
00033 #include <unistd.h>
00034 #include <dirent.h>
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include "URL.h"
00038 #include <logging/Log.h>
00039 #include <logging/LogAccess.h>
00040 #include <logging/LogAccessHttp.h>
00041 #include "HttpCompat.h"
00042 #include "I_Layout.h"
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 char *
00061 HttpBodyFactory::fabricate_with_old_api(const char *type, HttpTransact::State * context,
00062 int64_t max_buffer_length, int64_t *resulting_buffer_length,
00063 char* content_language_out_buf, size_t content_language_buf_size,
00064 char* content_type_out_buf, size_t content_type_buf_size,
00065 const char *format, va_list ap)
00066 {
00067 char *buffer = NULL;
00068 const char *lang_ptr = NULL;
00069 const char *charset_ptr = NULL;
00070 char url[1024];
00071 const char *set = NULL;
00072 bool found_requested_template = false;
00073 bool plain_flag = false;
00074
00075 lock();
00076
00077 *resulting_buffer_length = 0;
00078
00079 ink_strlcpy(content_language_out_buf, "en", content_language_buf_size);
00080 ink_strlcpy(content_type_out_buf, "text/html", content_type_buf_size);
00081
00082
00083
00084
00085 if (enable_logging) {
00086 url[0] = '\0';
00087 URL *u = context->hdr_info.client_request.url_get();
00088
00089 if (u->valid()) {
00090 size_t i;
00091 char *s = u->string_get(&context->arena);
00092 for (i = 0; (i < sizeof(url) - 1) && s[i]; i++)
00093 url[i] = s[i];
00094 url[i] = '\0';
00095 if (s)
00096 context->arena.str_free(s);
00097 }
00098 }
00099
00100
00101
00102 if (is_response_suppressed(context)) {
00103 if (enable_logging) {
00104 Log::error("BODY_FACTORY: suppressing '%s' response for url '%s'", type, url);
00105 }
00106 unlock();
00107 return (NULL);
00108 }
00109
00110
00111
00112
00113 StrList acpt_language_list(false);
00114 StrList acpt_charset_list(false);
00115
00116 if (enable_customizations == 2) {
00117 context->hdr_info.client_request.value_get_comma_list(MIME_FIELD_ACCEPT_LANGUAGE, MIME_LEN_ACCEPT_LANGUAGE,
00118 &acpt_language_list);
00119 context->hdr_info.client_request.value_get_comma_list(MIME_FIELD_ACCEPT_CHARSET, MIME_LEN_ACCEPT_CHARSET,
00120 &acpt_charset_list);
00121 }
00122
00123
00124
00125 if (format) {
00126
00127
00128 int l = ink_bvsprintf(NULL, format, ap);
00129 if (l <= max_buffer_length) {
00130 buffer = (char *)ats_malloc(l);
00131 *resulting_buffer_length = ink_bvsprintf(buffer, format, ap) - 1;
00132 plain_flag = true;
00133 }
00134 }
00135
00136
00137
00138 if (buffer == NULL) {
00139 buffer = fabricate(&acpt_language_list, &acpt_charset_list,
00140 type, context, resulting_buffer_length, &lang_ptr, &charset_ptr, &set);
00141 found_requested_template = (buffer != NULL);
00142 }
00143
00144
00145
00146 if (buffer == NULL) {
00147 buffer = fabricate(&acpt_language_list, &acpt_charset_list,
00148 "default", context, resulting_buffer_length, &lang_ptr, &charset_ptr, &set);
00149 }
00150
00151
00152
00153 if (buffer && (*resulting_buffer_length > max_buffer_length)) {
00154 if (enable_logging) {
00155 Log::error(("BODY_FACTORY: template '%s/%s' consumed %" PRId64 " bytes, "
00156 "exceeding %" PRId64 " byte limit, using internal default"),
00157 set, type, *resulting_buffer_length, max_buffer_length);
00158 }
00159 *resulting_buffer_length = 0;
00160 buffer = (char *)ats_free_null(buffer);
00161 }
00162
00163
00164
00165
00166
00167 if (buffer) {
00168 if (!plain_flag) {
00169 snprintf(content_language_out_buf, content_language_buf_size, "%s", lang_ptr);
00170 snprintf(content_type_out_buf, content_type_buf_size, "text/html; charset=%s", charset_ptr);
00171 }
00172
00173 if (enable_logging) {
00174 if (found_requested_template) {
00175 Log::error(("BODY_FACTORY: using custom template "
00176 "'%s/%s' for url '%s' (language '%s', charset '%s')"), set, type, url, lang_ptr, charset_ptr);
00177 } else {
00178 Log::error(("BODY_FACTORY: can't find custom template "
00179 "'%s/%s', using '%s/%s' for url '%s' (language '%s', charset '%s')"),
00180 set, type, set, "default", url, lang_ptr, charset_ptr);
00181 }
00182 }
00183 } else {
00184 if (enable_logging) {
00185 Log::error(("BODY_FACTORY: can't find templates '%s' or '%s' for url `%s'"),
00186 type, "default", url);
00187 }
00188 }
00189 unlock();
00190
00191 return (buffer);
00192 }
00193
00194 void
00195 HttpBodyFactory::dump_template_tables(FILE * fp)
00196 {
00197 RawHashTable *h1, *h2;
00198 RawHashTable_Key k1, k2;
00199 RawHashTable_Value v1, v2;
00200 RawHashTable_Binding *b1, *b2;
00201 RawHashTable_IteratorState i1, i2;
00202 HttpBodySet *body_set;
00203
00204 lock();
00205
00206 h1 = table_of_sets;
00207
00208 if (h1 != NULL) {
00209
00210
00211
00212
00213 for (b1 = h1->firstBinding(&i1); b1 != NULL; b1 = h1->nextBinding(&i1)) {
00214 k1 = table_of_sets->getKeyFromBinding(b1);
00215 v1 = table_of_sets->getValueFromBinding(b1);
00216 body_set = (HttpBodySet *) v1;
00217
00218 if (body_set != NULL) {
00219 fprintf(fp, "set %s: name '%s', lang '%s', charset '%s'\n",
00220 k1, body_set->set_name, body_set->content_language, body_set->content_charset);
00221
00222
00223
00224
00225
00226 ink_assert(body_set->is_sane());
00227 h2 = body_set->table_of_pages;
00228
00229 for (b2 = h2->firstBinding(&i2); b2 != NULL; b2 = h2->nextBinding(&i2)) {
00230 k2 = table_of_sets->getKeyFromBinding(b2);
00231 v2 = table_of_sets->getValueFromBinding(b2);
00232 HttpBodyTemplate *t = (HttpBodyTemplate *) v2;
00233
00234 fprintf(fp, " %-30s: %" PRId64 " bytes\n", k2, t->byte_count);
00235 }
00236 }
00237 }
00238 }
00239
00240 unlock();
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250 static int
00251 config_callback(const char * , RecDataT ,
00252 RecData , void *cookie)
00253 {
00254 HttpBodyFactory *body_factory = (HttpBodyFactory *) cookie;
00255 body_factory->reconfigure();
00256 return (0);
00257 }
00258
00259 void
00260 HttpBodyFactory::reconfigure()
00261
00262 {
00263 RecInt e;
00264 RecString s = NULL;
00265 bool all_found;
00266 int rec_err;
00267
00268 lock();
00269 sanity_check();
00270
00271 if (!callbacks_established) {
00272 unlock();
00273 return;
00274 }
00275
00276
00277
00278
00279
00280 Debug("body_factory", "config variables changed, reconfiguring...");
00281
00282 all_found = true;
00283
00284
00285 rec_err = RecGetRecordInt("proxy.config.body_factory.enable_customizations", &e);
00286 enable_customizations = ((rec_err == REC_ERR_OKAY) ? e : 0);
00287 all_found = all_found && (rec_err == REC_ERR_OKAY);
00288 Debug("body_factory", "enable_customizations = %d (found = %" PRId64")", enable_customizations, e);
00289
00290 rec_err = RecGetRecordInt("proxy.config.body_factory.enable_logging", &e);
00291 enable_logging = ((rec_err == REC_ERR_OKAY) ? (e ? true : false) : false);
00292 all_found = all_found && (rec_err == REC_ERR_OKAY);
00293 Debug("body_factory", "enable_logging = %d (found = %" PRId64")", enable_logging, e);
00294
00295 rec_err = RecGetRecordInt("proxy.config.body_factory.response_suppression_mode", &e);
00296 response_suppression_mode = ((rec_err == REC_ERR_OKAY) ? e : 0);
00297 all_found = all_found && (rec_err == REC_ERR_OKAY);
00298 Debug("body_factory", "response_suppression_mode = %d (found = %" PRId64")", response_suppression_mode, e);
00299
00300 ats_scoped_str directory_of_template_sets;
00301
00302 rec_err = RecGetRecordString_Xmalloc("proxy.config.body_factory.template_sets_dir", &s);
00303 all_found = all_found && (rec_err == REC_ERR_OKAY);
00304 if (rec_err == REC_ERR_OKAY) {
00305 directory_of_template_sets = Layout::get()->relative(s);
00306 if (access(directory_of_template_sets, R_OK) < 0) {
00307 Warning("Unable to access() directory '%s': %d, %s", (const char *)directory_of_template_sets, errno, strerror(errno));
00308 Warning(" Please set 'proxy.config.body_factory.template_sets_dir' ");
00309 }
00310
00311 }
00312
00313 Debug("body_factory", "directory_of_template_sets = '%s' (found = %s)", (const char *)directory_of_template_sets, s);
00314 ats_free(s);
00315
00316 if (!all_found) {
00317 Warning("config changed, but can't fetch all proxy.config.body_factory values");
00318 }
00319
00320
00321
00322
00323
00324 nuke_template_tables();
00325
00326
00327
00328
00329
00330
00331 if (directory_of_template_sets)
00332 table_of_sets = load_sets_from_directory(directory_of_template_sets);
00333
00334 unlock();
00335 }
00336
00337
00338
00339
00340
00341
00342
00343 HttpBodyFactory::HttpBodyFactory()
00344 {
00345 int i;
00346 bool status, no_registrations_failed;
00347
00348
00349
00350
00351
00352 magic = HTTP_BODY_FACTORY_MAGIC;
00353 ink_mutex_init(&mutex, "HttpBodyFactory::lock");
00354
00355 table_of_sets = NULL;
00356 enable_customizations = 0;
00357 enable_logging = true;
00358 callbacks_established = false;
00359
00360
00361
00362
00363
00364 static const char *config_record_names[] = {
00365 "proxy.config.body_factory.enable_customizations",
00366 "proxy.config.body_factory.enable_logging",
00367 "proxy.config.body_factory.template_sets_dir",
00368 "proxy.config.body_factory.response_suppression_mode",
00369 NULL
00370 };
00371
00372 no_registrations_failed = true;
00373 for (i = 0; config_record_names[i] != NULL; i++) {
00374 status = HTTP_RegisterConfigUpdateFunc(config_record_names[i], config_callback, (void *) this);
00375 if (status != REC_ERR_OKAY) {
00376 Warning("couldn't register variable '%s', is records.config up to date?", config_record_names[i]);
00377 }
00378 no_registrations_failed = no_registrations_failed && (status == REC_ERR_OKAY);
00379 }
00380
00381 if (no_registrations_failed == false) {
00382 Warning("couldn't setup all body_factory callbacks, disabling body_factory");
00383 } else {
00384 Debug("body_factory", "all callbacks established successfully");
00385 callbacks_established = true;
00386 reconfigure();
00387 }
00388 }
00389
00390
00391 HttpBodyFactory::~HttpBodyFactory()
00392 {
00393
00394 delete table_of_sets;
00395 }
00396
00397
00398
00399 char *
00400 HttpBodyFactory::fabricate(StrList * acpt_language_list,
00401 StrList * acpt_charset_list,
00402 const char *type, HttpTransact::State * context,
00403 int64_t *buffer_length_return,
00404 const char **content_language_return,
00405 const char **content_charset_return, const char **set_return)
00406 {
00407 char *buffer;
00408 const char *set;
00409 HttpBodyTemplate *t;
00410 HttpBodySet *body_set;
00411
00412 if (set_return)
00413 *set_return = "???";
00414 *content_language_return = NULL;
00415 *content_charset_return = NULL;
00416
00417 Debug("body_factory", "calling fabricate(type '%s')", type);
00418 *buffer_length_return = 0;
00419
00420
00421 if (is_response_suppressed(context)) {
00422 Debug("body_factory", " error suppression enabled, returning NULL template");
00423 return (NULL);
00424 }
00425
00426 if (!enable_customizations) {
00427 Debug("body_factory", " customization disabled, returning NULL template");
00428 return (NULL);
00429 }
00430
00431 if (enable_customizations == 2)
00432 set = determine_set_by_language(acpt_language_list, acpt_charset_list);
00433 else
00434 set = "default";
00435
00436 if (set_return)
00437 *set_return = set;
00438
00439
00440 t = find_template(set, type, &body_set);
00441 if (t == NULL) {
00442 Debug("body_factory", " can't find template, returning NULL template");
00443 return (NULL);
00444 }
00445
00446 *content_language_return = body_set->content_language;
00447 *content_charset_return = body_set->content_charset;
00448
00449
00450 buffer = t->build_instantiated_buffer(context, buffer_length_return);
00451 return (buffer);
00452 }
00453
00454
00455
00456 const char *
00457 HttpBodyFactory::determine_set_by_language(StrList * acpt_language_list, StrList * acpt_charset_list)
00458 {
00459 float Q_best;
00460 const char *set_best;
00461 int La_best, Lc_best, I_best;
00462
00463 set_best = HttpCompat::determine_set_by_language(table_of_sets, acpt_language_list, acpt_charset_list,
00464 &Q_best, &La_best, &Lc_best, &I_best);
00465
00466 return (set_best);
00467 }
00468
00469
00470 HttpBodyTemplate *
00471 HttpBodyFactory::find_template(const char *set, const char *type, HttpBodySet ** body_set_return)
00472 {
00473 RawHashTable_Value v;
00474
00475 Debug("body_factory", "calling find_template(%s,%s)", set, type);
00476
00477 *body_set_return = NULL;
00478
00479 if (table_of_sets == NULL)
00480 return (NULL);
00481 if (table_of_sets->getValue((RawHashTable_Key) set, &v)) {
00482 HttpBodySet *body_set = (HttpBodySet *) v;
00483 RawHashTable *table_of_types = body_set->table_of_pages;
00484
00485 if (table_of_types == NULL)
00486 return (NULL);
00487
00488 if (table_of_types->getValue((RawHashTable_Key) type, &v)) {
00489 HttpBodyTemplate *t = (HttpBodyTemplate *) v;
00490 if ((t == NULL) || (!t->is_sane()))
00491 return (NULL);
00492 *body_set_return = body_set;
00493
00494 Debug("body_factory", "find_template(%s,%s) -> (file %s, length %" PRId64", lang '%s', charset '%s')",
00495 set, type, t->template_pathname, t->byte_count, body_set->content_language, body_set->content_charset);
00496
00497 return (t);
00498 }
00499 }
00500 Debug("body_factory", "find_template(%s,%s) -> NULL", set, type);
00501
00502 return (NULL);
00503 }
00504
00505
00506
00507 bool
00508 HttpBodyFactory::is_response_suppressed(HttpTransact::State * context)
00509 {
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 if (response_suppression_mode == 0) {
00521 return (false);
00522 } else if (response_suppression_mode == 1) {
00523 return (true);
00524 } else if (response_suppression_mode == 2) {
00525 if (context->req_flavor == HttpTransact::REQ_FLAVOR_INTERCEPTED)
00526 return (true);
00527 else
00528 return (false);
00529 } else {
00530 return (false);
00531 }
00532 }
00533
00534
00535
00536 void
00537 HttpBodyFactory::nuke_template_tables()
00538 {
00539 RawHashTable *h1, *h2;
00540 RawHashTable_Value v1, v2;
00541 RawHashTable_Binding *b1, *b2;
00542 RawHashTable_IteratorState i1, i2;
00543 HttpBodySet *body_set;
00544 HttpBodyTemplate *hbt;
00545
00546 h1 = table_of_sets;
00547
00548 if (h1) {
00549 Debug("body_factory", "deleting pre-existing template tables");
00550 } else {
00551 Debug("body_factory", "no pre-existing template tables");
00552 }
00553 if (h1 != NULL) {
00554
00555
00556
00557
00558 for (b1 = h1->firstBinding(&i1); b1 != NULL; b1 = h1->nextBinding(&i1)) {
00559 v1 = h1->getValueFromBinding(b1);
00560
00561 body_set = (HttpBodySet *) v1;
00562 ink_assert(body_set->is_sane());
00563 h2 = body_set->table_of_pages;
00564
00565 if (h2 != NULL) {
00566 body_set->table_of_pages = NULL;
00567
00568
00569
00570
00571
00572 for (b2 = h2->firstBinding(&i2); b2 != NULL; b2 = h2->nextBinding(&i2)) {
00573 v2 = h2->getValueFromBinding(b2);
00574 if (v2) {
00575
00576 hbt = (HttpBodyTemplate *) v2;
00577 delete hbt;
00578 }
00579 }
00580
00581 delete h2;
00582 }
00583
00584 delete body_set;
00585 }
00586 delete h1;
00587 }
00588
00589 table_of_sets = NULL;
00590 }
00591
00592
00593
00594 RawHashTable *
00595 HttpBodyFactory::load_sets_from_directory(char *set_dir)
00596 {
00597 DIR *dir;
00598 struct dirent *entry_buffer, *result;
00599 RawHashTable *new_table_of_sets;
00600
00601 if (set_dir == NULL)
00602 return (NULL);
00603
00604 Debug("body_factory", "load_sets_from_directory(%s)", set_dir);
00605
00606
00607
00608
00609
00610 dir = opendir(set_dir);
00611 if (dir == NULL) {
00612 Warning("can't open response template directory '%s' (%s)",
00613 set_dir, (strerror(errno) ? strerror(errno) : "unknown reason"));
00614 Warning("no response templates --- using default error pages");
00615 return (NULL);
00616 }
00617
00618 new_table_of_sets = new RawHashTable(RawHashTable_KeyType_String);
00619 entry_buffer = (struct dirent *)ats_malloc(sizeof(struct dirent) + MAXPATHLEN + 1);
00620
00621
00622
00623
00624
00625 while ((readdir_r(dir, entry_buffer, &result) == 0) && (result != NULL)) {
00626 int status;
00627 struct stat stat_buf;
00628 char subdir[MAXPATHLEN + 1];
00629
00630
00631
00632
00633
00634 if ((entry_buffer->d_name)[0] == '.')
00635 continue;
00636 ink_filepath_make(subdir, sizeof(subdir), set_dir, entry_buffer->d_name);
00637 status = stat(subdir, &stat_buf);
00638 if (status != 0)
00639 continue;
00640 if (!S_ISDIR(stat_buf.st_mode))
00641 continue;
00642
00643
00644
00645
00646
00647 HttpBodySet *body_set = load_body_set_from_directory(entry_buffer->d_name, subdir);
00648 if (body_set != NULL) {
00649 Debug("body_factory", " %s -> %p", entry_buffer->d_name, body_set);
00650 new_table_of_sets->setValue((RawHashTable_Key) (entry_buffer->d_name), (RawHashTable_Value) body_set);
00651 }
00652 }
00653
00654 ats_free(entry_buffer);
00655 closedir(dir);
00656
00657 return (new_table_of_sets);
00658 }
00659
00660
00661
00662 HttpBodySet *
00663 HttpBodyFactory::load_body_set_from_directory(char *set_name, char *tmpl_dir)
00664 {
00665 DIR *dir;
00666 int status;
00667 struct stat stat_buf;
00668 char path[MAXPATHLEN + 1];
00669 struct dirent *entry_buffer, *result;
00670
00671
00672
00673
00674
00675 Debug("body_factory", " load_body_set_from_directory(%s)", tmpl_dir);
00676 dir = opendir(tmpl_dir);
00677 if (dir == NULL)
00678 return (NULL);
00679
00680
00681
00682
00683
00684 ink_filepath_make(path, sizeof(path), tmpl_dir, ".body_factory_info");
00685 status = stat(path, &stat_buf);
00686 if ((status < 0) || !S_ISREG(stat_buf.st_mode)) {
00687 closedir(dir);
00688 return (NULL);
00689 }
00690 Debug("body_factory", " found '%s'", path);
00691
00692
00693
00694
00695
00696 HttpBodySet *body_set = new HttpBodySet;
00697 body_set->init(set_name, tmpl_dir);
00698
00699 Debug("body_factory", " body_set = %p (set_name '%s', lang '%s', charset '%s')",
00700 body_set, body_set->set_name, body_set->content_language, body_set->content_charset);
00701 entry_buffer = (struct dirent *)ats_malloc(sizeof(struct dirent) + MAXPATHLEN + 1);
00702
00703 while ((readdir_r(dir, entry_buffer, &result) == 0) && (result != NULL)) {
00704 HttpBodyTemplate *tmpl;
00705
00706
00707
00708
00709
00710 if ((strchr(entry_buffer->d_name, '#') == NULL) && (strcmp(entry_buffer->d_name, "default") != 0))
00711 continue;
00712
00713 snprintf(path, sizeof(path), "%s/%s", tmpl_dir, entry_buffer->d_name);
00714 status = stat(path, &stat_buf);
00715 if (status != 0)
00716 continue;
00717 if (!S_ISREG(stat_buf.st_mode))
00718 continue;
00719
00720
00721
00722
00723
00724 tmpl = new HttpBodyTemplate();
00725 if (!tmpl->load_from_file(tmpl_dir, entry_buffer->d_name)) {
00726 delete tmpl;
00727 } else {
00728 Debug("body_factory", " %s -> %p", entry_buffer->d_name, tmpl);
00729 body_set->set_template_by_name(entry_buffer->d_name, tmpl);
00730 }
00731 }
00732 ats_free(entry_buffer);
00733 closedir(dir);
00734 return (body_set);
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744 HttpBodySet::HttpBodySet()
00745 {
00746 magic = HTTP_BODY_SET_MAGIC;
00747
00748 set_name = NULL;
00749 content_language = NULL;
00750 content_charset = NULL;
00751
00752 table_of_pages = NULL;
00753 }
00754
00755
00756 HttpBodySet::~HttpBodySet()
00757 {
00758 ats_free(set_name);
00759 ats_free(content_language);
00760 ats_free(content_charset);
00761 if (table_of_pages)
00762 delete table_of_pages;
00763 }
00764
00765
00766 int
00767 HttpBodySet::init(char *set, char *dir)
00768 {
00769 int fd, lineno, lines_added = 0;
00770 char info_path[MAXPATHLEN];
00771
00772 char buffer[1024], name[1025], value[1024];
00773
00774 ink_filepath_make(info_path, sizeof(info_path), dir, ".body_factory_info");
00775 fd = open(info_path, O_RDONLY | _O_ATTRIB_NORMAL);
00776 if (fd < 0)
00777 return (-1);
00778
00779 this->set_name = ats_strdup(set);
00780
00781 if (this->table_of_pages)
00782 delete(this->table_of_pages);
00783 this->table_of_pages = new RawHashTable(RawHashTable_KeyType_String);
00784
00785 lineno = 0;
00786
00787 while (1) {
00788 char *name_s, *name_e, *value_s, *value_e, *hash;
00789
00790 ++lineno;
00791 int bytes = ink_file_fd_readline(fd, sizeof(buffer), buffer);
00792 if (bytes <= 0)
00793 break;
00794
00795
00796
00797
00798
00799 hash = index(buffer, '#');
00800 if (hash)
00801 *hash = '\0';
00802
00803
00804
00805
00806
00807 name_s = buffer;
00808 while (*name_s && ParseRules::is_wslfcr(*name_s))
00809 ++name_s;
00810
00811 name_e = name_s;
00812 while (*name_e && ParseRules::is_http_field_name(*name_e))
00813 ++name_e;
00814
00815 if (name_s == name_e)
00816 continue;
00817
00818
00819
00820
00821
00822 value_s = name_e;
00823 while (*value_s && (ParseRules::is_wslfcr(*value_s)))
00824 ++value_s;
00825 if (*value_s != ':') {
00826 Warning("ignoring invalid body factory info line #%d in %s", lineno, info_path);
00827 continue;
00828 }
00829 ++value_s;
00830 while (*value_s && (ParseRules::is_wslfcr(*value_s)))
00831 ++value_s;
00832 value_e = buffer + strlen(buffer) - 1;
00833 while ((value_e > value_s) && ParseRules::is_wslfcr(*(value_e - 1)))
00834 --value_e;
00835
00836
00837
00838
00839
00840 memcpy(name, name_s, name_e - name_s);
00841 name[name_e - name_s] = '\0';
00842
00843 memcpy(value, value_s, value_e - value_s);
00844 value[value_e - value_s] = '\0';
00845
00846
00847
00848
00849
00850 if (strcasecmp(name, "Content-Language") == 0) {
00851 ats_free(this->content_language);
00852 this->content_language = ats_strdup(value);
00853 } else if (strcasecmp(name, "Content-Charset") == 0) {
00854 ats_free(this->content_charset);
00855 this->content_charset = ats_strdup(value);
00856 }
00857 }
00858
00859
00860
00861
00862
00863 if (!this->content_language) {
00864 if (strcmp(set, "default") == 0)
00865 this->content_language = ats_strdup("en");
00866 else
00867 this->content_language = ats_strdup(set);
00868 }
00869 if (!this->content_charset)
00870 this->content_charset = ats_strdup("utf-8");
00871
00872 close(fd);
00873 return (lines_added);
00874 }
00875
00876
00877 HttpBodyTemplate *
00878 HttpBodySet::get_template_by_name(const char *name)
00879 {
00880 RawHashTable_Value v;
00881
00882 Debug("body_factory", " calling get_template_by_name(%s)", name);
00883
00884 if (table_of_pages == NULL)
00885 return (NULL);
00886
00887 if (table_of_pages->getValue((RawHashTable_Key) name, &v)) {
00888 HttpBodyTemplate *t = (HttpBodyTemplate *) v;
00889 if ((t == NULL) || (!t->is_sane()))
00890 return (NULL);
00891 Debug("body_factory", " get_template_by_name(%s) -> (file %s, length %" PRId64")",
00892 name, t->template_pathname, t->byte_count);
00893 return (t);
00894 }
00895 Debug("body_factory", " get_template_by_name(%s) -> NULL", name);
00896 return (NULL);
00897 }
00898
00899
00900 void
00901 HttpBodySet::set_template_by_name(const char *name, HttpBodyTemplate * t)
00902 {
00903 table_of_pages->setValue((RawHashTable_Key) name, (RawHashTable_Value) t);
00904 }
00905
00906
00907
00908
00909
00910
00911
00912 HttpBodyTemplate::HttpBodyTemplate()
00913 {
00914 magic = HTTP_BODY_TEMPLATE_MAGIC;
00915 byte_count = 0;
00916 template_buffer = NULL;
00917 template_pathname = NULL;
00918 }
00919
00920
00921 HttpBodyTemplate::~HttpBodyTemplate()
00922 {
00923 reset();
00924 }
00925
00926
00927 void
00928 HttpBodyTemplate::reset()
00929 {
00930 ats_free(template_buffer);
00931 template_buffer = NULL;
00932 byte_count = 0;
00933 ats_free(template_pathname);
00934 }
00935
00936
00937 int
00938 HttpBodyTemplate::load_from_file(char *dir, char *file)
00939 {
00940 int fd, status;
00941 int64_t bytes_read;
00942 struct stat stat_buf;
00943 char path[MAXPATHLEN + 1];
00944 char *new_template_buffer;
00945 int64_t new_byte_count;
00946
00947
00948
00949
00950
00951 snprintf(path, sizeof(path), "%s/%s", dir, file);
00952
00953 status = stat(path, &stat_buf);
00954 if (status != 0)
00955 return (0);
00956 if (!S_ISREG(stat_buf.st_mode))
00957 return (0);
00958
00959
00960
00961
00962
00963
00964 fd = open(path, O_RDONLY | _O_ATTRIB_NORMAL);
00965 if (fd < 0)
00966 return (0);
00967
00968
00969
00970
00971
00972 new_byte_count = stat_buf.st_size;
00973 new_template_buffer = (char *)ats_malloc(new_byte_count + 1);
00974 bytes_read = read(fd, new_template_buffer, new_byte_count);
00975 new_template_buffer[new_byte_count] = '\0';
00976 close(fd);
00977
00978
00979
00980
00981
00982 if (bytes_read != new_byte_count) {
00983 Warning("reading template file '%s', got %" PRId64" bytes instead of %" PRId64" (%s)",
00984 path, bytes_read, new_byte_count, (strerror(errno) ? strerror(errno) : "unknown error"));
00985 ats_free(new_template_buffer);
00986 return (0);
00987 }
00988
00989 Debug("body_factory", " read %" PRId64" bytes from '%s'", new_byte_count, path);
00990
00991
00992
00993
00994
00995 reset();
00996 template_buffer = new_template_buffer;
00997 byte_count = new_byte_count;
00998 template_pathname = ats_strdup(path);
00999
01000 return (1);
01001 }
01002
01003 char *
01004 HttpBodyTemplate::build_instantiated_buffer(HttpTransact::State * context, int64_t *buflen_return)
01005 {
01006 char *buffer = NULL;
01007
01008 Debug("body_factory_instantiation", " before instantiation: [%s]", template_buffer);
01009
01010 LogAccessHttp la(context->state_machine);
01011
01012
01013 Log::access(&la);
01014 buffer = resolve_logfield_string((LogAccess *) & la, template_buffer);
01015
01016 *buflen_return = ((buffer == NULL) ? 0 : strlen(buffer));
01017 Debug("body_factory_instantiation", " after instantiation: [%s]", buffer);
01018 Debug("body_factory", " returning %" PRId64" byte instantiated buffer", *buflen_return);
01019
01020 return (buffer);
01021 }