You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2012/06/20 23:23:01 UTC
[4/14] Delete all the old files,
they are moved to plugins/experimental in our normal repo
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/fetcher/HttpDataFetcherImpl.cc
----------------------------------------------------------------------
diff --git a/esi/fetcher/HttpDataFetcherImpl.cc b/esi/fetcher/HttpDataFetcherImpl.cc
deleted file mode 100644
index 09eda83..0000000
--- a/esi/fetcher/HttpDataFetcherImpl.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#include "HttpDataFetcherImpl.h"
-#include "Utils.h"
-
-#include <arpa/inet.h>
-
-using std::string;
-using namespace EsiLib;
-
-const int HttpDataFetcherImpl::FETCH_EVENT_ID_BASE = 10000;
-
-inline void HttpDataFetcherImpl::_release(RequestData &req_data) {
- if (req_data.bufp) {
- if (req_data.hdr_loc) {
- TSHandleMLocRelease(req_data.bufp, TS_NULL_MLOC, req_data.hdr_loc);
- req_data.hdr_loc = 0;
- }
- TSMBufferDestroy(req_data.bufp);
- req_data.bufp = 0;
- }
-}
-
-HttpDataFetcherImpl::HttpDataFetcherImpl(TSCont contp,sockaddr const* client_addr,
- const char *debug_tag)
- : _contp(contp), _debug_tag(debug_tag), _n_pending_requests(0), _curr_event_id_base(FETCH_EVENT_ID_BASE),
- _headers_str(""),_client_addr(client_addr) {
- _http_parser = TSHttpParserCreate();
-}
-
-HttpDataFetcherImpl::~HttpDataFetcherImpl() {
- clear();
- TSHttpParserDestroy(_http_parser);
-}
-
-inline void
-HttpDataFetcherImpl::_buildHeadersString() {
- TSDebug(_debug_tag.c_str(), "[%s] Building header string...", __FUNCTION__);
- _headers_str.clear();
- for (StringHash::const_iterator iter = _headers.begin(); iter != _headers.end(); ++iter) {
- _headers_str.append(iter->first);
- _headers_str.append(": ");
- _headers_str.append(iter->second);
- _headers_str += "\r\n";
- }
-}
-
-void
-HttpDataFetcherImpl::_createRequest(std::string &http_req, const string &url) {
- http_req.assign("GET ");
- http_req.append(url);
- http_req.append(" HTTP/1.0\r\n");
- if (_headers.size()) {
- if (!_headers_str.size()) {
- _buildHeadersString();
- }
- http_req.append(_headers_str);
- }
- http_req.append("\r\n");
-}
-
-bool
-HttpDataFetcherImpl::addFetchRequest(const string &url, FetchedDataProcessor *callback_obj /* = 0 */) {
- // do we already have a request for this?
- std::pair<UrlToContentMap::iterator, bool> insert_result =
- _pages.insert(UrlToContentMap::value_type(url, RequestData()));
- if (callback_obj) {
- ((insert_result.first)->second).callback_objects.push_back(callback_obj);
- }
- if (!insert_result.second) {
- TSDebug(_debug_tag.c_str(), "[%s] Fetch request for url [%s] already added", __FUNCTION__,
- url.data());
- return true;
- }
-
- string http_req;
- _createRequest(http_req, url);
-
- TSFetchEvent event_ids;
- event_ids.success_event_id = _curr_event_id_base;
- event_ids.failure_event_id = _curr_event_id_base + 1;
- event_ids.timeout_event_id = _curr_event_id_base + 2;
- _curr_event_id_base += 3;
-
-//FIXME. This looks to be a regression.
-TSFetchUrl(http_req.data(), http_req.size(), _client_addr, _contp, AFTER_BODY,
- event_ids);
-/* if (TSFetchUrl(http_req.data(), http_req.size(), _client_addr, _contp, AFTER_BODY,
- event_ids) == TS_ERROR) {
- TSError("Failed to add fetch request for URL [%.*s]", url.size(), url.data());
- return false;
- }
-*/
-
- TSDebug(_debug_tag.c_str(), "[%s] Successfully added fetch request for URL [%s]",
- __FUNCTION__, url.data());
- _page_entry_lookup.push_back(insert_result.first);
- ++_n_pending_requests;
- return true;
-}
-
-bool
-HttpDataFetcherImpl::_isFetchEvent(TSEvent event, int &base_event_id) const {
- base_event_id = _getBaseEventId(event);
- if ((base_event_id < 0) || (base_event_id >= static_cast<int>(_page_entry_lookup.size()))) {
- TSDebug(_debug_tag.c_str(), "[%s] Event id %d not within fetch event id range [%d, %ld)",
- __FUNCTION__, event, FETCH_EVENT_ID_BASE, FETCH_EVENT_ID_BASE + (_page_entry_lookup.size() * 3));
- return false;
- }
- return true;
-}
-
-bool
-HttpDataFetcherImpl::handleFetchEvent(TSEvent event, void *edata) {
- int base_event_id;
- if (!_isFetchEvent(event, base_event_id)) {
- TSError("[%s] Event %d is not a fetch event", __FUNCTION__, event);
- return false;
- }
-
- UrlToContentMap::iterator &req_entry = _page_entry_lookup[base_event_id];
- const string &req_str = req_entry->first;
- RequestData &req_data = req_entry->second;
-
- if (req_data.complete) {
- // can only happen if there's a bug in this or fetch API code
- TSError("[%s] URL [%s] already completed; Retaining original data", __FUNCTION__, req_str.c_str());
- return false;
- }
-
- --_n_pending_requests;
- req_data.complete = true;
-
- int event_id = (static_cast<int>(event) - FETCH_EVENT_ID_BASE) % 3;
- if (event_id != 0) { // failure or timeout
- TSError("[%s] Received failure/timeout event id %d for request [%s]",
- __FUNCTION__, event_id, req_str.data());
- return true;
- }
-
- int page_data_len;
- const char *page_data = TSFetchRespGet(static_cast<TSHttpTxn>(edata), &page_data_len);
- req_data.response.assign(page_data, page_data_len);
- bool valid_data_received = false;
- const char *startptr = req_data.response.data(), *endptr = startptr + page_data_len;
-
- req_data.bufp = TSMBufferCreate();
- req_data.hdr_loc = TSHttpHdrCreate(req_data.bufp);
- TSHttpHdrTypeSet(req_data.bufp, req_data.hdr_loc, TS_HTTP_TYPE_RESPONSE);
- TSHttpParserClear(_http_parser);
-
- if (TSHttpHdrParseResp(_http_parser, req_data.bufp, req_data.hdr_loc, &startptr, endptr) == TS_PARSE_DONE) {
- TSHttpStatus resp_status = TSHttpHdrStatusGet(req_data.bufp, req_data.hdr_loc);
- if (resp_status == TS_HTTP_STATUS_OK) {
- valid_data_received = true;
- req_data.body_len = endptr - startptr;
- req_data.body = startptr;
- TSDebug(_debug_tag.c_str(),
- "[%s] Inserted page data of size %d starting with [%.6s] for request [%s]", __FUNCTION__,
- req_data.body_len, (req_data.body_len ? req_data.body : "(null)"), req_str.c_str());
- for (CallbackObjectList::iterator list_iter = req_data.callback_objects.begin();
- list_iter != req_data.callback_objects.end(); ++list_iter) {
- (*list_iter)->processData(req_str.data(), req_str.size(), req_data.body, req_data.body_len);
- }
- } else {
- TSDebug(_debug_tag.c_str(), "[%s] Received non-OK status %d for request [%s]",
- __FUNCTION__, resp_status, req_str.data());
- }
- } else {
- TSDebug(_debug_tag.c_str(), "[%s] Could not parse response for request [%s]",
- __FUNCTION__, req_str.data());
- }
-
- if (!valid_data_received) {
- _release(req_data);
- req_data.response.clear();
- }
-
- return true;
-}
-
-bool
-HttpDataFetcherImpl::getData(const string &url, ResponseData &resp_data) const {
- UrlToContentMap::const_iterator iter = _pages.find(url);
- if (iter == _pages.end()) {
- TSError("Content being requested for unregistered URL [%s]", url.data());
- return false;
- }
- const RequestData &req_data = iter->second; // handy reference
- if (!req_data.complete) {
- // request not completed yet
- TSError("Request for URL [%s] not complete", url.data());
- return false;
- }
- if (req_data.response.empty()) {
- // did not receive valid data
- TSError("No valid data received for URL [%s]; returning empty data to be safe", url.data());
- resp_data.clear();
- return false;
- }
- resp_data.set(req_data.body, req_data.body_len, req_data.bufp, req_data.hdr_loc);
- TSDebug(_debug_tag.c_str(), "[%s] Found data for URL [%s] of size %d starting with [%.5s]",
- __FUNCTION__, url.data(), req_data.body_len, req_data.body);
- return true;
-}
-
-void
-HttpDataFetcherImpl::clear() {
- for (UrlToContentMap::iterator iter = _pages.begin(); iter != _pages.end(); ++iter) {
- _release(iter->second);
- }
- _n_pending_requests = 0;
- _pages.clear();
- _page_entry_lookup.clear();
- _headers_str.clear();
- _headers.clear();
- _curr_event_id_base = FETCH_EVENT_ID_BASE;
-}
-
-DataStatus
-HttpDataFetcherImpl::getRequestStatus(const string &url) const {
- UrlToContentMap::const_iterator iter = _pages.find(url);
- if (iter == _pages.end()) {
- TSError("Status being requested for unregistered URL [%s]", url.data());
- return STATUS_ERROR;
- }
- if (!(iter->second).complete) {
- return STATUS_DATA_PENDING;
- }
- if ((iter->second).response.empty()) {
- return STATUS_ERROR;
- }
- return STATUS_DATA_AVAILABLE;
-}
-
-void
-HttpDataFetcherImpl::useHeader(const HttpHeader &header) {
- if (Utils::areEqual(header.name, header.name_len,
- TS_MIME_FIELD_ACCEPT_ENCODING, TS_MIME_LEN_ACCEPT_ENCODING)) {
- return;
- }
- string name(header.name, header.name_len);
- string value(header.value, header.value_len);
- std::pair<StringHash::iterator, bool> result = _headers.insert(StringHash::value_type(name, value));
- if (!result.second) {
- result.first->second = value;
- }
- if (_headers_str.size()) { // rebuild
- _buildHeadersString();
- }
-}
-
-void
-HttpDataFetcherImpl::useHeaders(const HttpHeaderList &headers) {
- for (HttpHeaderList::const_iterator iter = headers.begin(); iter != headers.end(); ++iter) {
- useHeader(*iter);
- }
-}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/fetcher/HttpDataFetcherImpl.h
----------------------------------------------------------------------
diff --git a/esi/fetcher/HttpDataFetcherImpl.h b/esi/fetcher/HttpDataFetcherImpl.h
deleted file mode 100644
index 726e20b..0000000
--- a/esi/fetcher/HttpDataFetcherImpl.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#ifndef _HTTP_DATA_FETCHER_IMPL_H
-#define _HTTP_DATA_FETCHER_IMPL_H
-
-#include <string>
-#include <list>
-#include <vector>
-
-#include "ts/ts.h"
-#include "StringHash.h"
-#include "HttpHeader.h"
-#include "HttpDataFetcher.h"
-
-class HttpDataFetcherImpl : public HttpDataFetcher
-{
-
-public:
-
- HttpDataFetcherImpl(TSCont contp, sockaddr const* client_addr, const char *debug_tag);
-
- void useHeader(const EsiLib::HttpHeader &header);
-
- void useHeaders(const EsiLib::HttpHeaderList &headers);
-
- bool addFetchRequest(const std::string &url, FetchedDataProcessor *callback_obj = 0);
-
- bool handleFetchEvent(TSEvent event, void *edata);
-
- bool isFetchEvent(TSEvent event) const {
- int base_event_id;
- return _isFetchEvent(event, base_event_id);
- }
-
- bool isFetchComplete() const { return (_n_pending_requests == 0); };
-
- DataStatus getRequestStatus(const std::string &url) const;
-
- int getNumPendingRequests() const { return _n_pending_requests; };
-
- // used to return data to callers
- struct ResponseData {
- const char *content;
- int content_len;
- TSMBuffer bufp;
- TSMLoc hdr_loc;
- ResponseData() { set(0, 0, 0, 0); }
- inline void set(const char *c, int clen, TSMBuffer b, TSMLoc loc);
- void clear() { set(0, 0, 0, 0); }
- };
-
- bool getData(const std::string &url, ResponseData &resp_data) const;
-
- bool getContent(const std::string &url, const char *&content, int &content_len) const {
- ResponseData resp;
- if (getData(url, resp)) {
- content = resp.content;
- content_len = resp.content_len;
- return true;
- }
- return false;
- }
-
- void clear();
-
- ~HttpDataFetcherImpl();
-
-private:
-
- TSCont _contp;
- std::string _debug_tag;
-
- typedef std::list<FetchedDataProcessor *> CallbackObjectList;
-
- // used to track a request that was made
- struct RequestData {
- std::string response;
- const char *body;
- int body_len;
- CallbackObjectList callback_objects;
- bool complete;
- TSMBuffer bufp;
- TSMLoc hdr_loc;
- RequestData() : body(0), body_len(0), complete(false), bufp(0), hdr_loc(0) { };
- };
-
- typedef __gnu_cxx::hash_map<std::string, RequestData, EsiLib::StringHasher> UrlToContentMap;
- UrlToContentMap _pages;
-
- typedef std::vector<UrlToContentMap::iterator> IteratorArray;
- IteratorArray _page_entry_lookup; // used to map event ids to requests
-
- int _n_pending_requests;
- int _curr_event_id_base;
- TSHttpParser _http_parser;
-
- static const int FETCH_EVENT_ID_BASE;
-
- int _getBaseEventId(TSEvent event) const {
- return (static_cast<int>(event) - FETCH_EVENT_ID_BASE) / 3; // integer division
- }
-
- bool _isFetchEvent(TSEvent event, int &base_event_id) const;
-
- EsiLib::StringHash _headers;
- std::string _headers_str;
-
- inline void _buildHeadersString();
- void _createRequest(std::string &http_req, const std::string &url);
- inline void _release(RequestData &req_data);
-
- sockaddr const* _client_addr;
-};
-
-inline void
-HttpDataFetcherImpl::ResponseData::set(const char *c, int clen, TSMBuffer b, TSMLoc loc) {
- content = c;
- content_len = clen;
- bufp = b;
- hdr_loc = loc;
-}
-
-#endif
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/handlers.cfg
----------------------------------------------------------------------
diff --git a/esi/handlers.cfg b/esi/handlers.cfg
deleted file mode 100644
index 6807612..0000000
--- a/esi/handlers.cfg
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Format of this file:
-#
-# <include-handler-id> <full-path-to-shared-object>
-#
-#
-# Example:
-#
-# ads /home/y/libexec/yts/esi_ads.so
-#
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/Attribute.h
----------------------------------------------------------------------
diff --git a/esi/lib/Attribute.h b/esi/lib/Attribute.h
deleted file mode 100644
index 0b284e0..0000000
--- a/esi/lib/Attribute.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#ifndef _ESI_ATTRIBUTE_H
-#define _ESI_ATTRIBUTE_H
-
-#include <list>
-
-namespace EsiLib {
-
-struct Attribute {
- const char *name;
- int32_t name_len;
- const char *value;
- int32_t value_len;
- Attribute(const char *n = 0, int32_t n_len = 0, const char *v = 0, int32_t v_len = 0)
- : name(n), name_len(n_len), value(v), value_len(v_len) { };
-};
-
-typedef std::list<Attribute> AttributeList;
-
-};
-
-#endif // _ESI_ATTRIBUTE_H
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/ComponentBase.h
----------------------------------------------------------------------
diff --git a/esi/lib/ComponentBase.h b/esi/lib/ComponentBase.h
deleted file mode 100644
index b1cb78c..0000000
--- a/esi/lib/ComponentBase.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#ifndef _ESI_COMPONENT_BASE_H
-#define _ESI_COMPONENT_BASE_H
-
-#include <string>
-
-namespace EsiLib {
-
-/** class that has common private characteristics */
-class ComponentBase
-{
-
-public:
-
- typedef void (*Debug)(const char *, const char *, ...);
- typedef void (*Error)(const char *, ...);
-
-protected:
-
- ComponentBase(const char *debug_tag, Debug debug_func, Error error_func)
- : _debug_tag(debug_tag), _debugLog(debug_func), _errorLog(error_func) { };
-
- std::string _debug_tag;
- Debug _debugLog;
- Error _errorLog;
-
- virtual ~ComponentBase() { };
-
-};
-
-};
-
-#endif // _ESI_COMPONENT_BASE_H
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/DocNode.cc
----------------------------------------------------------------------
diff --git a/esi/lib/DocNode.cc b/esi/lib/DocNode.cc
deleted file mode 100644
index 1d2e83c..0000000
--- a/esi/lib/DocNode.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#include "DocNode.h"
-#include "Utils.h"
-
-using std::string;
-using namespace EsiLib;
-
-const DocNode::TYPE DocNode::TYPE_UNKNOWN = 0;
-const DocNode::TYPE DocNode::TYPE_PRE = 1;
-const DocNode::TYPE DocNode::TYPE_INCLUDE = 2;
-const DocNode::TYPE DocNode::TYPE_COMMENT = 3;
-const DocNode::TYPE DocNode::TYPE_REMOVE = 4;
-const DocNode::TYPE DocNode::TYPE_VARS = 5;
-const DocNode::TYPE DocNode::TYPE_CHOOSE = 6;
-const DocNode::TYPE DocNode::TYPE_WHEN = 7;
-const DocNode::TYPE DocNode::TYPE_OTHERWISE = 8;
-const DocNode::TYPE DocNode::TYPE_TRY = 9;
-const DocNode::TYPE DocNode::TYPE_ATTEMPT = 10;
-const DocNode::TYPE DocNode::TYPE_EXCEPT = 11;
-const DocNode::TYPE DocNode::TYPE_HTML_COMMENT = 12;
-const DocNode::TYPE DocNode::TYPE_SPECIAL_INCLUDE = 13;
-
-const char *DocNode::type_names_[] = { "UNKNOWN",
- "PRE",
- "INCLUDE",
- "COMMENT",
- "REMOVE",
- "VARS",
- "CHOOSE",
- "WHEN",
- "OTHERWISE",
- "TRY",
- "ATTEMPT",
- "EXCEPT",
- "HTML_COMMENT",
- "SPECIAL_INCLUDE"
-};
-
-const char DocNode::VERSION = 1;
-
-// helper functions
-
-inline void
-packString(const char *str, int32_t str_len, string &buffer) {
- buffer.append(reinterpret_cast<const char *>(&str_len), sizeof(str_len));
- if (str_len) {
- buffer.append(str, str_len);
- }
-}
-
-inline void
-unpackString(const char *&packed_data, const char *&item, int32_t &item_len) {
- item_len = *(reinterpret_cast<const int32_t *>(packed_data));
- packed_data += sizeof(int32_t);
- item = item_len ? packed_data : 0;
- packed_data += item_len;
-}
-
-template<typename T> inline void
-unpackItem(const char *&packed_data, T &item) {
- item = *(reinterpret_cast<const T *>(packed_data));
- packed_data += sizeof(T);
-}
-
-void
-DocNode::pack(string &buffer) const {
- int32_t orig_buf_size = buffer.size();
- buffer += VERSION;
- buffer.append(sizeof(int32_t), ' '); // reserve space for length
- buffer.append(reinterpret_cast<const char *>(&type), sizeof(type));
- packString(data, data_len, buffer);
- int32_t n_elements = attr_list.size();
- buffer.append(reinterpret_cast<const char *>(&n_elements), sizeof(n_elements));
- for (AttributeList::const_iterator iter = attr_list.begin(); iter != attr_list.end(); ++iter) {
- packString(iter->name, iter->name_len, buffer);
- packString(iter->value, iter->value_len, buffer);
- }
- child_nodes.packToBuffer(buffer);
- *(reinterpret_cast<int32_t *>(&buffer[orig_buf_size + 1])) = buffer.size() - orig_buf_size;
-}
-
-bool
-DocNode::unpack(const char *packed_data, int packed_data_len, int &node_len) {
- const char *packed_data_start = packed_data;
-
- if (!packed_data || (packed_data_len < static_cast<int>((sizeof(char) + sizeof(int32_t))))) {
- Utils::ERROR_LOG("[%s] Invalid arguments (%p, %d)", __FUNCTION__, packed_data, packed_data_len);
- return false;
- }
- if (*packed_data != VERSION) {
- Utils::ERROR_LOG("[%s] Version %d not in supported set (%d)",
- __FUNCTION__, static_cast<int>(*packed_data), static_cast<int>(VERSION));
- return false;
- }
- ++packed_data;
-
- int32_t node_size;
- unpackItem(packed_data, node_size);
- if (node_size > packed_data_len) {
- Utils::ERROR_LOG("[%s] Data size (%d) not sufficient to hold node of size %d",
- __FUNCTION__, packed_data_len, node_size);
- return false;
- }
- node_len = node_size;
-
- unpackItem(packed_data, type);
-
- unpackString(packed_data, data, data_len);
-
- int32_t n_elements;
- unpackItem(packed_data, n_elements);
- Attribute attr;
- attr_list.clear();
- for (int i = 0; i < n_elements; ++i) {
- unpackString(packed_data, attr.name, attr.name_len);
- unpackString(packed_data, attr.value, attr.value_len);
- attr_list.push_back(attr);
- }
-
- if (!child_nodes.unpack(packed_data, packed_data_len - (packed_data - packed_data_start))) {
- Utils::ERROR_LOG("[%s] Could not unpack child nodes", __FUNCTION__);
- return false;
- }
- return true;
-}
-
-void
-DocNodeList::packToBuffer(string &buffer) const {
- int32_t n_elements = size();
- buffer.append(reinterpret_cast<const char *>(&n_elements), sizeof(n_elements));
- for (DocNodeList::const_iterator iter = begin(); iter != end(); ++iter) {
- iter->pack(buffer);
- }
-}
-
-bool
-DocNodeList::unpack(const char *data, int data_len) {
- if (!data || (data_len < static_cast<int>(sizeof(int32_t)))) {
- Utils::ERROR_LOG("[%s] Invalid arguments", __FUNCTION__);
- return false;
- }
- const char *data_start = data;
- int32_t n_elements;
- unpackItem(data, n_elements);
- clear();
- int data_offset = data - data_start, node_size;
- DocNode node;
- for (int i = 0; i < n_elements; ++i) {
- if (!node.unpack(data_start + data_offset, data_len - data_offset, node_size)) {
- Utils::ERROR_LOG("[%s] Could not unpack node", __FUNCTION__);
- return false;
- }
- data_offset += node_size;
- push_back(node);
- }
- return true;
-}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/DocNode.h
----------------------------------------------------------------------
diff --git a/esi/lib/DocNode.h b/esi/lib/DocNode.h
deleted file mode 100644
index a87f1e5..0000000
--- a/esi/lib/DocNode.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#ifndef _ESI_DOC_NODE_H
-#define _ESI_DOC_NODE_H
-
-#include <stdint.h>
-#include <list>
-#include <string>
-
-#include "Attribute.h"
-
-namespace EsiLib {
-
-struct DocNode;
-
-class DocNodeList : public std::list<DocNode> {
-
-public:
-
- inline void pack(std::string &buffer, bool retain_buffer_data = false) const {
- if (!retain_buffer_data) {
- buffer.clear();
- }
- packToBuffer(buffer);
- }
-
- inline std::string pack() const {
- std::string buffer("");
- pack(buffer);
- return buffer;
- }
-
- bool unpack(const char *data, int data_len);
-
- inline bool unpack(const std::string &data) {
- return unpack(data.data(), data.size());
- }
-
-private:
-
- void packToBuffer(std::string &buffer) const;
-
- friend class DocNode; // to use the method above
-
-};
-
-
-class DocNode
-{
-
-public:
-
- typedef int32_t TYPE;
- static const TYPE TYPE_UNKNOWN;
- static const TYPE TYPE_PRE;
- static const TYPE TYPE_INCLUDE;
- static const TYPE TYPE_COMMENT;
- static const TYPE TYPE_REMOVE;
- static const TYPE TYPE_VARS;
- static const TYPE TYPE_CHOOSE;
- static const TYPE TYPE_WHEN;
- static const TYPE TYPE_OTHERWISE;
- static const TYPE TYPE_TRY;
- static const TYPE TYPE_ATTEMPT;
- static const TYPE TYPE_EXCEPT;
- static const TYPE TYPE_HTML_COMMENT;
- static const TYPE TYPE_SPECIAL_INCLUDE;
-
- // Use with care - only types defined above will have valid names
- static const char *type_names_[];
-
- TYPE type;
- const char *data;
- int32_t data_len;
-
- AttributeList attr_list;
-
- DocNodeList child_nodes;
-
- DocNode(TYPE _type = TYPE_UNKNOWN, const char *_data = 0, int32_t _data_len = 0)
- : type(_type), data(_data), data_len(_data_len) { };
-
- void pack(std::string &buffer) const;
-
- bool unpack(const char *data, int data_len, int &node_len);
-
-private:
-
- static const char VERSION;
-
-};
-
-};
-
-#endif // _ESI_DOC_NODE_H
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/EsiParser.cc
----------------------------------------------------------------------
diff --git a/esi/lib/EsiParser.cc b/esi/lib/EsiParser.cc
deleted file mode 100644
index cdd6864..0000000
--- a/esi/lib/EsiParser.cc
+++ /dev/null
@@ -1,619 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#include "EsiParser.h"
-#include "Utils.h"
-
-#include <ctype.h>
-
-using std::string;
-using namespace EsiLib;
-
-
-const char *EsiParser::ESI_TAG_PREFIX = "<esi:";
-const int EsiParser::ESI_TAG_PREFIX_LEN = 5;
-
-const string EsiParser::SRC_ATTR_STR("src");
-const string EsiParser::TEST_ATTR_STR("test");
-const string EsiParser::HANDLER_ATTR_STR("handler");
-
-const unsigned int EsiParser::MAX_DOC_SIZE = 1024 * 1024;
-
-const EsiParser::EsiNodeInfo EsiParser::ESI_NODES[] = {
- EsiNodeInfo(DocNode::TYPE_INCLUDE, "include ", 8, "/>", 2),
- EsiNodeInfo(DocNode::TYPE_REMOVE, "remove>", 7, "</esi:remove>", 13),
- EsiNodeInfo(DocNode::TYPE_COMMENT, "comment ", 7, "/>", 2),
- EsiNodeInfo(DocNode::TYPE_VARS, "vars>", 5, "</esi:vars>", 11),
- EsiNodeInfo(DocNode::TYPE_CHOOSE, "choose>", 7, "</esi:choose>", 13),
- EsiNodeInfo(DocNode::TYPE_WHEN, "when ", 5, "</esi:when>", 11),
- EsiNodeInfo(DocNode::TYPE_OTHERWISE, "otherwise>", 10, "</esi:otherwise>", 16),
- EsiNodeInfo(DocNode::TYPE_TRY, "try>", 4, "</esi:try>", 10),
- EsiNodeInfo(DocNode::TYPE_ATTEMPT, "attempt> ", 8, "</esi:attempt>", 14),
- EsiNodeInfo(DocNode::TYPE_EXCEPT, "except> ", 7, "</esi:except>", 13),
- EsiNodeInfo(DocNode::TYPE_SPECIAL_INCLUDE, "special-include ", 15, "/>", 2),
- EsiNodeInfo(DocNode::TYPE_UNKNOWN, "", 0, "", 0) // serves as end marker
-};
-
-const EsiParser::EsiNodeInfo EsiParser::HTML_COMMENT_NODE_INFO(DocNode::TYPE_HTML_COMMENT,
- "<!--esi ", 8, "-->", 3);
-
-EsiParser::EsiParser(const char *debug_tag,
- ComponentBase::Debug debug_func,
- ComponentBase::Error error_func)
- : ComponentBase(debug_tag, debug_func, error_func), _parse_start_pos(-1) {
- // do this so that object doesn't move around in memory;
- // (because we return pointers into this object)
- _data.reserve(MAX_DOC_SIZE);
-}
-
-bool
-EsiParser::_setup(string &data, int &parse_start_pos, size_t &orig_output_list_size,
- DocNodeList &node_list, const char *data_ptr, int &data_len) const {
- bool retval = true;
- if (!data_ptr || !data_len) {
- _debugLog(_debug_tag.c_str(), "[%s] Returning true for empty data", __FUNCTION__);
- }
- else {
- if (data_len == -1) {
- data_len = strlen(data_ptr);
- }
- if ((data.size() + data_len) > MAX_DOC_SIZE) {
- _errorLog("[%s] Cannot allow attempted doc of size %d; Max allowed size is %d", __FUNCTION__,
- data.size() + data_len, MAX_DOC_SIZE);
- retval = false;
- }
- else {
- data.append(data_ptr, data_len);
- }
- }
- if (parse_start_pos == -1) { // first time this cycle that input is being provided
- parse_start_pos = 0;
- orig_output_list_size = node_list.size();
- }
- return retval;
-}
-
-bool
-EsiParser::parseChunk(const char *data, DocNodeList &node_list, int data_len /* = -1 */) {
- if (!_setup(_data, _parse_start_pos, _orig_output_list_size, node_list, data, data_len)) {
- return false;
- }
- if (!_parse(_data, _parse_start_pos, node_list)) {
- _errorLog("[%s] Failed to parse chunk of size %d starting with [%.5s]...", __FUNCTION__, data_len,
- (data_len ? data : "(null)"));
- return false;
- }
- return true;
-}
-
-bool
-EsiParser::_completeParse(string &data, int &parse_start_pos, size_t &orig_output_list_size,
- DocNodeList &node_list, const char *data_ptr /* = 0 */,
- int data_len /* = -1 */) const {
- if (!_setup(data, parse_start_pos, orig_output_list_size, node_list, data_ptr, data_len)) {
- return false;
- }
- if (!data.size()) {
- _debugLog(_debug_tag.c_str(), "[%s] No data to parse!", __FUNCTION__);
- return true;
- }
- if (!_parse(data, parse_start_pos, node_list, true)) {
- _errorLog("[%s] Failed to complete parse of data of total size %d starting with [%.5s]...",
- __FUNCTION__, data.size(), (data.size() ? data.data() : "(null)"));
- node_list.resize(orig_output_list_size);
- return false;
- }
- return true;
-}
-
-EsiParser::MATCH_TYPE
-EsiParser::_searchData(const string &data, size_t start_pos, const char *str, int str_len, size_t &pos) const {
- const char *data_ptr = data.data() + start_pos;
- int data_len = data.size() - start_pos;
- int i_data = 0, i_str = 0;
-
- while (i_data < data_len) {
- if (data_ptr[i_data] == str[i_str]) {
- ++i_str;
- if (i_str == str_len) {
- break;
- }
- } else {
- i_data -= i_str;
- i_str = 0;
- }
- ++i_data;
- }
-
- if (i_str == str_len) {
- pos = start_pos + i_data + 1 - i_str;
- _debugLog(_debug_tag.c_str(), "[%s] Found full match of %.*s in [%.5s...] at position %d",
- __FUNCTION__, str_len, str, data_ptr, pos);
- return COMPLETE_MATCH;
- } else if (i_str) {
- pos = start_pos + i_data - i_str;
- _debugLog(_debug_tag.c_str(), "[%s] Found partial match of %.*s in [%.5s...] at position %d",
- __FUNCTION__, str_len, str, data_ptr, pos);
- return PARTIAL_MATCH;
- } else {
- _debugLog(_debug_tag.c_str(), "[%s] Found no match of %.*s in [%.5s...]", __FUNCTION__, str_len, str, data_ptr);
- return NO_MATCH;
- }
-}
-
-EsiParser::MATCH_TYPE
-EsiParser::_compareData(const string &data, size_t pos, const char *str, int str_len) const {
- int i_str = 0;
- size_t i_data = pos;
- for (; i_data < data.size(); ++i_data) {
- if (data[i_data] == str[i_str]) {
- ++i_str;
- if (i_str == str_len) {
- _debugLog(_debug_tag.c_str(), "[%s] string [%.*s] is equal to data at position %d",
- __FUNCTION__, str_len, str, pos);
- return COMPLETE_MATCH;
- }
- }
- else {
- _debugLog(_debug_tag.c_str(), "[%s] string [%.*s] is not equal to data at position %d",
- __FUNCTION__, str_len, str, pos);
- return NO_MATCH;
- }
- }
- _debugLog(_debug_tag.c_str(), "[%s] string [%.*s] is partially equal to data at position %d",
- __FUNCTION__, str_len, str, pos);
- return PARTIAL_MATCH;
-}
-
-/** This implementation is optimized but not completely correct. If
- * the opening tag were to have a repeating opening sequence ('<e<esi'
- * or something like that), this will break. However that is not the
- * case for the two opening tags we are looking for */
-EsiParser::MATCH_TYPE
-EsiParser::_findOpeningTag(const string &data, size_t start_pos,
- size_t &opening_tag_pos, bool &is_html_comment_node) const {
- size_t i_data = start_pos;
- int i_esi = 0, i_html_comment = 0;
-
- while (i_data < data.size()) {
- if (data[i_data] == ESI_TAG_PREFIX[i_esi]) {
- if (++i_esi == ESI_TAG_PREFIX_LEN) {
- is_html_comment_node = false;
- opening_tag_pos = i_data - i_esi + 1;
- return COMPLETE_MATCH;
- }
- } else {
- if (i_esi) {
- i_esi = 0;
- --i_data; // we do this to reexamine the current char as target string might start from here
- if (i_html_comment) {
- --i_html_comment; // in case other target string has started matching, adjust it's index
- }
- }
- }
- // doing the exact same thing for the other target string
- if (data[i_data] == HTML_COMMENT_NODE_INFO.tag_suffix[i_html_comment]) {
- if (++i_html_comment == HTML_COMMENT_NODE_INFO.tag_suffix_len) {
- is_html_comment_node = true;
- opening_tag_pos = i_data - i_html_comment + 1;
- return COMPLETE_MATCH;
- }
- } else {
- if (i_html_comment) {
- i_html_comment = 0;
- --i_data; // same comments from above applies
- if (i_esi) {
- --i_esi;
- }
- }
- }
- ++i_data;
- }
- // partial matches; with the nature of our current opening tags, the
- // only way we can have a partial match for both target strings is
- // if the last char of the input string is '<' and that is not
- // enough information to differentiate the tags; Anyway, the parser
- // takes no action for a partial match
- if (i_esi) {
- is_html_comment_node = false;
- opening_tag_pos = i_data - i_esi;
- return PARTIAL_MATCH;
- }
- if (i_html_comment) {
- is_html_comment_node = true;
- opening_tag_pos = i_data - i_html_comment;
- return PARTIAL_MATCH;
- }
- return NO_MATCH;
-}
-
-inline bool
-EsiParser::_processSimpleContentTag(DocNode::TYPE node_type, const char *data, int data_len,
- DocNodeList &node_list) const {
- DocNode new_node(node_type);
- if (!parse(new_node.child_nodes, data, data_len)) {
- _errorLog("[%s] Could not parse simple content of [%s] node", __FUNCTION__,
- DocNode::type_names_[node_type]);
- return false;
- }
- node_list.push_back(new_node);
- return true;
-}
-
-bool
-EsiParser::_parse(const string &data, int &parse_start_pos,
- DocNodeList &node_list, bool last_chunk /* = false */) const {
- size_t orig_list_size = node_list.size();
- size_t curr_pos, end_pos;
- const char *data_ptr;
- const char *const data_start_ptr = data.data();
- size_t data_size = data.size();
- const EsiNodeInfo *node_info;
- MATCH_TYPE search_result;
- bool is_html_comment_node;
- bool parse_result;
-
- while (parse_start_pos < static_cast<int>(data_size)) {
- search_result = _findOpeningTag(data, static_cast<int>(parse_start_pos), curr_pos, is_html_comment_node);
- if (search_result == NO_MATCH) {
- // we could add this chunk as a PRE node, but it might be
- // possible that the next chunk is also a PRE node, in which
- // case it is more correct to create one PRE node than two PRE
- // nodes even though processing would result in the same final
- // output in either case. we are sacrificing a little
- // performance (we'll have to parse this chunk again next time)
- // for correctness
- break;
- }
- if (search_result == PARTIAL_MATCH) {
- goto lPartialMatch;
- }
-
- // we have a complete match of the opening tag
- if ((curr_pos - parse_start_pos) > 0) {
- // add text till here as a PRE node
- _debugLog(_debug_tag.c_str(), "[%s], Adding data of size %d before (newly found) ESI tag as PRE node",
- __FUNCTION__, curr_pos - parse_start_pos);
- node_list.push_back(DocNode(DocNode::TYPE_PRE,
- data_start_ptr + parse_start_pos, curr_pos - parse_start_pos));
- parse_start_pos = curr_pos;
- }
-
- if (is_html_comment_node) {
- _debugLog(_debug_tag.c_str(), "[%s] Found html comment tag at position %d", __FUNCTION__, curr_pos);
- data_ptr = data_start_ptr + curr_pos;
- node_info = &HTML_COMMENT_NODE_INFO;
- } else {
- curr_pos += ESI_TAG_PREFIX_LEN;
- data_ptr = data_start_ptr + curr_pos;
-
- for (node_info = ESI_NODES; node_info->type != DocNode::TYPE_UNKNOWN; ++node_info) {
- search_result = _compareData(data, curr_pos, node_info->tag_suffix, node_info->tag_suffix_len);
- if (search_result == COMPLETE_MATCH) {
- _debugLog(_debug_tag.c_str(), "[%s] Found [%s] tag at position %d",
- __FUNCTION__, DocNode::type_names_[node_info->type], curr_pos - ESI_TAG_PREFIX_LEN);
- break;
- } else if (search_result == PARTIAL_MATCH) {
- goto lPartialMatch;
- }
- }
- if (node_info->type == DocNode::TYPE_UNKNOWN) {
- _errorLog("[%s] Unknown ESI tag starting with [%.10s]...", __FUNCTION__, data_ptr - ESI_TAG_PREFIX_LEN);
- goto lFail;
- }
- }
-
- curr_pos += node_info->tag_suffix_len;
- search_result = _searchData(data, curr_pos, node_info->closing_tag, node_info->closing_tag_len, end_pos);
-
- if ((search_result == NO_MATCH) || (search_result == PARTIAL_MATCH)) {
- if (last_chunk) {
- _errorLog("[%s] ESI tag starting with [%.10s]... has no matching closing tag [%.*s]", __FUNCTION__,
- data_ptr - ESI_TAG_PREFIX_LEN, node_info->closing_tag_len, node_info->closing_tag);
- goto lFail;
- }
- else {
- goto lPartialMatch;
- }
- }
-
- parse_result = false;
-
- // now we process only complete nodes
- if (node_info->type == DocNode::TYPE_INCLUDE) {
- _debugLog(_debug_tag.c_str(), "[%s] Handling include tag...", __FUNCTION__);
- parse_result = _processIncludeTag(data, curr_pos, end_pos, node_list);
- } else if ((node_info->type == DocNode::TYPE_COMMENT) || (node_info->type == DocNode::TYPE_REMOVE)) {
- _debugLog(_debug_tag.c_str(), "[%s] Adding node [%s]", __FUNCTION__,
- DocNode::type_names_[node_info->type]);
- node_list.push_back(DocNode(node_info->type)); // no data required
- parse_result = true;
- } else if (node_info->type == DocNode::TYPE_WHEN) {
- _debugLog(_debug_tag.c_str(), "[%s] Handling when tag...", __FUNCTION__);
- parse_result = _processWhenTag(data, curr_pos, end_pos, node_list);
- } else if (node_info->type == DocNode::TYPE_TRY) {
- _debugLog(_debug_tag.c_str(), "[%s] Handling try tag...", __FUNCTION__);
- parse_result = _processTryTag(data, curr_pos, end_pos, node_list);
- } else if (node_info->type == DocNode::TYPE_CHOOSE) {
- _debugLog(_debug_tag.c_str(), "[%s] Handling choose tag...", __FUNCTION__);
- parse_result = _processChooseTag(data, curr_pos, end_pos, node_list);
- } else if ((node_info->type == DocNode::TYPE_OTHERWISE) ||
- (node_info->type == DocNode::TYPE_ATTEMPT) ||
- (node_info->type == DocNode::TYPE_EXCEPT)) {
- _debugLog(_debug_tag.c_str(), "[%s] Handling %s tag...", __FUNCTION__,
- DocNode::type_names_[node_info->type]);
- parse_result = _processSimpleContentTag(node_info->type, data.data() + curr_pos,
- end_pos - curr_pos, node_list);
- } else if ((node_info->type == DocNode::TYPE_VARS) ||
- (node_info->type == DocNode::TYPE_HTML_COMMENT)) {
- _debugLog(_debug_tag.c_str(), "[%s] added string of size %d starting with [%.5s] for node %s",
- __FUNCTION__, end_pos - curr_pos, data.data() + curr_pos,
- DocNode::type_names_[node_info->type]);
- node_list.push_back(DocNode(node_info->type, data.data() + curr_pos, end_pos - curr_pos));
- parse_result = true;
- } else if (node_info->type == DocNode::TYPE_SPECIAL_INCLUDE) {
- _debugLog(_debug_tag.c_str(), "[%s] Handling special include tag...", __FUNCTION__);
- parse_result = _processSpecialIncludeTag(data, curr_pos, end_pos, node_list);
- }
-
- if (!parse_result) {
- _errorLog("[%s] Cannot handle ESI tag [%.*s]", __FUNCTION__,
- node_info->tag_suffix_len, node_info->tag_suffix);
- goto lFail;
- }
-
- parse_start_pos = end_pos + node_info->closing_tag_len;
- continue;
-
- lPartialMatch:
- if (last_chunk) {
- _debugLog(_debug_tag.c_str(), "[%s] Found a partial ESI tag - will be treated as PRE text", __FUNCTION__);
- } else {
- _debugLog(_debug_tag.c_str(), "[%s] Deferring to next chunk to find complete tag", __FUNCTION__);
- }
- break;
- }
- if (last_chunk && (parse_start_pos < static_cast<int>(data_size))) {
- _debugLog(_debug_tag.c_str(), "[%s] Adding trailing text of size %d starting at [%.5s] as a PRE node",
- __FUNCTION__, data_size - parse_start_pos, data_start_ptr + parse_start_pos);
- node_list.push_back(DocNode(DocNode::TYPE_PRE,
- data_start_ptr + parse_start_pos, data_size - parse_start_pos));
- }
- _debugLog(_debug_tag.c_str(), "[%s] Added %d node(s) during parse", __FUNCTION__, node_list.size() - orig_list_size);
- return true;
-
-lFail:
- node_list.resize(orig_list_size); // delete whatever nodes we have added so far
- return false;
-}
-
-bool
-EsiParser::_processIncludeTag(const string &data, size_t curr_pos, size_t end_pos,
- DocNodeList &node_list) const {
- Attribute src_info;
- if (!Utils::getAttribute(data, SRC_ATTR_STR, curr_pos, end_pos, src_info)) {
- _errorLog("[%s] Could not find src attribute", __FUNCTION__);
- return false;
- }
- node_list.push_back(DocNode(DocNode::TYPE_INCLUDE));
- node_list.back().attr_list.push_back(src_info);
- _debugLog(_debug_tag.c_str(), "[%s] Added include tag with url [%.*s]",
- __FUNCTION__, src_info.value_len, src_info.value);
- return true;
-}
-
-bool
-EsiParser::_processSpecialIncludeTag(const string &data, size_t curr_pos, size_t end_pos,
- DocNodeList &node_list) const {
- Attribute handler_info;
- if (!Utils::getAttribute(data, HANDLER_ATTR_STR, curr_pos, end_pos, handler_info)) {
- _errorLog("[%s] Could not find handler attribute", __FUNCTION__);
- return false;
- }
- node_list.push_back(DocNode(DocNode::TYPE_SPECIAL_INCLUDE));
- DocNode &node = node_list.back();
- node.attr_list.push_back(handler_info);
- node.data = data.data() + curr_pos;
- node.data_len = end_pos - curr_pos;
- _debugLog(_debug_tag.c_str(), "[%s] Added special include tag with handler [%.*s] and data [%.*s]",
- __FUNCTION__, handler_info.value_len, handler_info.value, node.data_len, node.data);
- return true;
-}
-
-inline bool
-EsiParser::_isWhitespace(const char *data, int data_len) const {
- for (int i = 0; i < data_len; ++i) {
- if (!isspace(data[i])) {
- return false;
- }
- }
- return true;
-}
-
-bool
-EsiParser::_processWhenTag(const string &data, size_t curr_pos, size_t end_pos,
- DocNodeList &node_list) const {
- Attribute test_expr;
- size_t term_pos;
- if (!Utils::getAttribute(data, TEST_ATTR_STR, curr_pos, end_pos, test_expr, &term_pos, '>')) {
- _errorLog("[%s] Could not find test attribute", __FUNCTION__);
- return false;
- }
- ++term_pos; // go past the terminator
- const char *data_start_ptr = data.data() + term_pos;
- int data_size = end_pos - term_pos;
- if (!_processSimpleContentTag(DocNode::TYPE_WHEN, data_start_ptr, data_size, node_list)) {
- _errorLog("[%s] Could not parse when node's content", __FUNCTION__);
- return false;
- }
- node_list.back().attr_list.push_back(test_expr);
- _debugLog(_debug_tag.c_str(), "[%s] Added when tag with expression [%.*s] and data starting with [%.5s]",
- __FUNCTION__, test_expr.value_len, test_expr.value, data_start_ptr);
- return true;
-}
-
-bool
-EsiParser::_processTryTag(const string &data, size_t curr_pos, size_t end_pos,
- DocNodeList &node_list) const {
- const char *data_start_ptr = data.data() + curr_pos;
- int data_size = end_pos - curr_pos;
- DocNode try_node(DocNode::TYPE_TRY);
- if (!parse(try_node.child_nodes, data_start_ptr, data_size)) {
- _errorLog("[%s] Could not parse try node's content", __FUNCTION__);
- return false;
- }
-
- DocNodeList::iterator iter, end_node, attempt_node, except_node, temp_iter;
- end_node = try_node.child_nodes.end();
- attempt_node = except_node = end_node;
- iter = try_node.child_nodes.begin();
- while (iter != end_node) {
- if (iter->type == DocNode::TYPE_ATTEMPT) {
- if (attempt_node != end_node) {
- _errorLog("[%s] Can have exactly one attempt node in try block", __FUNCTION__);
- return false;
- }
- attempt_node = iter;
- } else if (iter->type == DocNode::TYPE_EXCEPT) {
- if (except_node != end_node) {
- _errorLog("[%s] Can have exactly one except node in try block", __FUNCTION__);
- return false;
- }
- except_node = iter;
- } else if (iter->type == DocNode::TYPE_PRE) {
- if (!_isWhitespace(iter->data, iter->data_len)) {
- _errorLog("[%s] Cannot have non-whitespace raw text as top level node in try block", __FUNCTION__);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] Ignoring top-level whitespace raw text", __FUNCTION__);
- temp_iter = iter;
- ++temp_iter;
- try_node.child_nodes.erase(iter);
- iter = temp_iter;
- continue; // skip the increment
- } else {
- _errorLog("[%s] Only attempt/except/text nodes allowed in try block; [%s] node invalid",
- __FUNCTION__, DocNode::type_names_[iter->type]);
- return false;
- }
- ++iter;
- }
- if ((attempt_node == end_node) || (except_node == end_node)) {
- _errorLog("[%s] try block must contain one each of attempt and except nodes", __FUNCTION__);
- return false;
- }
- node_list.push_back(try_node);
- _debugLog(_debug_tag.c_str(), "[%s] Added try node successfully", __FUNCTION__);
- return true;
-}
-
-bool
-EsiParser::_processChooseTag(const string &data, size_t curr_pos, size_t end_pos,
- DocNodeList &node_list) const {
- const char *data_start_ptr = data.data() + curr_pos;
- size_t data_size = end_pos - curr_pos;
- DocNode choose_node(DocNode::TYPE_CHOOSE);
- if (!parse(choose_node.child_nodes, data_start_ptr, data_size)) {
- _errorLog("[%s] Couldn't parse choose node content", __FUNCTION__);
- return false;
- }
- DocNodeList::iterator end_node = choose_node.child_nodes.end();
- DocNodeList::iterator otherwise_node = end_node, iter, temp_iter;
- iter = choose_node.child_nodes.begin();
- while (iter != end_node) {
- if (iter->type == DocNode::TYPE_OTHERWISE) {
- if (otherwise_node != end_node) {
- _errorLog("[%s] Cannot have more than one esi:otherwise node in an esi:choose node", __FUNCTION__);
- return false;
- }
- otherwise_node = iter;
- } else if (iter->type == DocNode::TYPE_PRE) {
- if (!_isWhitespace(iter->data, iter->data_len)) {
- _errorLog("[%s] Cannot have non-whitespace raw text as top-level node in choose data",
- __FUNCTION__, DocNode::type_names_[iter->type]);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] Ignoring top-level whitespace raw text", __FUNCTION__);
- temp_iter = iter;
- ++temp_iter;
- choose_node.child_nodes.erase(iter);
- iter = temp_iter;
- continue; // skip the increment
- } else if (iter->type != DocNode::TYPE_WHEN) {
- _errorLog("[%s] Cannot have %s as top-level node in choose data; only when/otherwise/whitespace-text "
- "permitted", __FUNCTION__, DocNode::type_names_[iter->type]);
- return false;
- }
- ++iter;
- }
- node_list.push_back(choose_node);
- return true;
-}
-
-void
-EsiParser::clear() {
- _data.clear();
- _parse_start_pos = -1;
-}
-
-EsiParser::~EsiParser() {
-}
-
-inline void
-EsiParser::_adjustPointers(DocNodeList::iterator node_iter, DocNodeList::iterator end,
- const char *ext_data_ptr, const char *int_data_start) const {
- AttributeList::iterator attr_iter;
- for (; node_iter != end; ++node_iter) {
- if (node_iter->data_len) {
- node_iter->data = ext_data_ptr + (node_iter->data - int_data_start);
- }
- for (attr_iter = node_iter->attr_list.begin(); attr_iter != node_iter->attr_list.end(); ++attr_iter) {
- if (attr_iter->name_len) {
- attr_iter->name = ext_data_ptr + (attr_iter->name - int_data_start);
- }
- if (attr_iter->value_len) {
- attr_iter->value = ext_data_ptr + (attr_iter->value - int_data_start);
- }
- }
- if (node_iter->child_nodes.size()) {
- _adjustPointers(node_iter->child_nodes.begin(), node_iter->child_nodes.end(),
- ext_data_ptr, int_data_start);
- }
- }
-}
-
-bool
-EsiParser::parse(DocNodeList &node_list, const char *ext_data_ptr, int data_len /* = -1 */) const {
- string data;
- size_t orig_output_list_size;
- int parse_start_pos = -1;
- bool retval = _completeParse(data, parse_start_pos, orig_output_list_size, node_list, ext_data_ptr, data_len);
- if (retval && (node_list.size() - orig_output_list_size)) {
- // adjust all pointers to addresses in input parameter
- const char *int_data_start = data.data();
- DocNodeList::iterator node_iter = node_list.begin();
- for (size_t i = 0; i < orig_output_list_size; ++i, ++node_iter);
- _adjustPointers(node_iter, node_list.end(), ext_data_ptr, int_data_start);
- }
- return retval;
-}
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/EsiParser.h
----------------------------------------------------------------------
diff --git a/esi/lib/EsiParser.h b/esi/lib/EsiParser.h
deleted file mode 100644
index c3779ce..0000000
--- a/esi/lib/EsiParser.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#ifndef _ESI_PARSER_H
-#define _ESI_PARSER_H
-
-#include <string>
-
-#include "ComponentBase.h"
-#include "DocNode.h"
-
-class EsiParser : private EsiLib::ComponentBase
-{
-
-public:
-
- EsiParser(const char *debug_tag, EsiLib::ComponentBase::Debug debug_func,
- EsiLib::ComponentBase::Error error_func);
-
- /** clears state */
- void clear();
-
- /** parses a chunk of the document; adds complete nodes found;
- * data is assumed to be NULL-terminated is data_len is set to -1.
- *
- * Output nodes contain pointers to internal data; use with care */
- bool parseChunk(const char *data, EsiLib::DocNodeList &node_list, int data_len = -1);
-
- /** convenient alternative to method above */
- bool parseChunk(const std::string &data, EsiLib::DocNodeList &node_list) {
- return parseChunk(data.data(), node_list, data.size());
- };
-
- /** completes the parse including data from previous chunk(s);
- * adds newly found nodes to list. optionally a final or the
- * only chunk can be provided.
- *
- * Output nodes contain pointers to internal data; use with care. */
- bool completeParse(EsiLib::DocNodeList &node_list, const char *data = 0, int data_len = -1) {
- return _completeParse(_data, _parse_start_pos, _orig_output_list_size, node_list, data, data_len);
- }
-
- /** convenient alternative to method above */
- bool completeParse(EsiLib::DocNodeList &node_list, const std::string &data) {
- return completeParse(node_list, data.data(), data.size());
- }
-
- /** stateless method that parses data and returns output nodes that
- * point to addresses in caller space */
- bool parse(EsiLib::DocNodeList &node_list, const char *ext_data_ptr, int data_len = -1) const;
-
- /** convenient alternative to method above */
- bool parse(EsiLib::DocNodeList &node_list, const std::string &ext_data) const {
- return parse(node_list, ext_data.data(), ext_data.size());
- }
-
- virtual ~EsiParser();
-
-private:
-
- struct EsiNodeInfo
- {
- EsiLib::DocNode::TYPE type;
- const char *tag_suffix;
- int tag_suffix_len;
- const char *closing_tag;
- int closing_tag_len;
- EsiNodeInfo(EsiLib::DocNode::TYPE t, const char *s, int s_len, const char *ct, int ct_len)
- : type(t), tag_suffix(s), tag_suffix_len(s_len), closing_tag(ct), closing_tag_len(ct_len) { };
- };
-
- std::string _data;
- int _parse_start_pos;
- size_t _orig_output_list_size;
-
- static const EsiNodeInfo ESI_NODES[];
- static const EsiNodeInfo HTML_COMMENT_NODE_INFO;
-
- static const char *ESI_TAG_PREFIX;
- static const int ESI_TAG_PREFIX_LEN;
-
- static const std::string SRC_ATTR_STR;
- static const std::string TEST_ATTR_STR;
- static const std::string HANDLER_ATTR_STR;
-
- static const unsigned int MAX_DOC_SIZE;
-
- enum MATCH_TYPE { NO_MATCH, COMPLETE_MATCH, PARTIAL_MATCH };
-
- MATCH_TYPE _searchData(const std::string &data, size_t start_pos, const char *str, int str_len,
- size_t &pos) const;
-
- MATCH_TYPE _compareData(const std::string &data, size_t pos, const char *str, int str_len) const;
-
- MATCH_TYPE _findOpeningTag(const std::string &data, size_t start_pos,
- size_t &opening_tag_pos, bool &is_html_comment_node) const;
-
- bool _parse(const std::string &data, int &parse_start_pos, EsiLib::DocNodeList &node_list,
- bool last_chunk = false) const;
-
- bool _processIncludeTag(const std::string &data, size_t curr_pos, size_t end_pos,
- EsiLib::DocNodeList &node_list) const;
-
- bool _processSpecialIncludeTag(const std::string &data, size_t curr_pos, size_t end_pos,
- EsiLib::DocNodeList &node_list) const;
-
- inline bool _isWhitespace(const char *data, int data_len) const;
-
- bool _processWhenTag(const std::string &data, size_t curr_pos, size_t end_pos,
- EsiLib::DocNodeList &node_list) const;
-
- bool _processChooseTag(const std::string &data, size_t curr_pos, size_t end_pos,
- EsiLib::DocNodeList &node_list) const;
-
- bool _processTryTag(const std::string &data, size_t curr_pos, size_t end_pos,
- EsiLib::DocNodeList &node_list) const;
-
- inline bool _processSimpleContentTag(EsiLib::DocNode::TYPE node_type, const char *data, int data_len,
- EsiLib::DocNodeList &node_list) const;
-
- bool _setup(std::string &data, int &parse_start_pos, size_t &orig_output_list_size,
- EsiLib::DocNodeList &node_list, const char *data_ptr, int &data_len) const;
-
- bool _completeParse(std::string &data, int &parse_start_pos, size_t &orig_output_list_size,
- EsiLib::DocNodeList &node_list, const char *data_ptr = 0, int data_len = -1) const;
-
- inline void _adjustPointers(EsiLib::DocNodeList::iterator node_iter, EsiLib::DocNodeList::iterator end,
- const char *ext_data_ptr, const char *int_data_start) const;
-
-};
-
-#endif // _ESI_PARSER_H
http://git-wip-us.apache.org/repos/asf/trafficserver-plugins/blob/ff849998/esi/lib/EsiProcessor.cc
----------------------------------------------------------------------
diff --git a/esi/lib/EsiProcessor.cc b/esi/lib/EsiProcessor.cc
deleted file mode 100644
index b0199a5..0000000
--- a/esi/lib/EsiProcessor.cc
+++ /dev/null
@@ -1,600 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#include "EsiProcessor.h"
-#include "Stats.h"
-#include "FailureInfo.h"
-#include <ctype.h>
-
-using std::string;
-using namespace EsiLib;
-extern pthread_key_t threadKey;
-// this needs to be a fixed address as only the address is used for comparision
-const char *EsiProcessor::INCLUDE_DATA_ID_ATTR = reinterpret_cast<const char *>(0xbeadface);
-
-#define FAILURE_INFO_TAG "plugin_esi_failureInfo"
-
-
-EsiProcessor::EsiProcessor(const char *debug_tag, const char *parser_debug_tag,
- const char *expression_debug_tag,
- ComponentBase::Debug debug_func, ComponentBase::Error error_func,
- HttpDataFetcher &fetcher, Variables &variables,
- const HandlerManager &handler_mgr)
- : ComponentBase(debug_tag, debug_func, error_func),
- _curr_state(STOPPED),
- _parser(parser_debug_tag, debug_func, error_func),
- _n_prescanned_nodes(0),
- _fetcher(fetcher), _esi_vars(variables),
- _expression(expression_debug_tag, debug_func, error_func, _esi_vars), _n_try_blocks_processed(0),
- _handler_manager(handler_mgr) {
-}
-
-bool
-EsiProcessor::start() {
- if (_curr_state != STOPPED) {
- _debugLog(_debug_tag.c_str(), "[%s] Implicit call to stop()", __FUNCTION__);
- stop();
- }
- _curr_state = PARSING;
- return true;
-}
-
-bool
-EsiProcessor::addParseData(const char *data, int data_len) {
- if (_curr_state == ERRORED) {
- return false;
- }
- if (_curr_state == STOPPED) {
- _debugLog(_debug_tag.c_str(), "[%s] Implicit call to start()", __FUNCTION__);
- start();
- } else if (_curr_state != PARSING) {
- _debugLog(_debug_tag.c_str(), "[%s] Can only parse in parse stage", __FUNCTION__);
- return false;
- }
-
- if (!_parser.parseChunk(data, _node_list, data_len)) {
- _errorLog("[%s] Failed to parse chunk; Stopping processor...", __FUNCTION__);
- error();
- Stats::increment(Stats::N_PARSE_ERRS);
- return false;
- }
- if (!_preprocess(_node_list, _n_prescanned_nodes)) {
- _errorLog("[%s] Failed to preprocess parsed nodes; Stopping processor...", __FUNCTION__);
- error();
- return false;
- }
- return true;
-}
-
-bool
-EsiProcessor::completeParse(const char *data /* = 0 */, int data_len /* = -1 */) {
- if (_curr_state == ERRORED) {
- return false;
- }
- if (_curr_state == STOPPED) {
- _debugLog(_debug_tag.c_str(), "[%s] Implicit call to start()", __FUNCTION__);
- start();
- } else if (_curr_state != PARSING) {
- _debugLog(_debug_tag.c_str(), "[%s] Can only parse in parse stage", __FUNCTION__);
- return false;
- }
-
- if (!_parser.completeParse(_node_list, data, data_len)) {
- _errorLog("[%s] Couldn't parse ESI document", __FUNCTION__);
- error();
- Stats::increment(Stats::N_PARSE_ERRS);
- return false;
- }
- return _handleParseComplete();
-}
-
-bool
-EsiProcessor::usePackedNodeList(const char *data, int data_len) {
- if (_curr_state != STOPPED) {
- _errorLog("[%s] Cannot use packed node list whilst processing other data", __FUNCTION__);
- return false;
- }
- start();
- if (!_node_list.unpack(data, data_len)) {
- _errorLog("[%s] Could not unpack node list from provided data!", __FUNCTION__);
- error();
- return false;
- }
- return _handleParseComplete();
-}
-
-bool
-EsiProcessor::_handleParseComplete() {
- if (_curr_state != PARSING) {
- _debugLog(_debug_tag.c_str(), "[%s] Cannot handle parse complete in state %d", __FUNCTION__, _curr_state);
- return false;
- }
- if (!_preprocess(_node_list, _n_prescanned_nodes)) {
- _errorLog("[%s] Failed to preprocess parsed nodes; Stopping processor...", __FUNCTION__);
- error();
- return false;
- }
- for (IncludeHandlerMap::iterator map_iter = _include_handlers.begin();
- map_iter != _include_handlers.end(); ++map_iter) {
- map_iter->second->handleParseComplete();
- }
-
- _debugLog(_debug_tag.c_str(), "[%s] Parsed ESI document with %d nodes", __FUNCTION__, _node_list.size());
- _curr_state = WAITING_TO_PROCESS;
-
- return true;
-}
-
-bool
-EsiProcessor::_getIncludeData(const DocNode &node, const char **content_ptr /* = 0 */,
- int *content_len_ptr /* = 0 */) {
- if (node.type == DocNode::TYPE_INCLUDE) {
- const Attribute &url = node.attr_list.front();
- string raw_url(url.value, url.value_len);
- StringHash::iterator iter = _include_urls.find(raw_url);
- if (iter == _include_urls.end()) {
- _errorLog("[%s] Data not requested for URL [%.*s]; no data to include",
- __FUNCTION__, url.value_len, url.value);
- return false;
- }
- const string &processed_url = iter->second;
- bool result;
- if (content_ptr && content_len_ptr) {
- result = _fetcher.getContent(processed_url, *content_ptr, *content_len_ptr);
- } else {
- result = (_fetcher.getRequestStatus(processed_url) == STATUS_DATA_AVAILABLE);
- }
- if (!result) {
- _errorLog("[%s] Couldn't get content for URL [%.*s]",
- __FUNCTION__, processed_url.size(), processed_url.data());
- Stats::increment(Stats::N_INCLUDE_ERRS);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] Got content successfully for URL [%.*s]", __FUNCTION__,
- processed_url.size(), processed_url.data());
- return true;
- } else if (node.type == DocNode::TYPE_SPECIAL_INCLUDE) {
- AttributeList::const_iterator attr_iter;
- for (attr_iter = node.attr_list.begin(); attr_iter != node.attr_list.end(); ++attr_iter) {
- if (attr_iter->name == INCLUDE_DATA_ID_ATTR) {
- break;
- }
- }
- int include_data_id = attr_iter->value_len;
- SpecialIncludeHandler *handler =
- reinterpret_cast<SpecialIncludeHandler *>(const_cast<char *>(attr_iter->value));
- bool result;
- if (content_ptr && content_len_ptr) {
- result = handler->getData(include_data_id, *content_ptr, *content_len_ptr);
- } else {
- result = (handler->getIncludeStatus(include_data_id) == STATUS_DATA_AVAILABLE);
- }
- if (!result) {
- _errorLog("[%s] Couldn't get content for special include with id %d", __FUNCTION__, include_data_id);
- Stats::increment(Stats::N_SPCL_INCLUDE_ERRS);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] Successfully got content for special include with id %d",
- __FUNCTION__, include_data_id);
- return true;
- }
- _errorLog("[%s] Cannot get include data for node of type %s",
- __FUNCTION__, DocNode::type_names_[node.type]);
- return false;
-}
-
-EsiProcessor::ReturnCode
-EsiProcessor::process(const char *&data, int &data_len) {
- if (_curr_state == ERRORED) {
- return FAILURE;
- }
- if (_curr_state != WAITING_TO_PROCESS) {
- _errorLog("[%s] Processor has to finish parsing via completeParse() before process() call", __FUNCTION__);
- return FAILURE;
- }
- DocNodeList::iterator node_iter,iter;
- bool attempt_succeeded;
- std::vector<std::string> attemptUrls;
- TryBlockList::iterator try_iter = _try_blocks.begin();
- for (int i = 0; i < _n_try_blocks_processed; ++i, ++try_iter);
- for (; _n_try_blocks_processed < static_cast<int>(_try_blocks.size()); ++try_iter) {
- ++_n_try_blocks_processed;
- attempt_succeeded = true;
- for (node_iter = try_iter->attempt_nodes.begin(); node_iter != try_iter->attempt_nodes.end(); ++node_iter) {
- if ((node_iter->type == DocNode::TYPE_INCLUDE) ||
- (node_iter->type == DocNode::TYPE_SPECIAL_INCLUDE)) {
- const Attribute &url = (*node_iter).attr_list.front();
- string raw_url(url.value, url.value_len);
- attemptUrls.push_back(_expression.expand(raw_url));
- if (!_getIncludeData(*node_iter)) {
- attempt_succeeded = false;
- break;
- }
- }
- }
-
- /* FAILURE CACHE */
- FailureData* data=static_cast<FailureData*>(pthread_getspecific(threadKey));
- _debugLog("plugin_esi_failureInfo","[%s]Fetched data related to thread specfic %p",__FUNCTION__,data);
-
- for (iter=try_iter->attempt_nodes.begin(); iter != try_iter->attempt_nodes.end(); ++iter) {
- if ((iter->type == DocNode::TYPE_INCLUDE) || iter->type == DocNode::TYPE_SPECIAL_INCLUDE)
- {
- if(!attempt_succeeded && iter==node_iter)
- continue;
- const Attribute &url = (*iter).attr_list.front();
- string raw_url(url.value, url.value_len);
- attemptUrls.push_back(_expression.expand(raw_url));
- }
- }
-
- if(attemptUrls.size()>0 && data)
- {
- FailureData::iterator it =data->find(attemptUrls[0]);
- FailureInfo* info;
-
- if(it == data->end())
- {
- _debugLog("plugin_esi_failureInfo","[%s]Inserting object for the attempt URLS",__FUNCTION__);
- info=new FailureInfo(FAILURE_INFO_TAG,_debugLog,_errorLog);
- for(int i=0;i<static_cast<int>(attemptUrls.size());i++)
- {
- _debugLog("plugin_esi_failureInfo", "[%s] Urls [%.*s]",__FUNCTION__,attemptUrls[i].size(),attemptUrls[i].data());
- (*data)[attemptUrls[i]]=info;
- }
-
- info->registerSuccFail(attempt_succeeded);
-
- } else {
- info=it->second;
- //Should be registered only if attemp was made
- //and it failed
- if(_reqAdded)
- info->registerSuccFail(attempt_succeeded);
-
- }
- }
- if (attempt_succeeded) {
- _debugLog(_debug_tag.c_str(), "[%s] attempt section succeded; using attempt section", __FUNCTION__);
- _node_list.splice(try_iter->pos, try_iter->attempt_nodes);
- } else {
- _debugLog(_debug_tag.c_str(), "[%s] attempt section errored; trying except section", __FUNCTION__);
- int n_prescanned_nodes = 0;
- if (!_preprocess(try_iter->except_nodes, n_prescanned_nodes)) {
- _errorLog("[%s] Failed to preprocess except nodes", __FUNCTION__);
- stop();
- return FAILURE;
- }
- _node_list.splice(try_iter->pos, try_iter->except_nodes);
- if (_fetcher.getNumPendingRequests()) {
- _debugLog(_debug_tag.c_str(), "[%s] New fetch requests were triggered by except block; "
- "Returning NEED_MORE_DATA...", __FUNCTION__);
- return NEED_MORE_DATA;
- }
- }
- }
- _curr_state = PROCESSED;
- for (node_iter = _node_list.begin(); node_iter != _node_list.end(); ++node_iter) {
- DocNode &doc_node = *node_iter; // handy reference
- _debugLog(_debug_tag.c_str(), "[%s] Processing ESI node [%s] with data of size %d starting with [%.5s...]",
- __FUNCTION__, DocNode::type_names_[doc_node.type], doc_node.data_len,
- (doc_node.data_len ? doc_node.data : "(null)"));
- if (doc_node.type == DocNode::TYPE_PRE) {
- // just copy the data
- _output_data.append(doc_node.data, doc_node.data_len);
- } else if (!_processEsiNode(node_iter)) {
- _errorLog("[%s] Failed to process ESI node [%.*s]", __FUNCTION__, doc_node.data_len, doc_node.data);
- stop();
- return FAILURE;
- }
- }
- _addFooterData();
- data = _output_data.c_str();
- data_len = _output_data.size();
- _debugLog(_debug_tag.c_str(), "[%s] ESI processed document of size %d starting with [%.10s]",
- __FUNCTION__, data_len, (data_len ? data : "(null)"));
- return SUCCESS;
-}
-
-void
-EsiProcessor::stop() {
- _output_data.clear();
- _node_list.clear();
- _include_urls.clear();
- _try_blocks.clear();
- _n_prescanned_nodes = 0;
- _n_try_blocks_processed = 0;
- for (IncludeHandlerMap::iterator map_iter = _include_handlers.begin();
- map_iter != _include_handlers.end(); ++map_iter) {
- delete map_iter->second;
- }
- _include_handlers.clear();
- _curr_state = STOPPED;
-}
-
-EsiProcessor::~EsiProcessor() {
- if (_curr_state != STOPPED) {
- stop();
- }
-}
-
-bool
-EsiProcessor::_processEsiNode(const DocNodeList::iterator &iter) {
- bool retval;
- const DocNode &node = *iter;
- if ((node.type == DocNode::TYPE_INCLUDE) || (node.type == DocNode::TYPE_SPECIAL_INCLUDE)) {
- const char *content;
- int content_len;
- if ((retval = _getIncludeData(node, &content, &content_len))) {
- _output_data.append(content, content_len);
- }
- } else if ((node.type == DocNode::TYPE_COMMENT) || (node.type == DocNode::TYPE_REMOVE) ||
- (node.type == DocNode::TYPE_TRY) || (node.type == DocNode::TYPE_CHOOSE) ||
- (node.type == DocNode::TYPE_HTML_COMMENT)) {
- // choose, try and html-comment would've been dealt with earlier
- _debugLog(_debug_tag.c_str(), "[%s] No-op for [%s] node", __FUNCTION__, DocNode::type_names_[node.type]);
- retval = true;
- } else if (node.type == DocNode::TYPE_VARS) {
- retval = _handleVars(node.data, node.data_len);
- } else {
- _errorLog("[%s] Unknown ESI Doc node type %d", __FUNCTION__, node.type);
- retval = false;
- }
- if (retval) {
- _debugLog(_debug_tag.c_str(), "[%s] Processed ESI [%s] node", __FUNCTION__, DocNode::type_names_[node.type]);
- } else {
- _errorLog("[%s] Failed to process ESI doc node of type %d", __FUNCTION__, node.type);
- }
- return retval;
-}
-
-inline bool
-EsiProcessor::_isWhitespace(const char *data, int data_len) {
- for (int i = 0; i < data_len; ++i) {
- if (!isspace(data[i])) {
- return false;
- }
- }
- return true;
-}
-
-bool
-EsiProcessor::_handleChoose(DocNodeList::iterator &curr_node) {
- DocNodeList::iterator iter, otherwise_node, winning_node, end_node;
- end_node = curr_node->child_nodes.end();
- otherwise_node = end_node;
- for (iter = curr_node->child_nodes.begin(); iter != end_node; ++iter) {
- if (iter->type == DocNode::TYPE_OTHERWISE) {
- otherwise_node = iter;
- break;
- }
- }
- winning_node = end_node;
- for (iter = curr_node->child_nodes.begin(); iter != end_node; ++iter) {
- if (iter->type == DocNode::TYPE_WHEN) {
- const Attribute &test_expr = iter->attr_list.front();
- if (_expression.evaluate(test_expr.value, test_expr.value_len)) {
- winning_node = iter;
- break;
- }
- }
- }
- if (winning_node == end_node) {
- _debugLog(_debug_tag.c_str(), "[%s] All when nodes failed to evaluate to true", __FUNCTION__);
- if (otherwise_node != end_node) {
- _debugLog(_debug_tag.c_str(), "[%s] Using otherwise node...", __FUNCTION__);
- winning_node = otherwise_node;
- } else {
- _debugLog(_debug_tag.c_str(), "[%s] No otherwise node, nothing to do...", __FUNCTION__);
- return true;
- }
- }
- // splice() inserts elements *before* given position, but we need to
- // insert new nodes after the choose node for them to be seen by
- // preprocess(); hence...
- DocNodeList::iterator next_node = curr_node;
- ++next_node;
- _node_list.splice(next_node, winning_node->child_nodes);
- return true;
-}
-
-bool
-EsiProcessor::_handleTry(DocNodeList::iterator &curr_node) {
- DocNodeList::iterator iter, end_node = curr_node->child_nodes.end();
- DocNodeList::iterator attempt_node = end_node, except_node = end_node;
- for (iter = curr_node->child_nodes.begin(); iter != end_node; ++iter) {
- if (iter->type == DocNode::TYPE_ATTEMPT) {
-
- attempt_node = iter;
- } else if (iter->type == DocNode::TYPE_EXCEPT) {
- except_node = iter;
- }
- }
- TryBlock try_info(attempt_node->child_nodes, except_node->child_nodes, curr_node);
- int n_prescanned_nodes = 0;
- if (!_preprocess(try_info.attempt_nodes, n_prescanned_nodes)) {
- _errorLog("[%s] Couldn't preprocess attempt node of try block", __FUNCTION__);
- return false;
- }
- _try_blocks.push_back(try_info);
- return true;
-}
-
-bool
-EsiProcessor::_handleVars(const char *str, int str_len) {
- const string &str_value = _expression.expand(str, str_len);
- _debugLog(_debug_tag.c_str(), "[%s] Vars expression [%.*s] expanded to [%.*s]",
- __FUNCTION__, str_len, str, str_value.size(), str_value.data());
- _output_data += str_value;
- return true;
-}
-
-bool
-EsiProcessor::_handleHtmlComment(const DocNodeList::iterator &curr_node) {
- DocNodeList inner_nodes;
- if (!_parser.parse(inner_nodes, curr_node->data, curr_node->data_len)) {
- _errorLog("[%s] Couldn't parse html comment node content", __FUNCTION__);
- Stats::increment(Stats::N_PARSE_ERRS);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] parsed %d inner nodes from html comment node", __FUNCTION__, inner_nodes.size());
- DocNodeList::iterator next_node = curr_node;
- ++next_node;
- _node_list.splice(next_node, inner_nodes); // insert after curr node for preprocessing
- return true;
-}
-
-bool
-EsiProcessor::_preprocess(DocNodeList &node_list, int &n_prescanned_nodes) {
- DocNodeList::iterator list_iter = node_list.begin();
- StringHash::iterator hash_iter;
- string raw_url;
-
- // skip previously examined nodes
- for (int i = 0; i < n_prescanned_nodes; ++i, ++list_iter);
-
- for (; list_iter != node_list.end(); ++list_iter, ++n_prescanned_nodes) {
- if (list_iter->type == DocNode::TYPE_CHOOSE) {
- if (!_handleChoose(list_iter)) {
- _errorLog("[%s] Failed to preprocess choose node", __FUNCTION__);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] handled choose node successfully", __FUNCTION__);
- } else if (list_iter->type == DocNode::TYPE_TRY) {
- if (!_handleTry(list_iter)) {
- _errorLog("[%s] Failed to preprocess try node", __FUNCTION__);
- return false;
- }
- _debugLog(_debug_tag.c_str(), "[%s] handled try node successfully", __FUNCTION__);
- } else if (list_iter->type == DocNode::TYPE_HTML_COMMENT) {
- if (!_handleHtmlComment(list_iter)) {
- _errorLog("[%s] Failed to preprocess try node", __FUNCTION__);
- return false;
- }
- } else if (list_iter->type == DocNode::TYPE_INCLUDE) {
- Stats::increment(Stats::N_INCLUDES);
- const Attribute &src = list_iter->attr_list.front();
- raw_url.assign(src.value, src.value_len);
- _debugLog(_debug_tag.c_str(), "[%s] Adding fetch request for url [%.*s]",
- __FUNCTION__, raw_url.size(), raw_url.data());
- hash_iter = _include_urls.find(raw_url);
- if (hash_iter != _include_urls.end()) { // we have already processed this URL
- _debugLog(_debug_tag.c_str(), "[%s] URL [%.*s] already processed",
- __FUNCTION__, raw_url.size(), raw_url.data());
- continue;
- }
- const string &expanded_url = _expression.expand(raw_url);
- if (!expanded_url.size()) {
- _errorLog("[%s] Couldn't expand raw URL [%.*s]", __FUNCTION__, raw_url.size(), raw_url.data());
- Stats::increment(Stats::N_INCLUDE_ERRS);
- continue;
- }
-
- bool fetch=true;
- FailureData* threadData;
- /* FAILURE CACHE */
- if((threadData=static_cast<FailureData*>(pthread_getspecific(threadKey))) == NULL){
- threadData=new FailureData();
- if(pthread_setspecific(threadKey,threadData))
- {
- TSError("[%s] Unable to set the key", __FUNCTION__);
- abort();
- }
- _debugLog("plugin_esi_failureInfo", "[%s] Data is set for this thread [threadData]%p [threadID]%u [%.*s]", __FUNCTION__,threadData,pthread_self(),expanded_url.size(),expanded_url.data());
- }else {
-
- _debugLog("plugin_esi_failureInfo", "[%s] URL request [%.*s] %u",
- __FUNCTION__, expanded_url.size(), expanded_url.data(),pthread_self());
-
- FailureData::iterator it =threadData->find(expanded_url);
- FailureInfo* info;
-
- if(it != threadData->end()) {
- info=it->second;
- fetch=_reqAdded=info->isAttemptReq();
- _debugLog(_debug_tag.c_str(),"[%s] Fetch result is %d",__FUNCTION__,fetch);
- }
- }
-
- if(fetch){
- if (!_fetcher.addFetchRequest(expanded_url)) {
- _errorLog("[%s] Couldn't add fetch request for URL [%.*s]",
- __FUNCTION__, raw_url.size(), raw_url.data());
- Stats::increment(Stats::N_INCLUDE_ERRS);
- continue;
- }
- _include_urls.insert(StringHash::value_type(raw_url, expanded_url));
- }
- else{
- _debugLog("plugin_esi_failureInfo","[%s] Not adding fetch request for [%.*s]",__FUNCTION__,expanded_url.size(),expanded_url.data());
- continue;
- }
- } else if (list_iter->type == DocNode::TYPE_SPECIAL_INCLUDE) {
- Stats::increment(Stats::N_SPCL_INCLUDES);
- const Attribute &handler_attr = list_iter->attr_list.front();
- string handler_id(handler_attr.value, handler_attr.value_len);
- SpecialIncludeHandler *handler;
- IncludeHandlerMap::const_iterator map_iter = _include_handlers.find(handler_id);
- if (map_iter == _include_handlers.end()) {
- handler = _handler_manager.getHandler(_esi_vars, _expression, _fetcher, handler_id);
- if (!handler) {
- _errorLog("[%s] Couldn't create handler with id [%s]", __FUNCTION__, handler_id.c_str());
- Stats::increment(Stats::N_SPCL_INCLUDE_ERRS);
- return false;
- }
- _include_handlers.insert(IncludeHandlerMap::value_type(handler_id, handler));
- _debugLog(_debug_tag.c_str(), "[%s] Created new special include handler object for id [%s]",
- __FUNCTION__, handler_id.c_str());
- } else {
- handler = map_iter->second;
- }
- int special_data_id = handler->handleInclude(list_iter->data, list_iter->data_len);
- if (special_data_id == -1) {
- _errorLog("[%s] Include handler [%s] couldn't process include with data [%.*s]",
- __FUNCTION__, handler_id.c_str(), list_iter->data_len, list_iter->data);
- Stats::increment(Stats::N_SPCL_INCLUDE_ERRS);
- return false;
- }
- // overloading this structure's members
- // handler will be in value and include id will be in value_len of the structure
- list_iter->attr_list.push_back(Attribute(INCLUDE_DATA_ID_ATTR, 0,
- reinterpret_cast<const char *>(handler),
- special_data_id));
- _debugLog(_debug_tag.c_str(), "[%s] Got id %d for special include at node %d from handler [%s]",
- __FUNCTION__, special_data_id, n_prescanned_nodes + 1, handler_id.c_str());
- }
- }
- return true;
-}
-
-void
-EsiProcessor::_addFooterData() {
- const char *footer;
- int footer_len;
- for (IncludeHandlerMap::iterator iter = _include_handlers.begin(); iter != _include_handlers.end(); ++iter) {
- iter->second->getFooter(footer, footer_len);
- if (footer_len > 0) {
- _output_data.append(footer, footer_len);
- }
- }
-}