00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ngx_http_xxslt_parse.h"
00023 #include "ngx_http_xxslt_selector.h"
00024
00025 static u_char *
00026 ngx_http_xxslt_parse_get_prefix(void);
00027 static u_char *
00028 ngx_http_xxslt_parse_get_suffix(void);
00029
00030 static ngx_http_xxslt_include_t *
00031 ngx_http_xxslt_parse_create_new_include(ngx_http_xxslt_parse_data_t *parse_data);
00032 static void
00033 ngx_http_xxslt_parse_get_include(ngx_http_xxslt_include_t *include, ngx_flag_t use_cache);
00034 static void
00035 ngx_http_xxslt_parse_use_alt_src(ngx_http_xxslt_include_t *include);
00036 static ngx_int_t
00037 ngx_http_xxslt_parse_get_external_include(ngx_http_xxslt_include_t *include);
00038 static ngx_int_t
00039 ngx_http_xxslt_parse_get_local_include(ngx_http_xxslt_include_t *include);
00040 static void
00041 ngx_http_xxslt_parse_download_handler(ngx_http_download_conn_t *dl_ctx);
00042 static ngx_int_t
00043 ngx_http_xxslt_parse_add_include(ngx_http_xxslt_include_t *include);
00044 static void
00045 ngx_http_xxslt_parse_add_buffer_chain(ngx_http_xxslt_parse_data_t *parse_data, ngx_chain_t *cl);
00046 static ngx_int_t
00047 ngx_http_xxslt_parse_set_cached_include(ngx_http_request_t *r, ngx_http_xxslt_include_t *include);
00048 static void
00049 ngx_http_xxslt_parse_mxcache_set_handler(ngx_http_mxcache_conn_t *conn);
00050 static ngx_int_t
00051 ngx_http_xxslt_parse_get_cached_include(ngx_http_request_t *r, ngx_http_xxslt_include_t *include, u_char *uri);
00052 static void
00053 ngx_http_xxslt_parse_mxcache_get_handler(ngx_http_mxcache_conn_t *conn);
00054
00055 static void
00056 ngx_http_xxslt_parse_process_include(ngx_http_xxslt_include_t *include, ngx_flag_t set_cache);
00057
00058 static void
00059 ngx_http_xxslt_parse_include_node(ngx_http_xxslt_parse_data_t *parse_data,
00060 int nb_attributes, const xmlChar **attributes);
00061
00062 static void
00063 ngx_http_xxslt_parse_include_error(ngx_http_xxslt_parse_data_t *parse_data, char *msg, ...);
00064
00065 static void ngx_http_xxslt_parse_sax_start_document(void *data);
00066 static void ngx_http_xxslt_parse_sax_end_document(void *data);
00067 static void ngx_http_xxslt_parse_sax_internal_subset(void *data, const xmlChar *name,
00068 const xmlChar *externalId, const xmlChar *systemId);
00069 static void ngx_http_xxslt_parse_sax_external_subset(void *data, const xmlChar *name,
00070 const xmlChar *externalId, const xmlChar *systemId);
00071 static void ngx_http_xxslt_parse_sax_entity_decl(void *data, const xmlChar *name,
00072 int type, const xmlChar *publicId, const xmlChar *systemId,
00073 xmlChar *content);
00074 static void ngx_http_xxslt_parse_sax_attribute_decl(void *data, const xmlChar *elem,
00075 const xmlChar *fullname, int type, int def, const xmlChar *defaultValue,
00076 xmlEnumerationPtr tree);
00077 static void ngx_http_xxslt_parse_sax_element_decl(void *data, const xmlChar * name,
00078 int type, xmlElementContentPtr content);
00079 static void ngx_http_xxslt_parse_sax_notation_decl(void *data, const xmlChar *name,
00080 const xmlChar *publicId, const xmlChar *systemId);
00081 static void ngx_http_xxslt_parse_sax_unparsed_entity_decl(void *data,
00082 const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId,
00083 const xmlChar *notationName);
00084 static void ngx_http_xxslt_parse_sax_start_element(void *data,
00085 const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI,
00086 int nb_namespaces, const xmlChar **namespaces, int nb_attributes,
00087 int nb_defaulted, const xmlChar **attributes);
00088 static void ngx_http_xxslt_parse_sax_end_element(void *data,
00089 const xmlChar * localname ATTRIBUTE_UNUSED,
00090 const xmlChar * prefix ATTRIBUTE_UNUSED,
00091 const xmlChar * URI ATTRIBUTE_UNUSED);
00092 static void ngx_http_xxslt_parse_sax_characters(void *data, const xmlChar *p, int len);
00093 static void ngx_http_xxslt_parse_sax_cdata_block(void *data, const xmlChar *p,
00094 int len);
00095 static xmlEntityPtr ngx_http_xxslt_parse_sax_get_entity(void *data,
00096 const xmlChar *name);
00097 static xmlEntityPtr ngx_http_xxslt_parse_sax_get_parameter_entity(void *data,
00098 const xmlChar *name);
00099 static xmlParserInputPtr ngx_http_xxslt_parse_sax_resolve_entity(void *data,
00100 const xmlChar *publicId, const xmlChar *systemId);
00101 static void ngx_http_xxslt_parse_sax_reference(void *data, const xmlChar *name);
00102 static void ngx_http_xxslt_parse_sax_comment(void *data, const xmlChar *value);
00103 static void ngx_http_xxslt_parse_sax_processing_instruction(void *data,
00104 const xmlChar *target, const xmlChar *pidata);
00105 static int ngx_http_xxslt_parse_sax_is_standalone(void *data);
00106 static int ngx_http_xxslt_parse_sax_has_internal_subset(void *data);
00107 static int ngx_http_xxslt_parse_sax_has_external_subset(void *data);
00108 static void ngx_cdecl ngx_http_xxslt_parse_sax_error(void *data, const char *msg, ...);
00109
00110
00111
00117 ngx_http_xxslt_parse_data_t *
00118 ngx_http_xxslt_parse_create_new(ngx_http_request_t *r)
00119 {
00120 ngx_http_xxslt_parse_data_t *parse_data;
00121 xmlSAXHandler *sax;
00122
00123 parse_data = ngx_pcalloc(r->pool, sizeof(ngx_http_xxslt_parse_data_t));
00124
00125 if( parse_data == NULL )
00126 {
00127 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00128 "[parse_create_new] alloc fail.");
00129 return NULL;
00130 }
00131
00132 parse_data->r = r;
00133
00134 parse_data->ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
00135
00136 if(parse_data->ctxt == NULL)
00137 {
00138 return NULL;
00139 }
00140
00141 parse_data->sax = ngx_palloc(r->pool, sizeof(xmlSAXHandler));
00142 if (parse_data->sax == NULL) {
00143 return NULL;
00144 }
00145
00146 sax = parse_data->ctxt->sax;
00147
00148 ngx_memcpy(parse_data->sax, sax, sizeof(xmlSAXHandler));
00149
00150 sax->startDocument = ngx_http_xxslt_parse_sax_start_document;
00151 sax->endDocument = ngx_http_xxslt_parse_sax_end_document;
00152
00153 sax->internalSubset = ngx_http_xxslt_parse_sax_internal_subset;
00154 sax->externalSubset = ngx_http_xxslt_parse_sax_external_subset;
00155 sax->entityDecl = ngx_http_xxslt_parse_sax_entity_decl;
00156 sax->attributeDecl = ngx_http_xxslt_parse_sax_attribute_decl;
00157 sax->elementDecl = ngx_http_xxslt_parse_sax_element_decl;
00158 sax->notationDecl = ngx_http_xxslt_parse_sax_notation_decl;
00159 sax->unparsedEntityDecl = ngx_http_xxslt_parse_sax_unparsed_entity_decl;
00160 sax->setDocumentLocator = NULL;
00161
00162 sax->startElementNs = ngx_http_xxslt_parse_sax_start_element;
00163 sax->endElementNs = ngx_http_xxslt_parse_sax_end_element;
00164
00165 sax->characters = ngx_http_xxslt_parse_sax_characters;
00166 sax->ignorableWhitespace = ngx_http_xxslt_parse_sax_characters;
00167 sax->cdataBlock = ngx_http_xxslt_parse_sax_cdata_block;
00168 sax->getEntity = ngx_http_xxslt_parse_sax_get_entity;
00169 sax->resolveEntity = ngx_http_xxslt_parse_sax_resolve_entity;
00170 sax->getParameterEntity = ngx_http_xxslt_parse_sax_get_parameter_entity;
00171 sax->reference = ngx_http_xxslt_parse_sax_reference;
00172 sax->comment = ngx_http_xxslt_parse_sax_comment;
00173 sax->processingInstruction = ngx_http_xxslt_parse_sax_processing_instruction;
00174
00175 sax->isStandalone = ngx_http_xxslt_parse_sax_is_standalone;
00176 sax->hasInternalSubset = ngx_http_xxslt_parse_sax_has_internal_subset;
00177 sax->hasExternalSubset = ngx_http_xxslt_parse_sax_has_external_subset;
00178
00179 sax->warning = NULL;
00180 sax->error = ngx_http_xxslt_parse_sax_error;
00181 sax->fatalError = ngx_http_xxslt_parse_sax_error;
00182
00183 parse_data->ctxt->userData = parse_data;
00184
00185 parse_data->ctxt->replaceEntities = 1;
00186 parse_data->ctxt->loadsubset = 1;
00187
00188
00189 parse_data->r = r;
00190
00191 return parse_data;
00192 }
00193
00202 ngx_int_t
00203 ngx_http_xxslt_parse_add_data_chunk(ngx_http_xxslt_parse_data_t *parse_data, ngx_chain_t *in)
00204 {
00205 int rc;
00206 ngx_buf_t *buf;
00207 xmlParserCtxtPtr ctxt;
00208 ngx_http_request_t *r;
00209 u_char *tmp;
00210 ngx_int_t len;
00211
00212 if(parse_data == NULL || in == NULL)
00213 {
00214 return NGX_ERROR;
00215 }
00216
00217 buf = in->buf;
00218 ctxt = parse_data->ctxt;
00219 r = parse_data->r;
00220
00221 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00222 "[parse_add_data_chunk]");
00223
00224 if(!parse_data->preffix_added)
00225 {
00226 tmp = ngx_http_xxslt_parse_get_prefix();
00227 len = ngx_strlen(tmp);
00228
00229 rc = xmlParseChunk(ctxt, (char *) tmp, (int) len, 0);
00230
00231 if(rc != 0)
00232 {
00233 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00234 "[parse_add_data_chunk] xmlParseChunk() failed, error:%d", rc);
00235 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00236 "<b>Error during XML parsing</b> :: %s", parse_data->libxml_error);
00237 }
00238
00239 parse_data->preffix_added = 1;
00240 }
00241
00242 while(in != NULL)
00243 {
00244 buf = in->buf;
00245
00246 rc = xmlParseChunk(ctxt, (char *) buf->pos, (int) (buf->last - buf->pos), 0);
00247
00248
00249 if(rc != 0)
00250 {
00251 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00252 "[parse_add_data_chunk] xmlParseChunk() failed, error:%d", rc);
00253 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00254 "<b>Error during XML parsing</b> :: %s", parse_data->libxml_error);
00255 }
00256
00257 if(parse_data->include_err != 0)
00258 {
00259 return ngx_http_xxslt_finalize_with_error(r, parse_data->include_err,
00260 (char *) parse_data->include_err_msg);
00261 }
00262
00263
00264 buf->pos = buf->last;
00265
00266 in = in->next;
00267 }
00268
00269 if( !buf->last_buf && !buf->last_in_chain ) {
00270 return NGX_OK;
00271 }
00272
00273 tmp = ngx_http_xxslt_parse_get_suffix();
00274 len = ngx_strlen(tmp);
00275
00276 rc = xmlParseChunk(ctxt, (char *) tmp, (int) len, 1);
00277
00278 if(rc != 0)
00279 {
00280 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00281 "[parse_add_data_chunk] xmlParseChunk() failed, error:%d", rc);
00282 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00283 "<b>Error during XML parsing</b> :: %s", parse_data->libxml_error);
00284 }
00285
00286 parse_data->doc = ctxt->myDoc;
00287
00288 if(parse_data->doc == NULL)
00289 {
00290 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00291 "[parse_add_data_chunk] xmlParseChunk() finalization failed");
00292 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00293 "<b>XML finalization failed</b> :: libxml error: %s", parse_data->libxml_error);
00294 }
00295 if(!ctxt->wellFormed)
00296 {
00297 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00298 "[parse_add_data_chunk] XML is not well formed");
00299 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00300 "<b>XML is not well formed</b> :: libxml error: %s", parse_data->libxml_error);
00301 }
00302
00303 if(parse_data->stylesheet_declared)
00304 {
00305 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00306 "[parse_add_data_chunk] parse doc to stylesheet :: %d", (ngx_int_t) parse_data->doc);
00307
00308 parse_data->stylesheet = xsltParseStylesheetDoc(parse_data->doc);
00309
00310 if(parse_data->stylesheet == NULL)
00311 {
00312 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00313 "[parse_add_data_chunk] Error during XSLT stylesheet parsing");
00314 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00315 "<b>Error during parsing XML to XSLT</b> :: libxml error: %s", parse_data->libxml_error);
00316 }
00317 }
00318
00319 parse_data->xslt_ready = 1;
00320
00321 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00322 "[parse_add_data_chunk] parse content end - downloads: %d", parse_data->dl_in_progress);
00323
00324 if(parse_data->dl_in_progress > 0) {
00325 return NGX_DONE;
00326 }
00327 else if(parse_data->dl_in_progress == 0) {
00328 parse_data->done = 1;
00329
00330
00331 return NGX_OK;
00332 }
00333 else {
00334 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00335 "[parse_add_data_chunk] - unknown error, downloads: %d", parse_data->dl_in_progress);
00336 return ngx_http_xxslt_finalize_with_error(r,
00337 NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
00338 }
00339 }
00340
00346 ngx_int_t
00347 ngx_http_xxslt_parse_apply(ngx_http_xxslt_parse_data_t *parse_data)
00348 {
00349 ngx_chain_t *cl;
00350 xmlDocPtr res;
00351 xmlChar *buf = NULL;
00352 int len;
00353 int rc;
00354
00355 ngx_http_request_t *r;
00356 r = parse_data->r;
00357
00358 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00359 "[parse_apply]");
00360
00361 if(parse_data->stylesheet != NULL)
00362 {
00363 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00364 "[parse_apply] application of stylesheet");
00365
00366
00367 res = xsltApplyStylesheet(parse_data->stylesheet, parse_data->includes, NULL);
00368
00369 if(res == NULL)
00370 {
00371 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00372 "[parse_apply] application of stylesheet failed");
00373 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00374 "<b>Application of stylesheet failed</b>");
00375 }
00376
00377 rc = xsltSaveResultToString(&buf, &len, res, parse_data->stylesheet);
00378
00379
00380 xmlFreeDoc(res);
00381
00382 if(rc != 0)
00383 {
00384 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00385 "[parse_apply] xsltSaveResultToString failed");
00386 return ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00387 "<b>xsltSaveResultToString failed</b>");
00388 }
00389 }
00390
00391 if(buf == NULL)
00392 {
00393 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00394 "[parse_apply] result is empty");
00395 len = 1;
00396 }
00397
00398 cl = ngx_pcalloc(r->pool, sizeof(ngx_chain_t));
00399 if(cl == NULL)
00400 {
00401 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00402 "[parse_apply] buffer chain allocation failed");
00403 xmlFree(buf);
00404 return ngx_http_xxslt_finalize_with_error(r,
00405 NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
00406 }
00407
00408 cl->buf = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
00409 if(cl->buf == NULL)
00410 {
00411 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00412 "[parse_apply] buffer allocation failed");
00413 xmlFree(buf);
00414 return ngx_http_xxslt_finalize_with_error(r,
00415 NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
00416 }
00417 cl->next = NULL;
00418
00419 cl->buf->pos = ngx_pcalloc(r->pool, len + 1);
00420 if(cl->buf->pos == NULL)
00421 {
00422 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00423 "[parse_apply] buffer content allocation failed");
00424 xmlFree(buf);
00425 return ngx_http_xxslt_finalize_with_error(r,
00426 NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
00427 }
00428
00429 if(buf != NULL)
00430 ngx_cpystrn(cl->buf->pos, (u_char *) buf, len+1);
00431 else
00432 {
00433 cl->buf->pos[0] = (u_char) ' ';
00434 cl->buf->pos[1] = (u_char) '\0';
00435 cl->buf->last = cl->buf->pos + len;
00436 }
00437
00438 cl->buf->last = cl->buf->pos + len;
00439 cl->buf->memory = 1;
00440
00441
00442 ngx_http_xxslt_parse_add_buffer_chain(parse_data, cl);
00443
00444 xmlFree(buf);
00445
00446 return NGX_OK;
00447 }
00448
00454 static void
00455 ngx_http_xxslt_parse_add_buffer_chain(ngx_http_xxslt_parse_data_t *parse_data, ngx_chain_t *in)
00456 {
00457 ngx_int_t chain_len = 0;
00458
00459 if(parse_data->buffer_chain == NULL)
00460 {
00461 parse_data->buffer_chain = in;
00462 }
00463 else
00464 {
00465 parse_data->buffer_chain_tail->next = in;
00466 }
00467
00468 while(in)
00469 {
00470 if(in->buf) {
00471 chain_len += in->buf->last - in->buf->pos;
00472 }
00473
00474 parse_data->buffer_chain_tail = in;
00475 in = in->next;
00476 }
00477 parse_data->res_len += chain_len;
00478 }
00479
00487 static ngx_http_xxslt_include_t *
00488 ngx_http_xxslt_parse_create_new_include(ngx_http_xxslt_parse_data_t *parse_data)
00489 {
00490 ngx_http_xxslt_include_t *include;
00491 ngx_http_request_t *r;
00492
00493 r = parse_data->r;
00494
00495 include = ngx_pcalloc(r->pool, sizeof(ngx_http_xxslt_include_t));
00496
00497 if(include == NULL)
00498 {
00499 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00500 "[parse_create_new_include] alloc failed");
00501 return NULL;
00502 }
00503
00504 include->parent_parse = parse_data;
00505
00506 if (parse_data->inc_list == NULL) {
00507 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00508 "[parse_create_new_include] new inc_list created");
00509
00510 parse_data->inc_list = parse_data->inc_list_tail = include;
00511 parse_data->inc_act = parse_data->inc_list;
00512 }
00513 else {
00514 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00515 "[parse_create_new_include] new include added to inc_list");
00516
00517 parse_data->inc_list_tail->next = include;
00518 parse_data->inc_list_tail = include;
00519 }
00520
00521 return include;
00522 }
00523
00532 static void
00533 ngx_http_xxslt_parse_get_include(ngx_http_xxslt_include_t *include, ngx_flag_t use_cache)
00534 {
00535 ngx_int_t rc;
00536 ngx_http_request_t *r;
00537 u_char *uri;
00538
00539 uri = include->src;
00540 r = include->parent_parse->r;
00541
00542 if(use_cache == XXSLT_USE_CACHE && include->ttl > 0)
00543 {
00544 rc = ngx_http_xxslt_parse_get_cached_include(r, include, uri);
00545 }
00546 else
00547 {
00548 rc = NGX_ERROR;
00549 }
00550
00551 if(rc == NGX_OK)
00552 return;
00553
00554
00555 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00556 "[parse_get_include] xcache get %s request failed, trying classic method", uri);
00557
00558
00559 if(ngx_strncmp(uri, (u_char *) "http://", 7) == 0)
00560 {
00561 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00562 "[parse_get_include] include URL: %s", uri);
00563
00564 rc = ngx_http_xxslt_parse_get_external_include(include);
00565 }
00566 else
00567 {
00568 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00569 "[parse_get_include] local URI: %s", uri);
00570
00571 rc = ngx_http_xxslt_parse_get_local_include(include);
00572 }
00573
00574
00575 if(rc != NGX_OK && rc != NGX_AGAIN)
00576 {
00577 include->error = 1;
00578 ngx_http_xxslt_parse_process_include(include, 0);
00579 }
00580 }
00581
00587 static void
00588 ngx_http_xxslt_parse_use_alt_src(ngx_http_xxslt_include_t *include)
00589 {
00590 if(include->alt == NULL)
00591 {
00592 return;
00593 }
00594
00595 include->src = include->alt;
00596 include->alt = NULL;
00597 include->error = 0;
00598
00599 ngx_http_xxslt_parse_get_include(include, XXSLT_USE_CACHE);
00600 }
00601
00608 static ngx_int_t
00609 ngx_http_xxslt_parse_get_external_include(ngx_http_xxslt_include_t *include)
00610 {
00611 ngx_http_download_conn_t *dl_ctx;
00612 ngx_http_request_t *r;
00613 ngx_str_t *url;
00614 ngx_int_t rc;
00615
00616 r = include->parent_parse->r;
00617
00618 dl_ctx = ngx_http_download_create_new(r);
00619
00620 dl_ctx->r = r;
00621
00622 dl_ctx->data = include;
00623
00624 dl_ctx->done_handler = ngx_http_xxslt_parse_download_handler;
00625
00626
00627 if(include->dl_timeout != NGX_CONF_UNSET_MSEC)
00628 {
00629 dl_ctx->connect_timeout = include->dl_timeout;
00630 dl_ctx->read_timeout = include->dl_timeout;
00631 dl_ctx->write_timeout = include->dl_timeout;
00632 }
00633
00634 if(include->download != NULL)
00635 {
00636 ngx_http_download_cleanup(include->download);
00637 }
00638
00639 include->download = dl_ctx;
00640
00641 url = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
00642
00643 if(url == NULL) {
00644 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00645 "[parse_get_external_include] alloc failed");
00646 return ngx_http_xxslt_finalize_with_error(r,
00647 NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
00648 }
00649
00650 url->data = include->src;
00651 url->len = strlen((char *) include->src);
00652
00653 rc = ngx_http_download_parse_url(url, dl_ctx);
00654
00655 if(rc != NGX_OK)
00656 {
00657 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00658 "[parse_get_external_include] parsing of url failed");
00659 return NGX_ERROR;
00660 }
00661
00662 rc = ngx_http_download_enqueue(dl_ctx);
00663
00664 if(rc != NGX_OK && rc != NGX_AGAIN)
00665 {
00666 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00667 "[parse_get_external_include] enqueue of download failed");
00668 return NGX_ERROR;
00669 }
00670
00671 include->parent_parse->dl_in_progress++;
00672
00673 return rc;
00674 }
00675
00683 static void
00684 ngx_http_xxslt_parse_download_handler(ngx_http_download_conn_t *dl_ctx)
00685 {
00686 ngx_http_xxslt_include_t *include;
00687 ngx_http_xxslt_parse_data_t *parse_data;
00688 ngx_http_request_t *r;
00689
00690 ngx_int_t headers_len;
00691
00692 include = dl_ctx->data;
00693 parse_data = include->parent_parse;
00694 r = parse_data->r;
00695
00696
00697 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00698 "[parse_include_ready]");
00699
00700 parse_data->dl_in_progress--;
00701
00702 include->ready = 1;
00703
00704 if(dl_ctx->error != NGX_OK || dl_ctx->status != 200)
00705 {
00706 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00707 "[parse_include_ready] error during include download: rc :: %d status:: %d", dl_ctx->error, dl_ctx->status);
00708 include->error = 1;
00709 }
00710
00711 if(dl_ctx->out_bufs != NULL &&
00712 dl_ctx->out_bufs->buf != NULL &&
00713 dl_ctx->out_bufs->buf->pos != NULL &&
00714 dl_ctx->body_start != NULL)
00715 {
00716 headers_len = dl_ctx->body_start - dl_ctx->out_bufs->buf->pos;
00717
00718 include->buffer_chain = dl_ctx->out_bufs;
00719 include->buffer_chain->buf->pos = dl_ctx->body_start;
00720 }
00721 else
00722 {
00723 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00724 "[parse_include_ready] error during include download - empty buffer");
00725 include->error = 1;
00726 }
00727
00728 ngx_http_xxslt_parse_process_include(include, XXSLT_USE_CACHE);
00729 }
00730
00739 static void
00740 ngx_http_xxslt_parse_process_include(ngx_http_xxslt_include_t *include, ngx_flag_t set_cache)
00741 {
00742 ngx_int_t rc;
00743 ngx_http_request_t *r;
00744 ngx_http_xxslt_parse_data_t *parse_data;
00745
00746 parse_data = include->parent_parse;
00747 r = parse_data->r;
00748
00749 if(include->error == 0)
00750 {
00751 if(set_cache == XXSLT_USE_CACHE && include->ttl > 0)
00752 {
00753 rc = ngx_http_xxslt_parse_set_cached_include(r, include);
00754 if( rc != NGX_OK ) {
00755 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00756 "[parse_process_include] xcache set request error");
00757 }
00758 }
00759
00760 rc = ngx_http_xxslt_parse_add_include(include);
00761
00762 if(rc != NGX_OK)
00763 {
00764 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00765 "[parse_process_include] add include error");
00766 include->error = 1;
00767 }
00768 }
00769 if(include->error != 0)
00770 {
00771 if(include->alt != NULL)
00772 {
00773 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00774 "[parse_process_include] broken include, trying to use alt source");
00775 ngx_http_xxslt_parse_use_alt_src(include);
00776 return;
00777 }
00778 else if(include->onerror == ERR_FAIL)
00779 {
00780 ngx_http_xxslt_finalize_with_error(r, NGX_ERROR,
00781 "Include [name=%s src=%s] is unavailable", include->name, include->src);
00782 return;
00783 }
00784 }
00785
00786
00787 if(parse_data->dl_in_progress == 0 && parse_data->xslt_ready)
00788 {
00789 parse_data->done = 1;
00790 }
00791
00792 ngx_http_xxslt_process_data(r);
00793 }
00794
00803 static ngx_int_t
00804 ngx_http_xxslt_parse_add_include(ngx_http_xxslt_include_t *include)
00805 {
00806 ngx_http_xxslt_parse_data_t *parse_data;
00807
00808 ngx_http_request_t *r;
00809
00810 ngx_chain_t *bc;
00811
00812 xmlDocPtr includesDoc;
00813 xmlNodePtr newInc;
00814 xmlNodePtr newNode;
00815 xmlParserCtxtPtr ctxt;
00816 xmlDocPtr incDoc;
00817
00818 ngx_int_t rc;
00819
00820 parse_data = include->parent_parse;
00821 includesDoc = parse_data->includes;
00822 r = parse_data->r;
00823
00824 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00825 "[parse_add_include]");
00826
00827 if(include->error)
00828 {
00829 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00830 "[parse_add_include] include broken");
00831 return NGX_ERROR;
00832 }
00833
00834 if(include->data_type == PARSE_XML)
00835 {
00836 bc = include->buffer_chain;
00837
00838 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
00839
00840 while(1)
00841 {
00842 rc = xmlParseChunk(ctxt, (char *) bc->buf->pos, (int) (bc->buf->last - bc->buf->pos),
00843 (bc->buf->last_buf) || (bc->buf->last_in_chain));
00844
00845 if(rc != 0)
00846 {
00847 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00848 "[parse_add_include] error during xml include parsing");
00849 return NGX_ERROR;
00850 }
00851
00852 if (bc->buf->last_buf == 1)
00853 break;
00854 else
00855 bc = bc->next;
00856 }
00857
00858 incDoc = ctxt->myDoc;
00859
00860
00861 xmlFreeParserCtxt(ctxt);
00862
00863 if(incDoc == NULL)
00864 {
00865 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00866 "[parse_add_include] error during xml include parsing");
00867 return NGX_ERROR;
00868 }
00869
00870 newInc = xmlDocGetRootElement(incDoc);
00871
00872 if(newInc == NULL)
00873 {
00874 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00875 "[parse_add_include] error during xml include parsing - no root element");
00876 xmlFreeDoc(incDoc);
00877 return NGX_ERROR;
00878 }
00879
00880 newInc = xmlDocCopyNodeList(includesDoc, newInc);
00881
00882
00883 xmlFreeDoc(incDoc);
00884
00885 if(newInc == NULL)
00886 {
00887 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00888 "[parse_add_include] error during xml include parsing - copy error");
00889 return NGX_ERROR;
00890 }
00891
00892
00893
00894 newNode = xmlNewChild(includesDoc->children, NULL, (xmlChar *) include->name, NULL);
00895
00896 if(newNode == NULL)
00897 {
00898 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00899 "[parse_add_include] adding new child to include doc failed");
00900 return NGX_ERROR;
00901 }
00902
00903 newInc = xmlAddChild(newNode, newInc);
00904
00905 if(newInc == NULL)
00906 {
00907 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00908 "[parse_add_include] adding new child to include doc failed");
00909 return NGX_ERROR;
00910 }
00911 }
00912 if(include->paste)
00913 {
00914 ngx_http_xxslt_parse_add_buffer_chain(parse_data, include->buffer_chain);
00915 }
00916
00917 return NGX_OK;
00918 }
00919
00927 static ngx_int_t
00928 ngx_http_xxslt_parse_get_local_include(ngx_http_xxslt_include_t *include)
00929 {
00930 ngx_int_t rc;
00931 ngx_http_request_t *r;
00932 ngx_str_t *uri_str;
00933 ngx_chain_t *buffer_chain = NULL;
00934
00935 r = include->parent_parse->r;
00936
00937 include->ready = 1;
00938
00939 uri_str = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
00940
00941 if(uri_str == NULL)
00942 {
00943 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
00944 "[parse_get_local_include] alloc failed");
00945 return ngx_http_xxslt_finalize_with_error(r,
00946 NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
00947 }
00948
00949 uri_str->data = include->src;
00950 uri_str->len = strlen((char *) include->src);
00951
00952 rc = ngx_http_filesync_get(r, uri_str, &buffer_chain);
00953
00954 if(rc != NGX_OK || buffer_chain == NULL)
00955 {
00956 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
00957 "[parse_get_local_include] fileasync failed");
00958 return NGX_ERROR;
00959 }
00960
00961 include->buffer_chain = buffer_chain;
00962
00963 ngx_http_xxslt_parse_process_include(include, XXSLT_USE_CACHE);
00964 return NGX_OK;
00965 }
00966
00971 void
00972 ngx_http_xxslt_parse_cleanup(ngx_http_xxslt_parse_data_t *parse_data)
00973 {
00974 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, parse_data->r->connection->log, 0,
00975 "[parse_cleanup] - parse_data: %d", (ngx_int_t)parse_data );
00976
00977 if(parse_data->stylesheet == NULL && parse_data->doc != NULL)
00978 {
00979 xmlFreeDoc(parse_data->doc);
00980 parse_data->doc = NULL;
00981 }
00982 if(parse_data->ctxt != NULL)
00983 {
00984 xmlFreeParserCtxt(parse_data->ctxt);
00985 parse_data->ctxt = NULL;
00986 }
00987 if(parse_data->stylesheet != NULL)
00988 {
00989 xsltFreeStylesheet(parse_data->stylesheet);
00990 parse_data->stylesheet = NULL;
00991 parse_data->doc = NULL;
00992 }
00993
00994
00995 while(parse_data->inc_list)
00996 {
00997
00998 if(parse_data->inc_list->download != NULL)
00999 {
01000 ngx_http_download_cleanup(parse_data->inc_list->download);
01001 }
01002
01003 if(parse_data->inc_list->xcache_get != NULL)
01004 {
01005 ngx_http_mxcache_cleanup(parse_data->inc_list->xcache_get);
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015 parse_data->inc_list = parse_data->inc_list->next;
01016 }
01017 }
01018
01023 static u_char *ngx_http_xxslt_parse_get_prefix(void)
01024 {
01025 return (u_char *) "<"
01026 PARSE_DUMMY_NODE
01027 ">\n";
01028 }
01029
01034 static u_char *ngx_http_xxslt_parse_get_suffix(void)
01035 {
01036 return (u_char *) "</"
01037 PARSE_DUMMY_NODE
01038 ">\n";
01039 }
01040
01049 static ngx_int_t
01050 ngx_http_xxslt_parse_get_cached_include(ngx_http_request_t *r, ngx_http_xxslt_include_t *include, u_char *uri)
01051 {
01052 ngx_http_mxcache_conn_t *xc_ctx;
01053 ngx_int_t rc;
01054 u_char *key;
01055
01056 if( !ngx_http_mxcache_is_enabled(r) ) {
01057 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
01058 "[parse_get_cached_include] mxcache disabled");
01059 return NGX_DONE;
01060 }
01061
01062 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
01063 "[parse_get_cached_include] get %s request", uri);
01064
01065 xc_ctx = ngx_http_mxcache_create_new(r);
01066
01067
01068 if(include->xcache_get != NULL)
01069 {
01070 ngx_http_mxcache_cleanup(include->xcache_get);
01071 }
01072 include->xcache_get = xc_ctx;
01073
01074
01075
01076 if( ngx_strncmp(uri, "http://", 7) == 0 ) {
01077 key = uri;
01078 }
01079 else {
01080 key = ngx_palloc(r->pool, r->uri.len + ngx_strlen(uri) + 1);
01081 ngx_cpystrn(key, r->uri.data, r->uri.len + 1);
01082 strcat((char*)key, (char*)uri);
01083 }
01084
01085
01086 xc_ctx->key = key;
01087 xc_ctx->data = include;
01088 xc_ctx->res_uri = uri;
01089 xc_ctx->rpool = r->pool;
01090
01091 xc_ctx->done_handler = ngx_http_xxslt_parse_mxcache_get_handler;
01092
01093 if(include->cache_timeout != NGX_CONF_UNSET_MSEC)
01094 {
01095 xc_ctx->read_timeout = include->cache_timeout;
01096 xc_ctx->write_timeout = include->cache_timeout;
01097 }
01098
01099 rc = ngx_http_mxcache_get(xc_ctx);
01100
01101 if(rc == NGX_OK)
01102 {
01103 include->parent_parse->dl_in_progress++;
01104 }
01105 return rc;
01106 }
01107
01115 static void
01116 ngx_http_xxslt_parse_mxcache_get_handler(ngx_http_mxcache_conn_t *conn)
01117 {
01118 ngx_http_xxslt_include_t *include;
01119 ngx_http_xxslt_parse_data_t *parse_data;
01120 ngx_http_request_t *r;
01121
01122
01123 include = conn->data;
01124
01125 parse_data = include->parent_parse;
01126 r = parse_data->r;
01127
01128
01129 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, conn->log, 0,
01130 "[parse_mxcache_get_handler] xcached get %s, rc: %d", conn->res_uri, conn->error);
01131
01132 parse_data->dl_in_progress--;
01133
01134 if( conn->error == NGX_OK && conn->out_bufs && conn->data_begin ) {
01135
01136 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
01137 "[parse_mxcache_get_handler] xcache get %s, OK!", conn->res_uri);
01138
01139 include->ready = 1;
01140 include->buffer_chain = conn->out_bufs;
01141
01142
01143 ngx_http_xxslt_parse_process_include(include, XXSLT_NO_CACHE);
01144 }
01145 else {
01146 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, conn->log, 0,
01147 "[parse_mxcache_get_handler] xcached get %s failed (rc: %d), trying classic method", conn->res_uri, conn->error);
01148
01149 ngx_http_xxslt_parse_get_include(include, XXSLT_NO_CACHE);
01150 }
01151 }
01152
01160 static ngx_int_t
01161 ngx_http_xxslt_parse_set_cached_include(ngx_http_request_t *r, ngx_http_xxslt_include_t *include)
01162 {
01163 ngx_http_mxcache_conn_t *xc_ctx;
01164 ngx_int_t bytes;
01165 ngx_int_t size;
01166 ngx_int_t rc;
01167 u_char *key;
01168 ngx_chain_t *cl;
01169 u_char *uri;
01170
01171
01172 if( !ngx_http_mxcache_is_enabled(r) ) {
01173 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
01174 "[parse_set_cached_include] xcache disabled");
01175 return NGX_DONE;
01176 }
01177
01178 cl = include->buffer_chain;
01179 uri = include->src;
01180
01181 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
01182 "[parse_set_cached_include] xcache set %s request", uri);
01183
01184 xc_ctx = ngx_http_mxcache_create_new(r);
01185
01186
01187
01188
01189 if( ngx_strncmp(uri, "http://", 7) == 0 ) {
01190 key = uri;
01191 }
01192 else {
01193 key = ngx_palloc(r->pool, r->uri.len + ngx_strlen(uri) + 1);
01194 ngx_cpystrn(key, r->uri.data, r->uri.len + 1);
01195 strcat((char*)key, (char*)uri);
01196 }
01197
01198
01199
01200 xc_ctx->key = key;
01201 xc_ctx->res_uri = uri;
01202
01203 if(include->cache_timeout != NGX_CONF_UNSET_MSEC)
01204 {
01205 xc_ctx->read_timeout = include->cache_timeout;
01206 xc_ctx->write_timeout = include->cache_timeout;
01207 }
01208
01209 if(include->ttl != NGX_CONF_UNSET_MSEC)
01210 xc_ctx->exp_time = include->ttl / 1000;
01211
01212 bytes = 0;
01213
01214 while( cl ) {
01215 bytes += ngx_buf_size(cl->buf);
01216
01217 if( xc_ctx->out_bufs == NULL ) {
01218 xc_ctx->out_bufs = xc_ctx->out_bufs_tail = ngx_alloc_chain_link(xc_ctx->pool);
01219 }
01220 else {
01221 xc_ctx->out_bufs_tail->next = ngx_alloc_chain_link(xc_ctx->pool);
01222 xc_ctx->out_bufs_tail = xc_ctx->out_bufs_tail->next;
01223 }
01224 size = cl->buf->last - cl->buf->pos;
01225 xc_ctx->out_bufs_tail->buf = ngx_create_temp_buf(xc_ctx->pool, size);
01226 ngx_memcpy(xc_ctx->out_bufs_tail->buf->pos, cl->buf->pos, size);
01227 xc_ctx->out_bufs_tail->buf->last = xc_ctx->out_bufs_tail->buf->pos + size;
01228
01229 cl = cl->next;
01230 }
01231 xc_ctx->out_bufs_tail->next = NULL;
01232
01233 xc_ctx->bytes = bytes;
01234
01235 xc_ctx->done_handler = ngx_http_xxslt_parse_mxcache_set_handler;
01236
01237 rc = ngx_http_mxcache_set(xc_ctx);
01238
01239 if( rc != NGX_OK ) {
01240
01241 ngx_http_mxcache_cleanup(xc_ctx);
01242 }
01243 return rc;
01244 }
01245
01252 static void
01253 ngx_http_xxslt_parse_mxcache_set_handler(ngx_http_mxcache_conn_t *conn)
01254 {
01255 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, conn->log, 0,
01256 "[xcache_set_handler] %s, rc: %d", conn->res_uri, conn->error);
01257
01258 ngx_http_mxcache_cleanup(conn);
01259 }
01260
01269 static void
01270 ngx_http_xxslt_parse_include_error(ngx_http_xxslt_parse_data_t *parse_data, char *msg, ...)
01271 {
01272 va_list args;
01273 u_char err_msg[NGX_MAX_ERROR_STR];
01274 ngx_int_t n;
01275
01276 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, parse_data->r->connection->log, 0,
01277 "[parse_include_error] include error");
01278
01279 parse_data->include_err = NGX_HTTP_INTERNAL_SERVER_ERROR;
01280
01281 if(msg == NULL)
01282 {
01283 return;
01284 }
01285
01286 err_msg[0] = '\0';
01287 va_start(args, msg);
01288 n = (size_t) vsnprintf((char *) err_msg, NGX_MAX_ERROR_STR, msg, args);
01289 va_end(args);
01290 err_msg[n] = '\0';
01291
01292 parse_data->include_err_msg = ngx_pcalloc(parse_data->r->pool, sizeof(u_char)*(n+1));
01293
01294 if(parse_data->include_err_msg == NULL)
01295 {
01296 return;
01297 }
01298
01299 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, parse_data->r->connection->log, 0,
01300 "[parse_include_error] finished");
01301
01302 parse_data->include_err = NGX_ERROR;
01303 ngx_cpystrn(parse_data->include_err_msg, err_msg, n+1);
01304 }
01305
01306
01316 static void
01317 ngx_http_xxslt_parse_include_node(ngx_http_xxslt_parse_data_t *parse_data,
01318 int nb_attributes, const xmlChar **attributes)
01319 {
01320 ngx_http_request_t *r = parse_data->r;
01321 ngx_http_xxslt_filter_loc_conf_t *conf;
01322
01323 ngx_http_xxslt_include_t *include;
01324
01325
01326
01327 conf = ngx_http_get_module_loc_conf(r, ngx_http_xxslt_filter_module);
01328
01329 if(conf == NULL)
01330 {
01331 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01332 "[parse_node] conf is null");
01333 ngx_http_xxslt_parse_include_error(parse_data, NULL);
01334 return;
01335 }
01336
01337 u_char *name = NULL;
01338 u_char *src = NULL;
01339 u_char *alt = NULL;
01340 u_char *stylesheet = NULL;
01341 ngx_flag_t data_type = PARSE_UNKNOWN;
01342 ngx_flag_t paste = 1;
01343 ngx_int_t dl_timeout = conf->download_timeout;
01344 ngx_int_t cache_timeout = conf->cache_timeout;
01345 ngx_int_t ttl = conf->cache_expire;
01346 ngx_flag_t nostore = 0;
01347 ngx_int_t onerror = ERR_FAIL;
01348
01349 ngx_int_t i;
01350 ngx_int_t len;
01351
01352 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
01353 "[parse_node] include found");
01354
01355
01356 for(i = 0; i < nb_attributes*5; i+= 5)
01357 {
01358 len = attributes[i+4] - attributes[i+3];
01359 if(xmlStrcmp(attributes[i], (xmlChar *) "name") == 0)
01360 {
01361 name = ngx_pcalloc(r->pool, sizeof(u_char) * (len+1));
01362 if(name == NULL)
01363 {
01364 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01365 "[parse_node] alloc failed");
01366 ngx_http_xxslt_parse_include_error(parse_data, NULL);
01367 return;
01368 }
01369 ngx_cpystrn(name, (u_char *) attributes[i+3], len+1);
01370 }
01371 else if(xmlStrcmp(attributes[i], (xmlChar *) "src") == 0)
01372 {
01373 src = ngx_pcalloc(r->pool, sizeof(u_char) * (len+1));
01374 if(src == NULL)
01375 {
01376 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01377 "[parse_node] alloc failed");
01378 ngx_http_xxslt_parse_include_error(parse_data, NULL);
01379 return;
01380 }
01381 ngx_cpystrn(src, (u_char *) attributes[i+3], len+1);
01382 }
01383 else if(xmlStrcmp(attributes[i], (xmlChar *) "alt") == 0)
01384 {
01385 alt = ngx_pcalloc(r->pool, sizeof(u_char) * (len+1));
01386 if(alt == NULL)
01387 {
01388 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01389 "[parse_node] alloc failed");
01390 ngx_http_xxslt_parse_include_error(parse_data, NULL);
01391 return;
01392 }
01393 ngx_cpystrn(alt, (u_char *) attributes[i+3], len+1);
01394 }
01395 else if(xmlStrcmp(attributes[i], (xmlChar *) "dca") == 0)
01396 {
01397 if(len == 4 && xmlStrncmp(attributes[i+3], (xmlChar *) "xslt", len) == 0)
01398 {
01399 data_type = PARSE_XML;
01400 paste = 0;
01401 }
01402 else if(len == 4 && xmlStrncmp(attributes[i+3], (xmlChar *) "none", len) == 0)
01403 {
01404 data_type = PARSE_UNKNOWN;
01405 paste = 1;
01406 }
01407 else
01408 data_type = -2;
01409 }
01410 else if(xmlStrcmp(attributes[i], (xmlChar *) "maxwait") == 0)
01411 {
01412 dl_timeout = ngx_atoi((u_char *)attributes[i+3], len);
01413 if(dl_timeout < 0)
01414 dl_timeout = -2;
01415 }
01416 else if(xmlStrcmp(attributes[i], (xmlChar *) "ttl") == 0)
01417 {
01418 ttl = ngx_atoi((u_char *)attributes[i+3], len);
01419 ttl *= 1000;
01420 if(ttl < 0)
01421 ttl = -2;
01422
01423 }
01424 else if(xmlStrcmp(attributes[i], (xmlChar *) "no-store") == 0)
01425 {
01426 nostore = 1;
01427 }
01428 else if(xmlStrcmp(attributes[i], (xmlChar *) "onerror") == 0)
01429 {
01430 if(len == 8 && xmlStrncmp(attributes[i+3], (xmlChar *) "continue", len) == 0)
01431 onerror = ERR_CONTINUE;
01432 else
01433 onerror = -2;
01434 }
01435 else
01436 {
01437 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01438 "[parse_node] error while parsing include directive - unknow tag: %s", attributes[i]);
01439 ngx_http_xxslt_parse_include_error(parse_data,
01440 "<b>Error while parsing include directive</b> <br> unknown tag: %s", attributes[i]);
01441 return;
01442 }
01443 }
01444
01445 if(src == NULL || name == NULL || data_type == -2 || paste == -2 || dl_timeout == -2
01446 || ttl == -2 || onerror == -2)
01447 {
01448 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01449 "[parse node] incomplete or wrong include definition");
01450 ngx_http_xxslt_parse_include_error(parse_data,
01451 "<b>Incomplete or wrong include definition</b> <br>"
01452 "[name=%s src=%s]", name, src);
01453 return;
01454 }
01455
01456
01457 include = ngx_http_xxslt_parse_create_new_include(parse_data);
01458
01459 if(include == NULL)
01460 {
01461 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
01462 "[parse_node] error while creating new include");
01463 ngx_http_xxslt_parse_include_error(parse_data, NULL);
01464 return;
01465 }
01466
01467
01468 if(nostore == 1)
01469 ttl = 0;
01470
01471 include->name = name;
01472 include->src = src;
01473 include->alt = alt;
01474 include->stylesheet = stylesheet;
01475 include->data_type = data_type;
01476 include->paste = paste;
01477 include->dl_timeout = dl_timeout;
01478 include->cache_timeout = cache_timeout;
01479 include->ttl = ttl;
01480 include->onerror = onerror;
01481
01482
01483 ngx_http_xxslt_parse_get_include(include, XXSLT_USE_CACHE);
01484 }
01485
01486
01487 static void
01488 ngx_http_xxslt_parse_sax_processing_instruction(void *data, const xmlChar *target,
01489 const xmlChar *pidata)
01490 {
01491 ngx_http_xxslt_parse_data_t *parse_data = data;
01492
01493 parse_data->sax->processingInstruction(parse_data->ctxt, target, pidata);
01494 }
01495
01496 static void
01497 ngx_http_xxslt_parse_sax_start_document(void *data)
01498 {
01499 ngx_http_xxslt_parse_data_t *parse_data = data;
01500
01501 parse_data->sax->startDocument(parse_data->ctxt);
01502 }
01503
01504 static void
01505 ngx_http_xxslt_parse_sax_end_document(void *data)
01506 {
01507 ngx_http_xxslt_parse_data_t *parse_data = data;
01508
01509 parse_data->sax->endDocument(parse_data->ctxt);
01510 }
01511
01512 static void
01513 ngx_http_xxslt_parse_sax_internal_subset(void *data, const xmlChar *name,
01514 const xmlChar *externalId, const xmlChar *systemId)
01515 {
01516 ngx_http_xxslt_parse_data_t *parse_data = data;
01517
01518 parse_data->sax->internalSubset(parse_data->ctxt, name, externalId, systemId);
01519 }
01520
01521 static void
01522 ngx_http_xxslt_parse_sax_external_subset(void *data, const xmlChar *name,
01523 const xmlChar *externalId, const xmlChar *systemId)
01524 {
01525
01526 }
01527
01528 static void
01529 ngx_http_xxslt_parse_sax_entity_decl(void *data, const xmlChar *name, int type,
01530 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
01531 {
01532 ngx_http_xxslt_parse_data_t *parse_data = data;
01533
01534
01535 parse_data->sax->entityDecl(parse_data->ctxt, name, type, publicId, systemId, content);
01536 }
01537
01538 static void
01539 ngx_http_xxslt_parse_sax_attribute_decl(void *data, const xmlChar *elem,
01540 const xmlChar *fullname, int type, int def, const xmlChar *defaultValue,
01541 xmlEnumerationPtr tree)
01542 {
01543 ngx_http_xxslt_parse_data_t *parse_data = data;
01544
01545
01546 parse_data->sax->attributeDecl(parse_data->ctxt, elem, fullname, type, def, defaultValue,
01547 tree);
01548 }
01549
01550 static void
01551 ngx_http_xxslt_parse_sax_element_decl(void *data, const xmlChar * name, int type,
01552 xmlElementContentPtr content)
01553 {
01554 ngx_http_xxslt_parse_data_t *parse_data = data;
01555
01556 parse_data->sax->elementDecl(parse_data->ctxt, name, type, content);
01557 }
01558
01559 static void
01560 ngx_http_xxslt_parse_sax_notation_decl(void *data, const xmlChar *name,
01561 const xmlChar *publicId, const xmlChar *systemId)
01562 {
01563 ngx_http_xxslt_parse_data_t *parse_data = data;
01564
01565 parse_data->sax->notationDecl(parse_data->ctxt, name, publicId, systemId);
01566 }
01567
01568 static void
01569 ngx_http_xxslt_parse_sax_unparsed_entity_decl(void *data, const xmlChar *name,
01570 const xmlChar *publicId, const xmlChar *systemId,
01571 const xmlChar *notationName)
01572 {
01573 ngx_http_xxslt_parse_data_t *parse_data = data;
01574
01575 parse_data->sax->unparsedEntityDecl(parse_data->ctxt, name, publicId, systemId,
01576 notationName);
01577 }
01578
01579 static void
01580 ngx_http_xxslt_parse_sax_start_element(void *data, const xmlChar *localname,
01581 const xmlChar *prefix, const xmlChar *URI, int nb_namespaces,
01582 const xmlChar **namespaces, int nb_attributes, int nb_defaulted,
01583 const xmlChar **attributes)
01584 {
01585 ngx_http_xxslt_parse_data_t *parse_data = data;
01586
01587 if(xmlStrcmp(localname, (xmlChar *) "include") == 0) {
01588 ngx_http_xxslt_parse_include_node(parse_data, nb_attributes, attributes);
01589 return ;
01590 }
01591
01592 if(xmlStrcmp(localname, (xmlChar *) PARSE_DUMMY_NODE) == 0)
01593 return;
01594
01595 if(xmlStrcmp(prefix, (xmlChar *) "xsl") == 0 &&
01596 xmlStrcmp(localname, (xmlChar *) "stylesheet") == 0)
01597 {
01598 parse_data->stylesheet_declared = 1;
01599 }
01600
01601 parse_data->sax->startElementNs(parse_data->ctxt, localname, prefix, URI, nb_namespaces,
01602 namespaces, nb_attributes, nb_defaulted, attributes);
01603 }
01604
01605 static void
01606 ngx_http_xxslt_parse_sax_end_element(void *data,
01607 const xmlChar * localname ATTRIBUTE_UNUSED,
01608 const xmlChar * prefix ATTRIBUTE_UNUSED,
01609 const xmlChar * URI ATTRIBUTE_UNUSED)
01610 {
01611 ngx_http_xxslt_parse_data_t *parse_data = data;
01612
01613
01614 if(xmlStrcmp(localname, (xmlChar *) "include") == 0)
01615 return;
01616
01617 if(xmlStrcmp(localname, (xmlChar *) PARSE_DUMMY_NODE) == 0)
01618 return;
01619
01620 parse_data->sax->endElementNs(parse_data->ctxt, localname, prefix, URI);
01621 }
01622
01623 static void
01624 ngx_http_xxslt_parse_sax_characters(void *data, const xmlChar *p, int len)
01625 {
01626 ngx_http_xxslt_parse_data_t *parse_data = data;
01627
01628 parse_data->sax->characters(parse_data->ctxt, p, len);
01629 }
01630
01631 static void
01632 ngx_http_xxslt_parse_sax_cdata_block(void *data, const xmlChar *p, int len)
01633 {
01634 ngx_http_xxslt_parse_data_t *parse_data = data;
01635
01636 parse_data->sax->cdataBlock(parse_data->ctxt, p, len);
01637 }
01638
01639 static xmlEntityPtr
01640 ngx_http_xxslt_parse_sax_get_entity(void *data, const xmlChar *name)
01641 {
01642 ngx_http_xxslt_parse_data_t *parse_data = data;
01643
01644
01645 return parse_data->sax->getEntity(parse_data->ctxt, name);
01646 }
01647
01648 static xmlEntityPtr
01649 ngx_http_xxslt_parse_sax_get_parameter_entity(void *data, const xmlChar *name)
01650 {
01651 ngx_http_xxslt_parse_data_t *parse_data = data;
01652
01653
01654 return parse_data->sax->getParameterEntity(parse_data->ctxt, name);
01655 }
01656
01657 static xmlParserInputPtr
01658 ngx_http_xxslt_parse_sax_resolve_entity(void *data, const xmlChar *publicId,
01659 const xmlChar *systemId)
01660 {
01661 ngx_http_xxslt_parse_data_t *parse_data = data;
01662
01663 return parse_data->sax->resolveEntity(parse_data->ctxt, publicId, systemId);
01664 }
01665
01666 static void
01667 ngx_http_xxslt_parse_sax_reference(void *data, const xmlChar *name)
01668 {
01669 ngx_http_xxslt_parse_data_t *parse_data = data;
01670
01671 parse_data->sax->reference(parse_data->ctxt, name);
01672 }
01673
01674 static void
01675 ngx_http_xxslt_parse_sax_comment(void *data, const xmlChar *value)
01676 {
01677 ngx_http_xxslt_parse_data_t *parse_data = data;
01678
01679 parse_data->sax->comment(parse_data->ctxt, value);
01680 }
01681
01682 static int
01683 ngx_http_xxslt_parse_sax_is_standalone(void *data)
01684 {
01685 ngx_http_xxslt_parse_data_t *parse_data = data;
01686
01687 return parse_data->sax->isStandalone(parse_data->ctxt);
01688 }
01689
01690 static int
01691 ngx_http_xxslt_parse_sax_has_internal_subset(void *data)
01692 {
01693 ngx_http_xxslt_parse_data_t *parse_data = data;
01694
01695 return parse_data->sax->hasInternalSubset(parse_data->ctxt);
01696 }
01697
01698 static int
01699 ngx_http_xxslt_parse_sax_has_external_subset(void *data)
01700 {
01701 ngx_http_xxslt_parse_data_t *parse_data = data;
01702
01703 return parse_data->sax->hasExternalSubset(parse_data->ctxt);
01704 }
01705
01706 static void ngx_cdecl
01707 ngx_http_xxslt_parse_sax_error(void *data, const char *msg, ...)
01708 {
01709 ngx_http_xxslt_parse_data_t *parse_data = data;
01710
01711 size_t n;
01712 va_list args;
01713
01714 u_char *buf;
01715
01716 buf = ngx_pcalloc(parse_data->r->pool, sizeof(u_char)*NGX_MAX_ERROR_STR+1);
01717
01718 buf[0] = '\0';
01719
01720 va_start(args, msg);
01721 n = (size_t) vsnprintf((char *) buf, NGX_MAX_ERROR_STR, msg, args);
01722 va_end(args);
01723
01724 while (--n && (buf[n] == CR || buf[n] == LF)) { }
01725
01726 parse_data->libxml_error = (char *) buf;
01727 }
01728