From b0db989bfbd0c3c55d9c56f262b6c12a3aec3502 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 17:01:42 +0900 Subject: [PATCH 01/43] Update getDocumentCount.xml --- modules/document/queries/getDocumentCount.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentCount.xml b/modules/document/queries/getDocumentCount.xml index ddc92d1ba..bac018204 100644 --- a/modules/document/queries/getDocumentCount.xml +++ b/modules/document/queries/getDocumentCount.xml @@ -8,7 +8,7 @@ - + From c22279cbb387d436b07a2d56ae61c85cf660fe51 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:24:48 +0900 Subject: [PATCH 02/43] Update document.model.php --- modules/document/document.model.php | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/modules/document/document.model.php b/modules/document/document.model.php index 8723577cd..d74477420 100644 --- a/modules/document/document.model.php +++ b/modules/document/document.model.php @@ -562,18 +562,9 @@ class documentModel extends document */ function getDocumentCount($module_srl, $search_obj = NULL) { - // Additional search options - $args =new stdClass(); - $args->module_srl = $module_srl; - $args->s_title = $search_obj->s_title; - $args->s_content = $search_obj->s_content; - $args->s_user_name = $search_obj->s_user_name; - $args->s_member_srl = $search_obj->s_member_srl; - $args->s_ipaddress = $search_obj->s_ipaddress; - $args->s_regdate = $search_obj->s_regdate; - $args->category_srl = $search_obj->category_srl; + $search_obj->module_srl = $module_srl; - $output = executeQuery('document.getDocumentCount', $args); + $output = executeQuery('document.getDocumentCount', $search_obj); // Return total number of $total_count = $output->data->count; return (int)$total_count; @@ -586,17 +577,7 @@ class documentModel extends document */ function getDocumentCountByGroupStatus($search_obj = NULL) { - // Additional search options - $args->module_srl = $search_obj->module_srl; - $args->s_title = $search_obj->s_title; - $args->s_content = $search_obj->s_content; - $args->s_user_name = $search_obj->s_user_name; - $args->s_member_srl = $search_obj->s_member_srl; - $args->s_ipaddress = $search_obj->s_ipaddress; - $args->s_regdate = $search_obj->s_regdate; - $args->category_srl = $search_obj->category_srl; - - $output = executeQuery('document.getDocumentCountByGroupStatus', $args); + $output = executeQuery('document.getDocumentCountByGroupStatus', $search_obj); if(!$output->toBool()) return array(); return $output->data; From d2aabf4780583ba7ca98beffd189134faaef17f9 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:25:29 +0900 Subject: [PATCH 03/43] Update getDocumentCount.xml --- modules/document/queries/getDocumentCount.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentCount.xml b/modules/document/queries/getDocumentCount.xml index bac018204..598287fd7 100644 --- a/modules/document/queries/getDocumentCount.xml +++ b/modules/document/queries/getDocumentCount.xml @@ -8,7 +8,7 @@ - + From 42e94da9485dcf65dc2a623e59bc806adbf69e5e Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:26:09 +0900 Subject: [PATCH 04/43] Update getDocumentCountByGroupStatus.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit category_srl 검색에 pipe="and" 가 빠져있고 숫자 filter 연결해둠 --- modules/document/queries/getDocumentCountByGroupStatus.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentCountByGroupStatus.xml b/modules/document/queries/getDocumentCountByGroupStatus.xml index d9150ca46..f72fafd54 100644 --- a/modules/document/queries/getDocumentCountByGroupStatus.xml +++ b/modules/document/queries/getDocumentCountByGroupStatus.xml @@ -9,7 +9,7 @@ - + From 8f58576bdbf561548653b4a626dbb584a7b54d3a Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:28:05 +0900 Subject: [PATCH 05/43] Update getDocumentCount.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit category 쪽에 pipe 연결 안 된 오류 수정 이메일 검색 s_email_address 오타 수정 --- modules/document/queries/getDocumentCount.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentCount.xml b/modules/document/queries/getDocumentCount.xml index 598287fd7..401f47a60 100644 --- a/modules/document/queries/getDocumentCount.xml +++ b/modules/document/queries/getDocumentCount.xml @@ -18,7 +18,7 @@ - + From bdd90c8817d4e21dc4027b4abf05f22da6128e6b Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:30:02 +0900 Subject: [PATCH 06/43] Update getDocumentCountByGroupStatus.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s_email_address 오타 수정 --- modules/document/queries/getDocumentCountByGroupStatus.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentCountByGroupStatus.xml b/modules/document/queries/getDocumentCountByGroupStatus.xml index f72fafd54..94bcb1894 100644 --- a/modules/document/queries/getDocumentCountByGroupStatus.xml +++ b/modules/document/queries/getDocumentCountByGroupStatus.xml @@ -19,7 +19,7 @@ - + From 3f091c0e1440dd067aaaa98c71cebc416a106f7a Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:31:27 +0900 Subject: [PATCH 07/43] Update getDocumentListExtraSort.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s_email_addres 로 적힌 s_email_address 오타 수정 --- modules/document/queries/getDocumentListExtraSort.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentListExtraSort.xml b/modules/document/queries/getDocumentListExtraSort.xml index e9102cdb0..e843f8900 100644 --- a/modules/document/queries/getDocumentListExtraSort.xml +++ b/modules/document/queries/getDocumentListExtraSort.xml @@ -26,7 +26,7 @@ - + From 038070b5e58ec2833d3872f23a550b95fa42e768 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:32:15 +0900 Subject: [PATCH 08/43] Update getDocumentListUseIndex.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s_email_addres 로 적힌 s_email_address 오타 수정 --- modules/document/queries/getDocumentListUseIndex.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentListUseIndex.xml b/modules/document/queries/getDocumentListUseIndex.xml index be456edaf..4182a5ad0 100644 --- a/modules/document/queries/getDocumentListUseIndex.xml +++ b/modules/document/queries/getDocumentListUseIndex.xml @@ -25,7 +25,7 @@ - + From b247105635228ea967f4761c3e4bc9b14fc2db77 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:33:55 +0900 Subject: [PATCH 09/43] Update getDocumentListWithinMember.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s_email_address 오타 수정 --- modules/document/queries/getDocumentListWithinMember.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getDocumentListWithinMember.xml b/modules/document/queries/getDocumentListWithinMember.xml index c87994f7c..49792e11d 100644 --- a/modules/document/queries/getDocumentListWithinMember.xml +++ b/modules/document/queries/getDocumentListWithinMember.xml @@ -15,7 +15,7 @@ - + From e7661f74cbc14266425442ec93b239f21e83aed0 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Sun, 30 Nov 2014 18:34:55 +0900 Subject: [PATCH 10/43] Update getTrashList.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s_email_address 오타 수정 --- modules/document/queries/getTrashList.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/queries/getTrashList.xml b/modules/document/queries/getTrashList.xml index a6be78d71..fe13af161 100644 --- a/modules/document/queries/getTrashList.xml +++ b/modules/document/queries/getTrashList.xml @@ -26,7 +26,7 @@ - + From 38094c75b9490bdca9121c0951702ad356e7f5db Mon Sep 17 00:00:00 2001 From: Xvezda Date: Fri, 2 Jan 2015 16:53:56 +0900 Subject: [PATCH 11/43] =?UTF-8?q?#1113=20Preview=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EB=8B=A4=EC=9A=B4=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/integration_search/integration_search.model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/integration_search/integration_search.model.php b/modules/integration_search/integration_search.model.php index 120869e1d..242a99b36 100644 --- a/modules/integration_search/integration_search.model.php +++ b/modules/integration_search/integration_search.model.php @@ -198,7 +198,7 @@ class integration_searchModel extends module else if(preg_match('/\.(swf|flv|wmv|avi|mpg|mpeg|asx|asf|mp3)$/i', $val->source_filename)) { $obj->type = 'multimedia'; - $obj->src = sprintf('', $obj->download_url); + $obj->src = sprintf('', $val->uploaded_filename); // Others } else From 80badf3a346c2a13334ccef77998aa50616bd2ef Mon Sep 17 00:00:00 2001 From: Eunsoo Lee Date: Wed, 7 Jan 2015 17:54:05 +0900 Subject: [PATCH 12/43] =?UTF-8?q?admin.iefix.css=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 파일 내용이 단순해서 minify 파일을 만들 필요 없음 --- classes/display/HTMLDisplayHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/display/HTMLDisplayHandler.php b/classes/display/HTMLDisplayHandler.php index cc61705da..4c08e48f5 100644 --- a/classes/display/HTMLDisplayHandler.php +++ b/classes/display/HTMLDisplayHandler.php @@ -432,7 +432,7 @@ class HTMLDisplayHandler { $oContext->loadFile(array('./modules/admin/tpl/css/admin.min.css', '', '', 10), true); $oContext->loadFile(array("./modules/admin/tpl/css/admin_{$lang_type}.css", '', '', 10), true); - $oContext->loadFile(array("./modules/admin/tpl/css/admin.iefix.min.css", '', 'ie', 10), true); + $oContext->loadFile(array("./modules/admin/tpl/css/admin.iefix.css", '', 'ie', 10), true); $oContext->loadFile('./modules/admin/tpl/js/admin.min.js', true); $oContext->loadFile(array('./modules/admin/tpl/css/admin.bootstrap.min.css', '', '', 1), true); $oContext->loadFile(array('./modules/admin/tpl/js/jquery.tmpl.js', '', '', 1), true); From 14164766760518c2a9dbb8eed76b0866a7044e80 Mon Sep 17 00:00:00 2001 From: Eunsoo Lee Date: Thu, 8 Jan 2015 14:59:27 +0900 Subject: [PATCH 13/43] =?UTF-8?q?XML=20Request=EC=97=90=EC=84=9C=200?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=92=EC=9D=84=20=EB=B0=9B=EC=9D=84=20=EC=88=98?= =?UTF-8?q?=20=EC=97=86=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- classes/context/Context.class.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 31164b97b..b61e8cb1e 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -1277,16 +1277,11 @@ class Context return $stack; } - $body = $this->_filterRequestVar($key, trim($val->body ? $val->body : ''), 0); - if($body) - { - return $body; - } - + $body = $this->_filterRequestVar($key, $val->body, 0); unset($val->node_name, $val->attrs, $val->body); if(!count(get_object_vars($val))) { - return NULL; + return $body; } $stack = new stdClass(); From eb8e46a9f3439915e36f5a59a54fcc1bea7ee02c Mon Sep 17 00:00:00 2001 From: whantae ji Date: Thu, 8 Jan 2015 18:26:19 +0900 Subject: [PATCH 14/43] =?UTF-8?q?=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EB=B9=84?= =?UTF-8?q?=EA=B3=B5=EA=B0=9C=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=EC=97=90?= =?UTF-8?q?=EB=8F=84=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EA=B8=B0=EB=A1=9C=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=A3=BC?= =?UTF-8?q?=EC=86=8C=20=EB=85=B8=EC=B6=9C=EB=90=98=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/member/member.model.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/member/member.model.php b/modules/member/member.model.php index f0f7f70d8..6913775eb 100644 --- a/modules/member/member.model.php +++ b/modules/member/member.model.php @@ -138,8 +138,14 @@ class memberModel extends member // When click other's nickname if($member_srl != $logged_info->member_srl && $logged_info->member_srl) { - // Send an email - if($member_info->email_address) + // Get email config + for($i = 0; $i < count($this->module_config->signupForm); $i++) + if($this->module_config->signupForm[$i]->name == 'email_address') + break; + $email_config = $this->module_config->signupForm[$i]; + + // Send an email only if email address is public + if($logged_info->is_admin == 'Y' || $email_config->isPublic == 'Y' && $member_info->email_address) { $url = 'mailto:'.htmlspecialchars($member_info->email_address, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); $oMemberController->addMemberPopupMenu($url,'cmd_send_email',$icon_path); From c31b9795e0afebc7a57388a7ab032bcc3a485989 Mon Sep 17 00:00:00 2001 From: Eunsoo Lee Date: Fri, 9 Jan 2015 14:39:55 +0900 Subject: [PATCH 15/43] =?UTF-8?q?=5FfilterRequestVar=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EC=8B=A4=ED=96=89=20=ED=9A=9F=EC=88=98=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- classes/context/Context.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index b61e8cb1e..642c1959e 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -1277,11 +1277,11 @@ class Context return $stack; } - $body = $this->_filterRequestVar($key, $val->body, 0); + $body = $val->body; unset($val->node_name, $val->attrs, $val->body); if(!count(get_object_vars($val))) { - return $body; + return $this->_filterRequestVar($key, $body, 0); } $stack = new stdClass(); From 3300e8c486534a63df3825abff6296d707ad4a49 Mon Sep 17 00:00:00 2001 From: Eunsoo Lee Date: Sat, 10 Jan 2015 17:05:49 +0900 Subject: [PATCH 16/43] =?UTF-8?q?=EC=84=A4=EB=AC=B8=EC=A1=B0=EC=82=AC=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/editor/components/poll_maker/tpl/filter/insert_poll.xml | 2 +- modules/poll/conf/module.xml | 2 +- modules/poll/poll.controller.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/editor/components/poll_maker/tpl/filter/insert_poll.xml b/modules/editor/components/poll_maker/tpl/filter/insert_poll.xml index 55d3413e3..42ed8801c 100644 --- a/modules/editor/components/poll_maker/tpl/filter/insert_poll.xml +++ b/modules/editor/components/poll_maker/tpl/filter/insert_poll.xml @@ -1,4 +1,4 @@ - +
diff --git a/modules/poll/conf/module.xml b/modules/poll/conf/module.xml index 10e8188b2..550e4a072 100644 --- a/modules/poll/conf/module.xml +++ b/modules/poll/conf/module.xml @@ -9,7 +9,7 @@ - + diff --git a/modules/poll/poll.controller.php b/modules/poll/poll.controller.php index dc8d04565..15dfb65a2 100644 --- a/modules/poll/poll.controller.php +++ b/modules/poll/poll.controller.php @@ -17,7 +17,7 @@ class pollController extends poll /** * @brief after a qeustion is created in the popup window, register the question during the save time */ - function procInsert() + function procPollInsert() { $stop_date = Context::get('stop_date'); if($stop_date < date('Ymd')) From 2f17be2f3f636d1538ff417449f4f41ae8b2e7fb Mon Sep 17 00:00:00 2001 From: Eunsoo Lee Date: Sat, 10 Jan 2015 17:52:28 +0900 Subject: [PATCH 17/43] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=EC=84=9C=20=ED=9A=8C=EC=9B=90=20=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=95=A0=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=82=AC=EC=9D=B4=ED=8A=B8=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/point/tpl/member_list.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/point/tpl/member_list.html b/modules/point/tpl/member_list.html index be1f490b1..1f8a2102c 100644 --- a/modules/point/tpl/member_list.html +++ b/modules/point/tpl/member_list.html @@ -78,7 +78,7 @@ @@ -143,6 +143,4 @@ - - From 3fb8847d5872abc100fd75837e61ce15f52777ad Mon Sep 17 00:00:00 2001 From: akasima Date: Mon, 12 Jan 2015 19:53:38 +0900 Subject: [PATCH 18/43] =?UTF-8?q?#1038=20point=EC=97=90=20=EC=9D=98?= =?UTF-8?q?=ED=95=B4=20=EA=B8=80=EC=9D=84=20=EC=9D=BD=EC=9D=84=20=EC=88=98?= =?UTF-8?q?=20=EC=97=86=EC=9D=84=20=EB=95=8C=20=ED=8A=B8=EB=A6=AC=EA=B1=B0?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=97=90=EB=9F=AC=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/point/point.controller.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/point/point.controller.php b/modules/point/point.controller.php index b3f32b9a3..3e7cdc3c1 100644 --- a/modules/point/point.controller.php +++ b/modules/point/point.controller.php @@ -422,8 +422,9 @@ class pointController extends point // When the requested points are negative, compared it with the current point if($config->disable_read_document == 'Y' && $point < 0 && abs($point)>$cur_point) { - $obj->add('content', sprintf(Context::getLang('msg_disallow_by_point'), abs($point), $cur_point)); - return new Object(); + $message = sprintf(Context::getLang('msg_disallow_by_point'), abs($point), $cur_point); + $obj->add('content', $message); + return new Object(-1, $message); } // If not logged in, pass if(!$logged_info->member_srl) return new Object(); From 570d889ee9a42a849b7a21a3f6b482a742538a9a Mon Sep 17 00:00:00 2001 From: Eunsoo Lee Date: Tue, 13 Jan 2015 01:26:11 +0900 Subject: [PATCH 19/43] =?UTF-8?q?#1056=20PR=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/point/tpl/member_list.html | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/point/tpl/member_list.html b/modules/point/tpl/member_list.html index 1f8a2102c..447944c6d 100644 --- a/modules/point/tpl/member_list.html +++ b/modules/point/tpl/member_list.html @@ -142,5 +142,6 @@ + From bd917c3d01417f4278239167a14535eced4b686d Mon Sep 17 00:00:00 2001 From: akasima Date: Tue, 13 Jan 2015 11:16:58 +0900 Subject: [PATCH 20/43] =?UTF-8?q?#1176=20=ED=8C=8C=EC=9D=BC=20=EC=B2=A8?= =?UTF-8?q?=EB=B6=80=20=EB=8C=80=EC=86=8C=EB=AC=B8=EC=9E=90=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/file/file.controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/file/file.controller.php b/modules/file/file.controller.php index ff4fd2551..66c0c5733 100644 --- a/modules/file/file.controller.php +++ b/modules/file/file.controller.php @@ -634,10 +634,10 @@ class fileController extends file $ext = array(); foreach($filetypes as $item) { $item = explode('.', $item); - $ext[] = $item[1]; + $ext[] = strtolower($item[1]); } $uploaded_ext = explode('.', $file_info['name']); - $uploaded_ext = array_pop($uploaded_ext); + $uploaded_ext = strtolower(array_pop($uploaded_ext)); if(!in_array($uploaded_ext, $ext)) { From 0005af60da335a5b5d61eff7510a8f1e9c42cfe2 Mon Sep 17 00:00:00 2001 From: akasima Date: Thu, 15 Jan 2015 14:03:43 +0900 Subject: [PATCH 21/43] #866 PEAR update --- config/func.inc.php | 2 +- libs/PEAR.1.9.5/HTTP/Request.php | 55 + libs/PEAR.1.9.5/HTTP/Request2.php | 1030 ++++++++++++++ libs/PEAR.1.9.5/HTTP/Request2/Adapter.php | 137 ++ .../PEAR.1.9.5/HTTP/Request2/Adapter/Curl.php | 567 ++++++++ .../PEAR.1.9.5/HTTP/Request2/Adapter/Mock.php | 166 +++ .../HTTP/Request2/Adapter/Socket.php | 1121 +++++++++++++++ libs/PEAR.1.9.5/HTTP/Request2/CookieJar.php | 494 +++++++ libs/PEAR.1.9.5/HTTP/Request2/Exception.php | 160 +++ .../HTTP/Request2/MultipartBody.php | 268 ++++ .../PEAR.1.9.5/HTTP/Request2/Observer/Log.php | 192 +++ libs/PEAR.1.9.5/HTTP/Request2/Response.php | 631 +++++++++ libs/PEAR.1.9.5/HTTP/Request2/SOCKS5.php | 135 ++ .../HTTP/Request2/SocketWrapper.php | 297 ++++ libs/PEAR.1.9.5/Net/URL2.php | 1219 +++++++++++++++++ libs/PEAR.1.9.5/PEAR.php | 1063 ++++++++++++++ libs/PEAR.1.9.5/PEAR/Exception.php | 389 ++++++ libs/PEAR.1.9.5/PEAR5.php | 33 + 18 files changed, 7958 insertions(+), 1 deletion(-) create mode 100644 libs/PEAR.1.9.5/HTTP/Request.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Adapter.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Adapter/Curl.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Adapter/Mock.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Adapter/Socket.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/CookieJar.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Exception.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/MultipartBody.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Observer/Log.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/Response.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/SOCKS5.php create mode 100644 libs/PEAR.1.9.5/HTTP/Request2/SocketWrapper.php create mode 100644 libs/PEAR.1.9.5/Net/URL2.php create mode 100644 libs/PEAR.1.9.5/PEAR.php create mode 100644 libs/PEAR.1.9.5/PEAR/Exception.php create mode 100644 libs/PEAR.1.9.5/PEAR5.php diff --git a/config/func.inc.php b/config/func.inc.php index d59ab3e43..3405c5f34 100644 --- a/config/func.inc.php +++ b/config/func.inc.php @@ -1505,7 +1505,7 @@ function requirePear() } else { - set_include_path(_XE_PATH_ . "libs/PEAR.1.9"); + set_include_path(_XE_PATH_ . "libs/PEAR.1.9.5"); } } diff --git a/libs/PEAR.1.9.5/HTTP/Request.php b/libs/PEAR.1.9.5/HTTP/Request.php new file mode 100644 index 000000000..b877c3ca8 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request.php @@ -0,0 +1,55 @@ +setHeader($name, $value); + } + + public function sendRequest($saveBody = true) + { + $response = $this->send(); + $this->response = $response; + return $response; + } + + public function getResponseCode() { + if($this->response) + { + return $this->response->getStatus(); + } + } + + public function getResponseHeader() { + if($this->response) + { + return $this->response->getHeader(); + } + } + + public function getResponseBody() { + if($this->response) + { + return $this->response->getBody(); + } + } + + public function getResponseCookies() { + if($this->response) + { + return $this->response->getCookies(); + } + } + + public function addPostData($name, $value, $preencoded = false) + { + $this->addPostParameter($name, $value); + } + +} + +?> diff --git a/libs/PEAR.1.9.5/HTTP/Request2.php b/libs/PEAR.1.9.5/HTTP/Request2.php new file mode 100644 index 000000000..d2f36e17b --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2.php @@ -0,0 +1,1030 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * A class representing an URL as per RFC 3986. + */ +require_once 'Net/URL2.php'; + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class representing a HTTP request message + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + * @link http://tools.ietf.org/html/rfc2616#section-5 + */ +class HTTP_Request2 implements SplSubject +{ + /**#@+ + * Constants for HTTP request methods + * + * @link http://tools.ietf.org/html/rfc2616#section-5.1.1 + */ + const METHOD_OPTIONS = 'OPTIONS'; + const METHOD_GET = 'GET'; + const METHOD_HEAD = 'HEAD'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_DELETE = 'DELETE'; + const METHOD_TRACE = 'TRACE'; + const METHOD_CONNECT = 'CONNECT'; + /**#@-*/ + + /**#@+ + * Constants for HTTP authentication schemes + * + * @link http://tools.ietf.org/html/rfc2617 + */ + const AUTH_BASIC = 'basic'; + const AUTH_DIGEST = 'digest'; + /**#@-*/ + + /** + * Regular expression used to check for invalid symbols in RFC 2616 tokens + * @link http://pear.php.net/bugs/bug.php?id=15630 + */ + const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!'; + + /** + * Regular expression used to check for invalid symbols in cookie strings + * @link http://pear.php.net/bugs/bug.php?id=15630 + * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html + */ + const REGEXP_INVALID_COOKIE = '/[\s,;]/'; + + /** + * Fileinfo magic database resource + * @var resource + * @see detectMimeType() + */ + private static $_fileinfoDb; + + /** + * Observers attached to the request (instances of SplObserver) + * @var array + */ + protected $observers = array(); + + /** + * Request URL + * @var Net_URL2 + */ + protected $url; + + /** + * Request method + * @var string + */ + protected $method = self::METHOD_GET; + + /** + * Authentication data + * @var array + * @see getAuth() + */ + protected $auth; + + /** + * Request headers + * @var array + */ + protected $headers = array(); + + /** + * Configuration parameters + * @var array + * @see setConfig() + */ + protected $config = array( + 'adapter' => 'HTTP_Request2_Adapter_Socket', + 'connect_timeout' => 10, + 'timeout' => 0, + 'use_brackets' => true, + 'protocol_version' => '1.1', + 'buffer_size' => 16384, + 'store_body' => true, + 'local_ip' => null, + + 'proxy_host' => '', + 'proxy_port' => '', + 'proxy_user' => '', + 'proxy_password' => '', + 'proxy_auth_scheme' => self::AUTH_BASIC, + 'proxy_type' => 'http', + + 'ssl_verify_peer' => true, + 'ssl_verify_host' => true, + 'ssl_cafile' => null, + 'ssl_capath' => null, + 'ssl_local_cert' => null, + 'ssl_passphrase' => null, + + 'digest_compat_ie' => false, + + 'follow_redirects' => false, + 'max_redirects' => 5, + 'strict_redirects' => false + ); + + /** + * Last event in request / response handling, intended for observers + * @var array + * @see getLastEvent() + */ + protected $lastEvent = array( + 'name' => 'start', + 'data' => null + ); + + /** + * Request body + * @var string|resource + * @see setBody() + */ + protected $body = ''; + + /** + * Array of POST parameters + * @var array + */ + protected $postParams = array(); + + /** + * Array of file uploads (for multipart/form-data POST requests) + * @var array + */ + protected $uploads = array(); + + /** + * Adapter used to perform actual HTTP request + * @var HTTP_Request2_Adapter + */ + protected $adapter; + + /** + * Cookie jar to persist cookies between requests + * @var HTTP_Request2_CookieJar + */ + protected $cookieJar = null; + + /** + * Constructor. Can set request URL, method and configuration array. + * + * Also sets a default value for User-Agent header. + * + * @param string|Net_Url2 $url Request URL + * @param string $method Request method + * @param array $config Configuration for this Request instance + */ + public function __construct( + $url = null, $method = self::METHOD_GET, array $config = array() + ) { + $this->setConfig($config); + if (!empty($url)) { + $this->setUrl($url); + } + if (!empty($method)) { + $this->setMethod($method); + } + $this->setHeader( + 'user-agent', 'HTTP_Request2/2.2.1 ' . + '(http://pear.php.net/package/http_request2) PHP/' . phpversion() + ); + } + + /** + * Sets the URL for this request + * + * If the URL has userinfo part (username & password) these will be removed + * and converted to auth data. If the URL does not have a path component, + * that will be set to '/'. + * + * @param string|Net_URL2 $url Request URL + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + */ + public function setUrl($url) + { + if (is_string($url)) { + $url = new Net_URL2( + $url, array(Net_URL2::OPTION_USE_BRACKETS => $this->config['use_brackets']) + ); + } + if (!$url instanceof Net_URL2) { + throw new HTTP_Request2_LogicException( + 'Parameter is not a valid HTTP URL', + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + // URL contains username / password? + if ($url->getUserinfo()) { + $username = $url->getUser(); + $password = $url->getPassword(); + $this->setAuth(rawurldecode($username), $password? rawurldecode($password): ''); + $url->setUserinfo(''); + } + if ('' == $url->getPath()) { + $url->setPath('/'); + } + $this->url = $url; + + return $this; + } + + /** + * Returns the request URL + * + * @return Net_URL2 + */ + public function getUrl() + { + return $this->url; + } + + /** + * Sets the request method + * + * @param string $method one of the methods defined in RFC 2616 + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException if the method name is invalid + */ + public function setMethod($method) + { + // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1 + if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) { + throw new HTTP_Request2_LogicException( + "Invalid request method '{$method}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + $this->method = $method; + + return $this; + } + + /** + * Returns the request method + * + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * Sets the configuration parameter(s) + * + * The following parameters are available: + *
    + *
  • 'adapter' - adapter to use (string)
  • + *
  • 'connect_timeout' - Connection timeout in seconds (integer)
  • + *
  • 'timeout' - Total number of seconds a request can take. + * Use 0 for no limit, should be greater than + * 'connect_timeout' if set (integer)
  • + *
  • 'use_brackets' - Whether to append [] to array variable names (bool)
  • + *
  • 'protocol_version' - HTTP Version to use, '1.0' or '1.1' (string)
  • + *
  • 'buffer_size' - Buffer size to use for reading and writing (int)
  • + *
  • 'store_body' - Whether to store response body in response object. + * Set to false if receiving a huge response and + * using an Observer to save it (boolean)
  • + *
  • 'local_ip' - Specifies the IP address that will be used for accessing + * the network (string)
  • + *
  • 'proxy_type' - Proxy type, 'http' or 'socks5' (string)
  • + *
  • 'proxy_host' - Proxy server host (string)
  • + *
  • 'proxy_port' - Proxy server port (integer)
  • + *
  • 'proxy_user' - Proxy auth username (string)
  • + *
  • 'proxy_password' - Proxy auth password (string)
  • + *
  • 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)
  • + *
  • 'proxy' - Shorthand for proxy_* parameters, proxy given as URL, + * e.g. 'socks5://localhost:1080/' (string)
  • + *
  • 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)
  • + *
  • 'ssl_verify_host' - Whether to check that Common Name in SSL + * certificate matches host name (bool)
  • + *
  • 'ssl_cafile' - Cerificate Authority file to verify the peer + * with (use with 'ssl_verify_peer') (string)
  • + *
  • 'ssl_capath' - Directory holding multiple Certificate + * Authority files (string)
  • + *
  • 'ssl_local_cert' - Name of a file containing local cerificate (string)
  • + *
  • 'ssl_passphrase' - Passphrase with which local certificate + * was encoded (string)
  • + *
  • 'digest_compat_ie' - Whether to imitate behaviour of MSIE 5 and 6 + * in using URL without query string in digest + * authentication (boolean)
  • + *
  • 'follow_redirects' - Whether to automatically follow HTTP Redirects (boolean)
  • + *
  • 'max_redirects' - Maximum number of redirects to follow (integer)
  • + *
  • 'strict_redirects' - Whether to keep request method on redirects via status 301 and + * 302 (true, needed for compatibility with RFC 2616) + * or switch to GET (false, needed for compatibility with most + * browsers) (boolean)
  • + *
+ * + * @param string|array $nameOrConfig configuration parameter name or array + * ('parameter name' => 'parameter value') + * @param mixed $value parameter value if $nameOrConfig is not an array + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException If the parameter is unknown + */ + public function setConfig($nameOrConfig, $value = null) + { + if (is_array($nameOrConfig)) { + foreach ($nameOrConfig as $name => $value) { + $this->setConfig($name, $value); + } + + } elseif ('proxy' == $nameOrConfig) { + $url = new Net_URL2($value); + $this->setConfig(array( + 'proxy_type' => $url->getScheme(), + 'proxy_host' => $url->getHost(), + 'proxy_port' => $url->getPort(), + 'proxy_user' => rawurldecode($url->getUser()), + 'proxy_password' => rawurldecode($url->getPassword()) + )); + + } else { + if (!array_key_exists($nameOrConfig, $this->config)) { + throw new HTTP_Request2_LogicException( + "Unknown configuration parameter '{$nameOrConfig}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + $this->config[$nameOrConfig] = $value; + } + + return $this; + } + + /** + * Returns the value(s) of the configuration parameter(s) + * + * @param string $name parameter name + * + * @return mixed value of $name parameter, array of all configuration + * parameters if $name is not given + * @throws HTTP_Request2_LogicException If the parameter is unknown + */ + public function getConfig($name = null) + { + if (null === $name) { + return $this->config; + } elseif (!array_key_exists($name, $this->config)) { + throw new HTTP_Request2_LogicException( + "Unknown configuration parameter '{$name}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + return $this->config[$name]; + } + + /** + * Sets the autentification data + * + * @param string $user user name + * @param string $password password + * @param string $scheme authentication scheme + * + * @return HTTP_Request2 + */ + public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC) + { + if (empty($user)) { + $this->auth = null; + } else { + $this->auth = array( + 'user' => (string)$user, + 'password' => (string)$password, + 'scheme' => $scheme + ); + } + + return $this; + } + + /** + * Returns the authentication data + * + * The array has the keys 'user', 'password' and 'scheme', where 'scheme' + * is one of the HTTP_Request2::AUTH_* constants. + * + * @return array + */ + public function getAuth() + { + return $this->auth; + } + + /** + * Sets request header(s) + * + * The first parameter may be either a full header string 'header: value' or + * header name. In the former case $value parameter is ignored, in the latter + * the header's value will either be set to $value or the header will be + * removed if $value is null. The first parameter can also be an array of + * headers, in that case method will be called recursively. + * + * Note that headers are treated case insensitively as per RFC 2616. + * + * + * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar' + * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz' + * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux' + * $req->setHeader('FOO'); // removes 'Foo' header from request + * + * + * @param string|array $name header name, header string ('Header: value') + * or an array of headers + * @param string|array|null $value header value if $name is not an array, + * header will be removed if value is null + * @param bool $replace whether to replace previous header with the + * same name or append to its value + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + */ + public function setHeader($name, $value = null, $replace = true) + { + if (is_array($name)) { + foreach ($name as $k => $v) { + if (is_string($k)) { + $this->setHeader($k, $v, $replace); + } else { + $this->setHeader($v, null, $replace); + } + } + } else { + if (null === $value && strpos($name, ':')) { + list($name, $value) = array_map('trim', explode(':', $name, 2)); + } + // Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2 + if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) { + throw new HTTP_Request2_LogicException( + "Invalid header name '{$name}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + // Header names are case insensitive anyway + $name = strtolower($name); + if (null === $value) { + unset($this->headers[$name]); + + } else { + if (is_array($value)) { + $value = implode(', ', array_map('trim', $value)); + } elseif (is_string($value)) { + $value = trim($value); + } + if (!isset($this->headers[$name]) || $replace) { + $this->headers[$name] = $value; + } else { + $this->headers[$name] .= ', ' . $value; + } + } + } + + return $this; + } + + /** + * Returns the request headers + * + * The array is of the form ('header name' => 'header value'), header names + * are lowercased + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Adds a cookie to the request + * + * If the request does not have a CookieJar object set, this method simply + * appends a cookie to "Cookie:" header. + * + * If a CookieJar object is available, the cookie is stored in that object. + * Data from request URL will be used for setting its 'domain' and 'path' + * parameters, 'expires' and 'secure' will be set to null and false, + * respectively. If you need further control, use CookieJar's methods. + * + * @param string $name cookie name + * @param string $value cookie value + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + * @see setCookieJar() + */ + public function addCookie($name, $value) + { + if (!empty($this->cookieJar)) { + $this->cookieJar->store( + array('name' => $name, 'value' => $value), $this->url + ); + + } else { + $cookie = $name . '=' . $value; + if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) { + throw new HTTP_Request2_LogicException( + "Invalid cookie: '{$cookie}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; '; + $this->setHeader('cookie', $cookies . $cookie); + } + + return $this; + } + + /** + * Sets the request body + * + * If you provide file pointer rather than file name, it should support + * fstat() and rewind() operations. + * + * @param string|resource|HTTP_Request2_MultipartBody $body Either a + * string with the body or filename containing body or + * pointer to an open file or object with multipart body data + * @param bool $isFilename Whether + * first parameter is a filename + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + */ + public function setBody($body, $isFilename = false) + { + if (!$isFilename && !is_resource($body)) { + if (!$body instanceof HTTP_Request2_MultipartBody) { + $this->body = (string)$body; + } else { + $this->body = $body; + } + } else { + $fileData = $this->fopenWrapper($body, empty($this->headers['content-type'])); + $this->body = $fileData['fp']; + if (empty($this->headers['content-type'])) { + $this->setHeader('content-type', $fileData['type']); + } + } + $this->postParams = $this->uploads = array(); + + return $this; + } + + /** + * Returns the request body + * + * @return string|resource|HTTP_Request2_MultipartBody + */ + public function getBody() + { + if (self::METHOD_POST == $this->method + && (!empty($this->postParams) || !empty($this->uploads)) + ) { + if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) { + $body = http_build_query($this->postParams, '', '&'); + if (!$this->getConfig('use_brackets')) { + $body = preg_replace('/%5B\d+%5D=/', '=', $body); + } + // support RFC 3986 by not encoding '~' symbol (request #15368) + return str_replace('%7E', '~', $body); + + } elseif (0 === strpos($this->headers['content-type'], 'multipart/form-data')) { + require_once 'HTTP/Request2/MultipartBody.php'; + return new HTTP_Request2_MultipartBody( + $this->postParams, $this->uploads, $this->getConfig('use_brackets') + ); + } + } + return $this->body; + } + + /** + * Adds a file to form-based file upload + * + * Used to emulate file upload via a HTML form. The method also sets + * Content-Type of HTTP request to 'multipart/form-data'. + * + * If you just want to send the contents of a file as the body of HTTP + * request you should use setBody() method. + * + * If you provide file pointers rather than file names, they should support + * fstat() and rewind() operations. + * + * @param string $fieldName name of file-upload field + * @param string|resource|array $filename full name of local file, + * pointer to open file or an array of files + * @param string $sendFilename filename to send in the request + * @param string $contentType content-type of file being uploaded + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + */ + public function addUpload( + $fieldName, $filename, $sendFilename = null, $contentType = null + ) { + if (!is_array($filename)) { + $fileData = $this->fopenWrapper($filename, empty($contentType)); + $this->uploads[$fieldName] = array( + 'fp' => $fileData['fp'], + 'filename' => !empty($sendFilename)? $sendFilename + :(is_string($filename)? basename($filename): 'anonymous.blob') , + 'size' => $fileData['size'], + 'type' => empty($contentType)? $fileData['type']: $contentType + ); + } else { + $fps = $names = $sizes = $types = array(); + foreach ($filename as $f) { + if (!is_array($f)) { + $f = array($f); + } + $fileData = $this->fopenWrapper($f[0], empty($f[2])); + $fps[] = $fileData['fp']; + $names[] = !empty($f[1])? $f[1] + :(is_string($f[0])? basename($f[0]): 'anonymous.blob'); + $sizes[] = $fileData['size']; + $types[] = empty($f[2])? $fileData['type']: $f[2]; + } + $this->uploads[$fieldName] = array( + 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types + ); + } + if (empty($this->headers['content-type']) + || 'application/x-www-form-urlencoded' == $this->headers['content-type'] + ) { + $this->setHeader('content-type', 'multipart/form-data'); + } + + return $this; + } + + /** + * Adds POST parameter(s) to the request. + * + * @param string|array $name parameter name or array ('name' => 'value') + * @param mixed $value parameter value (can be an array) + * + * @return HTTP_Request2 + */ + public function addPostParameter($name, $value = null) + { + if (!is_array($name)) { + $this->postParams[$name] = $value; + } else { + foreach ($name as $k => $v) { + $this->addPostParameter($k, $v); + } + } + if (empty($this->headers['content-type'])) { + $this->setHeader('content-type', 'application/x-www-form-urlencoded'); + } + + return $this; + } + + /** + * Attaches a new observer + * + * @param SplObserver $observer any object implementing SplObserver + */ + public function attach(SplObserver $observer) + { + foreach ($this->observers as $attached) { + if ($attached === $observer) { + return; + } + } + $this->observers[] = $observer; + } + + /** + * Detaches an existing observer + * + * @param SplObserver $observer any object implementing SplObserver + */ + public function detach(SplObserver $observer) + { + foreach ($this->observers as $key => $attached) { + if ($attached === $observer) { + unset($this->observers[$key]); + return; + } + } + } + + /** + * Notifies all observers + */ + public function notify() + { + foreach ($this->observers as $observer) { + $observer->update($this); + } + } + + /** + * Sets the last event + * + * Adapters should use this method to set the current state of the request + * and notify the observers. + * + * @param string $name event name + * @param mixed $data event data + */ + public function setLastEvent($name, $data = null) + { + $this->lastEvent = array( + 'name' => $name, + 'data' => $data + ); + $this->notify(); + } + + /** + * Returns the last event + * + * Observers should use this method to access the last change in request. + * The following event names are possible: + *
    + *
  • 'connect' - after connection to remote server, + * data is the destination (string)
  • + *
  • 'disconnect' - after disconnection from server
  • + *
  • 'sentHeaders' - after sending the request headers, + * data is the headers sent (string)
  • + *
  • 'sentBodyPart' - after sending a part of the request body, + * data is the length of that part (int)
  • + *
  • 'sentBody' - after sending the whole request body, + * data is request body length (int)
  • + *
  • 'receivedHeaders' - after receiving the response headers, + * data is HTTP_Request2_Response object
  • + *
  • 'receivedBodyPart' - after receiving a part of the response + * body, data is that part (string)
  • + *
  • 'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still + * encoded by Content-Encoding
  • + *
  • 'receivedBody' - after receiving the complete response + * body, data is HTTP_Request2_Response object
  • + *
+ * Different adapters may not send all the event types. Mock adapter does + * not send any events to the observers. + * + * @return array The array has two keys: 'name' and 'data' + */ + public function getLastEvent() + { + return $this->lastEvent; + } + + /** + * Sets the adapter used to actually perform the request + * + * You can pass either an instance of a class implementing HTTP_Request2_Adapter + * or a class name. The method will only try to include a file if the class + * name starts with HTTP_Request2_Adapter_, it will also try to prepend this + * prefix to the class name if it doesn't contain any underscores, so that + * + * $request->setAdapter('curl'); + * + * will work. + * + * @param string|HTTP_Request2_Adapter $adapter Adapter to use + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + */ + public function setAdapter($adapter) + { + if (is_string($adapter)) { + if (!class_exists($adapter, false)) { + if (false === strpos($adapter, '_')) { + $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter); + } + if (!class_exists($adapter, false) + && preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter) + ) { + include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php'; + } + if (!class_exists($adapter, false)) { + throw new HTTP_Request2_LogicException( + "Class {$adapter} not found", + HTTP_Request2_Exception::MISSING_VALUE + ); + } + } + $adapter = new $adapter; + } + if (!$adapter instanceof HTTP_Request2_Adapter) { + throw new HTTP_Request2_LogicException( + 'Parameter is not a HTTP request adapter', + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + $this->adapter = $adapter; + + return $this; + } + + /** + * Sets the cookie jar + * + * A cookie jar is used to maintain cookies across HTTP requests and + * responses. Cookies from jar will be automatically added to the request + * headers based on request URL. + * + * @param HTTP_Request2_CookieJar|bool $jar Existing CookieJar object, true to + * create a new one, false to remove + * + * @return HTTP_Request2 + * @throws HTTP_Request2_LogicException + */ + public function setCookieJar($jar = true) + { + if (!class_exists('HTTP_Request2_CookieJar', false)) { + require_once 'HTTP/Request2/CookieJar.php'; + } + + if ($jar instanceof HTTP_Request2_CookieJar) { + $this->cookieJar = $jar; + } elseif (true === $jar) { + $this->cookieJar = new HTTP_Request2_CookieJar(); + } elseif (!$jar) { + $this->cookieJar = null; + } else { + throw new HTTP_Request2_LogicException( + 'Invalid parameter passed to setCookieJar()', + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + + return $this; + } + + /** + * Returns current CookieJar object or null if none + * + * @return HTTP_Request2_CookieJar|null + */ + public function getCookieJar() + { + return $this->cookieJar; + } + + /** + * Sends the request and returns the response + * + * @throws HTTP_Request2_Exception + * @return HTTP_Request2_Response + */ + public function send() + { + // Sanity check for URL + if (!$this->url instanceof Net_URL2 + || !$this->url->isAbsolute() + || !in_array(strtolower($this->url->getScheme()), array('https', 'http')) + ) { + throw new HTTP_Request2_LogicException( + 'HTTP_Request2 needs an absolute HTTP(S) request URL, ' + . ($this->url instanceof Net_URL2 + ? "'" . $this->url->__toString() . "'" : 'none') + . ' given', + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + if (empty($this->adapter)) { + $this->setAdapter($this->getConfig('adapter')); + } + // magic_quotes_runtime may break file uploads and chunked response + // processing; see bug #4543. Don't use ini_get() here; see bug #16440. + if ($magicQuotes = get_magic_quotes_runtime()) { + set_magic_quotes_runtime(false); + } + // force using single byte encoding if mbstring extension overloads + // strlen() and substr(); see bug #1781, bug #10605 + if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('8bit'); + } + + try { + $response = $this->adapter->sendRequest($this); + } catch (Exception $e) { + } + // cleanup in either case (poor man's "finally" clause) + if ($magicQuotes) { + set_magic_quotes_runtime(true); + } + if (!empty($oldEncoding)) { + mb_internal_encoding($oldEncoding); + } + // rethrow the exception + if (!empty($e)) { + throw $e; + } + return $response; + } + + /** + * Wrapper around fopen()/fstat() used by setBody() and addUpload() + * + * @param string|resource $file file name or pointer to open file + * @param bool $detectType whether to try autodetecting MIME + * type of file, will only work if $file is a + * filename, not pointer + * + * @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type) + * @throws HTTP_Request2_LogicException + */ + protected function fopenWrapper($file, $detectType = false) + { + if (!is_string($file) && !is_resource($file)) { + throw new HTTP_Request2_LogicException( + "Filename or file pointer resource expected", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + $fileData = array( + 'fp' => is_string($file)? null: $file, + 'type' => 'application/octet-stream', + 'size' => 0 + ); + if (is_string($file)) { + if (!($fileData['fp'] = @fopen($file, 'rb'))) { + $error = error_get_last(); + throw new HTTP_Request2_LogicException( + $error['message'], HTTP_Request2_Exception::READ_ERROR + ); + } + if ($detectType) { + $fileData['type'] = self::detectMimeType($file); + } + } + if (!($stat = fstat($fileData['fp']))) { + throw new HTTP_Request2_LogicException( + "fstat() call failed", HTTP_Request2_Exception::READ_ERROR + ); + } + $fileData['size'] = $stat['size']; + + return $fileData; + } + + /** + * Tries to detect MIME type of a file + * + * The method will try to use fileinfo extension if it is available, + * deprecated mime_content_type() function in the other case. If neither + * works, default 'application/octet-stream' MIME type is returned + * + * @param string $filename file name + * + * @return string file MIME type + */ + protected static function detectMimeType($filename) + { + // finfo extension from PECL available + if (function_exists('finfo_open')) { + if (!isset(self::$_fileinfoDb)) { + self::$_fileinfoDb = @finfo_open(FILEINFO_MIME); + } + if (self::$_fileinfoDb) { + $info = finfo_file(self::$_fileinfoDb, $filename); + } + } + // (deprecated) mime_content_type function available + if (empty($info) && function_exists('mime_content_type')) { + return mime_content_type($filename); + } + return empty($info)? 'application/octet-stream': $info; + } +} +?> diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Adapter.php b/libs/PEAR.1.9.5/HTTP/Request2/Adapter.php new file mode 100644 index 000000000..4e4b0b10a --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Adapter.php @@ -0,0 +1,137 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Class representing a HTTP response + */ +require_once 'HTTP/Request2/Response.php'; + +/** + * Base class for HTTP_Request2 adapters + * + * HTTP_Request2 class itself only defines methods for aggregating the request + * data, all actual work of sending the request to the remote server and + * receiving its response is performed by adapters. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +abstract class HTTP_Request2_Adapter +{ + /** + * A list of methods that MUST NOT have a request body, per RFC 2616 + * @var array + */ + protected static $bodyDisallowed = array('TRACE'); + + /** + * Methods having defined semantics for request body + * + * Content-Length header (indicating that the body follows, section 4.3 of + * RFC 2616) will be sent for these methods even if no body was added + * + * @var array + * @link http://pear.php.net/bugs/bug.php?id=12900 + * @link http://pear.php.net/bugs/bug.php?id=14740 + */ + protected static $bodyRequired = array('POST', 'PUT'); + + /** + * Request being sent + * @var HTTP_Request2 + */ + protected $request; + + /** + * Request body + * @var string|resource|HTTP_Request2_MultipartBody + * @see HTTP_Request2::getBody() + */ + protected $requestBody; + + /** + * Length of the request body + * @var integer + */ + protected $contentLength; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 $request HTTP request message + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + abstract public function sendRequest(HTTP_Request2 $request); + + /** + * Calculates length of the request body, adds proper headers + * + * @param array &$headers associative array of request headers, this method + * will add proper 'Content-Length' and 'Content-Type' + * headers to this array (or remove them if not needed) + */ + protected function calculateRequestLength(&$headers) + { + $this->requestBody = $this->request->getBody(); + + if (is_string($this->requestBody)) { + $this->contentLength = strlen($this->requestBody); + } elseif (is_resource($this->requestBody)) { + $stat = fstat($this->requestBody); + $this->contentLength = $stat['size']; + rewind($this->requestBody); + } else { + $this->contentLength = $this->requestBody->getLength(); + $headers['content-type'] = 'multipart/form-data; boundary=' . + $this->requestBody->getBoundary(); + $this->requestBody->rewind(); + } + + if (in_array($this->request->getMethod(), self::$bodyDisallowed) + || 0 == $this->contentLength + ) { + // No body: send a Content-Length header nonetheless (request #12900), + // but do that only for methods that require a body (bug #14740) + if (in_array($this->request->getMethod(), self::$bodyRequired)) { + $headers['content-length'] = 0; + } else { + unset($headers['content-length']); + // if the method doesn't require a body and doesn't have a + // body, don't send a Content-Type header. (request #16799) + unset($headers['content-type']); + } + } else { + if (empty($headers['content-type'])) { + $headers['content-type'] = 'application/x-www-form-urlencoded'; + } + // Content-Length should not be sent for chunked Transfer-Encoding (bug #20125) + if (!isset($headers['transfer-encoding'])) { + $headers['content-length'] = $this->contentLength; + } + } + } +} +?> diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Curl.php b/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Curl.php new file mode 100644 index 000000000..ef75b8c95 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Curl.php @@ -0,0 +1,567 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Adapter for HTTP_Request2 wrapping around cURL extension + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter +{ + /** + * Mapping of header names to cURL options + * @var array + */ + protected static $headerMap = array( + 'accept-encoding' => CURLOPT_ENCODING, + 'cookie' => CURLOPT_COOKIE, + 'referer' => CURLOPT_REFERER, + 'user-agent' => CURLOPT_USERAGENT + ); + + /** + * Mapping of SSL context options to cURL options + * @var array + */ + protected static $sslContextMap = array( + 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER, + 'ssl_cafile' => CURLOPT_CAINFO, + 'ssl_capath' => CURLOPT_CAPATH, + 'ssl_local_cert' => CURLOPT_SSLCERT, + 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD + ); + + /** + * Mapping of CURLE_* constants to Exception subclasses and error codes + * @var array + */ + protected static $errorMap = array( + CURLE_UNSUPPORTED_PROTOCOL => array('HTTP_Request2_MessageException', + HTTP_Request2_Exception::NON_HTTP_REDIRECT), + CURLE_COULDNT_RESOLVE_PROXY => array('HTTP_Request2_ConnectionException'), + CURLE_COULDNT_RESOLVE_HOST => array('HTTP_Request2_ConnectionException'), + CURLE_COULDNT_CONNECT => array('HTTP_Request2_ConnectionException'), + // error returned from write callback + CURLE_WRITE_ERROR => array('HTTP_Request2_MessageException', + HTTP_Request2_Exception::NON_HTTP_REDIRECT), + CURLE_OPERATION_TIMEOUTED => array('HTTP_Request2_MessageException', + HTTP_Request2_Exception::TIMEOUT), + CURLE_HTTP_RANGE_ERROR => array('HTTP_Request2_MessageException'), + CURLE_SSL_CONNECT_ERROR => array('HTTP_Request2_ConnectionException'), + CURLE_LIBRARY_NOT_FOUND => array('HTTP_Request2_LogicException', + HTTP_Request2_Exception::MISCONFIGURATION), + CURLE_FUNCTION_NOT_FOUND => array('HTTP_Request2_LogicException', + HTTP_Request2_Exception::MISCONFIGURATION), + CURLE_ABORTED_BY_CALLBACK => array('HTTP_Request2_MessageException', + HTTP_Request2_Exception::NON_HTTP_REDIRECT), + CURLE_TOO_MANY_REDIRECTS => array('HTTP_Request2_MessageException', + HTTP_Request2_Exception::TOO_MANY_REDIRECTS), + CURLE_SSL_PEER_CERTIFICATE => array('HTTP_Request2_ConnectionException'), + CURLE_GOT_NOTHING => array('HTTP_Request2_MessageException'), + CURLE_SSL_ENGINE_NOTFOUND => array('HTTP_Request2_LogicException', + HTTP_Request2_Exception::MISCONFIGURATION), + CURLE_SSL_ENGINE_SETFAILED => array('HTTP_Request2_LogicException', + HTTP_Request2_Exception::MISCONFIGURATION), + CURLE_SEND_ERROR => array('HTTP_Request2_MessageException'), + CURLE_RECV_ERROR => array('HTTP_Request2_MessageException'), + CURLE_SSL_CERTPROBLEM => array('HTTP_Request2_LogicException', + HTTP_Request2_Exception::INVALID_ARGUMENT), + CURLE_SSL_CIPHER => array('HTTP_Request2_ConnectionException'), + CURLE_SSL_CACERT => array('HTTP_Request2_ConnectionException'), + CURLE_BAD_CONTENT_ENCODING => array('HTTP_Request2_MessageException'), + ); + + /** + * Response being received + * @var HTTP_Request2_Response + */ + protected $response; + + /** + * Whether 'sentHeaders' event was sent to observers + * @var boolean + */ + protected $eventSentHeaders = false; + + /** + * Whether 'receivedHeaders' event was sent to observers + * @var boolean + */ + protected $eventReceivedHeaders = false; + + /** + * Position within request body + * @var integer + * @see callbackReadBody() + */ + protected $position = 0; + + /** + * Information about last transfer, as returned by curl_getinfo() + * @var array + */ + protected $lastInfo; + + /** + * Creates a subclass of HTTP_Request2_Exception from curl error data + * + * @param resource $ch curl handle + * + * @return HTTP_Request2_Exception + */ + protected static function wrapCurlError($ch) + { + $nativeCode = curl_errno($ch); + $message = 'Curl error: ' . curl_error($ch); + if (!isset(self::$errorMap[$nativeCode])) { + return new HTTP_Request2_Exception($message, 0, $nativeCode); + } else { + $class = self::$errorMap[$nativeCode][0]; + $code = empty(self::$errorMap[$nativeCode][1]) + ? 0 : self::$errorMap[$nativeCode][1]; + return new $class($message, $code, $nativeCode); + } + } + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 $request HTTP request message + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + if (!extension_loaded('curl')) { + throw new HTTP_Request2_LogicException( + 'cURL extension not available', HTTP_Request2_Exception::MISCONFIGURATION + ); + } + + $this->request = $request; + $this->response = null; + $this->position = 0; + $this->eventSentHeaders = false; + $this->eventReceivedHeaders = false; + + try { + if (false === curl_exec($ch = $this->createCurlHandle())) { + $e = self::wrapCurlError($ch); + } + } catch (Exception $e) { + } + if (isset($ch)) { + $this->lastInfo = curl_getinfo($ch); + curl_close($ch); + } + + $response = $this->response; + unset($this->request, $this->requestBody, $this->response); + + if (!empty($e)) { + throw $e; + } + + if ($jar = $request->getCookieJar()) { + $jar->addCookiesFromResponse($response, $request->getUrl()); + } + + if (0 < $this->lastInfo['size_download']) { + $request->setLastEvent('receivedBody', $response); + } + return $response; + } + + /** + * Returns information about last transfer + * + * @return array associative array as returned by curl_getinfo() + */ + public function getInfo() + { + return $this->lastInfo; + } + + /** + * Creates a new cURL handle and populates it with data from the request + * + * @return resource a cURL handle, as created by curl_init() + * @throws HTTP_Request2_LogicException + * @throws HTTP_Request2_NotImplementedException + */ + protected function createCurlHandle() + { + $ch = curl_init(); + + curl_setopt_array($ch, array( + // setup write callbacks + CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'), + CURLOPT_WRITEFUNCTION => array($this, 'callbackWriteBody'), + // buffer size + CURLOPT_BUFFERSIZE => $this->request->getConfig('buffer_size'), + // connection timeout + CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'), + // save full outgoing headers, in case someone is interested + CURLINFO_HEADER_OUT => true, + // request url + CURLOPT_URL => $this->request->getUrl()->getUrl() + )); + + // set up redirects + if (!$this->request->getConfig('follow_redirects')) { + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); + } else { + if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)) { + throw new HTTP_Request2_LogicException( + 'Redirect support in curl is unavailable due to open_basedir or safe_mode setting', + HTTP_Request2_Exception::MISCONFIGURATION + ); + } + curl_setopt($ch, CURLOPT_MAXREDIRS, $this->request->getConfig('max_redirects')); + // limit redirects to http(s), works in 5.2.10+ + if (defined('CURLOPT_REDIR_PROTOCOLS')) { + curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + } + // works in 5.3.2+, http://bugs.php.net/bug.php?id=49571 + if ($this->request->getConfig('strict_redirects') && defined('CURLOPT_POSTREDIR')) { + curl_setopt($ch, CURLOPT_POSTREDIR, 3); + } + } + + // set local IP via CURLOPT_INTERFACE (request #19515) + if ($ip = $this->request->getConfig('local_ip')) { + curl_setopt($ch, CURLOPT_INTERFACE, $ip); + } + + // request timeout + if ($timeout = $this->request->getConfig('timeout')) { + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + } + + // set HTTP version + switch ($this->request->getConfig('protocol_version')) { + case '1.0': + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + break; + case '1.1': + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + } + + // set request method + switch ($this->request->getMethod()) { + case HTTP_Request2::METHOD_GET: + curl_setopt($ch, CURLOPT_HTTPGET, true); + break; + case HTTP_Request2::METHOD_POST: + curl_setopt($ch, CURLOPT_POST, true); + break; + case HTTP_Request2::METHOD_HEAD: + curl_setopt($ch, CURLOPT_NOBODY, true); + break; + case HTTP_Request2::METHOD_PUT: + curl_setopt($ch, CURLOPT_UPLOAD, true); + break; + default: + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod()); + } + + // set proxy, if needed + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_LogicException( + 'Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE + ); + } + curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port); + if ($user = $this->request->getConfig('proxy_user')) { + curl_setopt( + $ch, CURLOPT_PROXYUSERPWD, + $user . ':' . $this->request->getConfig('proxy_password') + ); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + break; + case HTTP_Request2::AUTH_DIGEST: + curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST); + } + } + if ($type = $this->request->getConfig('proxy_type')) { + switch ($type) { + case 'http': + curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + break; + case 'socks5': + curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + break; + default: + throw new HTTP_Request2_NotImplementedException( + "Proxy type '{$type}' is not supported" + ); + } + } + } + + // set authentication data + if ($auth = $this->request->getAuth()) { + curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']); + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + break; + case HTTP_Request2::AUTH_DIGEST: + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); + } + } + + // set SSL options + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_verify_host' == $name && null !== $value) { + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0); + } elseif (isset(self::$sslContextMap[$name]) && null !== $value) { + curl_setopt($ch, self::$sslContextMap[$name], $value); + } + } + + $headers = $this->request->getHeaders(); + // make cURL automagically send proper header + if (!isset($headers['accept-encoding'])) { + $headers['accept-encoding'] = ''; + } + + if (($jar = $this->request->getCookieJar()) + && ($cookies = $jar->getMatching($this->request->getUrl(), true)) + ) { + $headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies; + } + + // set headers having special cURL keys + foreach (self::$headerMap as $name => $option) { + if (isset($headers[$name])) { + curl_setopt($ch, $option, $headers[$name]); + unset($headers[$name]); + } + } + + $this->calculateRequestLength($headers); + if (isset($headers['content-length']) || isset($headers['transfer-encoding'])) { + $this->workaroundPhpBug47204($ch, $headers); + } + + // set headers not having special keys + $headersFmt = array(); + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersFmt[] = $canonicalName . ': ' . $value; + } + curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt); + + return $ch; + } + + /** + * Workaround for PHP bug #47204 that prevents rewinding request body + * + * The workaround consists of reading the entire request body into memory + * and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large + * file uploads, use Socket adapter instead. + * + * @param resource $ch cURL handle + * @param array &$headers Request headers + */ + protected function workaroundPhpBug47204($ch, &$headers) + { + // no redirects, no digest auth -> probably no rewind needed + if (!$this->request->getConfig('follow_redirects') + && (!($auth = $this->request->getAuth()) + || HTTP_Request2::AUTH_DIGEST != $auth['scheme']) + ) { + curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody')); + + } else { + // rewind may be needed, read the whole body into memory + if ($this->requestBody instanceof HTTP_Request2_MultipartBody) { + $this->requestBody = $this->requestBody->__toString(); + + } elseif (is_resource($this->requestBody)) { + $fp = $this->requestBody; + $this->requestBody = ''; + while (!feof($fp)) { + $this->requestBody .= fread($fp, 16384); + } + } + // curl hangs up if content-length is present + unset($headers['content-length']); + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody); + } + } + + /** + * Callback function called by cURL for reading the request body + * + * @param resource $ch cURL handle + * @param resource $fd file descriptor (not used) + * @param integer $length maximum length of data to return + * + * @return string part of the request body, up to $length bytes + */ + protected function callbackReadBody($ch, $fd, $length) + { + if (!$this->eventSentHeaders) { + $this->request->setLastEvent( + 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) + ); + $this->eventSentHeaders = true; + } + if (in_array($this->request->getMethod(), self::$bodyDisallowed) + || 0 == $this->contentLength || $this->position >= $this->contentLength + ) { + return ''; + } + if (is_string($this->requestBody)) { + $string = substr($this->requestBody, $this->position, $length); + } elseif (is_resource($this->requestBody)) { + $string = fread($this->requestBody, $length); + } else { + $string = $this->requestBody->read($length); + } + $this->request->setLastEvent('sentBodyPart', strlen($string)); + $this->position += strlen($string); + return $string; + } + + /** + * Callback function called by cURL for saving the response headers + * + * @param resource $ch cURL handle + * @param string $string response header (with trailing CRLF) + * + * @return integer number of bytes saved + * @see HTTP_Request2_Response::parseHeaderLine() + */ + protected function callbackWriteHeader($ch, $string) + { + // we may receive a second set of headers if doing e.g. digest auth + if ($this->eventReceivedHeaders || !$this->eventSentHeaders) { + // don't bother with 100-Continue responses (bug #15785) + if (!$this->eventSentHeaders + || $this->response->getStatus() >= 200 + ) { + $this->request->setLastEvent( + 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) + ); + } + $upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD); + // if body wasn't read by a callback, send event with total body size + if ($upload > $this->position) { + $this->request->setLastEvent( + 'sentBodyPart', $upload - $this->position + ); + $this->position = $upload; + } + if ($upload && (!$this->eventSentHeaders + || $this->response->getStatus() >= 200) + ) { + $this->request->setLastEvent('sentBody', $upload); + } + $this->eventSentHeaders = true; + // we'll need a new response object + if ($this->eventReceivedHeaders) { + $this->eventReceivedHeaders = false; + $this->response = null; + } + } + if (empty($this->response)) { + $this->response = new HTTP_Request2_Response( + $string, false, curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) + ); + } else { + $this->response->parseHeaderLine($string); + if ('' == trim($string)) { + // don't bother with 100-Continue responses (bug #15785) + if (200 <= $this->response->getStatus()) { + $this->request->setLastEvent('receivedHeaders', $this->response); + } + + if ($this->request->getConfig('follow_redirects') && $this->response->isRedirect()) { + $redirectUrl = new Net_URL2($this->response->getHeader('location')); + + // for versions lower than 5.2.10, check the redirection URL protocol + if (!defined('CURLOPT_REDIR_PROTOCOLS') && $redirectUrl->isAbsolute() + && !in_array($redirectUrl->getScheme(), array('http', 'https')) + ) { + return -1; + } + + if ($jar = $this->request->getCookieJar()) { + $jar->addCookiesFromResponse($this->response, $this->request->getUrl()); + if (!$redirectUrl->isAbsolute()) { + $redirectUrl = $this->request->getUrl()->resolve($redirectUrl); + } + if ($cookies = $jar->getMatching($redirectUrl, true)) { + curl_setopt($ch, CURLOPT_COOKIE, $cookies); + } + } + } + $this->eventReceivedHeaders = true; + } + } + return strlen($string); + } + + /** + * Callback function called by cURL for saving the response body + * + * @param resource $ch cURL handle (not used) + * @param string $string part of the response body + * + * @return integer number of bytes saved + * @throws HTTP_Request2_MessageException + * @see HTTP_Request2_Response::appendBody() + */ + protected function callbackWriteBody($ch, $string) + { + // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if + // response doesn't start with proper HTTP status line (see bug #15716) + if (empty($this->response)) { + throw new HTTP_Request2_MessageException( + "Malformed response: {$string}", + HTTP_Request2_Exception::MALFORMED_RESPONSE + ); + } + if ($this->request->getConfig('store_body')) { + $this->response->appendBody($string); + } + $this->request->setLastEvent('receivedBodyPart', $string); + return strlen($string); + } +} +?> diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Mock.php b/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Mock.php new file mode 100644 index 000000000..d6e274ab9 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Mock.php @@ -0,0 +1,166 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Mock adapter intended for testing + * + * Can be used to test applications depending on HTTP_Request2 package without + * actually performing any HTTP requests. This adapter will return responses + * previously added via addResponse() + * + * $mock = new HTTP_Request2_Adapter_Mock(); + * $mock->addResponse("HTTP/1.1 ... "); + * + * $request = new HTTP_Request2(); + * $request->setAdapter($mock); + * + * // This will return the response set above + * $response = $req->send(); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter +{ + /** + * A queue of responses to be returned by sendRequest() + * @var array + */ + protected $responses = array(); + + /** + * Returns the next response from the queue built by addResponse() + * + * Only responses without explicit URLs or with URLs equal to request URL + * will be considered. If matching response is not found or the queue is + * empty then default empty response with status 400 will be returned, + * if an Exception object was added to the queue it will be thrown. + * + * @param HTTP_Request2 $request HTTP request message + * + * @return HTTP_Request2_Response + * @throws Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + $requestUrl = (string)$request->getUrl(); + $response = null; + foreach ($this->responses as $k => $v) { + if (!$v[1] || $requestUrl == $v[1]) { + $response = $v[0]; + array_splice($this->responses, $k, 1); + break; + } + } + if (!$response) { + return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n"); + + } elseif ($response instanceof HTTP_Request2_Response) { + return $response; + + } else { + // rethrow the exception + $class = get_class($response); + $message = $response->getMessage(); + $code = $response->getCode(); + throw new $class($message, $code); + } + } + + /** + * Adds response to the queue + * + * @param mixed $response either a string, a pointer to an open file, + * an instance of HTTP_Request2_Response or Exception + * @param string $url A request URL this response should be valid for + * (see {@link http://pear.php.net/bugs/bug.php?id=19276}) + * + * @throws HTTP_Request2_Exception + */ + public function addResponse($response, $url = null) + { + if (is_string($response)) { + $response = self::createResponseFromString($response); + } elseif (is_resource($response)) { + $response = self::createResponseFromFile($response); + } elseif (!$response instanceof HTTP_Request2_Response && + !$response instanceof Exception + ) { + throw new HTTP_Request2_Exception('Parameter is not a valid response'); + } + $this->responses[] = array($response, $url); + } + + /** + * Creates a new HTTP_Request2_Response object from a string + * + * @param string $str string containing HTTP response message + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public static function createResponseFromString($str) + { + $parts = preg_split('!(\r?\n){2}!m', $str, 2); + $headerLines = explode("\n", $parts[0]); + $response = new HTTP_Request2_Response(array_shift($headerLines)); + foreach ($headerLines as $headerLine) { + $response->parseHeaderLine($headerLine); + } + $response->parseHeaderLine(''); + if (isset($parts[1])) { + $response->appendBody($parts[1]); + } + return $response; + } + + /** + * Creates a new HTTP_Request2_Response object from a file + * + * @param resource $fp file pointer returned by fopen() + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public static function createResponseFromFile($fp) + { + $response = new HTTP_Request2_Response(fgets($fp)); + do { + $headerLine = fgets($fp); + $response->parseHeaderLine($headerLine); + } while ('' != trim($headerLine)); + + while (!feof($fp)) { + $response->appendBody(fread($fp, 8192)); + } + return $response; + } +} +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Socket.php b/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Socket.php new file mode 100644 index 000000000..7946b0a37 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Adapter/Socket.php @@ -0,0 +1,1121 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** Base class for HTTP_Request2 adapters */ +require_once 'HTTP/Request2/Adapter.php'; + +/** Socket wrapper class */ +require_once 'HTTP/Request2/SocketWrapper.php'; + +/** + * Socket-based adapter for HTTP_Request2 + * + * This adapter uses only PHP sockets and will work on almost any PHP + * environment. Code is based on original HTTP_Request PEAR package. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter +{ + /** + * Regular expression for 'token' rule from RFC 2616 + */ + const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; + + /** + * Regular expression for 'quoted-string' rule from RFC 2616 + */ + const REGEXP_QUOTED_STRING = '"(?>[^"\\\\]+|\\\\.)*"'; + + /** + * Connected sockets, needed for Keep-Alive support + * @var array + * @see connect() + */ + protected static $sockets = array(); + + /** + * Data for digest authentication scheme + * + * The keys for the array are URL prefixes. + * + * The values are associative arrays with data (realm, nonce, nonce-count, + * opaque...) needed for digest authentication. Stored here to prevent making + * duplicate requests to digest-protected resources after we have already + * received the challenge. + * + * @var array + */ + protected static $challenges = array(); + + /** + * Connected socket + * @var HTTP_Request2_SocketWrapper + * @see connect() + */ + protected $socket; + + /** + * Challenge used for server digest authentication + * @var array + */ + protected $serverChallenge; + + /** + * Challenge used for proxy digest authentication + * @var array + */ + protected $proxyChallenge; + + /** + * Remaining length of the current chunk, when reading chunked response + * @var integer + * @see readChunked() + */ + protected $chunkLength = 0; + + /** + * Remaining amount of redirections to follow + * + * Starts at 'max_redirects' configuration parameter and is reduced on each + * subsequent redirect. An Exception will be thrown once it reaches zero. + * + * @var integer + */ + protected $redirectCountdown = null; + + /** + * Whether to wait for "100 Continue" response before sending request body + * @var bool + */ + protected $expect100Continue = false; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 $request HTTP request message + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + $this->request = $request; + + try { + $keepAlive = $this->connect(); + $headers = $this->prepareHeaders(); + $this->socket->write($headers); + // provide request headers to the observer, see request #7633 + $this->request->setLastEvent('sentHeaders', $headers); + + if (!$this->expect100Continue) { + $this->writeBody(); + $response = $this->readResponse(); + + } else { + $response = $this->readResponse(); + if (!$response || 100 == $response->getStatus()) { + $this->expect100Continue = false; + // either got "100 Continue" or timed out -> send body + $this->writeBody(); + $response = $this->readResponse(); + } + } + + + if ($jar = $request->getCookieJar()) { + $jar->addCookiesFromResponse($response, $request->getUrl()); + } + + if (!$this->canKeepAlive($keepAlive, $response)) { + $this->disconnect(); + } + + if ($this->shouldUseProxyDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($this->shouldUseServerDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($authInfo = $response->getHeader('authentication-info')) { + $this->updateChallenge($this->serverChallenge, $authInfo); + } + if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { + $this->updateChallenge($this->proxyChallenge, $proxyInfo); + } + + } catch (Exception $e) { + $this->disconnect(); + } + + unset($this->request, $this->requestBody); + + if (!empty($e)) { + $this->redirectCountdown = null; + throw $e; + } + + if (!$request->getConfig('follow_redirects') || !$response->isRedirect()) { + $this->redirectCountdown = null; + return $response; + } else { + return $this->handleRedirect($request, $response); + } + } + + /** + * Connects to the remote server + * + * @return bool whether the connection can be persistent + * @throws HTTP_Request2_Exception + */ + protected function connect() + { + $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); + $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $headers = $this->request->getHeaders(); + $reqHost = $this->request->getUrl()->getHost(); + if (!($reqPort = $this->request->getUrl()->getPort())) { + $reqPort = $secure? 443: 80; + } + + $httpProxy = $socksProxy = false; + if (!($host = $this->request->getConfig('proxy_host'))) { + $host = $reqHost; + $port = $reqPort; + } else { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_LogicException( + 'Proxy port not provided', + HTTP_Request2_Exception::MISSING_VALUE + ); + } + if ('http' == ($type = $this->request->getConfig('proxy_type'))) { + $httpProxy = true; + } elseif ('socks5' == $type) { + $socksProxy = true; + } else { + throw new HTTP_Request2_NotImplementedException( + "Proxy type '{$type}' is not supported" + ); + } + } + + if ($tunnel && !$httpProxy) { + throw new HTTP_Request2_LogicException( + "Trying to perform CONNECT request without proxy", + HTTP_Request2_Exception::MISSING_VALUE + ); + } + if ($secure && !in_array('ssl', stream_get_transports())) { + throw new HTTP_Request2_LogicException( + 'Need OpenSSL support for https:// requests', + HTTP_Request2_Exception::MISCONFIGURATION + ); + } + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if ($httpProxy && !$secure && !empty($headers['connection']) + && 'Keep-Alive' == $headers['connection'] + ) { + $this->request->setHeader('connection'); + } + + $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && + empty($headers['connection'])) || + (!empty($headers['connection']) && + 'Keep-Alive' == $headers['connection']); + + $options = array(); + if ($ip = $this->request->getConfig('local_ip')) { + $options['socket'] = array( + 'bindto' => (false === strpos($ip, ':') ? $ip : '[' . $ip . ']') . ':0' + ); + } + if ($secure || $tunnel) { + $options['ssl'] = array(); + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_' == substr($name, 0, 4) && null !== $value) { + if ('ssl_verify_host' == $name) { + if ($value) { + $options['ssl']['CN_match'] = $reqHost; + } + } else { + $options['ssl'][substr($name, 4)] = $value; + } + } + } + ksort($options['ssl']); + } + + // Use global request timeout if given, see feature requests #5735, #8964 + if ($timeout = $this->request->getConfig('timeout')) { + $deadline = time() + $timeout; + } else { + $deadline = null; + } + + // Changing SSL context options after connection is established does *not* + // work, we need a new connection if options change + $remote = ((!$secure || $httpProxy || $socksProxy)? 'tcp://': 'ssl://') + . $host . ':' . $port; + $socketKey = $remote . ( + ($secure && $httpProxy || $socksProxy) + ? "->{$reqHost}:{$reqPort}" : '' + ) . (empty($options)? '': ':' . serialize($options)); + unset($this->socket); + + // We use persistent connections and have a connected socket? + // Ensure that the socket is still connected, see bug #16149 + if ($keepAlive && !empty(self::$sockets[$socketKey]) + && !self::$sockets[$socketKey]->eof() + ) { + $this->socket =& self::$sockets[$socketKey]; + + } else { + if ($socksProxy) { + require_once 'HTTP/Request2/SOCKS5.php'; + + $this->socket = new HTTP_Request2_SOCKS5( + $remote, $this->request->getConfig('connect_timeout'), + $options, $this->request->getConfig('proxy_user'), + $this->request->getConfig('proxy_password') + ); + // handle request timeouts ASAP + $this->socket->setDeadline($deadline, $this->request->getConfig('timeout')); + $this->socket->connect($reqHost, $reqPort); + if (!$secure) { + $conninfo = "tcp://{$reqHost}:{$reqPort} via {$remote}"; + } else { + $this->socket->enableCrypto(); + $conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}"; + } + + } elseif ($secure && $httpProxy && !$tunnel) { + $this->establishTunnel(); + $conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}"; + + } else { + $this->socket = new HTTP_Request2_SocketWrapper( + $remote, $this->request->getConfig('connect_timeout'), $options + ); + } + $this->request->setLastEvent('connect', empty($conninfo)? $remote: $conninfo); + self::$sockets[$socketKey] =& $this->socket; + } + $this->socket->setDeadline($deadline, $this->request->getConfig('timeout')); + return $keepAlive; + } + + /** + * Establishes a tunnel to a secure remote server via HTTP CONNECT request + * + * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP + * sees that we are connected to a proxy server (duh!) rather than the server + * that presents its certificate. + * + * @link http://tools.ietf.org/html/rfc2817#section-5.2 + * @throws HTTP_Request2_Exception + */ + protected function establishTunnel() + { + $donor = new self; + $connect = new HTTP_Request2( + $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, + array_merge($this->request->getConfig(), array('adapter' => $donor)) + ); + $response = $connect->send(); + // Need any successful (2XX) response + if (200 > $response->getStatus() || 300 <= $response->getStatus()) { + throw new HTTP_Request2_ConnectionException( + 'Failed to connect via HTTPS proxy. Proxy response: ' . + $response->getStatus() . ' ' . $response->getReasonPhrase() + ); + } + $this->socket = $donor->socket; + $this->socket->enableCrypto(); + } + + /** + * Checks whether current connection may be reused or should be closed + * + * @param boolean $requestKeepAlive whether connection could + * be persistent in the first place + * @param HTTP_Request2_Response $response response object to check + * + * @return boolean + */ + protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) + { + // Do not close socket on successful CONNECT request + if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() + && 200 <= $response->getStatus() && 300 > $response->getStatus() + ) { + return true; + } + + $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) + || null !== $response->getHeader('content-length') + // no body possible for such responses, see also request #17031 + || HTTP_Request2::METHOD_HEAD == $this->request->getMethod() + || in_array($response->getStatus(), array(204, 304)); + $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || + (null === $response->getHeader('connection') && + '1.1' == $response->getVersion()); + return $requestKeepAlive && $lengthKnown && $persistent; + } + + /** + * Disconnects from the remote server + */ + protected function disconnect() + { + if (!empty($this->socket)) { + $this->socket = null; + $this->request->setLastEvent('disconnect'); + } + } + + /** + * Handles HTTP redirection + * + * This method will throw an Exception if redirect to a non-HTTP(S) location + * is attempted, also if number of redirects performed already is equal to + * 'max_redirects' configuration parameter. + * + * @param HTTP_Request2 $request Original request + * @param HTTP_Request2_Response $response Response containing redirect + * + * @return HTTP_Request2_Response Response from a new location + * @throws HTTP_Request2_Exception + */ + protected function handleRedirect( + HTTP_Request2 $request, HTTP_Request2_Response $response + ) { + if (is_null($this->redirectCountdown)) { + $this->redirectCountdown = $request->getConfig('max_redirects'); + } + if (0 == $this->redirectCountdown) { + $this->redirectCountdown = null; + // Copying cURL behaviour + throw new HTTP_Request2_MessageException( + 'Maximum (' . $request->getConfig('max_redirects') . ') redirects followed', + HTTP_Request2_Exception::TOO_MANY_REDIRECTS + ); + } + $redirectUrl = new Net_URL2( + $response->getHeader('location'), + array(Net_URL2::OPTION_USE_BRACKETS => $request->getConfig('use_brackets')) + ); + // refuse non-HTTP redirect + if ($redirectUrl->isAbsolute() + && !in_array($redirectUrl->getScheme(), array('http', 'https')) + ) { + $this->redirectCountdown = null; + throw new HTTP_Request2_MessageException( + 'Refusing to redirect to a non-HTTP URL ' . $redirectUrl->__toString(), + HTTP_Request2_Exception::NON_HTTP_REDIRECT + ); + } + // Theoretically URL should be absolute (see http://tools.ietf.org/html/rfc2616#section-14.30), + // but in practice it is often not + if (!$redirectUrl->isAbsolute()) { + $redirectUrl = $request->getUrl()->resolve($redirectUrl); + } + $redirect = clone $request; + $redirect->setUrl($redirectUrl); + if (303 == $response->getStatus() + || (!$request->getConfig('strict_redirects') + && in_array($response->getStatus(), array(301, 302))) + ) { + $redirect->setMethod(HTTP_Request2::METHOD_GET); + $redirect->setBody(''); + } + + if (0 < $this->redirectCountdown) { + $this->redirectCountdown--; + } + return $this->sendRequest($redirect); + } + + /** + * Checks whether another request should be performed with server digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 401 + * - auth credentials should be set in the request object + * - response should contain WWW-Authenticate header with digest challenge + * - there is either no challenge stored for this URL or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response $response response to check + * + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) + { + // no sense repeating a request if we don't have credentials + if (401 != $response->getStatus() || !$this->request->getAuth()) { + return false; + } + if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { + return false; + } + + $url = $this->request->getUrl(); + $scheme = $url->getScheme(); + $host = $scheme . '://' . $url->getHost(); + if ($port = $url->getPort()) { + if ((0 == strcasecmp($scheme, 'http') && 80 != $port) + || (0 == strcasecmp($scheme, 'https') && 443 != $port) + ) { + $host .= ':' . $port; + } + } + + if (!empty($challenge['domain'])) { + $prefixes = array(); + foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { + // don't bother with different servers + if ('/' == substr($prefix, 0, 1)) { + $prefixes[] = $host . $prefix; + } + } + } + if (empty($prefixes)) { + $prefixes = array($host . '/'); + } + + $ret = true; + foreach ($prefixes as $prefix) { + if (!empty(self::$challenges[$prefix]) + && (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + // probably credentials are invalid + $ret = false; + } + self::$challenges[$prefix] =& $challenge; + } + return $ret; + } + + /** + * Checks whether another request should be performed with proxy digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 407 + * - proxy auth credentials should be set in the request object + * - response should contain Proxy-Authenticate header with digest challenge + * - there is either no challenge stored for this proxy or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response $response response to check + * + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) + { + if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { + return false; + } + if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { + return false; + } + + $key = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + + if (!empty(self::$challenges[$key]) + && (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + $ret = false; + } else { + $ret = true; + } + self::$challenges[$key] = $challenge; + return $ret; + } + + /** + * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value + * + * There is a problem with implementation of RFC 2617: several of the parameters + * are defined as quoted-string there and thus may contain backslash escaped + * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as + * just value of quoted-string X without surrounding quotes, it doesn't speak + * about removing backslash escaping. + * + * Now realm parameter is user-defined and human-readable, strange things + * happen when it contains quotes: + * - Apache allows quotes in realm, but apparently uses realm value without + * backslashes for digest computation + * - Squid allows (manually escaped) quotes there, but it is impossible to + * authorize with either escaped or unescaped quotes used in digest, + * probably it can't parse the response (?) + * - Both IE and Firefox display realm value with backslashes in + * the password popup and apparently use the same value for digest + * + * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in + * quoted-string handling, unfortunately that means failure to authorize + * sometimes + * + * @param string $headerValue value of WWW-Authenticate or Proxy-Authenticate header + * + * @return mixed associative array with challenge parameters, false if + * no challenge is present in header value + * @throws HTTP_Request2_NotImplementedException in case of unsupported challenge parameters + */ + protected function parseDigestChallenge($headerValue) + { + $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; + $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; + if (!preg_match($challenge, $headerValue, $matches)) { + return false; + } + + preg_match_all('!' . $authParam . '!', $matches[0], $params); + $paramsAry = array(); + $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', + 'algorithm', 'qop'); + for ($i = 0; $i < count($params[0]); $i++) { + // section 3.2.1: Any unrecognized directive MUST be ignored. + if (in_array($params[1][$i], $knownParams)) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + } + // we only support qop=auth + if (!empty($paramsAry['qop']) + && !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) + ) { + throw new HTTP_Request2_NotImplementedException( + "Only 'auth' qop is currently supported in digest authentication, " . + "server requested '{$paramsAry['qop']}'" + ); + } + // we only support algorithm=MD5 + if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { + throw new HTTP_Request2_NotImplementedException( + "Only 'MD5' algorithm is currently supported in digest authentication, " . + "server requested '{$paramsAry['algorithm']}'" + ); + } + + return $paramsAry; + } + + /** + * Parses [Proxy-]Authentication-Info header value and updates challenge + * + * @param array &$challenge challenge to update + * @param string $headerValue value of [Proxy-]Authentication-Info header + * + * @todo validate server rspauth response + */ + protected function updateChallenge(&$challenge, $headerValue) + { + $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; + $paramsAry = array(); + + preg_match_all($authParam, $headerValue, $params); + for ($i = 0; $i < count($params[0]); $i++) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + // for now, just update the nonce value + if (!empty($paramsAry['nextnonce'])) { + $challenge['nonce'] = $paramsAry['nextnonce']; + $challenge['nc'] = 1; + } + } + + /** + * Creates a value for [Proxy-]Authorization header when using digest authentication + * + * @param string $user user name + * @param string $password password + * @param string $url request URL + * @param array &$challenge digest challenge parameters + * + * @return string value of [Proxy-]Authorization request header + * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 + */ + protected function createDigestResponse($user, $password, $url, &$challenge) + { + if (false !== ($q = strpos($url, '?')) + && $this->request->getConfig('digest_compat_ie') + ) { + $url = substr($url, 0, $q); + } + + $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); + $a2 = md5($this->request->getMethod() . ':' . $url); + + if (empty($challenge['qop'])) { + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); + } else { + $challenge['cnonce'] = 'Req2.' . rand(); + if (empty($challenge['nc'])) { + $challenge['nc'] = 1; + } + $nc = sprintf('%08x', $challenge['nc']++); + $digest = md5( + $a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . + $challenge['cnonce'] . ':auth:' . $a2 + ); + } + return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . + 'realm="' . $challenge['realm'] . '", ' . + 'nonce="' . $challenge['nonce'] . '", ' . + 'uri="' . $url . '", ' . + 'response="' . $digest . '"' . + (!empty($challenge['opaque'])? + ', opaque="' . $challenge['opaque'] . '"': + '') . + (!empty($challenge['qop'])? + ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': + ''); + } + + /** + * Adds 'Authorization' header (if needed) to request headers array + * + * @param array &$headers request headers + * @param string $requestHost request host (needed for digest authentication) + * @param string $requestUrl request URL (needed for digest authentication) + * + * @throws HTTP_Request2_NotImplementedException + */ + protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) + { + if (!($auth = $this->request->getAuth())) { + return; + } + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + $headers['authorization'] = 'Basic ' . base64_encode( + $auth['user'] . ':' . $auth['password'] + ); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->serverChallenge); + $fullUrl = ('/' == $requestUrl[0])? + $this->request->getUrl()->getScheme() . '://' . + $requestHost . $requestUrl: + $requestUrl; + foreach (array_keys(self::$challenges) as $key) { + if ($key == substr($fullUrl, 0, strlen($key))) { + $headers['authorization'] = $this->createDigestResponse( + $auth['user'], $auth['password'], + $requestUrl, self::$challenges[$key] + ); + $this->serverChallenge =& self::$challenges[$key]; + break; + } + } + break; + + default: + throw new HTTP_Request2_NotImplementedException( + "Unknown HTTP authentication scheme '{$auth['scheme']}'" + ); + } + } + + /** + * Adds 'Proxy-Authorization' header (if needed) to request headers array + * + * @param array &$headers request headers + * @param string $requestUrl request URL (needed for digest authentication) + * + * @throws HTTP_Request2_NotImplementedException + */ + protected function addProxyAuthorizationHeader(&$headers, $requestUrl) + { + if (!$this->request->getConfig('proxy_host') + || !($user = $this->request->getConfig('proxy_user')) + || (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) + && HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) + ) { + return; + } + + $password = $this->request->getConfig('proxy_password'); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + $headers['proxy-authorization'] = 'Basic ' . base64_encode( + $user . ':' . $password + ); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->proxyChallenge); + $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + if (!empty(self::$challenges[$proxyUrl])) { + $headers['proxy-authorization'] = $this->createDigestResponse( + $user, $password, + $requestUrl, self::$challenges[$proxyUrl] + ); + $this->proxyChallenge =& self::$challenges[$proxyUrl]; + } + break; + + default: + throw new HTTP_Request2_NotImplementedException( + "Unknown HTTP authentication scheme '" . + $this->request->getConfig('proxy_auth_scheme') . "'" + ); + } + } + + + /** + * Creates the string with the Request-Line and request headers + * + * @return string + * @throws HTTP_Request2_Exception + */ + protected function prepareHeaders() + { + $headers = $this->request->getHeaders(); + $url = $this->request->getUrl(); + $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $host = $url->getHost(); + + $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; + if (($port = $url->getPort()) && $port != $defaultPort || $connect) { + $host .= ':' . (empty($port)? $defaultPort: $port); + } + // Do not overwrite explicitly set 'Host' header, see bug #16146 + if (!isset($headers['host'])) { + $headers['host'] = $host; + } + + if ($connect) { + $requestUrl = $host; + + } else { + if (!$this->request->getConfig('proxy_host') + || 'http' != $this->request->getConfig('proxy_type') + || 0 == strcasecmp($url->getScheme(), 'https') + ) { + $requestUrl = ''; + } else { + $requestUrl = $url->getScheme() . '://' . $host; + } + $path = $url->getPath(); + $query = $url->getQuery(); + $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); + } + + if ('1.1' == $this->request->getConfig('protocol_version') + && extension_loaded('zlib') && !isset($headers['accept-encoding']) + ) { + $headers['accept-encoding'] = 'gzip, deflate'; + } + if (($jar = $this->request->getCookieJar()) + && ($cookies = $jar->getMatching($this->request->getUrl(), true)) + ) { + $headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies; + } + + $this->addAuthorizationHeader($headers, $host, $requestUrl); + $this->addProxyAuthorizationHeader($headers, $requestUrl); + $this->calculateRequestLength($headers); + if ('1.1' == $this->request->getConfig('protocol_version')) { + $this->updateExpectHeader($headers); + } else { + $this->expect100Continue = false; + } + + $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . + $this->request->getConfig('protocol_version') . "\r\n"; + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersStr .= $canonicalName . ': ' . $value . "\r\n"; + } + return $headersStr . "\r\n"; + } + + /** + * Adds or removes 'Expect: 100-continue' header from request headers + * + * Also sets the $expect100Continue property. Parsing of existing header + * is somewhat needed due to its complex structure and due to the + * requirement in section 8.2.3 of RFC 2616: + * > A client MUST NOT send an Expect request-header field (section + * > 14.20) with the "100-continue" expectation if it does not intend + * > to send a request body. + * + * @param array &$headers Array of headers prepared for the request + * + * @throws HTTP_Request2_LogicException + * @link http://pear.php.net/bugs/bug.php?id=19233 + * @link http://tools.ietf.org/html/rfc2616#section-8.2.3 + */ + protected function updateExpectHeader(&$headers) + { + $this->expect100Continue = false; + $expectations = array(); + if (isset($headers['expect'])) { + if ('' === $headers['expect']) { + // empty 'Expect' header is technically invalid, so just get rid of it + unset($headers['expect']); + return; + } + // build regexp to parse the value of existing Expect header + $expectParam = ';\s*' . self::REGEXP_TOKEN . '(?:\s*=\s*(?:' + . self::REGEXP_TOKEN . '|' + . self::REGEXP_QUOTED_STRING . '))?\s*'; + $expectExtension = self::REGEXP_TOKEN . '(?:\s*=\s*(?:' + . self::REGEXP_TOKEN . '|' + . self::REGEXP_QUOTED_STRING . ')\s*(?:' + . $expectParam . ')*)?'; + $expectItem = '!(100-continue|' . $expectExtension . ')!A'; + + $pos = 0; + $length = strlen($headers['expect']); + + while ($pos < $length) { + $pos += strspn($headers['expect'], " \t", $pos); + if (',' === substr($headers['expect'], $pos, 1)) { + $pos++; + continue; + + } elseif (!preg_match($expectItem, $headers['expect'], $m, 0, $pos)) { + throw new HTTP_Request2_LogicException( + "Cannot parse value '{$headers['expect']}' of Expect header", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + + } else { + $pos += strlen($m[0]); + if (strcasecmp('100-continue', $m[0])) { + $expectations[] = $m[0]; + } + } + } + } + + if (1024 < $this->contentLength) { + $expectations[] = '100-continue'; + $this->expect100Continue = true; + } + + if (empty($expectations)) { + unset($headers['expect']); + } else { + $headers['expect'] = implode(',', $expectations); + } + } + + /** + * Sends the request body + * + * @throws HTTP_Request2_MessageException + */ + protected function writeBody() + { + if (in_array($this->request->getMethod(), self::$bodyDisallowed) + || 0 == $this->contentLength + ) { + return; + } + + $position = 0; + $bufferSize = $this->request->getConfig('buffer_size'); + $headers = $this->request->getHeaders(); + $chunked = isset($headers['transfer-encoding']); + while ($position < $this->contentLength) { + if (is_string($this->requestBody)) { + $str = substr($this->requestBody, $position, $bufferSize); + } elseif (is_resource($this->requestBody)) { + $str = fread($this->requestBody, $bufferSize); + } else { + $str = $this->requestBody->read($bufferSize); + } + if (!$chunked) { + $this->socket->write($str); + } else { + $this->socket->write(dechex(strlen($str)) . "\r\n{$str}\r\n"); + } + // Provide the length of written string to the observer, request #7630 + $this->request->setLastEvent('sentBodyPart', strlen($str)); + $position += strlen($str); + } + + // write zero-length chunk + if ($chunked) { + $this->socket->write("0\r\n\r\n"); + } + $this->request->setLastEvent('sentBody', $this->contentLength); + } + + /** + * Reads the remote server's response + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + protected function readResponse() + { + $bufferSize = $this->request->getConfig('buffer_size'); + // http://tools.ietf.org/html/rfc2616#section-8.2.3 + // ...the client SHOULD NOT wait for an indefinite period before sending the request body + $timeout = $this->expect100Continue ? 1 : null; + + do { + try { + $response = new HTTP_Request2_Response( + $this->socket->readLine($bufferSize, $timeout), true, $this->request->getUrl() + ); + do { + $headerLine = $this->socket->readLine($bufferSize); + $response->parseHeaderLine($headerLine); + } while ('' != $headerLine); + + } catch (HTTP_Request2_MessageException $e) { + if (HTTP_Request2_Exception::TIMEOUT === $e->getCode() + && $this->expect100Continue + ) { + return null; + } + throw $e; + } + if ($this->expect100Continue && 100 == $response->getStatus()) { + return $response; + } + } while (in_array($response->getStatus(), array(100, 101))); + + $this->request->setLastEvent('receivedHeaders', $response); + + // No body possible in such responses + if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() + || (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() + && 200 <= $response->getStatus() && 300 > $response->getStatus()) + || in_array($response->getStatus(), array(204, 304)) + ) { + return $response; + } + + $chunked = 'chunked' == $response->getHeader('transfer-encoding'); + $length = $response->getHeader('content-length'); + $hasBody = false; + if ($chunked || null === $length || 0 < intval($length)) { + // RFC 2616, section 4.4: + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $toRead = ($chunked || null === $length)? null: $length; + $this->chunkLength = 0; + + while (!$this->socket->eof() && (is_null($toRead) || 0 < $toRead)) { + if ($chunked) { + $data = $this->readChunked($bufferSize); + } elseif (is_null($toRead)) { + $data = $this->socket->read($bufferSize); + } else { + $data = $this->socket->read(min($toRead, $bufferSize)); + $toRead -= strlen($data); + } + if ('' == $data && (!$this->chunkLength || $this->socket->eof())) { + break; + } + + $hasBody = true; + if ($this->request->getConfig('store_body')) { + $response->appendBody($data); + } + if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { + $this->request->setLastEvent('receivedEncodedBodyPart', $data); + } else { + $this->request->setLastEvent('receivedBodyPart', $data); + } + } + } + + if ($hasBody) { + $this->request->setLastEvent('receivedBody', $response); + } + return $response; + } + + /** + * Reads a part of response body encoded with chunked Transfer-Encoding + * + * @param int $bufferSize buffer size to use for reading + * + * @return string + * @throws HTTP_Request2_MessageException + */ + protected function readChunked($bufferSize) + { + // at start of the next chunk? + if (0 == $this->chunkLength) { + $line = $this->socket->readLine($bufferSize); + if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + throw new HTTP_Request2_MessageException( + "Cannot decode chunked response, invalid chunk length '{$line}'", + HTTP_Request2_Exception::DECODE_ERROR + ); + } else { + $this->chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->chunkLength) { + $this->socket->readLine($bufferSize); + return ''; + } + } + } + $data = $this->socket->read(min($this->chunkLength, $bufferSize)); + $this->chunkLength -= strlen($data); + if (0 == $this->chunkLength) { + $this->socket->readLine($bufferSize); // Trailing CRLF + } + return $data; + } +} + +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/CookieJar.php b/libs/PEAR.1.9.5/HTTP/Request2/CookieJar.php new file mode 100644 index 000000000..79ac08bb7 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/CookieJar.php @@ -0,0 +1,494 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** Class representing a HTTP request message */ +require_once 'HTTP/Request2.php'; + +/** + * Stores cookies and passes them between HTTP requests + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: @package_version@ + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_CookieJar implements Serializable +{ + /** + * Array of stored cookies + * + * The array is indexed by domain, path and cookie name + * .example.com + * / + * some_cookie => cookie data + * /subdir + * other_cookie => cookie data + * .example.org + * ... + * + * @var array + */ + protected $cookies = array(); + + /** + * Whether session cookies should be serialized when serializing the jar + * @var bool + */ + protected $serializeSession = false; + + /** + * Whether Public Suffix List should be used for domain matching + * @var bool + */ + protected $useList = true; + + /** + * Array with Public Suffix List data + * @var array + * @link http://publicsuffix.org/ + */ + protected static $psl = array(); + + /** + * Class constructor, sets various options + * + * @param bool $serializeSessionCookies Controls serializing session cookies, + * see {@link serializeSessionCookies()} + * @param bool $usePublicSuffixList Controls using Public Suffix List, + * see {@link usePublicSuffixList()} + */ + public function __construct( + $serializeSessionCookies = false, $usePublicSuffixList = true + ) { + $this->serializeSessionCookies($serializeSessionCookies); + $this->usePublicSuffixList($usePublicSuffixList); + } + + /** + * Returns current time formatted in ISO-8601 at UTC timezone + * + * @return string + */ + protected function now() + { + $dt = new DateTime(); + $dt->setTimezone(new DateTimeZone('UTC')); + return $dt->format(DateTime::ISO8601); + } + + /** + * Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields + * + * The checks are as follows: + * - cookie array should contain 'name' and 'value' fields; + * - name and value should not contain disallowed symbols; + * - 'expires' should be either empty parseable by DateTime; + * - 'domain' and 'path' should be either not empty or an URL where + * cookie was set should be provided. + * - if $setter is provided, then document at that URL should be allowed + * to set a cookie for that 'domain'. If $setter is not provided, + * then no domain checks will be made. + * + * 'expires' field will be converted to ISO8601 format from COOKIE format, + * 'domain' and 'path' will be set from setter URL if empty. + * + * @param array $cookie cookie data, as returned by + * {@link HTTP_Request2_Response::getCookies()} + * @param Net_URL2 $setter URL of the document that sent Set-Cookie header + * + * @return array Updated cookie array + * @throws HTTP_Request2_LogicException + * @throws HTTP_Request2_MessageException + */ + protected function checkAndUpdateFields(array $cookie, Net_URL2 $setter = null) + { + if ($missing = array_diff(array('name', 'value'), array_keys($cookie))) { + throw new HTTP_Request2_LogicException( + "Cookie array should contain 'name' and 'value' fields", + HTTP_Request2_Exception::MISSING_VALUE + ); + } + if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['name'])) { + throw new HTTP_Request2_LogicException( + "Invalid cookie name: '{$cookie['name']}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['value'])) { + throw new HTTP_Request2_LogicException( + "Invalid cookie value: '{$cookie['value']}'", + HTTP_Request2_Exception::INVALID_ARGUMENT + ); + } + $cookie += array('domain' => '', 'path' => '', 'expires' => null, 'secure' => false); + + // Need ISO-8601 date @ UTC timezone + if (!empty($cookie['expires']) + && !preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+0000$/', $cookie['expires']) + ) { + try { + $dt = new DateTime($cookie['expires']); + $dt->setTimezone(new DateTimeZone('UTC')); + $cookie['expires'] = $dt->format(DateTime::ISO8601); + } catch (Exception $e) { + throw new HTTP_Request2_LogicException($e->getMessage()); + } + } + + if (empty($cookie['domain']) || empty($cookie['path'])) { + if (!$setter) { + throw new HTTP_Request2_LogicException( + 'Cookie misses domain and/or path component, cookie setter URL needed', + HTTP_Request2_Exception::MISSING_VALUE + ); + } + if (empty($cookie['domain'])) { + if ($host = $setter->getHost()) { + $cookie['domain'] = $host; + } else { + throw new HTTP_Request2_LogicException( + 'Setter URL does not contain host part, can\'t set cookie domain', + HTTP_Request2_Exception::MISSING_VALUE + ); + } + } + if (empty($cookie['path'])) { + $path = $setter->getPath(); + $cookie['path'] = empty($path)? '/': substr($path, 0, strrpos($path, '/') + 1); + } + } + + if ($setter && !$this->domainMatch($setter->getHost(), $cookie['domain'])) { + throw new HTTP_Request2_MessageException( + "Domain " . $setter->getHost() . " cannot set cookies for " + . $cookie['domain'] + ); + } + + return $cookie; + } + + /** + * Stores a cookie in the jar + * + * @param array $cookie cookie data, as returned by + * {@link HTTP_Request2_Response::getCookies()} + * @param Net_URL2 $setter URL of the document that sent Set-Cookie header + * + * @throws HTTP_Request2_Exception + */ + public function store(array $cookie, Net_URL2 $setter = null) + { + $cookie = $this->checkAndUpdateFields($cookie, $setter); + + if (strlen($cookie['value']) + && (is_null($cookie['expires']) || $cookie['expires'] > $this->now()) + ) { + if (!isset($this->cookies[$cookie['domain']])) { + $this->cookies[$cookie['domain']] = array(); + } + if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) { + $this->cookies[$cookie['domain']][$cookie['path']] = array(); + } + $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie; + + } elseif (isset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']])) { + unset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']]); + } + } + + /** + * Adds cookies set in HTTP response to the jar + * + * @param HTTP_Request2_Response $response HTTP response message + * @param Net_URL2 $setter original request URL, needed for + * setting default domain/path + */ + public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter) + { + foreach ($response->getCookies() as $cookie) { + $this->store($cookie, $setter); + } + } + + /** + * Returns all cookies matching a given request URL + * + * The following checks are made: + * - cookie domain should match request host + * - cookie path should be a prefix for request path + * - 'secure' cookies will only be sent for HTTPS requests + * + * @param Net_URL2 $url Request url + * @param bool $asString Whether to return cookies as string for "Cookie: " header + * + * @return array|string Matching cookies + */ + public function getMatching(Net_URL2 $url, $asString = false) + { + $host = $url->getHost(); + $path = $url->getPath(); + $secure = 0 == strcasecmp($url->getScheme(), 'https'); + + $matched = $ret = array(); + foreach (array_keys($this->cookies) as $domain) { + if ($this->domainMatch($host, $domain)) { + foreach (array_keys($this->cookies[$domain]) as $cPath) { + if (0 === strpos($path, $cPath)) { + foreach ($this->cookies[$domain][$cPath] as $name => $cookie) { + if (!$cookie['secure'] || $secure) { + $matched[$name][strlen($cookie['path'])] = $cookie; + } + } + } + } + } + } + foreach ($matched as $cookies) { + krsort($cookies); + $ret = array_merge($ret, $cookies); + } + if (!$asString) { + return $ret; + } else { + $str = ''; + foreach ($ret as $c) { + $str .= (empty($str)? '': '; ') . $c['name'] . '=' . $c['value']; + } + return $str; + } + } + + /** + * Returns all cookies stored in a jar + * + * @return array + */ + public function getAll() + { + $cookies = array(); + foreach (array_keys($this->cookies) as $domain) { + foreach (array_keys($this->cookies[$domain]) as $path) { + foreach ($this->cookies[$domain][$path] as $name => $cookie) { + $cookies[] = $cookie; + } + } + } + return $cookies; + } + + /** + * Sets whether session cookies should be serialized when serializing the jar + * + * @param boolean $serialize serialize? + */ + public function serializeSessionCookies($serialize) + { + $this->serializeSession = (bool)$serialize; + } + + /** + * Sets whether Public Suffix List should be used for restricting cookie-setting + * + * Without PSL {@link domainMatch()} will only prevent setting cookies for + * top-level domains like '.com' or '.org'. However, it will not prevent + * setting a cookie for '.co.uk' even though only third-level registrations + * are possible in .uk domain. + * + * With the List it is possible to find the highest level at which a domain + * may be registered for a particular top-level domain and consequently + * prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by + * Firefox, Chrome and Opera browsers to restrict cookie setting. + * + * Note that PSL is licensed differently to HTTP_Request2 package (refer to + * the license information in public-suffix-list.php), so you can disable + * its use if this is an issue for you. + * + * @param boolean $useList use the list? + * + * @link http://publicsuffix.org/learn/ + */ + public function usePublicSuffixList($useList) + { + $this->useList = (bool)$useList; + } + + /** + * Returns string representation of object + * + * @return string + * + * @see Serializable::serialize() + */ + public function serialize() + { + $cookies = $this->getAll(); + if (!$this->serializeSession) { + for ($i = count($cookies) - 1; $i >= 0; $i--) { + if (empty($cookies[$i]['expires'])) { + unset($cookies[$i]); + } + } + } + return serialize(array( + 'cookies' => $cookies, + 'serializeSession' => $this->serializeSession, + 'useList' => $this->useList + )); + } + + /** + * Constructs the object from serialized string + * + * @param string $serialized string representation + * + * @see Serializable::unserialize() + */ + public function unserialize($serialized) + { + $data = unserialize($serialized); + $now = $this->now(); + $this->serializeSessionCookies($data['serializeSession']); + $this->usePublicSuffixList($data['useList']); + foreach ($data['cookies'] as $cookie) { + if (!empty($cookie['expires']) && $cookie['expires'] <= $now) { + continue; + } + if (!isset($this->cookies[$cookie['domain']])) { + $this->cookies[$cookie['domain']] = array(); + } + if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) { + $this->cookies[$cookie['domain']][$cookie['path']] = array(); + } + $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie; + } + } + + /** + * Checks whether a cookie domain matches a request host. + * + * The method is used by {@link store()} to check for whether a document + * at given URL can set a cookie with a given domain attribute and by + * {@link getMatching()} to find cookies matching the request URL. + * + * @param string $requestHost request host + * @param string $cookieDomain cookie domain + * + * @return bool match success + */ + public function domainMatch($requestHost, $cookieDomain) + { + if ($requestHost == $cookieDomain) { + return true; + } + // IP address, we require exact match + if (preg_match('/^(?:\d{1,3}\.){3}\d{1,3}$/', $requestHost)) { + return false; + } + if ('.' != $cookieDomain[0]) { + $cookieDomain = '.' . $cookieDomain; + } + // prevents setting cookies for '.com' and similar domains + if (!$this->useList && substr_count($cookieDomain, '.') < 2 + || $this->useList && !self::getRegisteredDomain($cookieDomain) + ) { + return false; + } + return substr('.' . $requestHost, -strlen($cookieDomain)) == $cookieDomain; + } + + /** + * Removes subdomains to get the registered domain (the first after top-level) + * + * The method will check Public Suffix List to find out where top-level + * domain ends and registered domain starts. It will remove domain parts + * to the left of registered one. + * + * @param string $domain domain name + * + * @return string|bool registered domain, will return false if $domain is + * either invalid or a TLD itself + */ + public static function getRegisteredDomain($domain) + { + $domainParts = explode('.', ltrim($domain, '.')); + + // load the list if needed + if (empty(self::$psl)) { + $path = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTTP_Request2'; + if (0 === strpos($path, '@' . 'data_dir@')) { + $path = realpath( + dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' + . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data' + ); + } + self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php'; + } + + if (!($result = self::checkDomainsList($domainParts, self::$psl))) { + // known TLD, invalid domain name + return false; + } + + // unknown TLD + if (!strpos($result, '.')) { + // fallback to checking that domain "has at least two dots" + if (2 > ($count = count($domainParts))) { + return false; + } + return $domainParts[$count - 2] . '.' . $domainParts[$count - 1]; + } + return $result; + } + + /** + * Recursive helper method for {@link getRegisteredDomain()} + * + * @param array $domainParts remaining domain parts + * @param mixed $listNode node in {@link HTTP_Request2_CookieJar::$psl} to check + * + * @return string|null concatenated domain parts, null in case of error + */ + protected static function checkDomainsList(array $domainParts, $listNode) + { + $sub = array_pop($domainParts); + $result = null; + + if (!is_array($listNode) || is_null($sub) + || array_key_exists('!' . $sub, $listNode) + ) { + return $sub; + + } elseif (array_key_exists($sub, $listNode)) { + $result = self::checkDomainsList($domainParts, $listNode[$sub]); + + } elseif (array_key_exists('*', $listNode)) { + $result = self::checkDomainsList($domainParts, $listNode['*']); + + } else { + return $sub; + } + + return (strlen($result) > 0) ? ($result . '.' . $sub) : null; + } +} +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Exception.php b/libs/PEAR.1.9.5/HTTP/Request2/Exception.php new file mode 100644 index 000000000..d0b5d4ee0 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Exception.php @@ -0,0 +1,160 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for exceptions in PEAR + */ +require_once 'PEAR/Exception.php'; + +/** + * Base exception class for HTTP_Request2 package + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=132 + */ +class HTTP_Request2_Exception extends PEAR_Exception +{ + /** An invalid argument was passed to a method */ + const INVALID_ARGUMENT = 1; + /** Some required value was not available */ + const MISSING_VALUE = 2; + /** Request cannot be processed due to errors in PHP configuration */ + const MISCONFIGURATION = 3; + /** Error reading the local file */ + const READ_ERROR = 4; + + /** Server returned a response that does not conform to HTTP protocol */ + const MALFORMED_RESPONSE = 10; + /** Failure decoding Content-Encoding or Transfer-Encoding of response */ + const DECODE_ERROR = 20; + /** Operation timed out */ + const TIMEOUT = 30; + /** Number of redirects exceeded 'max_redirects' configuration parameter */ + const TOO_MANY_REDIRECTS = 40; + /** Redirect to a protocol other than http(s):// */ + const NON_HTTP_REDIRECT = 50; + + /** + * Native error code + * @var int + */ + private $_nativeCode; + + /** + * Constructor, can set package error code and native error code + * + * @param string $message exception message + * @param int $code package error code, one of class constants + * @param int $nativeCode error code from underlying PHP extension + */ + public function __construct($message = null, $code = null, $nativeCode = null) + { + parent::__construct($message, $code); + $this->_nativeCode = $nativeCode; + } + + /** + * Returns error code produced by underlying PHP extension + * + * For Socket Adapter this may contain error number returned by + * stream_socket_client(), for Curl Adapter this will contain error number + * returned by curl_errno() + * + * @return integer + */ + public function getNativeCode() + { + return $this->_nativeCode; + } +} + +/** + * Exception thrown in case of missing features + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception +{ +} + +/** + * Exception that represents error in the program logic + * + * This exception usually implies a programmer's error, like passing invalid + * data to methods or trying to use PHP extensions that weren't installed or + * enabled. Usually exceptions of this kind will be thrown before request even + * starts. + * + * The exception will usually contain a package error code. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_LogicException extends HTTP_Request2_Exception +{ +} + +/** + * Exception thrown when connection to a web or proxy server fails + * + * The exception will not contain a package error code, but will contain + * native error code, as returned by stream_socket_client() or curl_errno(). + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception +{ +} + +/** + * Exception thrown when sending or receiving HTTP message fails + * + * The exception may contain both package error code and native error code. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_MessageException extends HTTP_Request2_Exception +{ +} +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/MultipartBody.php b/libs/PEAR.1.9.5/HTTP/Request2/MultipartBody.php new file mode 100644 index 000000000..c68b6602b --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/MultipartBody.php @@ -0,0 +1,268 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** Exception class for HTTP_Request2 package */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class for building multipart/form-data request body + * + * The class helps to reduce memory consumption by streaming large file uploads + * from disk, it also allows monitoring of upload progress (see request #7630) + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + * @link http://tools.ietf.org/html/rfc1867 + */ +class HTTP_Request2_MultipartBody +{ + /** + * MIME boundary + * @var string + */ + private $_boundary; + + /** + * Form parameters added via {@link HTTP_Request2::addPostParameter()} + * @var array + */ + private $_params = array(); + + /** + * File uploads added via {@link HTTP_Request2::addUpload()} + * @var array + */ + private $_uploads = array(); + + /** + * Header for parts with parameters + * @var string + */ + private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n"; + + /** + * Header for parts with uploads + * @var string + */ + private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n"; + + /** + * Current position in parameter and upload arrays + * + * First number is index of "current" part, second number is position within + * "current" part + * + * @var array + */ + private $_pos = array(0, 0); + + + /** + * Constructor. Sets the arrays with POST data. + * + * @param array $params values of form fields set via + * {@link HTTP_Request2::addPostParameter()} + * @param array $uploads file uploads set via + * {@link HTTP_Request2::addUpload()} + * @param bool $useBrackets whether to append brackets to array variable names + */ + public function __construct(array $params, array $uploads, $useBrackets = true) + { + $this->_params = self::_flattenArray('', $params, $useBrackets); + foreach ($uploads as $fieldName => $f) { + if (!is_array($f['fp'])) { + $this->_uploads[] = $f + array('name' => $fieldName); + } else { + for ($i = 0; $i < count($f['fp']); $i++) { + $upload = array( + 'name' => ($useBrackets? $fieldName . '[' . $i . ']': $fieldName) + ); + foreach (array('fp', 'filename', 'size', 'type') as $key) { + $upload[$key] = $f[$key][$i]; + } + $this->_uploads[] = $upload; + } + } + } + } + + /** + * Returns the length of the body to use in Content-Length header + * + * @return integer + */ + public function getLength() + { + $boundaryLength = strlen($this->getBoundary()); + $headerParamLength = strlen($this->_headerParam) - 4 + $boundaryLength; + $headerUploadLength = strlen($this->_headerUpload) - 8 + $boundaryLength; + $length = $boundaryLength + 6; + foreach ($this->_params as $p) { + $length += $headerParamLength + strlen($p[0]) + strlen($p[1]) + 2; + } + foreach ($this->_uploads as $u) { + $length += $headerUploadLength + strlen($u['name']) + strlen($u['type']) + + strlen($u['filename']) + $u['size'] + 2; + } + return $length; + } + + /** + * Returns the boundary to use in Content-Type header + * + * @return string + */ + public function getBoundary() + { + if (empty($this->_boundary)) { + $this->_boundary = '--' . md5('PEAR-HTTP_Request2-' . microtime()); + } + return $this->_boundary; + } + + /** + * Returns next chunk of request body + * + * @param integer $length Number of bytes to read + * + * @return string Up to $length bytes of data, empty string if at end + * @throws HTTP_Request2_LogicException + */ + public function read($length) + { + $ret = ''; + $boundary = $this->getBoundary(); + $paramCount = count($this->_params); + $uploadCount = count($this->_uploads); + while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) { + $oldLength = $length; + if ($this->_pos[0] < $paramCount) { + $param = sprintf( + $this->_headerParam, $boundary, $this->_params[$this->_pos[0]][0] + ) . $this->_params[$this->_pos[0]][1] . "\r\n"; + $ret .= substr($param, $this->_pos[1], $length); + $length -= min(strlen($param) - $this->_pos[1], $length); + + } elseif ($this->_pos[0] < $paramCount + $uploadCount) { + $pos = $this->_pos[0] - $paramCount; + $header = sprintf( + $this->_headerUpload, $boundary, $this->_uploads[$pos]['name'], + $this->_uploads[$pos]['filename'], $this->_uploads[$pos]['type'] + ); + if ($this->_pos[1] < strlen($header)) { + $ret .= substr($header, $this->_pos[1], $length); + $length -= min(strlen($header) - $this->_pos[1], $length); + } + $filePos = max(0, $this->_pos[1] - strlen($header)); + if ($filePos < $this->_uploads[$pos]['size']) { + while ($length > 0 && !feof($this->_uploads[$pos]['fp'])) { + if (false === ($chunk = fread($this->_uploads[$pos]['fp'], $length))) { + throw new HTTP_Request2_LogicException( + 'Failed reading file upload', HTTP_Request2_Exception::READ_ERROR + ); + } + $ret .= $chunk; + $length -= strlen($chunk); + } + } + if ($length > 0) { + $start = $this->_pos[1] + ($oldLength - $length) - + strlen($header) - $this->_uploads[$pos]['size']; + $ret .= substr("\r\n", $start, $length); + $length -= min(2 - $start, $length); + } + + } else { + $closing = '--' . $boundary . "--\r\n"; + $ret .= substr($closing, $this->_pos[1], $length); + $length -= min(strlen($closing) - $this->_pos[1], $length); + } + if ($length > 0) { + $this->_pos = array($this->_pos[0] + 1, 0); + } else { + $this->_pos[1] += $oldLength; + } + } + return $ret; + } + + /** + * Sets the current position to the start of the body + * + * This allows reusing the same body in another request + */ + public function rewind() + { + $this->_pos = array(0, 0); + foreach ($this->_uploads as $u) { + rewind($u['fp']); + } + } + + /** + * Returns the body as string + * + * Note that it reads all file uploads into memory so it is a good idea not + * to use this method with large file uploads and rely on read() instead. + * + * @return string + */ + public function __toString() + { + $this->rewind(); + return $this->read($this->getLength()); + } + + + /** + * Helper function to change the (probably multidimensional) associative array + * into the simple one. + * + * @param string $name name for item + * @param mixed $values item's values + * @param bool $useBrackets whether to append [] to array variables' names + * + * @return array array with the following items: array('item name', 'item value'); + */ + private static function _flattenArray($name, $values, $useBrackets) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, self::_flattenArray($newName, $v, $useBrackets)); + } + return $ret; + } + } +} +?> diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Observer/Log.php b/libs/PEAR.1.9.5/HTTP/Request2/Observer/Log.php new file mode 100644 index 000000000..341e29907 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Observer/Log.php @@ -0,0 +1,192 @@ + + * @author Alexey Borzov + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * A debug observer useful for debugging / testing. + * + * This observer logs to a log target data corresponding to the various request + * and response events, it logs by default to php://output but can be configured + * to log to a file or via the PEAR Log package. + * + * A simple example: + * + * require_once 'HTTP/Request2.php'; + * require_once 'HTTP/Request2/Observer/Log.php'; + * + * $request = new HTTP_Request2('http://www.example.com'); + * $observer = new HTTP_Request2_Observer_Log(); + * $request->attach($observer); + * $request->send(); + * + * + * A more complex example with PEAR Log: + * + * require_once 'HTTP/Request2.php'; + * require_once 'HTTP/Request2/Observer/Log.php'; + * require_once 'Log.php'; + * + * $request = new HTTP_Request2('http://www.example.com'); + * // we want to log with PEAR log + * $observer = new HTTP_Request2_Observer_Log(Log::factory('console')); + * + * // we only want to log received headers + * $observer->events = array('receivedHeaders'); + * + * $request->attach($observer); + * $request->send(); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author David Jean Louis + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_Observer_Log implements SplObserver +{ + // properties {{{ + + /** + * The log target, it can be a a resource or a PEAR Log instance. + * + * @var resource|Log $target + */ + protected $target = null; + + /** + * The events to log. + * + * @var array $events + */ + public $events = array( + 'connect', + 'sentHeaders', + 'sentBody', + 'receivedHeaders', + 'receivedBody', + 'disconnect', + ); + + // }}} + // __construct() {{{ + + /** + * Constructor. + * + * @param mixed $target Can be a file path (default: php://output), a resource, + * or an instance of the PEAR Log class. + * @param array $events Array of events to listen to (default: all events) + * + * @return void + */ + public function __construct($target = 'php://output', array $events = array()) + { + if (!empty($events)) { + $this->events = $events; + } + if (is_resource($target) || $target instanceof Log) { + $this->target = $target; + } elseif (false === ($this->target = @fopen($target, 'ab'))) { + throw new HTTP_Request2_Exception("Unable to open '{$target}'"); + } + } + + // }}} + // update() {{{ + + /** + * Called when the request notifies us of an event. + * + * @param HTTP_Request2 $subject The HTTP_Request2 instance + * + * @return void + */ + public function update(SplSubject $subject) + { + $event = $subject->getLastEvent(); + if (!in_array($event['name'], $this->events)) { + return; + } + + switch ($event['name']) { + case 'connect': + $this->log('* Connected to ' . $event['data']); + break; + case 'sentHeaders': + $headers = explode("\r\n", $event['data']); + array_pop($headers); + foreach ($headers as $header) { + $this->log('> ' . $header); + } + break; + case 'sentBody': + $this->log('> ' . $event['data'] . ' byte(s) sent'); + break; + case 'receivedHeaders': + $this->log(sprintf( + '< HTTP/%s %s %s', $event['data']->getVersion(), + $event['data']->getStatus(), $event['data']->getReasonPhrase() + )); + $headers = $event['data']->getHeader(); + foreach ($headers as $key => $val) { + $this->log('< ' . $key . ': ' . $val); + } + $this->log('< '); + break; + case 'receivedBody': + $this->log($event['data']->getBody()); + break; + case 'disconnect': + $this->log('* Disconnected'); + break; + } + } + + // }}} + // log() {{{ + + /** + * Logs the given message to the configured target. + * + * @param string $message Message to display + * + * @return void + */ + protected function log($message) + { + if ($this->target instanceof Log) { + $this->target->debug($message); + } elseif (is_resource($this->target)) { + fwrite($this->target, $message . "\r\n"); + } + } + + // }}} +} + +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/Response.php b/libs/PEAR.1.9.5/HTTP/Request2/Response.php new file mode 100644 index 000000000..d2f414cf6 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/Response.php @@ -0,0 +1,631 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class representing a HTTP response + * + * The class is designed to be used in "streaming" scenario, building the + * response as it is being received: + * + * $statusLine = read_status_line(); + * $response = new HTTP_Request2_Response($statusLine); + * do { + * $headerLine = read_header_line(); + * $response->parseHeaderLine($headerLine); + * } while ($headerLine != ''); + * + * while ($chunk = read_body()) { + * $response->appendBody($chunk); + * } + * + * var_dump($response->getHeader(), $response->getCookies(), $response->getBody()); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + * @link http://tools.ietf.org/html/rfc2616#section-6 + */ +class HTTP_Request2_Response +{ + /** + * HTTP protocol version (e.g. 1.0, 1.1) + * @var string + */ + protected $version; + + /** + * Status code + * @var integer + * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 + */ + protected $code; + + /** + * Reason phrase + * @var string + * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 + */ + protected $reasonPhrase; + + /** + * Effective URL (may be different from original request URL in case of redirects) + * @var string + */ + protected $effectiveUrl; + + /** + * Associative array of response headers + * @var array + */ + protected $headers = array(); + + /** + * Cookies set in the response + * @var array + */ + protected $cookies = array(); + + /** + * Name of last header processed by parseHederLine() + * + * Used to handle the headers that span multiple lines + * + * @var string + */ + protected $lastHeader = null; + + /** + * Response body + * @var string + */ + protected $body = ''; + + /** + * Whether the body is still encoded by Content-Encoding + * + * cURL provides the decoded body to the callback; if we are reading from + * socket the body is still gzipped / deflated + * + * @var bool + */ + protected $bodyEncoded; + + /** + * Associative array of HTTP status code / reason phrase. + * + * @var array + * @link http://tools.ietf.org/html/rfc2616#section-10 + */ + protected static $phrases = array( + + // 1xx: Informational - Request received, continuing process + 100 => 'Continue', + 101 => 'Switching Protocols', + + // 2xx: Success - The action was successfully received, understood and + // accepted + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + // 3xx: Redirection - Further action must be taken in order to complete + // the request + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', // 1.1 + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 307 => 'Temporary Redirect', + + // 4xx: Client Error - The request contains bad syntax or cannot be + // fulfilled + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + // 5xx: Server Error - The server failed to fulfill an apparently + // valid request + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 509 => 'Bandwidth Limit Exceeded', + + ); + + /** + * Returns the default reason phrase for the given code or all reason phrases + * + * @param int $code Response code + * + * @return string|array|null Default reason phrase for $code if $code is given + * (null if no phrase is available), array of all + * reason phrases if $code is null + * @link http://pear.php.net/bugs/18716 + */ + public static function getDefaultReasonPhrase($code = null) + { + if (null === $code) { + return self::$phrases; + } else { + return isset(self::$phrases[$code]) ? self::$phrases[$code] : null; + } + } + + /** + * Constructor, parses the response status line + * + * @param string $statusLine Response status line (e.g. "HTTP/1.1 200 OK") + * @param bool $bodyEncoded Whether body is still encoded by Content-Encoding + * @param string $effectiveUrl Effective URL of the response + * + * @throws HTTP_Request2_MessageException if status line is invalid according to spec + */ + public function __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null) + { + if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) { + throw new HTTP_Request2_MessageException( + "Malformed response: {$statusLine}", + HTTP_Request2_Exception::MALFORMED_RESPONSE + ); + } + $this->version = $m[1]; + $this->code = intval($m[2]); + $this->reasonPhrase = !empty($m[3]) ? trim($m[3]) : self::getDefaultReasonPhrase($this->code); + $this->bodyEncoded = (bool)$bodyEncoded; + $this->effectiveUrl = (string)$effectiveUrl; + } + + /** + * Parses the line from HTTP response filling $headers array + * + * The method should be called after reading the line from socket or receiving + * it into cURL callback. Passing an empty string here indicates the end of + * response headers and triggers additional processing, so be sure to pass an + * empty string in the end. + * + * @param string $headerLine Line from HTTP response + */ + public function parseHeaderLine($headerLine) + { + $headerLine = trim($headerLine, "\r\n"); + + if ('' == $headerLine) { + // empty string signals the end of headers, process the received ones + if (!empty($this->headers['set-cookie'])) { + $cookies = is_array($this->headers['set-cookie'])? + $this->headers['set-cookie']: + array($this->headers['set-cookie']); + foreach ($cookies as $cookieString) { + $this->parseCookie($cookieString); + } + unset($this->headers['set-cookie']); + } + foreach (array_keys($this->headers) as $k) { + if (is_array($this->headers[$k])) { + $this->headers[$k] = implode(', ', $this->headers[$k]); + } + } + + } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) { + // string of the form header-name: header value + $name = strtolower($m[1]); + $value = trim($m[2]); + if (empty($this->headers[$name])) { + $this->headers[$name] = $value; + } else { + if (!is_array($this->headers[$name])) { + $this->headers[$name] = array($this->headers[$name]); + } + $this->headers[$name][] = $value; + } + $this->lastHeader = $name; + + } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) { + // continuation of a previous header + if (!is_array($this->headers[$this->lastHeader])) { + $this->headers[$this->lastHeader] .= ' ' . trim($m[1]); + } else { + $key = count($this->headers[$this->lastHeader]) - 1; + $this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]); + } + } + } + + /** + * Parses a Set-Cookie header to fill $cookies array + * + * @param string $cookieString value of Set-Cookie header + * + * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html + */ + protected function parseCookie($cookieString) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + if (!strpos($cookieString, ';')) { + // Only a name=value pair + $pos = strpos($cookieString, '='); + $cookie['name'] = trim(substr($cookieString, 0, $pos)); + $cookie['value'] = trim(substr($cookieString, $pos + 1)); + + } else { + // Some optional parameters are supplied + $elements = explode(';', $cookieString); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->cookies[] = $cookie; + } + + /** + * Appends a string to the response body + * + * @param string $bodyChunk part of response body + */ + public function appendBody($bodyChunk) + { + $this->body .= $bodyChunk; + } + + /** + * Returns the effective URL of the response + * + * This may be different from the request URL if redirects were followed. + * + * @return string + * @link http://pear.php.net/bugs/bug.php?id=18412 + */ + public function getEffectiveUrl() + { + return $this->effectiveUrl; + } + + /** + * Returns the status code + * + * @return integer + */ + public function getStatus() + { + return $this->code; + } + + /** + * Returns the reason phrase + * + * @return string + */ + public function getReasonPhrase() + { + return $this->reasonPhrase; + } + + /** + * Whether response is a redirect that can be automatically handled by HTTP_Request2 + * + * @return bool + */ + public function isRedirect() + { + return in_array($this->code, array(300, 301, 302, 303, 307)) + && isset($this->headers['location']); + } + + /** + * Returns either the named header or all response headers + * + * @param string $headerName Name of header to return + * + * @return string|array Value of $headerName header (null if header is + * not present), array of all response headers if + * $headerName is null + */ + public function getHeader($headerName = null) + { + if (null === $headerName) { + return $this->headers; + } else { + $headerName = strtolower($headerName); + return isset($this->headers[$headerName])? $this->headers[$headerName]: null; + } + } + + /** + * Returns cookies set in response + * + * @return array + */ + public function getCookies() + { + return $this->cookies; + } + + /** + * Returns the body of the response + * + * @return string + * @throws HTTP_Request2_Exception if body cannot be decoded + */ + public function getBody() + { + if (0 == strlen($this->body) || !$this->bodyEncoded + || !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate')) + ) { + return $this->body; + + } else { + if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('8bit'); + } + + try { + switch (strtolower($this->getHeader('content-encoding'))) { + case 'gzip': + $decoded = self::decodeGzip($this->body); + break; + case 'deflate': + $decoded = self::decodeDeflate($this->body); + } + } catch (Exception $e) { + } + + if (!empty($oldEncoding)) { + mb_internal_encoding($oldEncoding); + } + if (!empty($e)) { + throw $e; + } + return $decoded; + } + } + + /** + * Get the HTTP version of the response + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Decodes the message-body encoded by gzip + * + * The real decoding work is done by gzinflate() built-in function, this + * method only parses the header and checks data for compliance with + * RFC 1952 + * + * @param string $data gzip-encoded data + * + * @return string decoded data + * @throws HTTP_Request2_LogicException + * @throws HTTP_Request2_MessageException + * @link http://tools.ietf.org/html/rfc1952 + */ + public static function decodeGzip($data) + { + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + if (!function_exists('gzinflate')) { + throw new HTTP_Request2_LogicException( + 'Unable to decode body: gzip extension not available', + HTTP_Request2_Exception::MISCONFIGURATION + ); + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: unknown compression method', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: reserved bits are set', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 2) { + if ($length - $headerLength - 2 < 8) { + throw new HTTP_Request2_MessageException( + 'Error parsing gzip header: data too short', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + throw new HTTP_Request2_MessageException( + 'Header CRC check failed', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + // don't pass $dataSize to gzinflate, see bugs #13135, #14370 + $unpacked = gzinflate(substr($data, $headerLength, -8)); + if (false === $unpacked) { + throw new HTTP_Request2_MessageException( + 'gzinflate() call failed', + HTTP_Request2_Exception::DECODE_ERROR + ); + } elseif ($dataSize != strlen($unpacked)) { + throw new HTTP_Request2_MessageException( + 'Data size check failed', + HTTP_Request2_Exception::DECODE_ERROR + ); + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { + throw new HTTP_Request2_Exception( + 'Data CRC check failed', + HTTP_Request2_Exception::DECODE_ERROR + ); + } + return $unpacked; + } + + /** + * Decodes the message-body encoded by deflate + * + * @param string $data deflate-encoded data + * + * @return string decoded data + * @throws HTTP_Request2_LogicException + */ + public static function decodeDeflate($data) + { + if (!function_exists('gzuncompress')) { + throw new HTTP_Request2_LogicException( + 'Unable to decode body: gzip extension not available', + HTTP_Request2_Exception::MISCONFIGURATION + ); + } + // RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950, + // while many applications send raw deflate stream from RFC 1951. + // We should check for presence of zlib header and use gzuncompress() or + // gzinflate() as needed. See bug #15305 + $header = unpack('n', substr($data, 0, 2)); + return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data); + } +} +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/SOCKS5.php b/libs/PEAR.1.9.5/HTTP/Request2/SOCKS5.php new file mode 100644 index 000000000..d54049585 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/SOCKS5.php @@ -0,0 +1,135 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** Socket wrapper class used by Socket Adapter */ +require_once 'HTTP/Request2/SocketWrapper.php'; + +/** + * SOCKS5 proxy connection class (used by Socket Adapter) + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + * @link http://pear.php.net/bugs/bug.php?id=19332 + * @link http://tools.ietf.org/html/rfc1928 + */ +class HTTP_Request2_SOCKS5 extends HTTP_Request2_SocketWrapper +{ + /** + * Constructor, tries to connect and authenticate to a SOCKS5 proxy + * + * @param string $address Proxy address, e.g. 'tcp://localhost:1080' + * @param int $timeout Connection timeout (seconds) + * @param array $contextOptions Stream context options + * @param string $username Proxy user name + * @param string $password Proxy password + * + * @throws HTTP_Request2_LogicException + * @throws HTTP_Request2_ConnectionException + * @throws HTTP_Request2_MessageException + */ + public function __construct( + $address, $timeout = 10, array $contextOptions = array(), + $username = null, $password = null + ) { + parent::__construct($address, $timeout, $contextOptions); + + if (strlen($username)) { + $request = pack('C4', 5, 2, 0, 2); + } else { + $request = pack('C3', 5, 1, 0); + } + $this->write($request); + $response = unpack('Cversion/Cmethod', $this->read(3)); + if (5 != $response['version']) { + throw new HTTP_Request2_MessageException( + 'Invalid version received from SOCKS5 proxy: ' . $response['version'], + HTTP_Request2_Exception::MALFORMED_RESPONSE + ); + } + switch ($response['method']) { + case 2: + $this->performAuthentication($username, $password); + case 0: + break; + default: + throw new HTTP_Request2_ConnectionException( + "Connection rejected by proxy due to unsupported auth method" + ); + } + } + + /** + * Performs username/password authentication for SOCKS5 + * + * @param string $username Proxy user name + * @param string $password Proxy password + * + * @throws HTTP_Request2_ConnectionException + * @throws HTTP_Request2_MessageException + * @link http://tools.ietf.org/html/rfc1929 + */ + protected function performAuthentication($username, $password) + { + $request = pack('C2', 1, strlen($username)) . $username + . pack('C', strlen($password)) . $password; + + $this->write($request); + $response = unpack('Cvn/Cstatus', $this->read(3)); + if (1 != $response['vn'] || 0 != $response['status']) { + throw new HTTP_Request2_ConnectionException( + 'Connection rejected by proxy due to invalid username and/or password' + ); + } + } + + /** + * Connects to a remote host via proxy + * + * @param string $remoteHost Remote host + * @param int $remotePort Remote port + * + * @throws HTTP_Request2_ConnectionException + * @throws HTTP_Request2_MessageException + */ + public function connect($remoteHost, $remotePort) + { + $request = pack('C5', 0x05, 0x01, 0x00, 0x03, strlen($remoteHost)) + . $remoteHost . pack('n', $remotePort); + + $this->write($request); + $response = unpack('Cversion/Creply/Creserved', $this->read(1024)); + if (5 != $response['version'] || 0 != $response['reserved']) { + throw new HTTP_Request2_MessageException( + 'Invalid response received from SOCKS5 proxy', + HTTP_Request2_Exception::MALFORMED_RESPONSE + ); + } elseif (0 != $response['reply']) { + throw new HTTP_Request2_ConnectionException( + "Unable to connect to {$remoteHost}:{$remotePort} through SOCKS5 proxy", + 0, $response['reply'] + ); + } + } +} +?> \ No newline at end of file diff --git a/libs/PEAR.1.9.5/HTTP/Request2/SocketWrapper.php b/libs/PEAR.1.9.5/HTTP/Request2/SocketWrapper.php new file mode 100644 index 000000000..43081a196 --- /dev/null +++ b/libs/PEAR.1.9.5/HTTP/Request2/SocketWrapper.php @@ -0,0 +1,297 @@ + + * @copyright 2008-2014 Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** Exception classes for HTTP_Request2 package */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Socket wrapper class used by Socket Adapter + * + * Needed to properly handle connection errors, global timeout support and + * similar things. Loosely based on Net_Socket used by older HTTP_Request. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License + * @version Release: 2.2.1 + * @link http://pear.php.net/package/HTTP_Request2 + * @link http://pear.php.net/bugs/bug.php?id=19332 + * @link http://tools.ietf.org/html/rfc1928 + */ +class HTTP_Request2_SocketWrapper +{ + /** + * PHP warning messages raised during stream_socket_client() call + * @var array + */ + protected $connectionWarnings = array(); + + /** + * Connected socket + * @var resource + */ + protected $socket; + + /** + * Sum of start time and global timeout, exception will be thrown if request continues past this time + * @var integer + */ + protected $deadline; + + /** + * Global timeout value, mostly for exception messages + * @var integer + */ + protected $timeout; + + /** + * Class constructor, tries to establish connection + * + * @param string $address Address for stream_socket_client() call, + * e.g. 'tcp://localhost:80' + * @param int $timeout Connection timeout (seconds) + * @param array $contextOptions Context options + * + * @throws HTTP_Request2_LogicException + * @throws HTTP_Request2_ConnectionException + */ + public function __construct($address, $timeout, array $contextOptions = array()) + { + if (!empty($contextOptions) + && !isset($contextOptions['socket']) && !isset($contextOptions['ssl']) + ) { + // Backwards compatibility with 2.1.0 and 2.1.1 releases + $contextOptions = array('ssl' => $contextOptions); + } + $context = stream_context_create(); + foreach ($contextOptions as $wrapper => $options) { + foreach ($options as $name => $value) { + if (!stream_context_set_option($context, $wrapper, $name, $value)) { + throw new HTTP_Request2_LogicException( + "Error setting '{$wrapper}' wrapper context option '{$name}'" + ); + } + } + } + set_error_handler(array($this, 'connectionWarningsHandler')); + $this->socket = stream_socket_client( + $address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context + ); + restore_error_handler(); + // if we fail to bind to a specified local address (see request #19515), + // connection still succeeds, albeit with a warning. Throw an Exception + // with the warning text in this case as that connection is unlikely + // to be what user wants and as Curl throws an error in similar case. + if ($this->connectionWarnings) { + if ($this->socket) { + fclose($this->socket); + } + $error = $errstr ? $errstr : implode("\n", $this->connectionWarnings); + throw new HTTP_Request2_ConnectionException( + "Unable to connect to {$address}. Error: {$error}", 0, $errno + ); + } + } + + /** + * Destructor, disconnects socket + */ + public function __destruct() + { + fclose($this->socket); + } + + /** + * Wrapper around fread(), handles global request timeout + * + * @param int $length Reads up to this number of bytes + * + * @return string Data read from socket + * @throws HTTP_Request2_MessageException In case of timeout + */ + public function read($length) + { + if ($this->deadline) { + stream_set_timeout($this->socket, max($this->deadline - time(), 1)); + } + $data = fread($this->socket, $length); + $this->checkTimeout(); + return $data; + } + + /** + * Reads until either the end of the socket or a newline, whichever comes first + * + * Strips the trailing newline from the returned data, handles global + * request timeout. Method idea borrowed from Net_Socket PEAR package. + * + * @param int $bufferSize buffer size to use for reading + * @param int $localTimeout timeout value to use just for this call + * (used when waiting for "100 Continue" response) + * + * @return string Available data up to the newline (not including newline) + * @throws HTTP_Request2_MessageException In case of timeout + */ + public function readLine($bufferSize, $localTimeout = null) + { + $line = ''; + while (!feof($this->socket)) { + if (null !== $localTimeout) { + stream_set_timeout($this->socket, $localTimeout); + } elseif ($this->deadline) { + stream_set_timeout($this->socket, max($this->deadline - time(), 1)); + } + + $line .= @fgets($this->socket, $bufferSize); + + if (null === $localTimeout) { + $this->checkTimeout(); + + } else { + $info = stream_get_meta_data($this->socket); + // reset socket timeout if we don't have request timeout specified, + // prevents further calls failing with a bogus Exception + if (!$this->deadline) { + $default = (int)@ini_get('default_socket_timeout'); + stream_set_timeout($this->socket, $default > 0 ? $default : PHP_INT_MAX); + } + if ($info['timed_out']) { + throw new HTTP_Request2_MessageException( + "readLine() call timed out", HTTP_Request2_Exception::TIMEOUT + ); + } + } + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Wrapper around fwrite(), handles global request timeout + * + * @param string $data String to be written + * + * @return int + * @throws HTTP_Request2_MessageException + */ + public function write($data) + { + if ($this->deadline) { + stream_set_timeout($this->socket, max($this->deadline - time(), 1)); + } + $written = fwrite($this->socket, $data); + $this->checkTimeout(); + // http://www.php.net/manual/en/function.fwrite.php#96951 + if ($written < strlen($data)) { + throw new HTTP_Request2_MessageException('Error writing request'); + } + return $written; + } + + /** + * Tests for end-of-file on a socket + * + * @return bool + */ + public function eof() + { + return feof($this->socket); + } + + /** + * Sets request deadline + * + * @param int $deadline Exception will be thrown if request continues + * past this time + * @param int $timeout Original request timeout value, to use in + * Exception message + */ + public function setDeadline($deadline, $timeout) + { + $this->deadline = $deadline; + $this->timeout = $timeout; + } + + /** + * Turns on encryption on a socket + * + * @throws HTTP_Request2_ConnectionException + */ + public function enableCrypto() + { + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + foreach ($modes as $mode) { + if (stream_socket_enable_crypto($this->socket, true, $mode)) { + return; + } + } + throw new HTTP_Request2_ConnectionException( + 'Failed to enable secure connection when connecting through proxy' + ); + } + + /** + * Throws an Exception if stream timed out + * + * @throws HTTP_Request2_MessageException + */ + protected function checkTimeout() + { + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->deadline && time() > $this->deadline) { + $reason = $this->deadline + ? "after {$this->timeout} second(s)" + : 'due to default_socket_timeout php.ini setting'; + throw new HTTP_Request2_MessageException( + "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT + ); + } + } + + /** + * Error handler to use during stream_socket_client() call + * + * One stream_socket_client() call may produce *multiple* PHP warnings + * (especially OpenSSL-related), we keep them in an array to later use for + * the message of HTTP_Request2_ConnectionException + * + * @param int $errno error level + * @param string $errstr error message + * + * @return bool + */ + protected function connectionWarningsHandler($errno, $errstr) + { + if ($errno & E_WARNING) { + array_unshift($this->connectionWarnings, $errstr); + } + return true; + } +} +?> diff --git a/libs/PEAR.1.9.5/Net/URL2.php b/libs/PEAR.1.9.5/Net/URL2.php new file mode 100644 index 000000000..d5bab1141 --- /dev/null +++ b/libs/PEAR.1.9.5/Net/URL2.php @@ -0,0 +1,1219 @@ + + * @copyright 2007-2009 Peytz & Co. A/S + * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause + * @version CVS: $Id$ + * @link https://tools.ietf.org/html/rfc3986 + */ + +/** + * Represents a URL as per RFC 3986. + * + * @category Networking + * @package Net_URL2 + * @author Christian Schmidt + * @copyright 2007-2009 Peytz & Co. A/S + * @license https://spdx.org/licenses/BSD-3-Clause BSD-3-Clause + * @version Release: 2.1.1 + * @link https://pear.php.net/package/Net_URL2 + */ +class Net_URL2 +{ + /** + * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default + * is true. + */ + const OPTION_STRICT = 'strict'; + + /** + * Represent arrays in query using PHP's [] notation. Default is true. + */ + const OPTION_USE_BRACKETS = 'use_brackets'; + + /** + * Drop zero-based integer sequences in query using PHP's [] notation. Default + * is true. + */ + const OPTION_DROP_SEQUENCE = 'drop_sequence'; + + /** + * URL-encode query variable keys. Default is true. + */ + const OPTION_ENCODE_KEYS = 'encode_keys'; + + /** + * Query variable separators when parsing the query string. Every character + * is considered a separator. Default is "&". + */ + const OPTION_SEPARATOR_INPUT = 'input_separator'; + + /** + * Query variable separator used when generating the query string. Default + * is "&". + */ + const OPTION_SEPARATOR_OUTPUT = 'output_separator'; + + /** + * Default options corresponds to how PHP handles $_GET. + */ + private $_options = array( + self::OPTION_STRICT => true, + self::OPTION_USE_BRACKETS => true, + self::OPTION_DROP_SEQUENCE => true, + self::OPTION_ENCODE_KEYS => true, + self::OPTION_SEPARATOR_INPUT => '&', + self::OPTION_SEPARATOR_OUTPUT => '&', + ); + + /** + * @var string|bool + */ + private $_scheme = false; + + /** + * @var string|bool + */ + private $_userinfo = false; + + /** + * @var string|bool + */ + private $_host = false; + + /** + * @var string|bool + */ + private $_port = false; + + /** + * @var string + */ + private $_path = ''; + + /** + * @var string|bool + */ + private $_query = false; + + /** + * @var string|bool + */ + private $_fragment = false; + + /** + * Constructor. + * + * @param string $url an absolute or relative URL + * @param array $options an array of OPTION_xxx constants + * + * @uses self::parseUrl() + */ + public function __construct($url, array $options = array()) + { + foreach ($options as $optionName => $value) { + if (array_key_exists($optionName, $this->_options)) { + $this->_options[$optionName] = $value; + } + } + + $this->parseUrl($url); + } + + /** + * Magic Setter. + * + * This method will magically set the value of a private variable ($var) + * with the value passed as the args + * + * @param string $var The private variable to set. + * @param mixed $arg An argument of any type. + * + * @return void + */ + public function __set($var, $arg) + { + $method = 'set' . $var; + if (method_exists($this, $method)) { + $this->$method($arg); + } + } + + /** + * Magic Getter. + * + * This is the magic get method to retrieve the private variable + * that was set by either __set() or it's setter... + * + * @param string $var The property name to retrieve. + * + * @return mixed $this->$var Either a boolean false if the + * property is not set or the value + * of the private property. + */ + public function __get($var) + { + $method = 'get' . $var; + if (method_exists($this, $method)) { + return $this->$method(); + } + + return false; + } + + /** + * Returns the scheme, e.g. "http" or "urn", or false if there is no + * scheme specified, i.e. if this is a relative URL. + * + * @return string|bool + */ + public function getScheme() + { + return $this->_scheme; + } + + /** + * Sets the scheme, e.g. "http" or "urn". Specify false if there is no + * scheme specified, i.e. if this is a relative URL. + * + * @param string|bool $scheme e.g. "http" or "urn", or false if there is no + * scheme specified, i.e. if this is a relative + * URL + * + * @return $this + * @see getScheme + */ + public function setScheme($scheme) + { + $this->_scheme = $scheme; + return $this; + } + + /** + * Returns the user part of the userinfo part (the part preceding the first + * ":"), or false if there is no userinfo part. + * + * @return string|bool + */ + public function getUser() + { + return $this->_userinfo !== false + ? preg_replace('(:.*$)', '', $this->_userinfo) + : false; + } + + /** + * Returns the password part of the userinfo part (the part after the first + * ":"), or false if there is no userinfo part (i.e. the URL does not + * contain "@" in front of the hostname) or the userinfo part does not + * contain ":". + * + * @return string|bool + */ + public function getPassword() + { + return $this->_userinfo !== false + ? substr(strstr($this->_userinfo, ':'), 1) + : false; + } + + /** + * Returns the userinfo part, or false if there is none, i.e. if the + * authority part does not contain "@". + * + * @return string|bool + */ + public function getUserinfo() + { + return $this->_userinfo; + } + + /** + * Sets the userinfo part. If two arguments are passed, they are combined + * in the userinfo part as username ":" password. + * + * @param string|bool $userinfo userinfo or username + * @param string|bool $password optional password, or false + * + * @return $this + */ + public function setUserinfo($userinfo, $password = false) + { + if ($password !== false) { + $userinfo .= ':' . $password; + } + + if ($userinfo !== false) { + $userinfo = $this->_encodeData($userinfo); + } + + $this->_userinfo = $userinfo; + return $this; + } + + /** + * Returns the host part, or false if there is no authority part, e.g. + * relative URLs. + * + * @return string|bool a hostname, an IP address, or false + */ + public function getHost() + { + return $this->_host; + } + + /** + * Sets the host part. Specify false if there is no authority part, e.g. + * relative URLs. + * + * @param string|bool $host a hostname, an IP address, or false + * + * @return $this + */ + public function setHost($host) + { + $this->_host = $host; + return $this; + } + + /** + * Returns the port number, or false if there is no port number specified, + * i.e. if the default port is to be used. + * + * @return string|bool + */ + public function getPort() + { + return $this->_port; + } + + /** + * Sets the port number. Specify false if there is no port number specified, + * i.e. if the default port is to be used. + * + * @param string|bool $port a port number, or false + * + * @return $this + */ + public function setPort($port) + { + $this->_port = $port; + return $this; + } + + /** + * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or + * false if there is no authority. + * + * @return string|bool + */ + public function getAuthority() + { + if (false === $this->_host) { + return false; + } + + $authority = ''; + + if (strlen($this->_userinfo)) { + $authority .= $this->_userinfo . '@'; + } + + $authority .= $this->_host; + + if ($this->_port !== false) { + $authority .= ':' . $this->_port; + } + + return $authority; + } + + /** + * Sets the authority part, i.e. [ userinfo "@" ] host [ ":" port ]. Specify + * false if there is no authority. + * + * @param string|bool $authority a hostname or an IP address, possibly + * with userinfo prefixed and port number + * appended, e.g. "foo:bar@example.org:81". + * + * @return $this + */ + public function setAuthority($authority) + { + $this->_userinfo = false; + $this->_host = false; + $this->_port = false; + + if ('' === $authority) { + $this->_host = $authority; + return $this; + } + + if (!preg_match('(^(([^\@]*)\@)?(.+?)(:(\d*))?$)', $authority, $matches)) { + return $this; + } + + if ($matches[1]) { + $this->_userinfo = $this->_encodeData($matches[2]); + } + + $this->_host = $matches[3]; + + if (isset($matches[5]) && strlen($matches[5])) { + $this->_port = $matches[5]; + } + return $this; + } + + /** + * Returns the path part (possibly an empty string). + * + * @return string + */ + public function getPath() + { + return $this->_path; + } + + /** + * Sets the path part (possibly an empty string). + * + * @param string $path a path + * + * @return $this + */ + public function setPath($path) + { + $this->_path = $path; + return $this; + } + + /** + * Returns the query string (excluding the leading "?"), or false if "?" + * is not present in the URL. + * + * @return string|bool + * @see getQueryVariables + */ + public function getQuery() + { + return $this->_query; + } + + /** + * Sets the query string (excluding the leading "?"). Specify false if "?" + * is not present in the URL. + * + * @param string|bool $query a query string, e.g. "foo=1&bar=2" + * + * @return $this + * @see setQueryVariables + */ + public function setQuery($query) + { + $this->_query = $query; + return $this; + } + + /** + * Returns the fragment name, or false if "#" is not present in the URL. + * + * @return string|bool + */ + public function getFragment() + { + return $this->_fragment; + } + + /** + * Sets the fragment name. Specify false if "#" is not present in the URL. + * + * @param string|bool $fragment a fragment excluding the leading "#", or + * false + * + * @return $this + */ + public function setFragment($fragment) + { + $this->_fragment = $fragment; + return $this; + } + + /** + * Returns the query string like an array as the variables would appear in + * $_GET in a PHP script. If the URL does not contain a "?", an empty array + * is returned. + * + * @return array + */ + public function getQueryVariables() + { + $separator = $this->getOption(self::OPTION_SEPARATOR_INPUT); + $encodeKeys = $this->getOption(self::OPTION_ENCODE_KEYS); + $useBrackets = $this->getOption(self::OPTION_USE_BRACKETS); + + $return = array(); + + for ($part = strtok($this->_query, $separator); + strlen($part); + $part = strtok($separator) + ) { + list($key, $value) = explode('=', $part, 2) + array(1 => ''); + + if ($encodeKeys) { + $key = rawurldecode($key); + } + $value = rawurldecode($value); + + if ($useBrackets) { + $return = $this->_queryArrayByKey($key, $value, $return); + } else { + if (isset($return[$key])) { + $return[$key] = (array) $return[$key]; + $return[$key][] = $value; + } else { + $return[$key] = $value; + } + } + } + + return $return; + } + + /** + * Parse a single query key=value pair into an existing php array + * + * @param string $key query-key + * @param string $value query-value + * @param array $array of existing query variables (if any) + * + * @return mixed + */ + private function _queryArrayByKey($key, $value, array $array = array()) + { + if (!strlen($key)) { + return $array; + } + + $offset = $this->_queryKeyBracketOffset($key); + if ($offset === false) { + $name = $key; + } else { + $name = substr($key, 0, $offset); + } + + if (!strlen($name)) { + return $array; + } + + if (!$offset) { + // named value + $array[$name] = $value; + } else { + // array + $brackets = substr($key, $offset); + if (!isset($array[$name])) { + $array[$name] = null; + } + $array[$name] = $this->_queryArrayByBrackets( + $brackets, $value, $array[$name] + ); + } + + return $array; + } + + /** + * Parse a key-buffer to place value in array + * + * @param string $buffer to consume all keys from + * @param string $value to be set/add + * @param array $array to traverse and set/add value in + * + * @throws Exception + * @return array + */ + private function _queryArrayByBrackets($buffer, $value, array $array = null) + { + $entry = &$array; + + for ($iteration = 0; strlen($buffer); $iteration++) { + $open = $this->_queryKeyBracketOffset($buffer); + if ($open !== 0) { + // Opening bracket [ must exist at offset 0, if not, there is + // no bracket to parse and the value dropped. + // if this happens in the first iteration, this is flawed, see + // as well the second exception below. + if ($iteration) { + break; + } + // @codeCoverageIgnoreStart + throw new Exception( + 'Net_URL2 Internal Error: '. __METHOD__ .'(): ' . + 'Opening bracket [ must exist at offset 0' + ); + // @codeCoverageIgnoreEnd + } + + $close = strpos($buffer, ']', 1); + if (!$close) { + // this error condition should never be reached as this is a + // private method and bracket pairs are checked beforehand. + // See as well the first exception for the opening bracket. + // @codeCoverageIgnoreStart + throw new Exception( + 'Net_URL2 Internal Error: '. __METHOD__ .'(): ' . + 'Closing bracket ] must exist, not found' + ); + // @codeCoverageIgnoreEnd + } + + $index = substr($buffer, 1, $close - 1); + if (strlen($index)) { + $entry = &$entry[$index]; + } else { + if (!is_array($entry)) { + $entry = array(); + } + $entry[] = &$new; + $entry = &$new; + unset($new); + } + $buffer = substr($buffer, $close + 1); + } + + $entry = $value; + + return $array; + } + + /** + * Query-key has brackets ("...[]") + * + * @param string $key query-key + * + * @return bool|int offset of opening bracket, false if no brackets + */ + private function _queryKeyBracketOffset($key) + { + if (false !== $open = strpos($key, '[') + and false === strpos($key, ']', $open + 1) + ) { + $open = false; + } + + return $open; + } + + /** + * Sets the query string to the specified variable in the query string. + * + * @param array $array (name => value) array + * + * @return $this + */ + public function setQueryVariables(array $array) + { + if (!$array) { + $this->_query = false; + } else { + $this->_query = $this->buildQuery( + $array, + $this->getOption(self::OPTION_SEPARATOR_OUTPUT) + ); + } + return $this; + } + + /** + * Sets the specified variable in the query string. + * + * @param string $name variable name + * @param mixed $value variable value + * + * @return $this + */ + public function setQueryVariable($name, $value) + { + $array = $this->getQueryVariables(); + $array[$name] = $value; + $this->setQueryVariables($array); + return $this; + } + + /** + * Removes the specified variable from the query string. + * + * @param string $name a query string variable, e.g. "foo" in "?foo=1" + * + * @return void + */ + public function unsetQueryVariable($name) + { + $array = $this->getQueryVariables(); + unset($array[$name]); + $this->setQueryVariables($array); + } + + /** + * Returns a string representation of this URL. + * + * @return string + */ + public function getURL() + { + // See RFC 3986, section 5.3 + $url = ''; + + if ($this->_scheme !== false) { + $url .= $this->_scheme . ':'; + } + + $authority = $this->getAuthority(); + if ($authority === false && strtolower($this->_scheme) === 'file') { + $authority = ''; + } + + $url .= $this->_buildAuthorityAndPath($authority, $this->_path); + + if ($this->_query !== false) { + $url .= '?' . $this->_query; + } + + if ($this->_fragment !== false) { + $url .= '#' . $this->_fragment; + } + + return $url; + } + + /** + * Put authority and path together, wrapping authority + * into proper separators/terminators. + * + * @param string|bool $authority authority + * @param string $path path + * + * @return string + */ + private function _buildAuthorityAndPath($authority, $path) + { + if ($authority === false) { + return $path; + } + + $terminator = ($path !== '' && $path[0] !== '/') ? '/' : ''; + + return '//' . $authority . $terminator . $path; + } + + /** + * Returns a string representation of this URL. + * + * @return string + * @link https://php.net/language.oop5.magic#object.tostring + */ + public function __toString() + { + return $this->getURL(); + } + + /** + * Returns a normalized string representation of this URL. This is useful + * for comparison of URLs. + * + * @return string + */ + public function getNormalizedURL() + { + $url = clone $this; + $url->normalize(); + return $url->getUrl(); + } + + /** + * Normalizes the URL + * + * See RFC 3986, Section 6. Normalization and Comparison + * + * @link https://tools.ietf.org/html/rfc3986#section-6 + * + * @return void + */ + public function normalize() + { + // See RFC 3986, section 6 + + // Scheme is case-insensitive + if ($this->_scheme) { + $this->_scheme = strtolower($this->_scheme); + } + + // Hostname is case-insensitive + if ($this->_host) { + $this->_host = strtolower($this->_host); + } + + // Remove default port number for known schemes (RFC 3986, section 6.2.3) + if ('' === $this->_port + || $this->_port + && $this->_scheme + && $this->_port == getservbyname($this->_scheme, 'tcp') + ) { + $this->_port = false; + } + + // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1) + // Normalize percentage-encoded unreserved characters (section 6.2.2.2) + $fields = array(&$this->_userinfo, &$this->_host, &$this->_path, + &$this->_query, &$this->_fragment); + foreach ($fields as &$field) { + if ($field !== false) { + $field = $this->_normalize("$field"); + } + } + unset($field); + + // Path segment normalization (RFC 3986, section 6.2.2.3) + $this->_path = self::removeDotSegments($this->_path); + + // Scheme based normalization (RFC 3986, section 6.2.3) + if (false !== $this->_host && '' === $this->_path) { + $this->_path = '/'; + } + + // path should start with '/' if there is authority (section 3.3.) + if (strlen($this->getAuthority()) + && strlen($this->_path) + && $this->_path[0] !== '/' + ) { + $this->_path = '/' . $this->_path; + } + } + + /** + * Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1) + * Normalize percentage-encoded unreserved characters (section 6.2.2.2) + * + * @param string|array $mixed string or array of strings to normalize + * + * @return string|array + * @see normalize + * @see _normalizeCallback() + */ + private function _normalize($mixed) + { + return preg_replace_callback( + '((?:%[0-9a-fA-Z]{2})+)', array($this, '_normalizeCallback'), + $mixed + ); + } + + /** + * Callback for _normalize() of %XX percentage-encodings + * + * @param array $matches as by preg_replace_callback + * + * @return string + * @see normalize + * @see _normalize + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + private function _normalizeCallback($matches) + { + return self::urlencode(urldecode($matches[0])); + } + + /** + * Returns whether this instance represents an absolute URL. + * + * @return bool + */ + public function isAbsolute() + { + return (bool) $this->_scheme; + } + + /** + * Returns an Net_URL2 instance representing an absolute URL relative to + * this URL. + * + * @param Net_URL2|string $reference relative URL + * + * @throws Exception + * @return $this + */ + public function resolve($reference) + { + if (!$reference instanceof Net_URL2) { + $reference = new self($reference); + } + if (!$reference->_isFragmentOnly() && !$this->isAbsolute()) { + throw new Exception( + 'Base-URL must be absolute if reference is not fragment-only' + ); + } + + // A non-strict parser may ignore a scheme in the reference if it is + // identical to the base URI's scheme. + if (!$this->getOption(self::OPTION_STRICT) + && $reference->_scheme == $this->_scheme + ) { + $reference->_scheme = false; + } + + $target = new self(''); + if ($reference->_scheme !== false) { + $target->_scheme = $reference->_scheme; + $target->setAuthority($reference->getAuthority()); + $target->_path = self::removeDotSegments($reference->_path); + $target->_query = $reference->_query; + } else { + $authority = $reference->getAuthority(); + if ($authority !== false) { + $target->setAuthority($authority); + $target->_path = self::removeDotSegments($reference->_path); + $target->_query = $reference->_query; + } else { + if ($reference->_path == '') { + $target->_path = $this->_path; + if ($reference->_query !== false) { + $target->_query = $reference->_query; + } else { + $target->_query = $this->_query; + } + } else { + if (substr($reference->_path, 0, 1) == '/') { + $target->_path = self::removeDotSegments($reference->_path); + } else { + // Merge paths (RFC 3986, section 5.2.3) + if ($this->_host !== false && $this->_path == '') { + $target->_path = '/' . $reference->_path; + } else { + $i = strrpos($this->_path, '/'); + if ($i !== false) { + $target->_path = substr($this->_path, 0, $i + 1); + } + $target->_path .= $reference->_path; + } + $target->_path = self::removeDotSegments($target->_path); + } + $target->_query = $reference->_query; + } + $target->setAuthority($this->getAuthority()); + } + $target->_scheme = $this->_scheme; + } + + $target->_fragment = $reference->_fragment; + + return $target; + } + + /** + * URL is fragment-only + * + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + * @return bool + */ + private function _isFragmentOnly() + { + return ( + $this->_fragment !== false + && $this->_query === false + && $this->_path === '' + && $this->_port === false + && $this->_host === false + && $this->_userinfo === false + && $this->_scheme === false + ); + } + + /** + * Removes dots as described in RFC 3986, section 5.2.4, e.g. + * "/foo/../bar/baz" => "/bar/baz" + * + * @param string $path a path + * + * @return string a path + */ + public static function removeDotSegments($path) + { + $path = (string) $path; + $output = ''; + + // Make sure not to be trapped in an infinite loop due to a bug in this + // method + $loopLimit = 256; + $j = 0; + while ('' !== $path && $j++ < $loopLimit) { + if (substr($path, 0, 2) === './') { + // Step 2.A + $path = substr($path, 2); + } elseif (substr($path, 0, 3) === '../') { + // Step 2.A + $path = substr($path, 3); + } elseif (substr($path, 0, 3) === '/./' || $path === '/.') { + // Step 2.B + $path = '/' . substr($path, 3); + } elseif (substr($path, 0, 4) === '/../' || $path === '/..') { + // Step 2.C + $path = '/' . substr($path, 4); + $i = strrpos($output, '/'); + $output = $i === false ? '' : substr($output, 0, $i); + } elseif ($path === '.' || $path === '..') { + // Step 2.D + $path = ''; + } else { + // Step 2.E + $i = strpos($path, '/', $path[0] === '/'); + if ($i === false) { + $output .= $path; + $path = ''; + break; + } + $output .= substr($path, 0, $i); + $path = substr($path, $i); + } + } + + if ($path !== '') { + $message = sprintf( + 'Unable to remove dot segments; hit loop limit %d (left: %s)', + $j, var_export($path, true) + ); + trigger_error($message, E_USER_WARNING); + } + + return $output; + } + + /** + * Percent-encodes all non-alphanumeric characters except these: _ . - ~ + * Similar to PHP's rawurlencode(), except that it also encodes ~ in PHP + * 5.2.x and earlier. + * + * @param string $string string to encode + * + * @return string + */ + public static function urlencode($string) + { + $encoded = rawurlencode($string); + + // This is only necessary in PHP < 5.3. + $encoded = str_replace('%7E', '~', $encoded); + return $encoded; + } + + /** + * Returns a Net_URL2 instance representing the canonical URL of the + * currently executing PHP script. + * + * @throws Exception + * @return string + */ + public static function getCanonical() + { + if (!isset($_SERVER['REQUEST_METHOD'])) { + // ALERT - no current URL + throw new Exception('Script was not called through a webserver'); + } + + // Begin with a relative URL + $url = new self($_SERVER['PHP_SELF']); + $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->_host = $_SERVER['SERVER_NAME']; + $port = $_SERVER['SERVER_PORT']; + if ($url->_scheme == 'http' && $port != 80 + || $url->_scheme == 'https' && $port != 443 + ) { + $url->_port = $port; + } + return $url; + } + + /** + * Returns the URL used to retrieve the current request. + * + * @return string + */ + public static function getRequestedURL() + { + return self::getRequested()->getUrl(); + } + + /** + * Returns a Net_URL2 instance representing the URL used to retrieve the + * current request. + * + * @throws Exception + * @return $this + */ + public static function getRequested() + { + if (!isset($_SERVER['REQUEST_METHOD'])) { + // ALERT - no current URL + throw new Exception('Script was not called through a webserver'); + } + + // Begin with a relative URL + $url = new self($_SERVER['REQUEST_URI']); + $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + // Set host and possibly port + $url->setAuthority($_SERVER['HTTP_HOST']); + return $url; + } + + /** + * Returns the value of the specified option. + * + * @param string $optionName The name of the option to retrieve + * + * @return mixed + */ + public function getOption($optionName) + { + return isset($this->_options[$optionName]) + ? $this->_options[$optionName] : false; + } + + /** + * A simple version of http_build_query in userland. The encoded string is + * percentage encoded according to RFC 3986. + * + * @param array $data An array, which has to be converted into + * QUERY_STRING. Anything is possible. + * @param string $separator Separator {@link self::OPTION_SEPARATOR_OUTPUT} + * @param string $key For stacked values (arrays in an array). + * + * @return string + */ + protected function buildQuery(array $data, $separator, $key = null) + { + $query = array(); + $drop_names = ( + $this->_options[self::OPTION_DROP_SEQUENCE] === true + && array_keys($data) === array_keys(array_values($data)) + ); + foreach ($data as $name => $value) { + if ($this->getOption(self::OPTION_ENCODE_KEYS) === true) { + $name = rawurlencode($name); + } + if ($key !== null) { + if ($this->getOption(self::OPTION_USE_BRACKETS) === true) { + $drop_names && $name = ''; + $name = $key . '[' . $name . ']'; + } else { + $name = $key; + } + } + if (is_array($value)) { + $query[] = $this->buildQuery($value, $separator, $name); + } else { + $query[] = $name . '=' . rawurlencode($value); + } + } + return implode($separator, $query); + } + + /** + * This method uses a regex to parse the url into the designated parts. + * + * @param string $url URL + * + * @return void + * @uses self::$_scheme, self::setAuthority(), self::$_path, self::$_query, + * self::$_fragment + * @see __construct + */ + protected function parseUrl($url) + { + // The regular expression is copied verbatim from RFC 3986, appendix B. + // The expression does not validate the URL but matches any string. + preg_match( + '(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)', + $url, $matches + ); + + // "path" is always present (possibly as an empty string); the rest + // are optional. + $this->_scheme = !empty($matches[1]) ? $matches[2] : false; + $this->setAuthority(!empty($matches[3]) ? $matches[4] : false); + $this->_path = $this->_encodeData($matches[5]); + $this->_query = !empty($matches[6]) + ? $this->_encodeData($matches[7]) + : false + ; + $this->_fragment = !empty($matches[8]) ? $matches[9] : false; + } + + /** + * Encode characters that might have been forgotten to encode when passing + * in an URL. Applied onto Userinfo, Path and Query. + * + * @param string $url URL + * + * @return string + * @see parseUrl + * @see setAuthority + * @link https://pear.php.net/bugs/bug.php?id=20425 + */ + private function _encodeData($url) + { + return preg_replace_callback( + '([\x-\x20\x22\x3C\x3E\x7F-\xFF]+)', + array($this, '_encodeCallback'), $url + ); + } + + /** + * callback for encoding character data + * + * @param array $matches Matches + * + * @return string + * @see _encodeData + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + private function _encodeCallback(array $matches) + { + return rawurlencode($matches[0]); + } +} diff --git a/libs/PEAR.1.9.5/PEAR.php b/libs/PEAR.1.9.5/PEAR.php new file mode 100644 index 000000000..e6f8edc2a --- /dev/null +++ b/libs/PEAR.1.9.5/PEAR.php @@ -0,0 +1,1063 @@ + + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2010 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/**#@+ + * ERROR constants + */ +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); +/** + * WARNING: obsolete + * @deprecated + */ +define('PEAR_ERROR_EXCEPTION', 32); +/**#@-*/ +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +@ini_set('track_errors', true); + +/** + * Base class for other PEAR classes. Provides rudimentary + * emulation of destructors. + * + * If you want a destructor in your class, inherit PEAR and make a + * destructor method called _yourclassname (same name as the + * constructor, but with a "_" prefix). Also, in your constructor you + * have to call the PEAR constructor: $this->PEAR();. + * The destructor method will be called without parameters. Note that + * at in some SAPI implementations (such as Apache), any output during + * the request shutdown (in which destructors are called) seems to be + * discarded. If you need to get any debug information from your + * destructor, use error_log(), syslog() or something similar. + * + * IMPORTANT! To use the emulated destructors you need to create the + * objects by reference: $obj =& new PEAR_child; + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Greg Beaver + * @copyright 1997-2006 The PHP Group + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 1.9.5 + * @link http://pear.php.net/package/PEAR + * @see PEAR_Error + * @since Class available since PHP 4.0.2 + * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear + */ +class PEAR +{ + /** + * Whether to enable internal debug messages. + * + * @var bool + * @access private + */ + var $_debug = false; + + /** + * Default error mode for this object. + * + * @var int + * @access private + */ + var $_default_error_mode = null; + + /** + * Default error options used for this object when error mode + * is PEAR_ERROR_TRIGGER. + * + * @var int + * @access private + */ + var $_default_error_options = null; + + /** + * Default error handler (callback) for this object, if error mode is + * PEAR_ERROR_CALLBACK. + * + * @var string + * @access private + */ + var $_default_error_handler = ''; + + /** + * Which class to use for error objects. + * + * @var string + * @access private + */ + var $_error_class = 'PEAR_Error'; + + /** + * An array of expected errors. + * + * @var array + * @access private + */ + var $_expected_errors = array(); + + /** + * Constructor. Registers this object in + * $_PEAR_destructor_object_list for destructor emulation if a + * destructor object exists. + * + * @param string $error_class (optional) which class to use for + * error objects, defaults to PEAR_Error. + * @access public + * @return void + */ + function PEAR($error_class = null) + { + $classname = strtolower(get_class($this)); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + + if ($error_class !== null) { + $this->_error_class = $error_class; + } + + while ($classname && strcasecmp($classname, "pear")) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + /** + * Destructor (the emulated type of...). Does nothing right now, + * but is included for forward compatibility, so subclass + * destructors should always call it. + * + * See the note in the class desciption about output from + * destructors. + * + * @access public + * @return void + */ + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); + } + } + + /** + * If you have a class that's mostly/entirely static, and you need static + * properties, you can use this method to simulate them. Eg. in your method(s) + * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); + * You MUST use a reference, or they will not persist! + * + * @access public + * @param string $class The calling classname, to prevent clashes + * @param string $var The variable to retrieve. + * @return mixed A reference to the variable. If not set it will be + * auto initialised to NULL. + */ + function &getStaticProperty($class, $var) + { + static $properties; + if (!isset($properties[$class])) { + $properties[$class] = array(); + } + + if (!array_key_exists($var, $properties[$class])) { + $properties[$class][$var] = null; + } + + return $properties[$class][$var]; + } + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @param mixed $func The function name (or array of class/method) to call + * @param mixed $args The arguments to pass to the function + * @return void + */ + function registerShutdownFunc($func, $args = array()) + { + // if we are called statically, there is a potential + // that no shutdown func is registered. Bug #6445 + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + /** + * Tell whether a value is a PEAR error. + * + * @param mixed $data the value to test + * @param int $code if $data is an error object, return true + * only if $code is a string and + * $obj->getMessage() == $code or + * $code is an integer and $obj->getCode() == $code + * @access public + * @return bool true if parameter is an error + */ + function isError($data, $code = null) + { + if (!is_a($data, 'PEAR_Error')) { + return false; + } + + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } + + return $data->getCode() == $code; + } + + /** + * Sets how errors generated by this object should be handled. + * Can be invoked both in objects and statically. If called + * statically, setErrorHandling sets the default behaviour for all + * PEAR objects. If called in an object, setErrorHandling sets + * the default behaviour for that object. + * + * @param int $mode + * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. + * + * @param mixed $options + * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one + * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * + * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected + * to be the callback function or method. A callback + * function is a string with the name of the function, a + * callback method is an array of two elements: the element + * at index 0 is the object, and the element at index 1 is + * the name of the method to call in the object. + * + * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is + * a printf format string used when printing the error + * message. + * + * @access public + * @return void + * @see PEAR_ERROR_RETURN + * @see PEAR_ERROR_PRINT + * @see PEAR_ERROR_TRIGGER + * @see PEAR_ERROR_DIE + * @see PEAR_ERROR_CALLBACK + * @see PEAR_ERROR_EXCEPTION + * + * @since PHP 4.0.5 + */ + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + /** + * This method is used to tell which errors you expect to get. + * Expected errors are always returned with error mode + * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, + * and this method pushes a new element onto it. The list of + * expected errors are in effect until they are popped off the + * stack with the popExpect() method. + * + * Note that this method can not be called statically + * + * @param mixed $code a single error code or an array of error codes to expect + * + * @return int the new depth of the "expected errors" stack + * @access public + */ + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return count($this->_expected_errors); + } + + /** + * This method pops one element off the expected error codes + * stack. + * + * @return array the list of error codes that were popped + */ + function popExpect() + { + return array_pop($this->_expected_errors); + } + + /** + * This method checks unsets an error code if available + * + * @param mixed error code + * @return bool true if the error code was unset, false otherwise + * @access private + * @since PHP 4.3.0 + */ + function _checkDelExpect($error_code) + { + $deleted = false; + foreach ($this->_expected_errors as $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + // clean up empty arrays + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + + return $deleted; + } + + /** + * This method deletes all occurences of the specified element from + * the expected error codes stack. + * + * @param mixed $error_code error code that should be deleted + * @return mixed list of error codes that were deleted or error + * @access public + * @since PHP 4.3.0 + */ + function delExpect($error_code) + { + $deleted = false; + if ((is_array($error_code) && (0 != count($error_code)))) { + // $error_code is a non-empty array here; we walk through it trying + // to unset all values + foreach ($error_code as $key => $error) { + $deleted = $this->_checkDelExpect($error) ? true : false; + } + + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + // $error_code comes alone, trying to unset it + if ($this->_checkDelExpect($error_code)) { + return true; + } + + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + + /** + * This method is a wrapper that returns an instance of the + * configured error class with this object's default error + * handling applied. If the $mode and $options parameters are not + * specified, the object's defaults are used. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. + * + * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter + * specifies the PHP-internal error level (one of + * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * If $mode is PEAR_ERROR_CALLBACK, this + * parameter specifies the callback function or + * method. In other error modes this parameter + * is ignored. + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @param string $error_class The returned error object will be + * instantiated from this class, if specified. + * + * @param bool $skipmsg If true, raiseError will only pass error codes, + * the error message parameter will be dropped. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function &raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message->error_message_prefix = ''; + $message = $message->getMessage(); + } + + if ( + isset($this) && + isset($this->_expected_errors) && + count($this->_expected_errors) > 0 && + count($exp = end($this->_expected_errors)) + ) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp)) + ) { + $mode = PEAR_ERROR_RETURN; + } + } + + // No mode given, try global ones + if ($mode === null) { + // Class error handler + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + // Global error handler + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + + if (intval(PHP_VERSION) < 5) { + // little non-eval hack to fix bug #12147 + include 'PEAR/FixPHP5PEARWarnings.php'; + return $a; + } + + if ($skipmsg) { + $a = new $ec($code, $mode, $options, $userinfo); + } else { + $a = new $ec($message, $code, $mode, $options, $userinfo); + } + + return $a; + } + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @access public + * @return object a PEAR error object + * @see PEAR::raiseError + */ + function &throwError($message = null, $code = null, $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $a = &$this->raiseError($message, $code, null, null, $userinfo); + return $a; + } + + $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + return $a; + } + + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + // class/object method callback + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + + /** + * Push a new error handler on top of the error handler options stack. With this + * you can easily override the actual error handler for some code and restore + * it later with popErrorHandling. + * + * @param mixed $mode (same as setErrorHandling) + * @param mixed $options (same as setErrorHandling) + * + * @return bool Always true + * + * @see PEAR::setErrorHandling + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + /** + * OS independent PHP extension load. Remember to take care + * on the correct extension name for case sensitive OSes. + * + * @param string $ext The extension name + * @return bool Success or not on the dl() call + */ + function loadExtension($ext) + { + if (extension_loaded($ext)) { + return true; + } + + // if either returns true dl() will produce a FATAL error, stop that + if ( + function_exists('dl') === false || + ini_get('enable_dl') != 1 || + ini_get('safe_mode') == 1 + ) { + return false; + } + + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } +} + +if (PEAR_ZE2) { + include_once 'PEAR5.php'; +} + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + if (PEAR_ZE2) { + $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo'); + } else { + $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo'); + } + + if ($destructLifoExists) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } + + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + // Empty the object list to ensure that destructors are + // not called more than once. + $_PEAR_destructor_object_list = array(); + } + + // Now call the shutdown functions + if ( + isset($GLOBALS['_PEAR_shutdown_funcs']) && + is_array($GLOBALS['_PEAR_shutdown_funcs']) && + !empty($GLOBALS['_PEAR_shutdown_funcs']) + ) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +/** + * Standard PEAR error class for PHP 4 + * + * This class is supserseded by {@link PEAR_Exception} in PHP 5 + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Gregory Beaver + * @copyright 1997-2006 The PHP Group + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 1.9.5 + * @link http://pear.php.net/manual/en/core.pear.pear-error.php + * @see PEAR::raiseError(), PEAR::throwError() + * @since Class available since PHP 4.0.2 + */ +class PEAR_Error +{ + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + /** + * PEAR_Error constructor + * + * @param string $message message + * + * @param int $code (optional) error code + * + * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, + * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION + * + * @param mixed $options (optional) error level, _OR_ in the case of + * PEAR_ERROR_CALLBACK, the callback function or object/method + * tuple. + * + * @param string $userinfo (optional) additional user/debug info + * + * @access public + * + */ + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + + if (PEAR_ZE2) { + $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace'); + } else { + $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace'); + } + + if (!$skiptrace) { + $this->backtrace = debug_backtrace(); + if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { + unset($this->backtrace[0]['object']); + } + } + + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + + $this->level = $options; + $this->callback = null; + } + + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + + printf($format, $this->getMessage()); + } + + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + + if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) { + call_user_func($this->callback, $this); + } + + if ($this->mode & PEAR_ERROR_EXCEPTION) { + trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);throw($e);'); + } + } + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() + { + return $this->mode; + } + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() + { + return $this->callback; + } + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + /** + * Get the call backtrace from where the error was generated. + * Supported with PHP 4.3.0 or newer. + * + * @param int $frame (optional) what frame to fetch + * @return array Backtrace, or NULL if not available. + * @access public + */ + function getBacktrace($frame = null) + { + if (defined('PEAR_IGNORE_BACKTRACE')) { + return null; + } + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + function __toString() + { + return $this->getMessage(); + } + + /** + * Make a string representation of this object. + * + * @return string a string with an object summary + * @access public + */ + function toString() + { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } +} + +/* + * Local Variables: + * mode: php + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/libs/PEAR.1.9.5/PEAR/Exception.php b/libs/PEAR.1.9.5/PEAR/Exception.php new file mode 100644 index 000000000..2990cb612 --- /dev/null +++ b/libs/PEAR.1.9.5/PEAR/Exception.php @@ -0,0 +1,389 @@ + + * @author Hans Lellelid + * @author Bertrand Mansion + * @author Greg Beaver + * @copyright 1997-2009 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.3.3 + */ + + +/** + * Base PEAR_Exception Class + * + * 1) Features: + * + * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) + * - Definable triggers, shot when exceptions occur + * - Pretty and informative error messages + * - Added more context info available (like class, method or cause) + * - cause can be a PEAR_Exception or an array of mixed + * PEAR_Exceptions/PEAR_ErrorStack warnings + * - callbacks for specific exception classes and their children + * + * 2) Ideas: + * + * - Maybe a way to define a 'template' for the output + * + * 3) Inherited properties from PHP Exception Class: + * + * protected $message + * protected $code + * protected $line + * protected $file + * private $trace + * + * 4) Inherited methods from PHP Exception Class: + * + * __clone + * __construct + * getMessage + * getCode + * getFile + * getLine + * getTraceSafe + * getTraceSafeAsString + * __toString + * + * 5) Usage example + * + * + * require_once 'PEAR/Exception.php'; + * + * class Test { + * function foo() { + * throw new PEAR_Exception('Error Message', ERROR_CODE); + * } + * } + * + * function myLogger($pear_exception) { + * echo $pear_exception->getMessage(); + * } + * // each time a exception is thrown the 'myLogger' will be called + * // (its use is completely optional) + * PEAR_Exception::addObserver('myLogger'); + * $test = new Test; + * try { + * $test->foo(); + * } catch (PEAR_Exception $e) { + * print $e; + * } + * + * + * @category pear + * @package PEAR + * @author Tomas V.V.Cox + * @author Hans Lellelid + * @author Bertrand Mansion + * @author Greg Beaver + * @copyright 1997-2009 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 1.9.5 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.3.3 + * + */ +class PEAR_Exception extends Exception +{ + const OBSERVER_PRINT = -2; + const OBSERVER_TRIGGER = -4; + const OBSERVER_DIE = -8; + protected $cause; + private static $_observers = array(); + private static $_uniqueid = 0; + private $_trace; + + /** + * Supported signatures: + * - PEAR_Exception(string $message); + * - PEAR_Exception(string $message, int $code); + * - PEAR_Exception(string $message, Exception $cause); + * - PEAR_Exception(string $message, Exception $cause, int $code); + * - PEAR_Exception(string $message, PEAR_Error $cause); + * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); + * - PEAR_Exception(string $message, array $causes); + * - PEAR_Exception(string $message, array $causes, int $code); + * @param string exception message + * @param int|Exception|PEAR_Error|array|null exception cause + * @param int|null exception code or null + */ + public function __construct($message, $p2 = null, $p3 = null) + { + if (is_int($p2)) { + $code = $p2; + $this->cause = null; + } elseif (is_object($p2) || is_array($p2)) { + // using is_object allows both Exception and PEAR_Error + if (is_object($p2) && !($p2 instanceof Exception)) { + if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { + throw new PEAR_Exception('exception cause must be Exception, ' . + 'array, or PEAR_Error'); + } + } + $code = $p3; + if (is_array($p2) && isset($p2['message'])) { + // fix potential problem of passing in a single warning + $p2 = array($p2); + } + $this->cause = $p2; + } else { + $code = null; + $this->cause = null; + } + parent::__construct($message, $code); + $this->signal(); + } + + /** + * @param mixed $callback - A valid php callback, see php func is_callable() + * - A PEAR_Exception::OBSERVER_* constant + * - An array(const PEAR_Exception::OBSERVER_*, + * mixed $options) + * @param string $label The name of the observer. Use this if you want + * to remove it later with removeObserver() + */ + public static function addObserver($callback, $label = 'default') + { + self::$_observers[$label] = $callback; + } + + public static function removeObserver($label = 'default') + { + unset(self::$_observers[$label]); + } + + /** + * @return int unique identifier for an observer + */ + public static function getUniqueId() + { + return self::$_uniqueid++; + } + + private function signal() + { + foreach (self::$_observers as $func) { + if (is_callable($func)) { + call_user_func($func, $this); + continue; + } + settype($func, 'array'); + switch ($func[0]) { + case self::OBSERVER_PRINT : + $f = (isset($func[1])) ? $func[1] : '%s'; + printf($f, $this->getMessage()); + break; + case self::OBSERVER_TRIGGER : + $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; + trigger_error($this->getMessage(), $f); + break; + case self::OBSERVER_DIE : + $f = (isset($func[1])) ? $func[1] : '%s'; + die(printf($f, $this->getMessage())); + break; + default: + trigger_error('invalid observer type', E_USER_WARNING); + } + } + } + + /** + * Return specific error information that can be used for more detailed + * error messages or translation. + * + * This method may be overridden in child exception classes in order + * to add functionality not present in PEAR_Exception and is a placeholder + * to define API + * + * The returned array must be an associative array of parameter => value like so: + *
+     * array('name' => $name, 'context' => array(...))
+     * 
+ * @return array + */ + public function getErrorData() + { + return array(); + } + + /** + * Returns the exception that caused this exception to be thrown + * @access public + * @return Exception|array The context of the exception + */ + public function getCause() + { + return $this->cause; + } + + /** + * Function must be public to call on caused exceptions + * @param array + */ + public function getCauseMessage(&$causes) + { + $trace = $this->getTraceSafe(); + $cause = array('class' => get_class($this), + 'message' => $this->message, + 'file' => 'unknown', + 'line' => 'unknown'); + if (isset($trace[0])) { + if (isset($trace[0]['file'])) { + $cause['file'] = $trace[0]['file']; + $cause['line'] = $trace[0]['line']; + } + } + $causes[] = $cause; + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } elseif ($this->cause instanceof Exception) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => $this->cause->getFile(), + 'line' => $this->cause->getLine()); + } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } elseif ($cause instanceof Exception) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => $cause->getFile(), + 'line' => $cause->getLine()); + } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($cause) && isset($cause['message'])) { + // PEAR_ErrorStack warning + $causes[] = array( + 'class' => $cause['package'], + 'message' => $cause['message'], + 'file' => isset($cause['context']['file']) ? + $cause['context']['file'] : + 'unknown', + 'line' => isset($cause['context']['line']) ? + $cause['context']['line'] : + 'unknown', + ); + } + } + } + } + + public function getTraceSafe() + { + if (!isset($this->_trace)) { + $this->_trace = $this->getTrace(); + if (empty($this->_trace)) { + $backtrace = debug_backtrace(); + $this->_trace = array($backtrace[count($backtrace)-1]); + } + } + return $this->_trace; + } + + public function getErrorClass() + { + $trace = $this->getTraceSafe(); + return $trace[0]['class']; + } + + public function getErrorMethod() + { + $trace = $this->getTraceSafe(); + return $trace[0]['function']; + } + + public function __toString() + { + if (isset($_SERVER['REQUEST_URI'])) { + return $this->toHtml(); + } + return $this->toText(); + } + + public function toHtml() + { + $trace = $this->getTraceSafe(); + $causes = array(); + $this->getCauseMessage($causes); + $html = '' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '\n"; + } + $html .= '' . "\n" + . '' + . '' + . '' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '' + . '' + . '' . "\n"; + } + $html .= '' + . '' + . '' . "\n" + . '
' + . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' + . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' + . 'on line ' . $cause['line'] . '' + . "
Exception trace
#FunctionLocation
' . $k . ''; + if (!empty($v['class'])) { + $html .= $v['class'] . $v['type']; + } + $html .= $v['function']; + $args = array(); + if (!empty($v['args'])) { + foreach ($v['args'] as $arg) { + if (is_null($arg)) $args[] = 'null'; + elseif (is_array($arg)) $args[] = 'Array'; + elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; + elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; + elseif (is_int($arg) || is_double($arg)) $args[] = $arg; + else { + $arg = (string)$arg; + $str = htmlspecialchars(substr($arg, 0, 16)); + if (strlen($arg) > 16) $str .= '…'; + $args[] = "'" . $str . "'"; + } + } + } + $html .= '(' . implode(', ',$args) . ')' + . '' . (isset($v['file']) ? $v['file'] : 'unknown') + . ':' . (isset($v['line']) ? $v['line'] : 'unknown') + . '
' . ($k+1) . '{main} 
'; + return $html; + } + + public function toText() + { + $causes = array(); + $this->getCauseMessage($causes); + $causeMsg = ''; + foreach ($causes as $i => $cause) { + $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' + . $cause['message'] . ' in ' . $cause['file'] + . ' on line ' . $cause['line'] . "\n"; + } + return $causeMsg . $this->getTraceAsString(); + } +} \ No newline at end of file diff --git a/libs/PEAR.1.9.5/PEAR5.php b/libs/PEAR.1.9.5/PEAR5.php new file mode 100644 index 000000000..428606780 --- /dev/null +++ b/libs/PEAR.1.9.5/PEAR5.php @@ -0,0 +1,33 @@ + Date: Sat, 17 Jan 2015 11:49:08 +0900 Subject: [PATCH 22/43] =?UTF-8?q?exec=5Fjson=EC=9C=BC=EB=A1=9C=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EC=97=86=EC=9D=B4=20notice=5Flist,=20category=5Fli?= =?UTF-8?q?st,=20file=5Flist,=20comment=5Flist=EB=A5=BC=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=20=EC=98=AC=20=EC=88=98=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/board/board.api.php | 2 +- modules/board/board.view.php | 70 +++++++++++++++++++++++++++++++++++ modules/board/conf/module.xml | 2 +- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/modules/board/board.api.php b/modules/board/board.api.php index ace3a1c50..221208fa9 100644 --- a/modules/board/board.api.php +++ b/modules/board/board.api.php @@ -50,7 +50,7 @@ class boardAPI extends board { /** * @brief category list **/ - function dispBoardCatogoryList(&$oModule) { + function dispBoardCategoryList(&$oModule) { $oModule->add('category_list',Context::get('category_list')); } diff --git a/modules/board/board.view.php b/modules/board/board.view.php index c6420fed8..97465b585 100644 --- a/modules/board/board.view.php +++ b/modules/board/board.view.php @@ -212,6 +212,13 @@ class boardView extends board // check if the use_category option is enabled if($this->module_info->use_category=='Y') { + // check the grant + if(!$this->grant->list) + { + Context::set('category_list', array()); + return; + } + $oDocumentModel = getModel('document'); Context::set('category_list', $oDocumentModel->getCategoryList($this->module_srl)); @@ -323,6 +330,59 @@ class boardView extends board * @brief display the document file list (can be used by API) **/ function dispBoardContentFileList(){ + /** + * check the access grant (all the grant has been set by the module object) + **/ + if(!$this->grant->access) + { + return $this->dispBoardMessage('msg_not_permitted'); + } + + // check document view grant + $this->dispBoardContentView(); + + // Check if a permission for file download is granted + // Get configurations (using module model object) + $oModuleModel = getModel('module'); + $file_module_config = $oModuleModel->getModulePartConfig('file',$this->module_srl); + + $downloadGrantCount = 0; + if(is_array($file_module_config->download_grant)) + { + foreach($file_module_config->download_grant AS $value) + if($value) $downloadGrantCount++; + } + + if(is_array($file_module_config->download_grant) && $downloadGrantCount>0) + { + if(!Context::get('is_logged')) return $this->stop('msg_not_permitted_download'); + $logged_info = Context::get('logged_info'); + if($logged_info->is_admin != 'Y') + { + $oModuleModel =& getModel('module'); + $columnList = array('module_srl', 'site_srl'); + $module_info = $oModuleModel->getModuleInfoByModuleSrl($this->module_srl, $columnList); + + if(!$oModuleModel->isSiteAdmin($logged_info, $module_info->site_srl)) + { + $oMemberModel =& getModel('member'); + $member_groups = $oMemberModel->getMemberGroups($logged_info->member_srl, $module_info->site_srl); + + $is_permitted = false; + for($i=0;$idownload_grant);$i++) + { + $group_srl = $file_module_config->download_grant[$i]; + if($member_groups[$group_srl]) + { + $is_permitted = true; + break; + } + } + if(!$is_permitted) return $this->stop('msg_not_permitted_download'); + } + } + } + $oDocumentModel = getModel('document'); $document_srl = Context::get('document_srl'); $oDocument = $oDocumentModel->getDocument($document_srl); @@ -336,6 +396,9 @@ class boardView extends board * @brief display the document comment list (can be used by API) **/ function dispBoardContentCommentList(){ + // check document view grant + $this->dispBoardContentView(); + $oDocumentModel = getModel('document'); $document_srl = Context::get('document_srl'); $oDocument = $oDocumentModel->getDocument($document_srl); @@ -360,6 +423,13 @@ class boardView extends board * @brief display notice list (can be used by API) **/ function dispBoardNoticeList(){ + // check the grant + if(!$this->grant->list) + { + Context::set('notice_list', array()); + return; + } + $oDocumentModel = getModel('document'); $args = new stdClass(); $args->module_srl = $this->module_srl; diff --git a/modules/board/conf/module.xml b/modules/board/conf/module.xml index ccce75f29..72002fed7 100644 --- a/modules/board/conf/module.xml +++ b/modules/board/conf/module.xml @@ -60,7 +60,7 @@ - + From 0c5f5279a6e9665f717c0beb6dcc93f1e7b4fc8a Mon Sep 17 00:00:00 2001 From: YJSoft Date: Sat, 17 Jan 2015 20:50:38 +0900 Subject: [PATCH 23/43] =?UTF-8?q?#1111=20=EC=82=AC=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=A0=EA=B8=88=20=EC=82=AC=EC=9A=A9=EC=8B=9C=20=EB=8C=80?= =?UTF-8?q?=EC=8B=9C=EB=B3=B4=EB=93=9C=EC=97=90=20=EA=B2=BD=EA=B3=A0=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 사이트 잠금을 해둔 것을 잊어 버리는 것을 방지 겸 reminder. --- modules/admin/admin.admin.view.php | 3 +++ modules/admin/lang/lang.xml | 7 +++++++ modules/admin/tpl/index.html | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/modules/admin/admin.admin.view.php b/modules/admin/admin.admin.view.php index 4c9baaa6e..7d6b7a800 100644 --- a/modules/admin/admin.admin.view.php +++ b/modules/admin/admin.admin.view.php @@ -248,6 +248,9 @@ class adminAdminView extends admin */ function dispAdminIndex() { + $db_info = Context::getDBInfo(); + Context::set('db_info',$db_info); + // Get statistics $args = new stdClass(); $args->date = date("Ymd000000", $_SERVER['REQUEST_TIME'] - 60 * 60 * 24); diff --git a/modules/admin/lang/lang.xml b/modules/admin/lang/lang.xml index aad7294c4..ed6277a3b 100644 --- a/modules/admin/lang/lang.xml +++ b/modules/admin/lang/lang.xml @@ -1606,4 +1606,11 @@ + + + + + + + diff --git a/modules/admin/tpl/index.html b/modules/admin/tpl/index.html index 15f754e49..04c73e0a3 100644 --- a/modules/admin/tpl/index.html +++ b/modules/admin/tpl/index.html @@ -19,6 +19,11 @@

{$XE_VALIDATOR_MESSAGE}

+
+

{$lang->sitelock_in_use}

+

{$lang->about_sitelock_in_use}

+
+
From 8fac041af6af296125206ff7d7db586d9fbd0ab3 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 21 Jan 2015 13:17:56 +0900 Subject: [PATCH 24/43] =?UTF-8?q?jshint=20=EC=84=A4=EC=A0=95=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jshintignore | 9 +++++++ .jshintrc | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ Gruntfile.js | 9 ------- 3 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 .jshintignore create mode 100644 .jshintrc diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 000000000..5f00d3da3 --- /dev/null +++ b/.jshintignore @@ -0,0 +1,9 @@ +common/js/jquery*.js +common/js/modernizr.js +common/js/xe.js +common/js/x.js +common/js/*.min.js +common/js/unittest/* +common/js/plugins/* +common/js/foggyLayer.js +common/js/html5.js diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 000000000..ae1b55f2c --- /dev/null +++ b/.jshintrc @@ -0,0 +1,68 @@ +{ + "globalstrict": false, + "undef": false, + "eqeqeq": false, + "browser": true, + "devel": true, + "jquery": true, + "evil": true, + "globals": { + "window": true, + "current_url": true, + "exec_json": true, + "exec_xml": true, + "procFilter": true, + "xe": true, + "request_uri": true, + "xAddEventListener": false, + "xResizeEvent": false, + "xScrollEvent": false, + "xAppendChild": false, + "xClientHeight": false, + "xClientWidth": false, + "xCreateElement": false, + "xDef": false, + "xDeleteCookie": false, + "xDisplay": false, + "xEvent": false, + "xFirstChild": false, + "xGetBodyWidth": false, + "xGetBodyHeight": false, + "xGetComputedStyle": false, + "xGetCookie": false, + "xGetElementById": false, + "xGetElementsByAttribute": false, + "xGetElementsByClassName": false, + "xGetElementsByTagName": false, + "xGetURLArguments": false, + "xHeight": false, + "xHex": false, + "xHide": false, + "xInnerHtml": false, + "xLeft": false, + "xMoveTo": false, + "xName": false, + "xNextSib": false, + "xNum": false, + "xOffsetLeft": false, + "xOffsetTop": false, + "xPad": false, + "xPageX": false, + "xPageY": false, + "xParent": false, + "xPreventDefault": false, + "xPrevSib": false, + "xRemoveEventListener": false, + "xResizeTo": false, + "xScrollLeft": false, + "xScrollTop": false, + "xSetCookie": false, + "xShow": false, + "xStr": false, + "xTop": false, + "xVisibility": false, + "xWidth": false, + "xZIndex": false, + "xStopPropagation": false + } +} diff --git a/Gruntfile.js b/Gruntfile.js index 9b9f7a502..2adb308a0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -172,15 +172,6 @@ module.exports = function(grunt) { 'modules/widget/tpl/js/*.js', ], options : { - globalstrict: false, - undef : false, - eqeqeq: false, - browser : true, - globals: { - "jQuery" : true, - "console" : true, - "window" : true - }, ignores : [ '**/jquery*.js', '**/swfupload.js', From 12e87048ba74300371f3b39552fe28db1da5b979 Mon Sep 17 00:00:00 2001 From: BJRambo Date: Wed, 21 Jan 2015 17:19:51 +0900 Subject: [PATCH 25/43] =?UTF-8?q?$bUseHistory=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20=ED=95=98=EC=97=AC=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=8B=9C=20=EA=B6=8C=ED=95=9C=EC=9D=B4=20=ED=83=88=EC=B7=A8?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=EC=A0=90=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/document/document.controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/document/document.controller.php b/modules/document/document.controller.php index accc182e3..4a2bedfd0 100644 --- a/modules/document/document.controller.php +++ b/modules/document/document.controller.php @@ -443,7 +443,7 @@ class documentController extends document if(Context::get('is_logged')) { $logged_info = Context::get('logged_info'); - if($source_obj->get('member_srl')==$logged_info->member_srl || $bUseHistory) + if($source_obj->get('member_srl')==$logged_info->member_srl) { $obj->member_srl = $logged_info->member_srl; $obj->user_name = htmlspecialchars_decode($logged_info->user_name); From b3e9e782012c38b2922007735ad47ba5e88cac58 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Fri, 23 Jan 2015 12:32:08 +0900 Subject: [PATCH 26/43] Update Extravar.class.php --- classes/extravar/Extravar.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/extravar/Extravar.class.php b/classes/extravar/Extravar.class.php index 93ea4427d..ed15074c5 100644 --- a/classes/extravar/Extravar.class.php +++ b/classes/extravar/Extravar.class.php @@ -297,7 +297,7 @@ class ExtraItem return ($value) ? sprintf('%s', $value, $value) : ""; case 'tel' : - return sprintf('%s - %s - %s', $value[0], $value[1], $value[2]); + return sprintf('%s-%s-%s', $value[0], $value[1], $value[2]); case 'textarea' : return nl2br($value); From 311cd49302ee4086a850102128a8604700e52200 Mon Sep 17 00:00:00 2001 From: sejin7940 Date: Fri, 23 Jan 2015 12:37:50 +0900 Subject: [PATCH 27/43] Update getDocumentListWithinTag.xml --- modules/document/queries/getDocumentListWithinTag.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/document/queries/getDocumentListWithinTag.xml b/modules/document/queries/getDocumentListWithinTag.xml index 12fe072fc..641ec1061 100644 --- a/modules/document/queries/getDocumentListWithinTag.xml +++ b/modules/document/queries/getDocumentListWithinTag.xml @@ -14,6 +14,7 @@ + From c174a68f58607e52192f40a98929e22b9ef8d7c2 Mon Sep 17 00:00:00 2001 From: khongchi Date: Wed, 28 Jan 2015 16:01:43 +0900 Subject: [PATCH 28/43] #1208 remove gravatar from oembed provider --- addons/oembed/jquery.oembed.js | 140 --------------------------------- 1 file changed, 140 deletions(-) diff --git a/addons/oembed/jquery.oembed.js b/addons/oembed/jquery.oembed.js index 41f9d4509..dd17f4841 100755 --- a/addons/oembed/jquery.oembed.js +++ b/addons/oembed/jquery.oembed.js @@ -781,12 +781,6 @@ from: 'htmlstring' } }), - new $.fn.oembed.OEmbedProvider("gravtar", "photo", ["mailto:.+"], null, { - templateRegex: /mailto:([^\/]+).*/, - template: function (wm, email) { - return 'on Gravtar'; - } - }), //Rich new $.fn.oembed.OEmbedProvider("twitter", "rich", ["twitter.com/.+"], "https://api.twitter.com/1/statuses/oembed.json"), @@ -1062,137 +1056,3 @@ }) ]; })(jQuery); - -//This is needed for gravatar :( -String.prototype.md5 = function () { - var a = function (a, b) { - var c = (a & 65535) + (b & 65535); - var d = (a >> 16) + (b >> 16) + (c >> 16); - return d << 16 | c & 65535 - }; - var b = function (a, b) { - return a << b | a >>> 32 - b - }; - var c = function (c, d, e, f, g, h) { - return a(b(a(a(d, c), a(f, h)), g), e) - }; - var d = function (a, b, d, e, f, g, h) { - return c(b & d | ~b & e, a, b, f, g, h) - }; - var e = function (a, b, d, e, f, g, h) { - return c(b & e | d & ~e, a, b, f, g, h) - }; - var f = function (a, b, d, e, f, g, h) { - return c(b ^ d ^ e, a, b, f, g, h) - }; - var g = function (a, b, d, e, f, g, h) { - return c(d ^ (b | ~e), a, b, f, g, h) - }; - var h = function (b) { - var c, h, i, j, k, l = b.length; - var m = 1732584193; - var n = -271733879; - var o = -1732584194; - var p = 271733878; - for(k = 0; k < l; k += 16) { - c = m; - h = n; - i = o; - j = p; - m = d(m, n, o, p, b[k + 0], 7, -680876936); - p = d(p, m, n, o, b[k + 1], 12, -389564586); - o = d(o, p, m, n, b[k + 2], 17, 606105819); - n = d(n, o, p, m, b[k + 3], 22, -1044525330); - m = d(m, n, o, p, b[k + 4], 7, -176418897); - p = d(p, m, n, o, b[k + 5], 12, 1200080426); - o = d(o, p, m, n, b[k + 6], 17, -1473231341); - n = d(n, o, p, m, b[k + 7], 22, -45705983); - m = d(m, n, o, p, b[k + 8], 7, 1770035416); - p = d(p, m, n, o, b[k + 9], 12, -1958414417); - o = d(o, p, m, n, b[k + 10], 17, -42063); - n = d(n, o, p, m, b[k + 11], 22, -1990404162); - m = d(m, n, o, p, b[k + 12], 7, 1804603682); - p = d(p, m, n, o, b[k + 13], 12, -40341101); - o = d(o, p, m, n, b[k + 14], 17, -1502002290); - n = d(n, o, p, m, b[k + 15], 22, 1236535329); - m = e(m, n, o, p, b[k + 1], 5, -165796510); - p = e(p, m, n, o, b[k + 6], 9, -1069501632); - o = e(o, p, m, n, b[k + 11], 14, 643717713); - n = e(n, o, p, m, b[k + 0], 20, -373897302); - m = e(m, n, o, p, b[k + 5], 5, -701558691); - p = e(p, m, n, o, b[k + 10], 9, 38016083); - o = e(o, p, m, n, b[k + 15], 14, -660478335); - n = e(n, o, p, m, b[k + 4], 20, -405537848); - m = e(m, n, o, p, b[k + 9], 5, 568446438); - p = e(p, m, n, o, b[k + 14], 9, -1019803690); - o = e(o, p, m, n, b[k + 3], 14, -187363961); - n = e(n, o, p, m, b[k + 8], 20, 1163531501); - m = e(m, n, o, p, b[k + 13], 5, -1444681467); - p = e(p, m, n, o, b[k + 2], 9, -51403784); - o = e(o, p, m, n, b[k + 7], 14, 1735328473); - n = e(n, o, p, m, b[k + 12], 20, -1926607734); - m = f(m, n, o, p, b[k + 5], 4, -378558); - p = f(p, m, n, o, b[k + 8], 11, -2022574463); - o = f(o, p, m, n, b[k + 11], 16, 1839030562); - n = f(n, o, p, m, b[k + 14], 23, -35309556); - m = f(m, n, o, p, b[k + 1], 4, -1530992060); - p = f(p, m, n, o, b[k + 4], 11, 1272893353); - o = f(o, p, m, n, b[k + 7], 16, -155497632); - n = f(n, o, p, m, b[k + 10], 23, -1094730640); - m = f(m, n, o, p, b[k + 13], 4, 681279174); - p = f(p, m, n, o, b[k + 0], 11, -358537222); - o = f(o, p, m, n, b[k + 3], 16, -722521979); - n = f(n, o, p, m, b[k + 6], 23, 76029189); - m = f(m, n, o, p, b[k + 9], 4, -640364487); - p = f(p, m, n, o, b[k + 12], 11, -421815835); - o = f(o, p, m, n, b[k + 15], 16, 530742520); - n = f(n, o, p, m, b[k + 2], 23, -995338651); - m = g(m, n, o, p, b[k + 0], 6, -198630844); - p = g(p, m, n, o, b[k + 7], 10, 1126891415); - o = g(o, p, m, n, b[k + 14], 15, -1416354905); - n = g(n, o, p, m, b[k + 5], 21, -57434055); - m = g(m, n, o, p, b[k + 12], 6, 1700485571); - p = g(p, m, n, o, b[k + 3], 10, -1894986606); - o = g(o, p, m, n, b[k + 10], 15, -1051523); - n = g(n, o, p, m, b[k + 1], 21, -2054922799); - m = g(m, n, o, p, b[k + 8], 6, 1873313359); - p = g(p, m, n, o, b[k + 15], 10, -30611744); - o = g(o, p, m, n, b[k + 6], 15, -1560198380); - n = g(n, o, p, m, b[k + 13], 21, 1309151649); - m = g(m, n, o, p, b[k + 4], 6, -145523070); - p = g(p, m, n, o, b[k + 11], 10, -1120210379); - o = g(o, p, m, n, b[k + 2], 15, 718787259); - n = g(n, o, p, m, b[k + 9], 21, -343485551); - m = a(m, c); - n = a(n, h); - o = a(o, i); - p = a(p, j) - } - return [m, n, o, p] - }; - var i = function (a) { - var b = "0123456789abcdef", - c = "", - d, e = a.length * 4; - for(d = 0; d < e; d++) { - c += b.charAt(a[d >> 2] >> d % 4 * 8 + 4 & 15) + b.charAt(a[d >> 2] >> d % 4 * 8 & 15) - } - return c - }; - var j = function (a) { - var b = (a.length + 8 >> 6) + 1; - var c = [], - d, e = b * 16, - f, g = a.length; - for(d = 0; d < e; d++) { - c.push(0) - } - for(f = 0; f < g; f++) { - c[f >> 2] |= (a.charCodeAt(f) & 255) << f % 4 * 8 - } - c[f >> 2] |= 128 << f % 4 * 8; - c[b * 16 - 2] = g * 8; - return c - }; - return i(h(j(this))) -} From a897ec4efffe6b28d4735ecdf873672bb2e0e2da Mon Sep 17 00:00:00 2001 From: bnu Date: Fri, 30 Jan 2015 14:36:53 +0900 Subject: [PATCH 29/43] =?UTF-8?q?Revert=20"zdate()=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=ED=8A=9C=EB=8B=9D"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/func.inc.php | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/config/func.inc.php b/config/func.inc.php index 3405c5f34..19355d372 100644 --- a/config/func.inc.php +++ b/config/func.inc.php @@ -714,9 +714,43 @@ function zdate($str, $format = 'Y-m-d H:i:s', $conversion = TRUE) } } - $date = new DateTime($str); - $string = $date->format($format); + // If year value is less than 1970, handle it separately. + if((int) substr($str, 0, 4) < 1970) + { + $hour = (int) substr($str, 8, 2); + $min = (int) substr($str, 10, 2); + $sec = (int) substr($str, 12, 2); + $year = (int) substr($str, 0, 4); + $month = (int) substr($str, 4, 2); + $day = (int) substr($str, 6, 2); + // leading zero? + $lz = create_function('$n', 'return ($n>9?"":"0").$n;'); + + $trans = array( + 'Y' => $year, + 'y' => $lz($year % 100), + 'm' => $lz($month), + 'n' => $month, + 'd' => $lz($day), + 'j' => $day, + 'G' => $hour, + 'H' => $lz($hour), + 'g' => $hour % 12, + 'h' => $lz($hour % 12), + 'i' => $lz($min), + 's' => $lz($sec), + 'M' => getMonthName($month), + 'F' => getMonthName($month, FALSE) + ); + + $string = strtr($format, $trans); + } + else + { + // if year value is greater than 1970, get unixtime by using ztime() for date() function's argument. + $string = date($format, ztime($str)); + } // change day and am/pm for each language $unit_week = Context::getLang('unit_week'); $unit_meridiem = Context::getLang('unit_meridiem'); From bcea05b6c9fd301c6222f5d125bb258f1b5a76a3 Mon Sep 17 00:00:00 2001 From: bnu Date: Fri, 30 Jan 2015 14:34:13 +0900 Subject: [PATCH 30/43] =?UTF-8?q?fix=20#1165=20=EC=9C=84=EC=A0=AF=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=84=A4=EC=A0=95=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=84=20=EC=9E=98=EB=AA=BB=20=EC=B2=98=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/widget/widget.model.php | 102 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/modules/widget/widget.model.php b/modules/widget/widget.model.php index 77014aba4..9589bd32f 100644 --- a/modules/widget/widget.model.php +++ b/modules/widget/widget.model.php @@ -281,86 +281,88 @@ class widgetModel extends widget $xml_obj = $tmp_xml_obj->widgetstyle; if(!$xml_obj) return; - $buff = ''; + $buff = array(); + $buff[] = 'widgetStyle = "%s";', $widgetStyle); - $buff .= sprintf('$widgetStyle_info->path = "%s";', $widgetStyle_path); - $buff .= sprintf('$widgetStyle_info->title = "%s";', $xml_obj->title->body); - $buff .= sprintf('$widgetStyle_info->description = "%s";', $xml_obj->description->body); - $buff .= sprintf('$widgetStyle_info->version = "%s";', $xml_obj->version->body); + $buff[] = sprintf('$widgetStyle_info->widgetStyle = "%s";', $widgetStyle); + $buff[] = sprintf('$widgetStyle_info->path = "%s";', $widgetStyle_path); + $buff[] = sprintf('$widgetStyle_info->title = "%s";', $xml_obj->title->body); + $buff[] = sprintf('$widgetStyle_info->description = "%s";', $xml_obj->description->body); + $buff[] = sprintf('$widgetStyle_info->version = "%s";', $xml_obj->version->body); sscanf($xml_obj->date->body, '%d-%d-%d', $date_obj->y, $date_obj->m, $date_obj->d); $date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); - $buff .= sprintf('$widgetStyle_info->date = "%s";', $date); - $buff .= sprintf('$widgetStyle_info->homepage = "%s";', $xml_obj->link->body); - $buff .= sprintf('$widgetStyle_info->license = "%s";', $xml_obj->license->body); - $buff .= sprintf('$widgetStyle_info->license_link = "%s";', $xml_obj->license->attrs->link); + $buff[] = sprintf('$widgetStyle_info->date = "%s";', $date); + $buff[] = sprintf('$widgetStyle_info->homepage = "%s";', $xml_obj->link->body); + $buff[] = sprintf('$widgetStyle_info->license = "%s";', $xml_obj->license->body); + $buff[] = sprintf('$widgetStyle_info->license_link = "%s";', $xml_obj->license->attrs->link); // preview if(!$xml_obj->preview->body) $xml_obj->preview->body = 'preview.jpg'; $preview_file = sprintf("%s%s", $widgetStyle_path,$xml_obj->preview->body); - if(file_exists($preview_file)) $buff .= sprintf('$widgetStyle_info->preview = "%s";', $preview_file); - // Author information - if(!is_array($xml_obj->author)) $author_list[] = $xml_obj->author; - else $author_list = $xml_obj->author; + if(file_exists($preview_file)) $buff[] = sprintf('$widgetStyle_info->preview = "%s";', $preview_file); - for($i=0; $i < count($author_list); $i++) + // Author information + $author_list = (!is_array($author_list)) ? array($author_list) : $author_list; + + foreach($author_list as $idx => $author) { - $buff .= '$widgetStyle_info->author['.$i.'] = new stdClass;'; - $buff .= sprintf('$widgetStyle_info->author['.$i.']->name = "%s";', $author_list[$i]->name->body); - $buff .= sprintf('$widgetStyle_info->author['.$i.']->email_address = "%s";', $author_list[$i]->attrs->email_address); - $buff .= sprintf('$widgetStyle_info->author['.$i.']->homepage = "%s";', $author_list[$i]->attrs->link); + $buff[] = sprintf('$widgetStyle_info->author[%d] = new stdClass();', $idx); + $buff[] = sprintf('$widgetStyle_info->author[%d]->name = "%s";', $idx, $author->name->body); + $buff[] = sprintf('$widgetStyle_info->author[%d]->email_address = "%s";', $idx, $author->attrs->email_address); + $buff[] = sprintf('$widgetStyle_info->author[%d]->homepage = "%s";', $idx, $author->attrs->link); } // Extra vars (user defined variables to use in a template) $extra_var_groups = $xml_obj->extra_vars->group; if(!$extra_var_groups) $extra_var_groups = $xml_obj->extra_vars; if(!is_array($extra_var_groups)) $extra_var_groups = array($extra_var_groups); + + $extra_var_count = 0; + $buff[] = sprintf('$widgetStyle_info->extra_var = new stdClass();', $extra_var_count); foreach($extra_var_groups as $group) { - $extra_vars = $group->var; - if(!is_array($group->var)) $extra_vars = array($group->var); + $extra_vars = (!is_array($group->var)) ? array($group->var) : $group->var; if($extra_vars[0]->attrs->id || $extra_vars[0]->attrs->name) { - $extra_var_count = count($extra_vars); - - $buff .= sprintf('$widgetStyle_info->extra_var_count = "%s";$widgetStyle_info->extra_var = new stdClass;', $extra_var_count); - for($i=0;$i<$extra_var_count;$i++) + foreach($extra_vars as $var) { - unset($var); - unset($options); - $var = $extra_vars[$i]; + $extra_var_count++; + $id = ($var->attrs->id) ? $var->attrs->id : $var->attrs->name; + $name = ($var->name->body) ? $var->name->body : $var->title->body; + $type = ($var->attrs->type) ? $var->attrs->type : $var->type->body; - $id = $var->attrs->id?$var->attrs->id:$var->attrs->name; - $name = $var->name->body?$var->name->body:$var->title->body; - $type = $var->attrs->type?$var->attrs->type:$var->type->body; - - $buff .= sprintf('$widgetStyle_info->extra_var->%s = new stdClass;', $id); - $buff .= sprintf('$widgetStyle_info->extra_var->%s->group = "%s";', $id, $group->title->body); - $buff .= sprintf('$widgetStyle_info->extra_var->%s->name = "%s";', $id, $name); - $buff .= sprintf('$widgetStyle_info->extra_var->%s->type = "%s";', $id, $type); - if($type =='filebox') $buff .= sprintf('$widgetStyle_info->extra_var->%s->filter = "%s";', $id, $var->attrs->filter); - if($type =='filebox') $buff .= sprintf('$widgetStyle_info->extra_var->%s->allow_multiple = "%s";', $id, $var->attrs->allow_multiple); - $buff .= sprintf('$widgetStyle_info->extra_var->%s->value = $vars->%s;', $id, $id); - $buff .= sprintf('$widgetStyle_info->extra_var->%s->description = "%s";', $id, str_replace('"','\"',$var->description->body)); - - $options = $var->options; - if(!$options) continue; - - if(!is_array($options)) $options = array($options); - $options_count = count($options); - for($j=0;$j<$options_count;$j++) + $buff[] = sprintf('$widgetStyle_info->extra_var->%s = new stdClass();', $id); + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->group = "%s";', $id, $group->title->body); + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->name = "%s";', $id, $name); + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->type = "%s";', $id, $type); + if($type =='filebox') { - $buff .= sprintf('$widgetStyle_info->extra_var->%s->options["%s"] = "%s";', $id, $options[$j]->value->body, $options[$j]->name->body); + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->filter = "%s";', $id, $var->attrs->filter); + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->allow_multiple = "%s";', $id, $var->attrs->allow_multiple); + } + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->value = $vars->%s;', $id, $id); + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->description = "%s";', $id, str_replace('"','\"',$var->description->body)); + + if($var->options) + { + $var_options = (!is_array($var->options)) ? array($var->options) : $var->options; + foreach($var_options as $option_item) + { + $buff[] = sprintf('$widgetStyle_info->extra_var->%s->options["%s"] = "%s";', $id, $option_item->value->body, $option_item->name->body); + } } } } } + $buff[] = sprintf('$widgetStyle_info->extra_var_count = %d;', $extra_var_count); - $buff = ''; - FileHandler::writeFile($cache_file, $buff); + FileHandler::writeFile($cache_file, implode(PHP_EOL, $buff)); if(file_exists($cache_file)) @include($cache_file); + return $widgetStyle_info; } } From 460a4dbc933a6bd007be15625fd830521b008356 Mon Sep 17 00:00:00 2001 From: bnu Date: Fri, 30 Jan 2015 16:29:09 +0900 Subject: [PATCH 31/43] =?UTF-8?q?fix=20#1209=20https=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EC=8B=A4=ED=8C=A8=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/editor/tpl/js/uploader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/editor/tpl/js/uploader.js b/modules/editor/tpl/js/uploader.js index 59fc4ed55..beb4807a0 100755 --- a/modules/editor/tpl/js/uploader.js +++ b/modules/editor/tpl/js/uploader.js @@ -49,7 +49,7 @@ var uploadAutosaveChecker = false; settings = { flash_url : request_uri + 'modules/editor/tpl/images/SWFUpload.swf', - upload_url : request_uri.replace(/^https/i, 'http')+'index.php', + upload_url : request_uri + 'index.php', post_params : { mid : current_mid, act : 'procFileUpload', From ae55711dc451da08b753a1799716211aaac3e960 Mon Sep 17 00:00:00 2001 From: bnu Date: Fri, 30 Jan 2015 17:10:40 +0900 Subject: [PATCH 32/43] =?UTF-8?q?#1195=20=EB=B3=B4=EC=99=84.=20=EA=B8=80?= =?UTF-8?q?=20=EB=B3=B4=EA=B8=B0=20=EA=B6=8C=ED=95=9C=EC=9D=B4=20=EC=97=86?= =?UTF-8?q?=EC=9D=84=20=EB=95=8C=20=EA=B8=80=20=EB=AA=A9=EB=A1=9D=EC=97=90?= =?UTF-8?q?=EC=84=9C=20content,=20tags,=20extra=5Fvars=20=EA=B0=90?= =?UTF-8?q?=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/board/board.api.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/board/board.api.php b/modules/board/board.api.php index 221208fa9..4c825dbf4 100644 --- a/modules/board/board.api.php +++ b/modules/board/board.api.php @@ -97,10 +97,18 @@ class boardAPI extends board { function arrangeContent($content) { + $oBoardView = getView('board'); $output = new stdClass; if($content){ $output = $content->gets('document_srl','category_srl','member_srl','nick_name','user_id','user_name','title','content','tags','readed_count','voted_count','blamed_count','comment_count','regdate','last_update','extra_vars','status'); + if(!$oBoardView->grant->view) + { + unset($output->content); + unset($output->tags); + unset($output->extra_vars); + } + $t_width = Context::get('thumbnail_width'); $t_height = Context::get('thumbnail_height'); $t_type = Context::get('thumbnail_type'); From 14ffdbe5f0fdc48b9bcffa6f2730ef1763d9569a Mon Sep 17 00:00:00 2001 From: bnu Date: Fri, 30 Jan 2015 17:36:14 +0900 Subject: [PATCH 33/43] =?UTF-8?q?#1182=20=EB=B3=B4=EC=99=84=20-=20file::?= =?UTF-8?q?=5FchangeBytes()=EB=A5=BC=20FIleHandler::returnBytes()=EB=A1=9C?= =?UTF-8?q?=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- classes/file/FileHandler.class.php | 17 ++++++----------- modules/file/file.admin.controller.php | 8 ++++---- modules/file/file.admin.view.php | 8 ++++---- modules/file/file.class.php | 19 ------------------- modules/file/file.model.php | 4 ++-- modules/file/tpl/adminConfig.html | 2 +- 6 files changed, 17 insertions(+), 41 deletions(-) diff --git a/classes/file/FileHandler.class.php b/classes/file/FileHandler.class.php index 03eb3ce96..9cc2458d7 100644 --- a/classes/file/FileHandler.class.php +++ b/classes/file/FileHandler.class.php @@ -635,18 +635,13 @@ class FileHandler */ function returnBytes($val) { - $last = strtolower(substr(trim($val), -1)); - switch ($last) + $unit = strtoupper(substr($val, -1)); + $val = (int)$val; + switch ($unit) { - case 'g': - $val *= 1024 * 1024 * 1024; - break; - case 'm': - $val *= 1024 * 1024; - break; - case 'k': - $val *= 1024; - break; + case 'G': $val *= 1024; + case 'M': $val *= 1024; + case 'K': $val *= 1024; } return $val; diff --git a/modules/file/file.admin.controller.php b/modules/file/file.admin.controller.php index 09952be77..af453c707 100644 --- a/modules/file/file.admin.controller.php +++ b/modules/file/file.admin.controller.php @@ -134,10 +134,10 @@ class fileAdminController extends file else $file_config->download_grant = $download_grant; //관리자가 허용한 첨부파일의 사이즈가 php.ini의 값보다 큰지 확인하기 - by ovclas - $userFileAllowSize = $this->_changeBytes($file_config->allowed_filesize.'M'); - $userAttachAllowSize = $this->_changeBytes($file_config->allowed_attach_size.'M'); - $iniPostMaxSize = $this->_changeBytes(ini_get('post_max_size')); - $iniUploadMaxSize = $this->_changeBytes(ini_get('upload_max_filesize')); + $userFileAllowSize = FileHandler::returnbytes($file_config->allowed_filesize.'M'); + $userAttachAllowSize = FileHandler::returnbytes($file_config->allowed_attach_size.'M'); + $iniPostMaxSize = FileHandler::returnbytes(ini_get('post_max_size')); + $iniUploadMaxSize = FileHandler::returnbytes(ini_get('upload_max_filesize')); $iniMinSzie = min($iniPostMaxSize, $iniUploadMaxSize); if($userFileAllowSize > $iniMinSzie || $userAttachAllowSize > $iniMinSzie) diff --git a/modules/file/file.admin.view.php b/modules/file/file.admin.view.php index 4cc68621f..d04516664 100644 --- a/modules/file/file.admin.view.php +++ b/modules/file/file.admin.view.php @@ -201,7 +201,7 @@ class fileAdminView extends file // Set a template $security = new Security(); $security->encodeHTML('file_list..'); - $security->encodeHTML('module_list..'); + $security->encodeHTML('module_list..'); $this->setTemplatePath($this->module_path.'tpl'); $this->setTemplateFile('file_list'); @@ -217,10 +217,10 @@ class fileAdminView extends file $oFileModel = getModel('file'); $config = $oFileModel->getFileConfig(); Context::set('config',$config); - $iniPostMaxSize = $this->_changeBytes(ini_get('post_max_size')); - $iniUploadMaxSize = $this->_changeBytes(ini_get('upload_max_filesize')); + $iniPostMaxSize = FileHandler::returnbytes(ini_get('post_max_size')); + $iniUploadMaxSize = FileHandler::returnbytes(ini_get('upload_max_filesize')); $iniMinSize = min($iniPostMaxSize, $iniUploadMaxSize); - Context::set('upload_max_filesize',$this->_changeBytes($iniMinSize / 1048576)); + Context::set('upload_max_filesize', FileHandler::filesize($iniMinSize)); // Set a template file $this->setTemplatePath($this->module_path.'tpl'); $this->setTemplateFile('adminConfig'); diff --git a/modules/file/file.class.php b/modules/file/file.class.php index 93361ca43..a0a6f5ec4 100644 --- a/modules/file/file.class.php +++ b/modules/file/file.class.php @@ -150,25 +150,6 @@ class file extends ModuleObject function recompileCache() { } - - /** - * Change value from human readable to byte unit - * - * @param string $size_str Size string - * @return int The byte value for input - */ - function _changeBytes($size_str) - { - $unit = strtoupper(substr($size_str, -1)); - $size_str = (int)$size_str; - switch ($unit) - { - case 'G': $size_str *= 1024; - case 'M': $size_str *= 1024; - case 'K': $size_str *= 1024; - } - return $size_str; - } } /* End of file file.class.php */ /* Location: ./modules/file/file.class.php */ diff --git a/modules/file/file.model.php b/modules/file/file.model.php index 2e58e312e..fa4bf8242 100644 --- a/modules/file/file.model.php +++ b/modules/file/file.model.php @@ -238,8 +238,8 @@ class fileModel extends file if($logged_info->is_admin == 'Y') { - $iniPostMaxSize = $this->_changeBytes(ini_get('post_max_size')); - $iniUploadMaxSize = $this->_changeBytes(ini_get('upload_max_filesize')); + $iniPostMaxSize = FileHandler::returnbytes(ini_get('post_max_size')); + $iniUploadMaxSize = FileHandler::returnbytes(ini_get('upload_max_filesize')); $size = min($iniPostMaxSize, $iniUploadMaxSize) / 1048576; $file_config->allowed_attach_size = $size; $file_config->allowed_filesize = $size; diff --git a/modules/file/tpl/adminConfig.html b/modules/file/tpl/adminConfig.html index 07fa7dff3..1d4bd8782 100644 --- a/modules/file/tpl/adminConfig.html +++ b/modules/file/tpl/adminConfig.html @@ -34,7 +34,7 @@
- MB/{$upload_max_filesize}MB + MB/{$upload_max_filesize}
From a33a4b3081e4c231cadccfa2a1f76f983467c324 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 13:49:21 +0900 Subject: [PATCH 34/43] =?UTF-8?q?fix=20#1227=20SECISSUE=20-=20XXE=20?= =?UTF-8?q?=EC=B7=A8=EC=95=BD=EC=A0=90=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=20-=20Drupal=EC=9D=98=20=EC=86=8C=EC=8A=A4=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EC=B0=B8=EA=B3=A0=ED=95=98=EC=97=AC=20`Se?= =?UTF-8?q?curity::detectingXEE()`=20=EC=B6=94=EA=B0=80=20=20=20-=20https:?= =?UTF-8?q?//github.com/drupal/drupal/commit/90e884ad0f7f2cf269d953f7d7096?= =?UTF-8?q?6de9fd821ff=20-=20blogapi=20=EC=95=A0=EB=93=9C=EC=98=A8=20?= =?UTF-8?q?=EB=B0=8F=20`Context::=5FsetXmlRpcArgument()`=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=B7=A8=EC=95=BD=EC=A0=90=20=EB=B0=A9=EC=96=B4=20-=20?= =?UTF-8?q?=EC=A0=9C=EB=B3=B4=20:=20=ED=95=9C=EA=B5=AD=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=EB=84=B7=EC=A7=84=ED=9D=A5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/blogapi/blogapi.addon.php | 13 ++++++-- classes/context/Context.class.php | 9 +++++- classes/security/Security.class.php | 49 +++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/addons/blogapi/blogapi.addon.php b/addons/blogapi/blogapi.addon.php index d78bf0eb7..913f3ae4c 100644 --- a/addons/blogapi/blogapi.addon.php +++ b/addons/blogapi/blogapi.addon.php @@ -30,8 +30,10 @@ if($_REQUEST['act'] != 'api') // Read func file require_once(_XE_PATH_ . 'addons/blogapi/blogapi.func.php'); +$xml = $GLOBALS['HTTP_RAW_POST_DATA']; + // If HTTP_RAW_POST_DATA is NULL, Print error message -if(!$GLOBALS['HTTP_RAW_POST_DATA']) +if(!$xml) { $content = getXmlRpcFailure(1, 'Invalid Method Call'); printContent($content); @@ -39,7 +41,14 @@ if(!$GLOBALS['HTTP_RAW_POST_DATA']) // xmlprc parsing // Parse the requested xmlrpc -$xml = new SimpleXMLElement($GLOBALS['HTTP_RAW_POST_DATA']); +if(Security::detectingXEE($xml)) +{ + header("HTTP/1.0 400 Bad Request"); + exit; +} + +if(version_compare(PHP_VERSION, '5.2.11', '<=')) libxml_disable_entity_loader(true); +$xml = new SimpleXMLElement($xml, LIBXML_NONET | LIBXML_NOENT); $method_name = (string)$xml->methodName; $params = $xml->params->param; diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 0cad7d3f5..1ed44854d 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -1240,8 +1240,15 @@ class Context return; } + $xml = $GLOBALS['HTTP_RAW_POST_DATA']; + if(Security::detectingXEE($xml)) + { + header("HTTP/1.0 400 Bad Request"); + exit; + } + $oXml = new XmlParser(); - $xml_obj = $oXml->parse(); + $xml_obj = $oXml->parse($xml); $params = $xml_obj->methodcall->params; unset($params->node_name, $params->attrs, $params->body); diff --git a/classes/security/Security.class.php b/classes/security/Security.class.php index c326d6a34..176ba0ed5 100644 --- a/classes/security/Security.class.php +++ b/classes/security/Security.class.php @@ -175,6 +175,55 @@ class Security return $var; } + /** + * @brief check XML External Entity + * + * @see from drupal. https://github.com/drupal/drupal/commit/90e884ad0f7f2cf269d953f7d70966de9fd821ff + * + * @param string $xml + * @return bool + */ + static function detectingXEE($xml) + { + if(!$xml) return FALSE; + + if(strpos($xml, '/s', '', substr($xml, 0, 100), 1); + $xml = trim(substr_replace($xml, $header, 0, 100)); + if($xml == '') + { + return TRUE; + } + + // Strip DTD. + $header = preg_replace('/^]*+>/i', '', substr($xml, 0, 200), 1); + $xml = trim(substr_replace($xml, $header, 0, 200)); + if($xml == '') + { + return TRUE; + } + + // Confirm the XML now starts with a valid root tag. A root tag can end in [> \t\r\n] + $root_tag = substr($xml, 0, strcspn(substr($xml, 0, 20), "> \t\r\n")); + + // Reject a second DTD. + if(strtoupper($root_tag) == ' Date: Wed, 4 Feb 2015 13:52:42 +0900 Subject: [PATCH 35/43] =?UTF-8?q?fix=20#1230=20SECISSUE=20-=20`xeVirtualRe?= =?UTF-8?q?questUrl`=20parameter=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=9C=20?= =?UTF-8?q?XSS=20=EC=B7=A8=EC=95=BD=EC=A0=90=20-=20=EC=A0=9C=EB=B3=B4=20:?= =?UTF-8?q?=20=ED=95=9C=EA=B5=AD=EC=9D=B8=ED=84=B0=EB=84=B7=EC=A7=84?= =?UTF-8?q?=ED=9D=A5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- classes/display/VirtualXMLDisplayHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/display/VirtualXMLDisplayHandler.php b/classes/display/VirtualXMLDisplayHandler.php index 08e0a6045..aa67ee21d 100644 --- a/classes/display/VirtualXMLDisplayHandler.php +++ b/classes/display/VirtualXMLDisplayHandler.php @@ -14,8 +14,8 @@ class VirtualXMLDisplayHandler $message = $oModule->getMessage(); $redirect_url = $oModule->get('redirect_url'); $request_uri = Context::get('xeRequestURI'); - $request_url = Context::get('xeVirtualRequestUrl'); - $output = new stdClass; + $request_url = Context::getRequestUri(); + $output = new stdClass(); if(substr_compare($request_url, '/', -1) !== 0) { From 0f3140b491a0525b82105ed0adddd8c288b82a66 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 13:53:48 +0900 Subject: [PATCH 36/43] =?UTF-8?q?fix=20#1231=20SECISSUE=20-=20`dispModuleF?= =?UTF-8?q?ileBox`=20act=EC=97=90=20`input`=20parameter=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=9C=20XSS=20=EC=B7=A8=EC=95=BD=EC=A0=90?= =?UTF-8?q?=20-=20=EC=A0=9C=EB=B3=B4=20:=20=ED=95=9C=EA=B5=AD=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=EB=84=B7=EC=A7=84=ED=9D=A5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/module/module.view.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/module/module.view.php b/modules/module/module.view.php index 35dccc2a4..fa987e011 100644 --- a/modules/module/module.view.php +++ b/modules/module/module.view.php @@ -140,6 +140,10 @@ class moduleView extends module if($logged_info->is_admin !='Y' && !$logged_info->is_site_admin) return new Object(-1, 'msg_not_permitted'); $input_name = Context::get('input'); + if(!preg_match('/^[a-z0-9_]+$/i', $input_name)) + { + return new Object(-1, 'msg_invalid_request'); + } if(!$input_name) return new Object(-1, 'msg_not_permitted'); From 15c33963d4388d764154d5fc9af5e5b578b41ef1 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 14:08:28 +0900 Subject: [PATCH 37/43] =?UTF-8?q?fix=20#1216=20SECISSUE=20=EC=9C=84?= =?UTF-8?q?=EC=A0=AF=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=95=98=EB=8A=94=20`blockWidgetCode()`=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20`removeHackTag()`=EC=97=90=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/func.inc.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/config/func.inc.php b/config/func.inc.php index 19355d372..62c8abaa5 100644 --- a/config/func.inc.php +++ b/config/func.inc.php @@ -1101,8 +1101,22 @@ function removeHackTag($content) */ $content = preg_replace_callback('@<(/?)([a-z]+[0-9]?)((?>"[^"]*"|\'[^\']*\'|[^>])*?\b(?:on[a-z]+|data|style|background|href|(?:dyn|low)?src)\s*=[\s\S]*?)(/?)($|>|<)@i', 'removeSrcHack', $content); - // xmp tag ?뺤씤 �??�붽? $content = checkXmpTag($content); + $content = blockWidgetCode($content); + + return $content; +} + +/** + * blocking widget code + * + * @param string $content Taget content + * @return string + **/ +function blockWidgetCode($content) +{ + $content = preg_replace('/(<(?:img|div)(?:[^>]*))(widget)(?:(=([^>]*?)>))/is', '$1blocked-widget$3', $content); + return $content; } From db557b848851a2eb3097d761edad54e1f70e0217 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 14:09:54 +0900 Subject: [PATCH 38/43] =?UTF-8?q?fix=20#1216=20SECISSUE=20-=20content=20?= =?UTF-8?q?=EC=9C=84=EC=A0=AF=EC=97=90=EC=84=9C=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=EB=A5=BC=20=EB=8B=B4=EC=9D=84=20=EB=95=8C=20strip=5Ft?= =?UTF-8?q?ags()=20=EC=A0=81=EC=9A=A9=20-=20RSS=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=EB=A5=BC=20=EA=B0=80=EC=A0=B8=EC=98=AC=20=EB=95=8C=20?= =?UTF-8?q?XSS=20=EC=B7=A8=EC=95=BD=EC=A0=90=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EC=A0=9C=EB=B3=B4=20:=20=ED=95=9C?= =?UTF-8?q?=EA=B5=AD=EC=9D=B8=ED=84=B0=EB=84=B7=EC=A7=84=ED=9D=A5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- widgets/content/content.class.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/widgets/content/content.class.php b/widgets/content/content.class.php index a2b8be3b5..dc85cbfd1 100644 --- a/widgets/content/content.class.php +++ b/widgets/content/content.class.php @@ -811,37 +811,36 @@ class contentItem extends Object } function setLink($url) { - $this->add('url',$url); + $this->add('url', strip_tags($url)); } function setTitle($title) { - $this->add('title',$title); + $this->add('title', strip_tags($title)); } - function setThumbnail($thumbnail) { - $this->add('thumbnail',$thumbnail); + $this->add('thumbnail', $thumbnail); } function setContent($content) { - $this->add('content',$content); + $this->add('content', removeHackTag($content)); } function setRegdate($regdate) { - $this->add('regdate',$regdate); + $this->add('regdate', strip_tags($regdate)); } function setNickName($nick_name) { - $this->add('nick_name',$nick_name); + $this->add('nick_name', strip_tags($nick_name)); } // Save author's homepage url. By misol function setAuthorSite($site_url) { - $this->add('author_site',$site_url); + $this->add('author_site', strip_tags($site_url)); } function setCategory($category) { - $this->add('category',$category); + $this->add('category', strip_tags($category)); } function getBrowserTitle() { From e20859eef779acfbf3e1ee28578bcd8268820900 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 18:49:15 +0900 Subject: [PATCH 39/43] =?UTF-8?q?#1070=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/document/document.model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/document/document.model.php b/modules/document/document.model.php index 7daf0f66a..1b9415997 100644 --- a/modules/document/document.model.php +++ b/modules/document/document.model.php @@ -562,6 +562,7 @@ class documentModel extends document */ function getDocumentCount($module_srl, $search_obj = NULL) { + if(is_null($search_obj)) $search_obj = new stdClass(); $search_obj->module_srl = $module_srl; $output = executeQuery('document.getDocumentCount', $search_obj); From 32f88c15809c65177bcfe455ca3d9fd414ab1943 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 18:58:28 +0900 Subject: [PATCH 40/43] =?UTF-8?q?#1159=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/member/member.model.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/member/member.model.php b/modules/member/member.model.php index 6913775eb..aa9a4781d 100644 --- a/modules/member/member.model.php +++ b/modules/member/member.model.php @@ -139,13 +139,17 @@ class memberModel extends member if($member_srl != $logged_info->member_srl && $logged_info->member_srl) { // Get email config - for($i = 0; $i < count($this->module_config->signupForm); $i++) - if($this->module_config->signupForm[$i]->name == 'email_address') + foreach($this->module_config->signupForm as $field) + { + if($field->name == 'email_address') + { + $email_config = $field; break; - $email_config = $this->module_config->signupForm[$i]; + } + } // Send an email only if email address is public - if($logged_info->is_admin == 'Y' || $email_config->isPublic == 'Y' && $member_info->email_address) + if(($logged_info->is_admin == 'Y' || $email_config->isPublic == 'Y') && $member_info->email_address) { $url = 'mailto:'.htmlspecialchars($member_info->email_address, ENT_COMPAT | ENT_HTML401, 'UTF-8', false); $oMemberController->addMemberPopupMenu($url,'cmd_send_email',$icon_path); From 1969a5ea506e7154d8e545c0bb42d56c6e42a69d Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 19:58:19 +0900 Subject: [PATCH 41/43] MINIFY --- addons/oembed/jquery.oembed.min.js | 4 ++-- addons/oembed/jquery.oembed.min.map | 2 +- modules/editor/tpl/js/uploader.min.js | 2 +- modules/editor/tpl/js/uploader.min.map | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/oembed/jquery.oembed.min.js b/addons/oembed/jquery.oembed.min.js index e14a2a87a..2f2bd153b 100644 --- a/addons/oembed/jquery.oembed.min.js +++ b/addons/oembed/jquery.oembed.min.js @@ -1,3 +1,3 @@ -!function(a){function b(a,c){return c=c?c:"",a?b(--a,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(60*Math.random()))+c):c}function c(a,b){var c,d=a.apiendpoint,e="";d+=d.indexOf("?")<=0?"?":"&",d=d.replace("#","%23"),null===a.maxWidth||"undefined"!=typeof a.params.maxwidth&&null!==a.params.maxwidth||(a.params.maxwidth=a.maxWidth),null===a.maxHeight||"undefined"!=typeof a.params.maxheight&&null!==a.params.maxheight||(a.params.maxheight=a.maxHeight);for(c in a.params)c!=a.callbackparameter&&null!==a.params[c]&&(e+="&"+escape(c)+"="+a.params[c]);return d+="format="+a.format+"&url="+escape(b)+e,"json"!=a.dataType&&(d+="&"+a.callbackparameter+"=?"),d}function d(b,c,d){a("#jqoembeddata").data(c,b.code),g.beforeEmbed.call(d,b),g.onEmbed.call(d,b),g.afterEmbed.call(d,b)}function e(e,f,h){if(void 0!=a("#jqoembeddata").data(f)&&"iframe"!=h.embedtag.tag){var i={code:a("#jqoembeddata").data(f)};d(i,f,e)}else if(h.yql){var j=h.yql.from||"htmlstring",k=h.yql.url?h.yql.url(f):f,l="SELECT * FROM "+j+' WHERE url="'+k+'" and '+(/html/.test(j)?"xpath":"itemPath")+"='"+(h.yql.xpath||"/")+"'";"html"==j&&(l+=" and compat='html5'");var m=a.extend({url:"http://query.yahooapis.com/v1/public/yql",dataType:"jsonp",data:{q:l,format:"json",env:"store://datatables.org/alltableswithkeys",callback:"?"},success:function(b){var c;if(h.yql.xpath&&"//meta|//title|//link"==h.yql.xpath){var g={};null==b.query.results&&(b.query.results={meta:[]});for(var i=0,j=b.query.results.meta.length;j>i;i++){var k=b.query.results.meta[i].name||b.query.results.meta[i].property||null;null!=k&&(g[k.toLowerCase()]=b.query.results.meta[i].content)}g.hasOwnProperty("title")&&g.hasOwnProperty("og:title")||null!=b.query.results.title&&(g.title=b.query.results.title),c=h.yql.datareturn(g)}else c=h.yql.datareturn?h.yql.datareturn(b.query.results):b.query.results.result;if(c!==!1){var l=a.extend({},c);l.code=c,d(l,f,e)}},error:g.onError.call(e,f,h)},g.ajaxOptions||{});a.ajax(m)}else if(h.templateRegex)if(""!==h.embedtag.tag){var n=h.embedtag.flashvars||"",o=h.embedtag.tag||"embed",p=h.embedtag.width||"auto",q=(h.embedtag.nocache||0,h.embedtag.height||"auto"),r=f.replace(h.templateRegex,h.apiendpoint);h.nocache||(r+="&jqoemcache="+b(5)),h.apikey&&(r=r.replace("_APIKEY_",g.apikeys[h.name]));var s=a("<"+o+"/>").attr("src",r).attr("width",p).attr("height",q).attr("allowfullscreen",h.embedtag.allowfullscreen||"true").attr("allowscriptaccess",h.embedtag.allowfullscreen||"always").css("max-height",g.maxHeight||"auto").css("max-width",g.maxWidth||"auto");"embed"==o&&s.attr("type",h.embedtag.type||"application/x-shockwave-flash").attr("flashvars",f.replace(h.templateRegex,n)),"iframe"==o&&s.attr("scrolling",h.embedtag.scrolling||"no").attr("frameborder",h.embedtag.frameborder||"0");var i={code:s};d(i,f,e)}else if(h.apiendpoint)h.apikey&&(h.apiendpoint=h.apiendpoint.replace("_APIKEY_",g.apikeys[h.name])),m=a.extend({url:f.replace(h.templateRegex,h.apiendpoint),dataType:"jsonp",success:function(b){var c=a.extend({},b);c.code=h.templateData(b),c.code&&d(c,f,e)},error:g.onError.call(e,f,h)},g.ajaxOptions||{}),a.ajax(m);else{var i={code:f.replace(h.templateRegex,h.template)};d(i,f,e)}else{var t=c(h,f),m=a.extend({url:t,dataType:h.dataType||"jsonp",success:function(b){var c=a.extend({},b);switch(c.type){case"file":case"photo":c.code=a.fn.oembed.getPhotoCode(f,c);break;case"video":case"rich":c.code=a.fn.oembed.getRichCode(f,c);break;default:c.code=a.fn.oembed.getGenericCode(f,c)}d(c,f,e)},error:g.onError.call(e,f,h)},g.ajaxOptions||{});a.ajax(m)}}function f(a){if(null===a)return null;var b,c={};for(b in a)null!==b&&(c[b.toLowerCase()]=a[b]);return c}a.fn.oembed=function(b,c,d){g=a.extend(!0,a.fn.oembed.defaults,c);var h=["0rz.tw","1link.in","1url.com","2.gp","2big.at","2tu.us","3.ly","307.to","4ms.me","4sq.com","4url.cc","6url.com","7.ly","a.gg","a.nf","aa.cx","abcurl.net","ad.vu","adf.ly","adjix.com","afx.cc","all.fuseurl.com","alturl.com","amzn.to","ar.gy","arst.ch","atu.ca","azc.cc","b23.ru","b2l.me","bacn.me","bcool.bz","binged.it","bit.ly","bizj.us","bloat.me","bravo.ly","bsa.ly","budurl.com","canurl.com","chilp.it","chzb.gr","cl.lk","cl.ly","clck.ru","cli.gs","cliccami.info","clickthru.ca","clop.in","conta.cc","cort.as","cot.ag","crks.me","ctvr.us","cutt.us","dai.ly","decenturl.com","dfl8.me","digbig.com","http://digg.com/[^/]+$","disq.us","dld.bz","dlvr.it","do.my","doiop.com","dopen.us","easyuri.com","easyurl.net","eepurl.com","eweri.com","fa.by","fav.me","fb.me","fbshare.me","ff.im","fff.to","fire.to","firsturl.de","firsturl.net","flic.kr","flq.us","fly2.ws","fon.gs","freak.to","fuseurl.com","fuzzy.to","fwd4.me","fwib.net","g.ro.lt","gizmo.do","gl.am","go.9nl.com","go.ign.com","go.usa.gov","goo.gl","goshrink.com","gurl.es","hex.io","hiderefer.com","hmm.ph","href.in","hsblinks.com","htxt.it","huff.to","hulu.com","hurl.me","hurl.ws","icanhaz.com","idek.net","ilix.in","is.gd","its.my","ix.lt","j.mp","jijr.com","kl.am","klck.me","korta.nu","krunchd.com","l9k.net","lat.ms","liip.to","liltext.com","linkbee.com","linkbun.ch","liurl.cn","ln-s.net","ln-s.ru","lnk.gd","lnk.ms","lnkd.in","lnkurl.com","lru.jp","lt.tl","lurl.no","macte.ch","mash.to","merky.de","migre.me","miniurl.com","minurl.fr","mke.me","moby.to","moourl.com","mrte.ch","myloc.me","myurl.in","n.pr","nbc.co","nblo.gs","nn.nf","not.my","notlong.com","nsfw.in","nutshellurl.com","nxy.in","nyti.ms","o-x.fr","oc1.us","om.ly","omf.gd","omoikane.net","on.cnn.com","on.mktw.net","onforb.es","orz.se","ow.ly","ping.fm","pli.gs","pnt.me","politi.co","post.ly","pp.gg","profile.to","ptiturl.com","pub.vitrue.com","qlnk.net","qte.me","qu.tc","qy.fi","r.ebay.com","r.im","rb6.me","read.bi","readthis.ca","reallytinyurl.com","redir.ec","redirects.ca","redirx.com","retwt.me","ri.ms","rickroll.it","riz.gd","rt.nu","ru.ly","rubyurl.com","rurl.org","rww.tw","s4c.in","s7y.us","safe.mn","sameurl.com","sdut.us","shar.es","shink.de","shorl.com","short.ie","short.to","shortlinks.co.uk","shorturl.com","shout.to","show.my","shrinkify.com","shrinkr.com","shrt.fr","shrt.st","shrten.com","shrunkin.com","simurl.com","slate.me","smallr.com","smsh.me","smurl.name","sn.im","snipr.com","snipurl.com","snurl.com","sp2.ro","spedr.com","srnk.net","srs.li","starturl.com","stks.co","su.pr","surl.co.uk","surl.hu","t.cn","t.co","t.lh.com","ta.gd","tbd.ly","tcrn.ch","tgr.me","tgr.ph","tighturl.com","tiniuri.com","tiny.cc","tiny.ly","tiny.pl","tinylink.in","tinyuri.ca","tinyurl.com","tk.","tl.gd","tmi.me","tnij.org","tnw.to","tny.com","to.ly","togoto.us","totc.us","toysr.us","tpm.ly","tr.im","tra.kz","trunc.it","twhub.com","twirl.at","twitclicks.com","twitterurl.net","twitterurl.org","twiturl.de","twurl.cc","twurl.nl","u.mavrev.com","u.nu","u76.org","ub0.cc","ulu.lu","updating.me","ur1.ca","url.az","url.co.uk","url.ie","url360.me","url4.eu","urlborg.com","urlbrief.com","urlcover.com","urlcut.com","urlenco.de","urli.nl","urls.im","urlshorteningservicefortwitter.com","urlx.ie","urlzen.com","usat.ly","use.my","vb.ly","vevo.ly","vgn.am","vl.am","vm.lc","w55.de","wapo.st","wapurl.co.uk","wipi.es","wp.me","x.vu","xr.com","xrl.in","xrl.us","xurl.es","xurl.jp","y.ahoo.it","yatuc.com","ye.pe","yep.it","yfrog.com","yhoo.it","yiyd.com","youtu.be","yuarel.com","z0p.de","zi.ma","zi.mu","zipmyurl.com","zud.me","zurl.ws","zz.gd","zzang.kr","›.ws","✩.ws","✿.ws","❥.ws","➔.ws","➞.ws","➡.ws","➨.ws","➯.ws","➹.ws","➽.ws"];return 0===a("#jqoembeddata").length&&a('').appendTo("body"),this.each(function(){var c,i=a(this),j=!b||b.indexOf("http://")&&b.indexOf("https://")?i.attr("href"):b;if(d?g.onEmbed=d:g.onEmbed||(g.onEmbed=function(b){a.fn.oembed.insertCode(this,g.embedMethod,b)}),null!==j&&void 0!==j){for(var k=0,l=h.length;l>k;k++){var m=new RegExp("://"+h[k]+"/","i");if(null!==j.match(m)){var n=a.extend({url:"http://api.longurl.org/v2/expand",dataType:"jsonp",data:{url:j,format:"json"},success:function(b){j=b["long-url"],c=a.fn.oembed.getOEmbedProvider(b["long-url"]),null!==c?(c.params=f(g[c.name])||{},c.maxWidth=g.maxWidth,c.maxHeight=g.maxHeight,e(i,j,c)):g.onProviderNotFound.call(i,j)}},g.ajaxOptions||{});return a.ajax(n),i}}c=a.fn.oembed.getOEmbedProvider(j),null!==c?(c.params=f(g[c.name])||{},c.maxWidth=g.maxWidth,c.maxHeight=g.maxHeight,e(i,j,c)):g.onProviderNotFound.call(i,j)}return i})};var g;a.fn.oembed.defaults={maxWidth:null,maxHeight:null,includeHandle:!0,embedMethod:"auto",onProviderNotFound:function(){},beforeEmbed:function(){},afterEmbed:function(){},onEmbed:!1,onError:function(){},ajaxOptions:{}},a.fn.oembed.insertCode=function(b,c,d){if(null!==d)switch("auto"==c&&null!==b.attr("href")?c="append":"auto"==c&&(c="replace"),c){case"replace":b.replaceWith(d.code);break;case"fill":b.html(d.code);break;case"append":b.wrap('
');var e=b.parent();g.includeHandle&&a('').insertBefore(b).click(function(){var b=encodeURIComponent(a(this).text());a(this).html("%E2%86%91"==b?"↓":"↑"),a(this).parent().children().last().toggle()}),e.append("
");try{d.code.clone().appendTo(e)}catch(f){e.append(d.code)}if(g.maxWidth){var h=e.parent().width();if(h'+d+'
';else if(b.thumbnail_url){var e=b.thumbnail_url.replace("_s","_b");c='
'+d+'
'}else c="
Error loading this picture
";return b.html&&(c+="
"+b.html+"
"),c},a.fn.oembed.getRichCode=function(a,b){var c=b.html;return c},a.fn.oembed.getGenericCode=function(a,b){var c=null!==b.title?b.title:a,d="";return b.html&&(d+='
'+c+"
"+jQuery(b.html).text().substring(0,200)+'... more
'),d},a.fn.oembed.getOEmbedProvider=function(b){for(var c=0;cd;d++){var f=new RegExp(a.fn.oembed.providers[c].urlschemes[d],"i");if(null!==b.match(f))return a.fn.oembed.providers[c]}return null},a.fn.oembed.OEmbedProvider=function(a,b,c,d,e){this.name=a,this.type=b,this.urlschemes=c,this.apiendpoint=d,this.maxWidth=500,this.maxHeight=400,e=e||{},e.useYQL&&(e.yql="xml"==e.useYQL?{xpath:"//oembed/html",from:"xml",apiendpoint:this.apiendpoint,url:function(a){return this.apiendpoint+"?format=xml&url="+a},datareturn:function(a){return a.html.replace(/.*\[CDATA\[(.*)\]\]>$/,"$1")||""}}:{from:"json",apiendpoint:this.apiendpoint,url:function(a){return this.apiendpoint+"?format=json&url="+a},datareturn:function(a){return"video"!=a.json.type&&(a.json.url||a.json.thumbnail_url)?'':a.json.html||""}},this.apiendpoint=null);for(var f in e)this[f]=e[f];this.format=this.format||"json",this.callbackparameter=this.callbackparameter||"callback",this.embedtag=this.embedtag||{tag:""}},a.fn.updateOEmbedProvider=function(b,c,d,e,f){for(var g=0;g':!1}}}),new a.fn.oembed.OEmbedProvider("deviantart","photo",["deviantart.com/.+","fav.me/.+","deviantart.com/.+"],"http://backend.deviantart.com/oembed",{format:"jsonp"}),new a.fn.oembed.OEmbedProvider("skitch","photo",["skitch.com/.+"],null,{yql:{xpath:"json",from:"json",url:function(a){return"http://skitch.com/oembed/?format=json&url="+a},datareturn:function(b){return a.fn.oembed.getPhotoCode(b.json.url,b.json)}}}),new a.fn.oembed.OEmbedProvider("mobypicture","photo",["mobypicture.com/user/.+/view/.+","moby.to/.+"],"http://api.mobypicture.com/oEmbed"),new a.fn.oembed.OEmbedProvider("flickr","photo",["flickr\\.com/photos/.+"],"http://flickr.com/services/oembed",{callbackparameter:"jsoncallback"}),new a.fn.oembed.OEmbedProvider("photobucket","photo",["photobucket\\.com/(albums|groups)/.+"],"http://photobucket.com/oembed/"),new a.fn.oembed.OEmbedProvider("instagram","photo",["instagr\\.?am(\\.com)?/.+"],"http://api.instagram.com/oembed"),new a.fn.oembed.OEmbedProvider("SmugMug","photo",["smugmug.com/[-.\\w@]+/.+"],"http://api.smugmug.com/services/oembed/"),new a.fn.oembed.OEmbedProvider("dribbble","photo",["dribbble.com/shots/.+"],"http://api.dribbble.com/shots/$1?callback=?",{templateRegex:/.*shots\/([\d]+).*/,templateData:function(a){return a.image_teaser_url?'':!1}}),new a.fn.oembed.OEmbedProvider("chart.ly","photo",["chart\\.ly/[a-z0-9]{6,8}"],"http://chart.ly/uploads/large_$1.png",{templateRegex:/.*ly\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("circuitlab","photo",["circuitlab.com/circuit/.+"],"https://www.circuitlab.com/circuit/$1/screenshot/540x405/",{templateRegex:/.*circuit\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("23hq","photo",["23hq.com/[-.\\w@]+/photo/.+"],"http://www.23hq.com/23/oembed",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("img.ly","photo",["img\\.ly/.+"],"http://img.ly/show/thumb/$1",{templateRegex:/.*ly\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("twitgoo.com","photo",["twitgoo\\.com/.+"],"http://twitgoo.com/show/thumb/$1",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("imgur.com","photo",["imgur\\.com/gallery/.+"],"http://imgur.com/$1l.jpg",{templateRegex:/.*gallery\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("visual.ly","rich",["visual\\.ly/.+"],null,{yql:{xpath:"//a[@id=\\'gc_article_graphic_image\\']/img",from:"htmlstring"}}),new a.fn.oembed.OEmbedProvider("gravtar","photo",["mailto:.+"],null,{templateRegex:/mailto:([^\/]+).*/,template:function(a,b){return'on Gravtar'}}),new a.fn.oembed.OEmbedProvider("twitter","rich",["twitter.com/.+"],"https://api.twitter.com/1/statuses/oembed.json"),new a.fn.oembed.OEmbedProvider("gmep","rich",["gmep.imeducate.com/.*","gmep.org/.*"],"http://gmep.org/oembed.json"),new a.fn.oembed.OEmbedProvider("urtak","rich",["urtak.com/(u|clr)/.+"],"http://oembed.urtak.com/1/oembed"),new a.fn.oembed.OEmbedProvider("cacoo","rich",["cacoo.com/.+"],"http://cacoo.com/oembed.json"),new a.fn.oembed.OEmbedProvider("dailymile","rich",["dailymile.com/people/.*/entries/.*"],"http://api.dailymile.com/oembed"),new a.fn.oembed.OEmbedProvider("dipity","rich",["dipity.com/timeline/.+"],"http://www.dipity.com/oembed/timeline/",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("sketchfab","rich",["sketchfab.com/show/.+"],"http://sketchfab.com/oembed",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("speakerdeck","rich",["speakerdeck.com/.+"],"http://speakerdeck.com/oembed.json",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("popplet","rich",["popplet.com/app/.*"],"http://popplet.com/app/Popplet_Alpha.swf?page_id=$1&em=1",{templateRegex:/.*#\/([^\/]+).*/,embedtag:{width:460,height:460}}),new a.fn.oembed.OEmbedProvider("pearltrees","rich",["pearltrees.com/.*"],"http://cdn.pearltrees.com/s/embed/getApp?",{templateRegex:/.*N-f=1_(\d+).*N-p=(\d+).*/,embedtag:{width:460,height:460,flashvars:"lang=en_US&embedId=pt-embed-$1-693&treeId=$1&pearlId=$2&treeTitle=Diagrams%2FVisualization&site=www.pearltrees.com%2FF"}}),new a.fn.oembed.OEmbedProvider("prezi","rich",["prezi.com/.*"],"http://prezi.com/bin/preziloader.swf?",{templateRegex:/.*com\/([^\/]+)\/.*/,embedtag:{width:550,height:400,flashvars:"prezi_id=$1&lock_to_path=0&color=ffffff&autoplay=no&autohide_ctrls=0"}}),new a.fn.oembed.OEmbedProvider("tourwrist","rich",["tourwrist.com/tours/.+"],null,{templateRegex:/.*tours.([\d]+).*/,template:function(a,b){return setTimeout(function(){loadEmbeds&&loadEmbeds()},2e3),"
"}}),new a.fn.oembed.OEmbedProvider("meetup","rich",["meetup\\.(com|ps)/.+"],"http://api.meetup.com/oembed"),new a.fn.oembed.OEmbedProvider("ebay","rich",["ebay\\.*"],"http://togo.ebay.com/togo/togo.swf?2008013100",{templateRegex:/.*\/([^\/]+)\/(\d{10,13}).*/,embedtag:{width:355,height:300,flashvars:"base=http://togo.ebay.com/togo/&lang=en-us&mode=normal&itemid=$2&query=$1"}}),new a.fn.oembed.OEmbedProvider("wikipedia","rich",["wikipedia.org/wiki/.+"],"http://$1.wikipedia.org/w/api.php?action=parse&page=$2&format=json§ion=0&callback=?",{templateRegex:/.*\/\/([\w]+).*\/wiki\/([^\/]+).*/,templateData:function(a){if(!a.parse)return!1;var b=a.parse.text["*"].replace(/href="\/wiki/g,'href="http://en.wikipedia.org/wiki');return'
'+a.parse.displaytitle+"
"+jQuery(b).text().substring(0,200)+"...
"}}),new a.fn.oembed.OEmbedProvider("imdb","rich",["imdb.com/title/.+"],"http://www.imdbapi.com/?i=$1&callback=?",{templateRegex:/.*\/title\/([^\/]+).*/,templateData:function(a){return a.Title?'

'+a.Title+" ("+a.Year+")

Rating: "+a.imdbRating+"
Genre: "+a.Genre+"
Starring: "+a.Actors+'

'+a.Plot+"
":!1}}),new a.fn.oembed.OEmbedProvider("livejournal","rich",["livejournal.com/"],"http://ljpic.seacrow.com/json/$2$4?jsonp=?",{templateRegex:/(http:\/\/(((?!users).)+)\.livejournal\.com|.*users\.livejournal\.com\/([^\/]+)).*/,templateData:function(a){return a.username?'
[info]'+a.username+"
"+a.name+"
":!1}}),new a.fn.oembed.OEmbedProvider("circuitbee","rich",["circuitbee\\.com/circuit/view/.+"],"http://c.circuitbee.com/build/r/schematic-embed.html?id=$1",{templateRegex:/.*circuit\/view\/(\d+).*/,embedtag:{tag:"iframe",width:"500",height:"350"}}),new a.fn.oembed.OEmbedProvider("googlecalendar","rich",["www.google.com/calendar/embed?.+"],"$1",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"800",height:"600"}}),new a.fn.oembed.OEmbedProvider("jsfiddle","rich",["jsfiddle.net/[^/]+/?"],"http://jsfiddle.net/$1/embedded/result,js,resources,html,css/?",{templateRegex:/.*net\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"300"}}),new a.fn.oembed.OEmbedProvider("jsbin","rich",["jsbin.com/.+"],"http://jsbin.com/$1/?",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"300"}}),new a.fn.oembed.OEmbedProvider("jotform","rich",["form.jotform.co/form/.+"],"$1?",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"100%",height:"507"}}),new a.fn.oembed.OEmbedProvider("reelapp","rich",["reelapp\\.com/.+"],"http://www.reelapp.com/$1/embed",{templateRegex:/.*com\/(\S{6}).*/,embedtag:{tag:"iframe",width:"400",height:"338"}}),new a.fn.oembed.OEmbedProvider("linkedin","rich",["linkedin.com/pub/.+"],"https://www.linkedin.com/cws/member/public_profile?public_profile_url=$1&format=inline&isFramed=true",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"368px",height:"auto"}}),new a.fn.oembed.OEmbedProvider("timetoast","rich",["timetoast.com/timelines/[0-9]+"],"http://www.timetoast.com/flash/TimelineViewer.swf?passedTimelines=$1",{templateRegex:/.*timelines\/([0-9]*)/,embedtag:{width:550,height:400,nocache:1}}),new a.fn.oembed.OEmbedProvider("pastebin","rich",["pastebin\\.com/[\\S]{8}"],"http://pastebin.com/embed_iframe.php?i=$1",{templateRegex:/.*\/(\S{8}).*/,embedtag:{tag:"iframe",width:"100%",height:"auto"}}),new a.fn.oembed.OEmbedProvider("mixlr","rich",["mixlr.com/.+"],"http://mixlr.com/embed/$1?autoplay=ae",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"auto"}}),new a.fn.oembed.OEmbedProvider("pastie","rich",["pastie\\.org/pastes/.+"],null,{yql:{xpath:'//pre[@class="textmate-source"]'}}),new a.fn.oembed.OEmbedProvider("github","rich",["gist.github.com/.+"],"https://github.com/api/oembed"),new a.fn.oembed.OEmbedProvider("github","rich",["github.com/[-.\\w@]+/[-.\\w@]+"],"https://api.github.com/repos/$1/$2?callback=?",{templateRegex:/.*\/([^\/]+)\/([^\/]+).*/,templateData:function(a){return a.data.html_url?'

'+a.data.name+'

'+a.data.description+'

Last updated: '+a.data.pushed_at+"

":!1}}),new a.fn.oembed.OEmbedProvider("facebook","rich",["facebook.com/(people/[^\\/]+/\\d+|[^\\/]+$)"],"https://graph.facebook.com/$2$3/?callback=?",{templateRegex:/.*facebook.com\/(people\/[^\/]+\/(\d+).*|([^\/]+$))/,templateData:function(a){if(!a.id)return!1;var b='
facebook ';return b+=a.from?''+a.from.name+"":a.link?''+a.name+"":a.username?''+a.name+"":''+a.name+"",b+='
',b+=a.picture?'':'',a.from&&(b+=''+a.name+""),a.founded&&(b+="Founded: "+a.founded+"
"),a.category&&(b+="Category: "+a.category+"
"),a.website&&(b+='Website: '+a.website+"
"),a.gender&&(b+="Gender: "+a.gender+"
"),a.description&&(b+=a.description+"
"),b+="
"}}),new a.fn.oembed.OEmbedProvider("stackoverflow","rich",["stackoverflow.com/questions/[\\d]+"],"http://api.stackoverflow.com/1.1/questions/$1?body=true&jsonp=?",{templateRegex:/.*questions\/([\d]+).*/,templateData:function(b){if(!b.questions)return!1;var c=b.questions[0],d=a(c.body).text(),e='
'+(c.up_vote_count-c.down_vote_count)+'
vote(s)
'+c.answer_count+'answer
'+c.view_count+' view(s)

'+c.title+'

'+d.substring(0,100)+'...
';for(i in c.tags)e+='";return e+='
" -}}),new a.fn.oembed.OEmbedProvider("wordpress","rich",["wordpress\\.com/.+","blogs\\.cnn\\.com/.+","techcrunch\\.com/.+","wp\\.me/.+"],"http://public-api.wordpress.com/oembed/1.0/?for=jquery-oembed-all"),new a.fn.oembed.OEmbedProvider("screenr","rich",["screenr.com"],"http://www.screenr.com/embed/$1",{templateRegex:/.*\/([^\/]+).*/,embedtag:{tag:"iframe",width:"650",height:396}}),new a.fn.oembed.OEmbedProvider("gigpans","rich",["gigapan\\.org/[-.\\w@]+/\\d+"],"http://gigapan.org/gigapans/$1/options/nosnapshots/iframe/flash.html",{templateRegex:/.*\/(\d+)\/?.*/,embedtag:{tag:"iframe",width:"100%",height:400}}),new a.fn.oembed.OEmbedProvider("scribd","rich",["scribd\\.com/.+"],"http://www.scribd.com/embeds/$1/content?start_page=1&view_mode=list",{templateRegex:/.*doc\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:600}}),new a.fn.oembed.OEmbedProvider("kickstarter","rich",["kickstarter\\.com/projects/.+"],"$1/widget/card.html",{templateRegex:/([^\?]+).*/,embedtag:{tag:"iframe",width:"220",height:380}}),new a.fn.oembed.OEmbedProvider("amazon","rich",["amzn.com/B+","amazon.com.*/(B\\S+)($|\\/.*)"],"http://rcm.amazon.com/e/cm?t=_APIKEY_&o=1&p=8&l=as1&asins=$1&ref=qf_br_asin_til&fc1=000000&IS2=1<1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr",{apikey:!0,templateRegex:/.*\/(B[0-9A-Z]+)($|\/.*)/,embedtag:{tag:"iframe",width:"120px",height:"240px"}}),new a.fn.oembed.OEmbedProvider("slideshare","rich",["slideshare.net"],"http://www.slideshare.net/api/oembed/2",{format:"jsonp"}),new a.fn.oembed.OEmbedProvider("roomsharejp","rich",["roomshare\\.jp/(en/)?post/.*"],"http://roomshare.jp/oembed.json"),new a.fn.oembed.OEmbedProvider("lanyard","rich",["lanyrd.com/\\d+/.+"],null,{yql:{xpath:'(//div[@class="primary"])[1]',from:"htmlstring",datareturn:function(a){return a.result?'
'+a.result+"
":!1}}}),new a.fn.oembed.OEmbedProvider("asciiartfarts","rich",["asciiartfarts.com/\\d+.html"],null,{yql:{xpath:"//pre/font",from:"htmlstring",datareturn:function(a){return a.result?'
'+a.result+"
":!1}}})]}(jQuery),String.prototype.md5=function(){var a=function(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c},b=function(a,b){return a<>>32-b},c=function(c,d,e,f,g,h){return a(b(a(a(d,c),a(f,h)),g),e)},d=function(a,b,d,e,f,g,h){return c(b&d|~b&e,a,b,f,g,h)},e=function(a,b,d,e,f,g,h){return c(b&e|d&~e,a,b,f,g,h)},f=function(a,b,d,e,f,g,h){return c(b^d^e,a,b,f,g,h)},g=function(a,b,d,e,f,g,h){return c(d^(b|~e),a,b,f,g,h)},h=function(b){var c,h,i,j,k,l=b.length,m=1732584193,n=-271733879,o=-1732584194,p=271733878;for(k=0;l>k;k+=16)c=m,h=n,i=o,j=p,m=d(m,n,o,p,b[k+0],7,-680876936),p=d(p,m,n,o,b[k+1],12,-389564586),o=d(o,p,m,n,b[k+2],17,606105819),n=d(n,o,p,m,b[k+3],22,-1044525330),m=d(m,n,o,p,b[k+4],7,-176418897),p=d(p,m,n,o,b[k+5],12,1200080426),o=d(o,p,m,n,b[k+6],17,-1473231341),n=d(n,o,p,m,b[k+7],22,-45705983),m=d(m,n,o,p,b[k+8],7,1770035416),p=d(p,m,n,o,b[k+9],12,-1958414417),o=d(o,p,m,n,b[k+10],17,-42063),n=d(n,o,p,m,b[k+11],22,-1990404162),m=d(m,n,o,p,b[k+12],7,1804603682),p=d(p,m,n,o,b[k+13],12,-40341101),o=d(o,p,m,n,b[k+14],17,-1502002290),n=d(n,o,p,m,b[k+15],22,1236535329),m=e(m,n,o,p,b[k+1],5,-165796510),p=e(p,m,n,o,b[k+6],9,-1069501632),o=e(o,p,m,n,b[k+11],14,643717713),n=e(n,o,p,m,b[k+0],20,-373897302),m=e(m,n,o,p,b[k+5],5,-701558691),p=e(p,m,n,o,b[k+10],9,38016083),o=e(o,p,m,n,b[k+15],14,-660478335),n=e(n,o,p,m,b[k+4],20,-405537848),m=e(m,n,o,p,b[k+9],5,568446438),p=e(p,m,n,o,b[k+14],9,-1019803690),o=e(o,p,m,n,b[k+3],14,-187363961),n=e(n,o,p,m,b[k+8],20,1163531501),m=e(m,n,o,p,b[k+13],5,-1444681467),p=e(p,m,n,o,b[k+2],9,-51403784),o=e(o,p,m,n,b[k+7],14,1735328473),n=e(n,o,p,m,b[k+12],20,-1926607734),m=f(m,n,o,p,b[k+5],4,-378558),p=f(p,m,n,o,b[k+8],11,-2022574463),o=f(o,p,m,n,b[k+11],16,1839030562),n=f(n,o,p,m,b[k+14],23,-35309556),m=f(m,n,o,p,b[k+1],4,-1530992060),p=f(p,m,n,o,b[k+4],11,1272893353),o=f(o,p,m,n,b[k+7],16,-155497632),n=f(n,o,p,m,b[k+10],23,-1094730640),m=f(m,n,o,p,b[k+13],4,681279174),p=f(p,m,n,o,b[k+0],11,-358537222),o=f(o,p,m,n,b[k+3],16,-722521979),n=f(n,o,p,m,b[k+6],23,76029189),m=f(m,n,o,p,b[k+9],4,-640364487),p=f(p,m,n,o,b[k+12],11,-421815835),o=f(o,p,m,n,b[k+15],16,530742520),n=f(n,o,p,m,b[k+2],23,-995338651),m=g(m,n,o,p,b[k+0],6,-198630844),p=g(p,m,n,o,b[k+7],10,1126891415),o=g(o,p,m,n,b[k+14],15,-1416354905),n=g(n,o,p,m,b[k+5],21,-57434055),m=g(m,n,o,p,b[k+12],6,1700485571),p=g(p,m,n,o,b[k+3],10,-1894986606),o=g(o,p,m,n,b[k+10],15,-1051523),n=g(n,o,p,m,b[k+1],21,-2054922799),m=g(m,n,o,p,b[k+8],6,1873313359),p=g(p,m,n,o,b[k+15],10,-30611744),o=g(o,p,m,n,b[k+6],15,-1560198380),n=g(n,o,p,m,b[k+13],21,1309151649),m=g(m,n,o,p,b[k+4],6,-145523070),p=g(p,m,n,o,b[k+11],10,-1120210379),o=g(o,p,m,n,b[k+2],15,718787259),n=g(n,o,p,m,b[k+9],21,-343485551),m=a(m,c),n=a(n,h),o=a(o,i),p=a(p,j);return[m,n,o,p]},i=function(a){var b,c="0123456789abcdef",d="",e=4*a.length;for(b=0;e>b;b++)d+=c.charAt(a[b>>2]>>b%4*8+4&15)+c.charAt(a[b>>2]>>b%4*8&15);return d},j=function(a){var b,c,d=(a.length+8>>6)+1,e=[],f=16*d,g=a.length;for(b=0;f>b;b++)e.push(0);for(c=0;g>c;c++)e[c>>2]|=(255&a.charCodeAt(c))<>2]|=128<i;i++){var k=b.query.results.meta[i].name||b.query.results.meta[i].property||null;null!=k&&(g[k.toLowerCase()]=b.query.results.meta[i].content)}g.hasOwnProperty("title")&&g.hasOwnProperty("og:title")||null!=b.query.results.title&&(g.title=b.query.results.title),c=h.yql.datareturn(g)}else c=h.yql.datareturn?h.yql.datareturn(b.query.results):b.query.results.result;if(c!==!1){var l=a.extend({},c);l.code=c,d(l,f,e)}},error:g.onError.call(e,f,h)},g.ajaxOptions||{});a.ajax(m)}else if(h.templateRegex)if(""!==h.embedtag.tag){var n=h.embedtag.flashvars||"",o=h.embedtag.tag||"embed",p=h.embedtag.width||"auto",q=(h.embedtag.nocache||0,h.embedtag.height||"auto"),r=f.replace(h.templateRegex,h.apiendpoint);h.nocache||(r+="&jqoemcache="+b(5)),h.apikey&&(r=r.replace("_APIKEY_",g.apikeys[h.name]));var s=a("<"+o+"/>").attr("src",r).attr("width",p).attr("height",q).attr("allowfullscreen",h.embedtag.allowfullscreen||"true").attr("allowscriptaccess",h.embedtag.allowfullscreen||"always").css("max-height",g.maxHeight||"auto").css("max-width",g.maxWidth||"auto");"embed"==o&&s.attr("type",h.embedtag.type||"application/x-shockwave-flash").attr("flashvars",f.replace(h.templateRegex,n)),"iframe"==o&&s.attr("scrolling",h.embedtag.scrolling||"no").attr("frameborder",h.embedtag.frameborder||"0");var i={code:s};d(i,f,e)}else if(h.apiendpoint)h.apikey&&(h.apiendpoint=h.apiendpoint.replace("_APIKEY_",g.apikeys[h.name])),m=a.extend({url:f.replace(h.templateRegex,h.apiendpoint),dataType:"jsonp",success:function(b){var c=a.extend({},b);c.code=h.templateData(b),c.code&&d(c,f,e)},error:g.onError.call(e,f,h)},g.ajaxOptions||{}),a.ajax(m);else{var i={code:f.replace(h.templateRegex,h.template)};d(i,f,e)}else{var t=c(h,f),m=a.extend({url:t,dataType:h.dataType||"jsonp",success:function(b){var c=a.extend({},b);switch(c.type){case"file":case"photo":c.code=a.fn.oembed.getPhotoCode(f,c);break;case"video":case"rich":c.code=a.fn.oembed.getRichCode(f,c);break;default:c.code=a.fn.oembed.getGenericCode(f,c)}d(c,f,e)},error:g.onError.call(e,f,h)},g.ajaxOptions||{});a.ajax(m)}}function f(a){if(null===a)return null;var b,c={};for(b in a)null!==b&&(c[b.toLowerCase()]=a[b]);return c}a.fn.oembed=function(b,c,d){g=a.extend(!0,a.fn.oembed.defaults,c);var h=["0rz.tw","1link.in","1url.com","2.gp","2big.at","2tu.us","3.ly","307.to","4ms.me","4sq.com","4url.cc","6url.com","7.ly","a.gg","a.nf","aa.cx","abcurl.net","ad.vu","adf.ly","adjix.com","afx.cc","all.fuseurl.com","alturl.com","amzn.to","ar.gy","arst.ch","atu.ca","azc.cc","b23.ru","b2l.me","bacn.me","bcool.bz","binged.it","bit.ly","bizj.us","bloat.me","bravo.ly","bsa.ly","budurl.com","canurl.com","chilp.it","chzb.gr","cl.lk","cl.ly","clck.ru","cli.gs","cliccami.info","clickthru.ca","clop.in","conta.cc","cort.as","cot.ag","crks.me","ctvr.us","cutt.us","dai.ly","decenturl.com","dfl8.me","digbig.com","http://digg.com/[^/]+$","disq.us","dld.bz","dlvr.it","do.my","doiop.com","dopen.us","easyuri.com","easyurl.net","eepurl.com","eweri.com","fa.by","fav.me","fb.me","fbshare.me","ff.im","fff.to","fire.to","firsturl.de","firsturl.net","flic.kr","flq.us","fly2.ws","fon.gs","freak.to","fuseurl.com","fuzzy.to","fwd4.me","fwib.net","g.ro.lt","gizmo.do","gl.am","go.9nl.com","go.ign.com","go.usa.gov","goo.gl","goshrink.com","gurl.es","hex.io","hiderefer.com","hmm.ph","href.in","hsblinks.com","htxt.it","huff.to","hulu.com","hurl.me","hurl.ws","icanhaz.com","idek.net","ilix.in","is.gd","its.my","ix.lt","j.mp","jijr.com","kl.am","klck.me","korta.nu","krunchd.com","l9k.net","lat.ms","liip.to","liltext.com","linkbee.com","linkbun.ch","liurl.cn","ln-s.net","ln-s.ru","lnk.gd","lnk.ms","lnkd.in","lnkurl.com","lru.jp","lt.tl","lurl.no","macte.ch","mash.to","merky.de","migre.me","miniurl.com","minurl.fr","mke.me","moby.to","moourl.com","mrte.ch","myloc.me","myurl.in","n.pr","nbc.co","nblo.gs","nn.nf","not.my","notlong.com","nsfw.in","nutshellurl.com","nxy.in","nyti.ms","o-x.fr","oc1.us","om.ly","omf.gd","omoikane.net","on.cnn.com","on.mktw.net","onforb.es","orz.se","ow.ly","ping.fm","pli.gs","pnt.me","politi.co","post.ly","pp.gg","profile.to","ptiturl.com","pub.vitrue.com","qlnk.net","qte.me","qu.tc","qy.fi","r.ebay.com","r.im","rb6.me","read.bi","readthis.ca","reallytinyurl.com","redir.ec","redirects.ca","redirx.com","retwt.me","ri.ms","rickroll.it","riz.gd","rt.nu","ru.ly","rubyurl.com","rurl.org","rww.tw","s4c.in","s7y.us","safe.mn","sameurl.com","sdut.us","shar.es","shink.de","shorl.com","short.ie","short.to","shortlinks.co.uk","shorturl.com","shout.to","show.my","shrinkify.com","shrinkr.com","shrt.fr","shrt.st","shrten.com","shrunkin.com","simurl.com","slate.me","smallr.com","smsh.me","smurl.name","sn.im","snipr.com","snipurl.com","snurl.com","sp2.ro","spedr.com","srnk.net","srs.li","starturl.com","stks.co","su.pr","surl.co.uk","surl.hu","t.cn","t.co","t.lh.com","ta.gd","tbd.ly","tcrn.ch","tgr.me","tgr.ph","tighturl.com","tiniuri.com","tiny.cc","tiny.ly","tiny.pl","tinylink.in","tinyuri.ca","tinyurl.com","tk.","tl.gd","tmi.me","tnij.org","tnw.to","tny.com","to.ly","togoto.us","totc.us","toysr.us","tpm.ly","tr.im","tra.kz","trunc.it","twhub.com","twirl.at","twitclicks.com","twitterurl.net","twitterurl.org","twiturl.de","twurl.cc","twurl.nl","u.mavrev.com","u.nu","u76.org","ub0.cc","ulu.lu","updating.me","ur1.ca","url.az","url.co.uk","url.ie","url360.me","url4.eu","urlborg.com","urlbrief.com","urlcover.com","urlcut.com","urlenco.de","urli.nl","urls.im","urlshorteningservicefortwitter.com","urlx.ie","urlzen.com","usat.ly","use.my","vb.ly","vevo.ly","vgn.am","vl.am","vm.lc","w55.de","wapo.st","wapurl.co.uk","wipi.es","wp.me","x.vu","xr.com","xrl.in","xrl.us","xurl.es","xurl.jp","y.ahoo.it","yatuc.com","ye.pe","yep.it","yfrog.com","yhoo.it","yiyd.com","youtu.be","yuarel.com","z0p.de","zi.ma","zi.mu","zipmyurl.com","zud.me","zurl.ws","zz.gd","zzang.kr","›.ws","✩.ws","✿.ws","❥.ws","➔.ws","➞.ws","➡.ws","➨.ws","➯.ws","➹.ws","➽.ws"];return 0===a("#jqoembeddata").length&&a('').appendTo("body"),this.each(function(){var c,i=a(this),j=!b||b.indexOf("http://")&&b.indexOf("https://")?i.attr("href"):b;if(d?g.onEmbed=d:g.onEmbed||(g.onEmbed=function(b){a.fn.oembed.insertCode(this,g.embedMethod,b)}),null!==j&&void 0!==j){for(var k=0,l=h.length;l>k;k++){var m=new RegExp("://"+h[k]+"/","i");if(null!==j.match(m)){var n=a.extend({url:"http://api.longurl.org/v2/expand",dataType:"jsonp",data:{url:j,format:"json"},success:function(b){j=b["long-url"],c=a.fn.oembed.getOEmbedProvider(b["long-url"]),null!==c?(c.params=f(g[c.name])||{},c.maxWidth=g.maxWidth,c.maxHeight=g.maxHeight,e(i,j,c)):g.onProviderNotFound.call(i,j)}},g.ajaxOptions||{});return a.ajax(n),i}}c=a.fn.oembed.getOEmbedProvider(j),null!==c?(c.params=f(g[c.name])||{},c.maxWidth=g.maxWidth,c.maxHeight=g.maxHeight,e(i,j,c)):g.onProviderNotFound.call(i,j)}return i})};var g;a.fn.oembed.defaults={maxWidth:null,maxHeight:null,includeHandle:!0,embedMethod:"auto",onProviderNotFound:function(){},beforeEmbed:function(){},afterEmbed:function(){},onEmbed:!1,onError:function(){},ajaxOptions:{}},a.fn.oembed.insertCode=function(b,c,d){if(null!==d)switch("auto"==c&&null!==b.attr("href")?c="append":"auto"==c&&(c="replace"),c){case"replace":b.replaceWith(d.code);break;case"fill":b.html(d.code);break;case"append":b.wrap('
');var e=b.parent();g.includeHandle&&a('').insertBefore(b).click(function(){var b=encodeURIComponent(a(this).text());a(this).html("%E2%86%91"==b?"↓":"↑"),a(this).parent().children().last().toggle()}),e.append("
");try{d.code.clone().appendTo(e)}catch(f){e.append(d.code)}if(g.maxWidth){var h=e.parent().width();if(h'+d+'';else if(b.thumbnail_url){var e=b.thumbnail_url.replace("_s","_b");c='
'+d+'
'}else c="
Error loading this picture
";return b.html&&(c+="
"+b.html+"
"),c},a.fn.oembed.getRichCode=function(a,b){var c=b.html;return c},a.fn.oembed.getGenericCode=function(a,b){var c=null!==b.title?b.title:a,d="";return b.html&&(d+='
'+c+"
"+jQuery(b.html).text().substring(0,200)+'... more
'),d},a.fn.oembed.getOEmbedProvider=function(b){for(var c=0;cd;d++){var f=new RegExp(a.fn.oembed.providers[c].urlschemes[d],"i");if(null!==b.match(f))return a.fn.oembed.providers[c]}return null},a.fn.oembed.OEmbedProvider=function(a,b,c,d,e){this.name=a,this.type=b,this.urlschemes=c,this.apiendpoint=d,this.maxWidth=500,this.maxHeight=400,e=e||{},e.useYQL&&(e.yql="xml"==e.useYQL?{xpath:"//oembed/html",from:"xml",apiendpoint:this.apiendpoint,url:function(a){return this.apiendpoint+"?format=xml&url="+a},datareturn:function(a){return a.html.replace(/.*\[CDATA\[(.*)\]\]>$/,"$1")||""}}:{from:"json",apiendpoint:this.apiendpoint,url:function(a){return this.apiendpoint+"?format=json&url="+a},datareturn:function(a){return"video"!=a.json.type&&(a.json.url||a.json.thumbnail_url)?'':a.json.html||""}},this.apiendpoint=null);for(var f in e)this[f]=e[f];this.format=this.format||"json",this.callbackparameter=this.callbackparameter||"callback",this.embedtag=this.embedtag||{tag:""}},a.fn.updateOEmbedProvider=function(b,c,d,e,f){for(var g=0;g':!1}}}),new a.fn.oembed.OEmbedProvider("deviantart","photo",["deviantart.com/.+","fav.me/.+","deviantart.com/.+"],"http://backend.deviantart.com/oembed",{format:"jsonp"}),new a.fn.oembed.OEmbedProvider("skitch","photo",["skitch.com/.+"],null,{yql:{xpath:"json",from:"json",url:function(a){return"http://skitch.com/oembed/?format=json&url="+a},datareturn:function(b){return a.fn.oembed.getPhotoCode(b.json.url,b.json)}}}),new a.fn.oembed.OEmbedProvider("mobypicture","photo",["mobypicture.com/user/.+/view/.+","moby.to/.+"],"http://api.mobypicture.com/oEmbed"),new a.fn.oembed.OEmbedProvider("flickr","photo",["flickr\\.com/photos/.+"],"http://flickr.com/services/oembed",{callbackparameter:"jsoncallback"}),new a.fn.oembed.OEmbedProvider("photobucket","photo",["photobucket\\.com/(albums|groups)/.+"],"http://photobucket.com/oembed/"),new a.fn.oembed.OEmbedProvider("instagram","photo",["instagr\\.?am(\\.com)?/.+"],"http://api.instagram.com/oembed"),new a.fn.oembed.OEmbedProvider("SmugMug","photo",["smugmug.com/[-.\\w@]+/.+"],"http://api.smugmug.com/services/oembed/"),new a.fn.oembed.OEmbedProvider("dribbble","photo",["dribbble.com/shots/.+"],"http://api.dribbble.com/shots/$1?callback=?",{templateRegex:/.*shots\/([\d]+).*/,templateData:function(a){return a.image_teaser_url?'':!1}}),new a.fn.oembed.OEmbedProvider("chart.ly","photo",["chart\\.ly/[a-z0-9]{6,8}"],"http://chart.ly/uploads/large_$1.png",{templateRegex:/.*ly\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("circuitlab","photo",["circuitlab.com/circuit/.+"],"https://www.circuitlab.com/circuit/$1/screenshot/540x405/",{templateRegex:/.*circuit\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("23hq","photo",["23hq.com/[-.\\w@]+/photo/.+"],"http://www.23hq.com/23/oembed",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("img.ly","photo",["img\\.ly/.+"],"http://img.ly/show/thumb/$1",{templateRegex:/.*ly\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("twitgoo.com","photo",["twitgoo\\.com/.+"],"http://twitgoo.com/show/thumb/$1",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("imgur.com","photo",["imgur\\.com/gallery/.+"],"http://imgur.com/$1l.jpg",{templateRegex:/.*gallery\/([^\/]+).*/,embedtag:{tag:"img"},nocache:1}),new a.fn.oembed.OEmbedProvider("visual.ly","rich",["visual\\.ly/.+"],null,{yql:{xpath:"//a[@id=\\'gc_article_graphic_image\\']/img",from:"htmlstring"}}),new a.fn.oembed.OEmbedProvider("twitter","rich",["twitter.com/.+"],"https://api.twitter.com/1/statuses/oembed.json"),new a.fn.oembed.OEmbedProvider("gmep","rich",["gmep.imeducate.com/.*","gmep.org/.*"],"http://gmep.org/oembed.json"),new a.fn.oembed.OEmbedProvider("urtak","rich",["urtak.com/(u|clr)/.+"],"http://oembed.urtak.com/1/oembed"),new a.fn.oembed.OEmbedProvider("cacoo","rich",["cacoo.com/.+"],"http://cacoo.com/oembed.json"),new a.fn.oembed.OEmbedProvider("dailymile","rich",["dailymile.com/people/.*/entries/.*"],"http://api.dailymile.com/oembed"),new a.fn.oembed.OEmbedProvider("dipity","rich",["dipity.com/timeline/.+"],"http://www.dipity.com/oembed/timeline/",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("sketchfab","rich",["sketchfab.com/show/.+"],"http://sketchfab.com/oembed",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("speakerdeck","rich",["speakerdeck.com/.+"],"http://speakerdeck.com/oembed.json",{useYQL:"json"}),new a.fn.oembed.OEmbedProvider("popplet","rich",["popplet.com/app/.*"],"http://popplet.com/app/Popplet_Alpha.swf?page_id=$1&em=1",{templateRegex:/.*#\/([^\/]+).*/,embedtag:{width:460,height:460}}),new a.fn.oembed.OEmbedProvider("pearltrees","rich",["pearltrees.com/.*"],"http://cdn.pearltrees.com/s/embed/getApp?",{templateRegex:/.*N-f=1_(\d+).*N-p=(\d+).*/,embedtag:{width:460,height:460,flashvars:"lang=en_US&embedId=pt-embed-$1-693&treeId=$1&pearlId=$2&treeTitle=Diagrams%2FVisualization&site=www.pearltrees.com%2FF"}}),new a.fn.oembed.OEmbedProvider("prezi","rich",["prezi.com/.*"],"http://prezi.com/bin/preziloader.swf?",{templateRegex:/.*com\/([^\/]+)\/.*/,embedtag:{width:550,height:400,flashvars:"prezi_id=$1&lock_to_path=0&color=ffffff&autoplay=no&autohide_ctrls=0"}}),new a.fn.oembed.OEmbedProvider("tourwrist","rich",["tourwrist.com/tours/.+"],null,{templateRegex:/.*tours.([\d]+).*/,template:function(a,b){return setTimeout(function(){loadEmbeds&&loadEmbeds()},2e3),"
"}}),new a.fn.oembed.OEmbedProvider("meetup","rich",["meetup\\.(com|ps)/.+"],"http://api.meetup.com/oembed"),new a.fn.oembed.OEmbedProvider("ebay","rich",["ebay\\.*"],"http://togo.ebay.com/togo/togo.swf?2008013100",{templateRegex:/.*\/([^\/]+)\/(\d{10,13}).*/,embedtag:{width:355,height:300,flashvars:"base=http://togo.ebay.com/togo/&lang=en-us&mode=normal&itemid=$2&query=$1"}}),new a.fn.oembed.OEmbedProvider("wikipedia","rich",["wikipedia.org/wiki/.+"],"http://$1.wikipedia.org/w/api.php?action=parse&page=$2&format=json§ion=0&callback=?",{templateRegex:/.*\/\/([\w]+).*\/wiki\/([^\/]+).*/,templateData:function(a){if(!a.parse)return!1;var b=a.parse.text["*"].replace(/href="\/wiki/g,'href="http://en.wikipedia.org/wiki');return'
'+a.parse.displaytitle+"
"+jQuery(b).text().substring(0,200)+"...
"}}),new a.fn.oembed.OEmbedProvider("imdb","rich",["imdb.com/title/.+"],"http://www.imdbapi.com/?i=$1&callback=?",{templateRegex:/.*\/title\/([^\/]+).*/,templateData:function(a){return a.Title?'

'+a.Title+" ("+a.Year+")

Rating: "+a.imdbRating+"
Genre: "+a.Genre+"
Starring: "+a.Actors+'

'+a.Plot+"
":!1}}),new a.fn.oembed.OEmbedProvider("livejournal","rich",["livejournal.com/"],"http://ljpic.seacrow.com/json/$2$4?jsonp=?",{templateRegex:/(http:\/\/(((?!users).)+)\.livejournal\.com|.*users\.livejournal\.com\/([^\/]+)).*/,templateData:function(a){return a.username?'
[info]'+a.username+"
"+a.name+"
":!1}}),new a.fn.oembed.OEmbedProvider("circuitbee","rich",["circuitbee\\.com/circuit/view/.+"],"http://c.circuitbee.com/build/r/schematic-embed.html?id=$1",{templateRegex:/.*circuit\/view\/(\d+).*/,embedtag:{tag:"iframe",width:"500",height:"350"}}),new a.fn.oembed.OEmbedProvider("googlecalendar","rich",["www.google.com/calendar/embed?.+"],"$1",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"800",height:"600"}}),new a.fn.oembed.OEmbedProvider("jsfiddle","rich",["jsfiddle.net/[^/]+/?"],"http://jsfiddle.net/$1/embedded/result,js,resources,html,css/?",{templateRegex:/.*net\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"300"}}),new a.fn.oembed.OEmbedProvider("jsbin","rich",["jsbin.com/.+"],"http://jsbin.com/$1/?",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"300"}}),new a.fn.oembed.OEmbedProvider("jotform","rich",["form.jotform.co/form/.+"],"$1?",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"100%",height:"507"}}),new a.fn.oembed.OEmbedProvider("reelapp","rich",["reelapp\\.com/.+"],"http://www.reelapp.com/$1/embed",{templateRegex:/.*com\/(\S{6}).*/,embedtag:{tag:"iframe",width:"400",height:"338"}}),new a.fn.oembed.OEmbedProvider("linkedin","rich",["linkedin.com/pub/.+"],"https://www.linkedin.com/cws/member/public_profile?public_profile_url=$1&format=inline&isFramed=true",{templateRegex:/(.*)/,embedtag:{tag:"iframe",width:"368px",height:"auto"}}),new a.fn.oembed.OEmbedProvider("timetoast","rich",["timetoast.com/timelines/[0-9]+"],"http://www.timetoast.com/flash/TimelineViewer.swf?passedTimelines=$1",{templateRegex:/.*timelines\/([0-9]*)/,embedtag:{width:550,height:400,nocache:1}}),new a.fn.oembed.OEmbedProvider("pastebin","rich",["pastebin\\.com/[\\S]{8}"],"http://pastebin.com/embed_iframe.php?i=$1",{templateRegex:/.*\/(\S{8}).*/,embedtag:{tag:"iframe",width:"100%",height:"auto"}}),new a.fn.oembed.OEmbedProvider("mixlr","rich",["mixlr.com/.+"],"http://mixlr.com/embed/$1?autoplay=ae",{templateRegex:/.*com\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:"auto"}}),new a.fn.oembed.OEmbedProvider("pastie","rich",["pastie\\.org/pastes/.+"],null,{yql:{xpath:'//pre[@class="textmate-source"]'}}),new a.fn.oembed.OEmbedProvider("github","rich",["gist.github.com/.+"],"https://github.com/api/oembed"),new a.fn.oembed.OEmbedProvider("github","rich",["github.com/[-.\\w@]+/[-.\\w@]+"],"https://api.github.com/repos/$1/$2?callback=?",{templateRegex:/.*\/([^\/]+)\/([^\/]+).*/,templateData:function(a){return a.data.html_url?'

'+a.data.name+'

'+a.data.description+'

Last updated: '+a.data.pushed_at+"

":!1}}),new a.fn.oembed.OEmbedProvider("facebook","rich",["facebook.com/(people/[^\\/]+/\\d+|[^\\/]+$)"],"https://graph.facebook.com/$2$3/?callback=?",{templateRegex:/.*facebook.com\/(people\/[^\/]+\/(\d+).*|([^\/]+$))/,templateData:function(a){if(!a.id)return!1;var b='
facebook ';return b+=a.from?''+a.from.name+"":a.link?''+a.name+"":a.username?''+a.name+"":''+a.name+"",b+='
',b+=a.picture?'':'',a.from&&(b+=''+a.name+""),a.founded&&(b+="Founded: "+a.founded+"
"),a.category&&(b+="Category: "+a.category+"
"),a.website&&(b+='Website: '+a.website+"
"),a.gender&&(b+="Gender: "+a.gender+"
"),a.description&&(b+=a.description+"
"),b+="
"}}),new a.fn.oembed.OEmbedProvider("stackoverflow","rich",["stackoverflow.com/questions/[\\d]+"],"http://api.stackoverflow.com/1.1/questions/$1?body=true&jsonp=?",{templateRegex:/.*questions\/([\d]+).*/,templateData:function(b){if(!b.questions)return!1;var c=b.questions[0],d=a(c.body).text(),e='
'+(c.up_vote_count-c.down_vote_count)+'
vote(s)
'+c.answer_count+'answer
'+c.view_count+' view(s)

'+c.title+'

'+d.substring(0,100)+'...
';for(i in c.tags)e+='";return e+='
" +}}),new a.fn.oembed.OEmbedProvider("wordpress","rich",["wordpress\\.com/.+","blogs\\.cnn\\.com/.+","techcrunch\\.com/.+","wp\\.me/.+"],"http://public-api.wordpress.com/oembed/1.0/?for=jquery-oembed-all"),new a.fn.oembed.OEmbedProvider("screenr","rich",["screenr.com"],"http://www.screenr.com/embed/$1",{templateRegex:/.*\/([^\/]+).*/,embedtag:{tag:"iframe",width:"650",height:396}}),new a.fn.oembed.OEmbedProvider("gigpans","rich",["gigapan\\.org/[-.\\w@]+/\\d+"],"http://gigapan.org/gigapans/$1/options/nosnapshots/iframe/flash.html",{templateRegex:/.*\/(\d+)\/?.*/,embedtag:{tag:"iframe",width:"100%",height:400}}),new a.fn.oembed.OEmbedProvider("scribd","rich",["scribd\\.com/.+"],"http://www.scribd.com/embeds/$1/content?start_page=1&view_mode=list",{templateRegex:/.*doc\/([^\/]+).*/,embedtag:{tag:"iframe",width:"100%",height:600}}),new a.fn.oembed.OEmbedProvider("kickstarter","rich",["kickstarter\\.com/projects/.+"],"$1/widget/card.html",{templateRegex:/([^\?]+).*/,embedtag:{tag:"iframe",width:"220",height:380}}),new a.fn.oembed.OEmbedProvider("amazon","rich",["amzn.com/B+","amazon.com.*/(B\\S+)($|\\/.*)"],"http://rcm.amazon.com/e/cm?t=_APIKEY_&o=1&p=8&l=as1&asins=$1&ref=qf_br_asin_til&fc1=000000&IS2=1<1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr",{apikey:!0,templateRegex:/.*\/(B[0-9A-Z]+)($|\/.*)/,embedtag:{tag:"iframe",width:"120px",height:"240px"}}),new a.fn.oembed.OEmbedProvider("slideshare","rich",["slideshare.net"],"http://www.slideshare.net/api/oembed/2",{format:"jsonp"}),new a.fn.oembed.OEmbedProvider("roomsharejp","rich",["roomshare\\.jp/(en/)?post/.*"],"http://roomshare.jp/oembed.json"),new a.fn.oembed.OEmbedProvider("lanyard","rich",["lanyrd.com/\\d+/.+"],null,{yql:{xpath:'(//div[@class="primary"])[1]',from:"htmlstring",datareturn:function(a){return a.result?'
'+a.result+"
":!1}}}),new a.fn.oembed.OEmbedProvider("asciiartfarts","rich",["asciiartfarts.com/\\d+.html"],null,{yql:{xpath:"//pre/font",from:"htmlstring",datareturn:function(a){return a.result?'
'+a.result+"
":!1}}})]}(jQuery); //# sourceMappingURL=jquery.oembed.min.map \ No newline at end of file diff --git a/addons/oembed/jquery.oembed.min.map b/addons/oembed/jquery.oembed.min.map index 9c240de84..38eee72e3 100644 --- a/addons/oembed/jquery.oembed.min.map +++ b/addons/oembed/jquery.oembed.min.map @@ -1 +1 @@ -{"version":3,"file":"jquery.oembed.min.js","sources":["jquery.oembed.js"],"names":["$","rand","length","current","charAt","Math","floor","random","getRequestUrl","provider","externalUrl","i","url","apiendpoint","qs","indexOf","replace","maxWidth","params","maxwidth","maxHeight","maxheight","callbackparameter","escape","format","dataType","success","oembedData","container","data","code","settings","beforeEmbed","call","onEmbed","afterEmbed","embedCode","embedProvider","undefined","embedtag","tag","yql","from","query","test","xpath","ajaxopts","extend","q","env","callback","result","meta","results","l","name","property","toLowerCase","content","hasOwnProperty","title","datareturn","error","onError","ajaxOptions","ajax","templateRegex","flashvars","width","height","nocache","src","apikey","apikeys","attr","allowfullscreen","css","type","scrolling","frameborder","templateData","template","requestUrl","fn","oembed","getPhotoCode","getRichCode","getGenericCode","getNormalizedParams","key","normalizedParams","options","embedAction","defaults","shortURLList","appendTo","this","each","resourceURL","insertCode","embedMethod","j","regExp","RegExp","match","getOEmbedProvider","onProviderNotFound","includeHandle","replaceWith","html","wrap","oembedContainer","parent","insertBefore","click","encodedString","encodeURIComponent","text","children","last","toggle","append","clone","e","post_width","iframe_width_orig","iframe_height_orig","ratio","alt","author_name","provider_name","thumbnail_url","newURL","jQuery","substring","providers","urlschemes","OEmbedProvider","urlschemesarray","extraSettings","useYQL","externalurl","json","updateOEmbedProvider","image_teaser_url","wm","email","md5","tourid","setTimeout","loadEmbeds","parse","Title","imdbID","Year","imdbRating","Genre","Actors","Plot","username","image","html_url","language","watchers","forks","description","pushed_at","id","out","link","picture","founded","category","website","gender","questions","body","up_vote_count","down_vote_count","answer_count","view_count","question_id","tags","owner","user_id","display_name","email_hash","reputation","String","prototype","a","b","c","d","f","g","h","k","m","n","o","p","push","charCodeAt"],"mappings":"CAYA,SAAWA,GAmHV,QAASC,GAAKC,EAAQC,GAErB,MADAA,GAAUA,EAAUA,EAAU,GACvBD,EAASD,IAAOC,EAAQ,gEAAgEE,OAAOC,KAAKC,MAAsB,GAAhBD,KAAKE,WAAkBJ,GAAWA,EAGpJ,QAASK,GAAcC,EAAUC,GAChC,GAECC,GAFGC,EAAMH,EAASI,YAClBC,EAAK,EAENF,IAAQA,EAAIG,QAAQ,MAAQ,EAAK,IAAM,IACvCH,EAAMA,EAAII,QAAQ,IAAK,OAEE,OAAtBP,EAASQ,UAA0D,mBAA7BR,GAASS,OAAOC,UAAyD,OAA7BV,EAASS,OAAOC,WACpGV,EAASS,OAAOC,SAAWV,EAASQ,UAGX,OAAvBR,EAASW,WAA4D,mBAA9BX,GAASS,OAAOG,WAA2D,OAA9BZ,EAASS,OAAOG,YACtGZ,EAASS,OAAOG,UAAYZ,EAASW,UAGtC,KAAIT,IAAKF,GAASS,OAEdP,GAAKF,EAASa,mBAGS,OAAvBb,EAASS,OAAOP,KAAaG,GAAM,IAAMS,OAAOZ,GAAK,IAAMF,EAASS,OAAOP,GAM/E,OAHAC,IAAO,UAAYH,EAASe,OAAS,QAAUD,OAAOb,GAAeI,EAC7C,QAArBL,EAASgB,WAAoBb,GAAO,IAAMH,EAASa,kBAAoB,MAEnEV,EAGR,QAASc,GAAQC,EAAYjB,EAAakB,GACzC5B,EAAE,iBAAiB6B,KAAKnB,EAAaiB,EAAWG,MAChDC,EAASC,YAAYC,KAAKL,EAAWD,GACrCI,EAASG,QAAQD,KAAKL,EAAWD,GACjCI,EAASI,WAAWF,KAAKL,EAAWD,GAGrC,QAASS,GAAUR,EAAWlB,EAAa2B,GAC1C,GAA2CC,QAAxCtC,EAAE,iBAAiB6B,KAAKnB,IAA2D,UAA9B2B,EAAcE,SAASC,IAAiB,CAC/F,GAAIb,IACHG,KAAM9B,EAAE,iBAAiB6B,KAAKnB,GAE/BgB,GAAQC,EAAYjB,EAAakB,OAC3B,IAAGS,EAAcI,IAAK,CAC5B,GAAIC,GAAOL,EAAcI,IAAIC,MAAQ,aACjC9B,EAAMyB,EAAcI,IAAI7B,IAAMyB,EAAcI,IAAI7B,IAAIF,GAAeA,EACnEiC,EAAQ,iBAAmBD,EAAO,eAAiB,EAAQ,UAAiB,OAAOE,KAAKF,GAAQ,QAAU,YAAc,MAAQL,EAAcI,IAAII,OAAS,KAAO,GAC3J,SAARH,IAAgBC,GAAS,sBAC5B,IAAIG,GAAW9C,EAAE+C,QAChBnC,IAAK,2CACLa,SAAU,QACVI,MACCmB,EAAGL,EACHnB,OAAQ,OACRyB,IAAK,2CACLC,SAAU,KAEXxB,QAAS,SAAUG,GAClB,GAAIsB,EACJ,IAAGd,EAAcI,IAAII,OAAoC,yBAA3BR,EAAcI,IAAII,MAAkC,CACjF,GAAIO,KACqB,OAAtBvB,EAAKc,MAAMU,UACbxB,EAAKc,MAAMU,SACVD,SAGF,KAAI,GAAIzC,GAAI,EAAG2C,EAAIzB,EAAKc,MAAMU,QAAQD,KAAKlD,OAAYoD,EAAJ3C,EAAOA,IAAK,CAC9D,GAAI4C,GAAO1B,EAAKc,MAAMU,QAAQD,KAAKzC,GAAG4C,MAAQ1B,EAAKc,MAAMU,QAAQD,KAAKzC,GAAG6C,UAAY,IAC1E,OAARD,IACHH,EAAKG,EAAKE,eAAiB5B,EAAKc,MAAMU,QAAQD,KAAKzC,GAAG+C,SAEnDN,EAAKO,eAAe,UAAaP,EAAKO,eAAe,aACzB,MAA5B9B,EAAKc,MAAMU,QAAQO,QACrBR,EAAKQ,MAAQ/B,EAAKc,MAAMU,QAAQO,OAGlCT,EAASd,EAAcI,IAAIoB,WAAWT,OAEtCD,GAASd,EAAcI,IAAIoB,WAAaxB,EAAcI,IAAIoB,WAAWhC,EAAKc,MAAMU,SAAWxB,EAAKc,MAAMU,QAAQF,MAE/G,IAAGA,KAAW,EAAd,CACA,GAAIxB,GAAa3B,EAAE+C,UAAWI,EAC9BxB,GAAWG,KAAOqB,EAClBzB,EAAQC,EAAYjB,EAAakB,KAElCkC,MAAO/B,EAASgC,QAAQ9B,KAAKL,EAAWlB,EAAa2B,IACnDN,EAASiC,gBAEZhE,GAAEiE,KAAKnB,OACD,IAAGT,EAAc6B,cACvB,GAAkC,KAA/B7B,EAAcE,SAASC,IAAY,CACrC,GAAI2B,GAAY9B,EAAcE,SAAS4B,WAAa,GAChD3B,EAAMH,EAAcE,SAASC,KAAO,QACpC4B,EAAQ/B,EAAcE,SAAS6B,OAAS,OAExCC,GADUhC,EAAcE,SAAS+B,SAAW,EACnCjC,EAAcE,SAAS8B,QAAU,QAC1CE,EAAM7D,EAAYM,QAAQqB,EAAc6B,cAAe7B,EAAcxB,YACrEwB,GAAciC,UAASC,GAAO,eAAiBtE,EAAK,IACrDoC,EAAcmC,SAAQD,EAAMA,EAAIvD,QAAQ,WAAYe,EAAS0C,QAAQpC,EAAckB,OAEtF,IAAIzB,GAAO9B,EAAE,IAAMwC,EAAM,MACvBkC,KAAK,MAAOH,GACZG,KAAK,QAASN,GACdM,KAAK,SAAUL,GACfK,KAAK,kBAAmBrC,EAAcE,SAASoC,iBAAmB,QAClED,KAAK,oBAAqBrC,EAAcE,SAASoC,iBAAmB,UACpEC,IAAI,aAAc7C,EAASX,WAAa,QACxCwD,IAAI,YAAa7C,EAASd,UAAY,OAC9B,UAAPuB,GACFV,EACE4C,KAAK,OAAQrC,EAAcE,SAASsC,MAAQ,iCAC5CH,KAAK,YAAahE,EAAYM,QAAQqB,EAAc6B,cAAeC,IAE5D,UAAP3B,GACFV,EACE4C,KAAK,YAAarC,EAAcE,SAASuC,WAAa,MACtDJ,KAAK,cAAerC,EAAcE,SAASwC,aAAe,IAG7D,IAAIpD,IACHG,KAAMA,EAEPJ,GAAQC,EAAYjB,EAAakB,OAC3B,IAAGS,EAAcxB,YAEpBwB,EAAcmC,SAAQnC,EAAcxB,YAAcwB,EAAcxB,YAAYG,QAAQ,WAAYe,EAAS0C,QAAQpC,EAAckB,QAClIT,EAAW9C,EAAE+C,QACZnC,IAAKF,EAAYM,QAAQqB,EAAc6B,cAAe7B,EAAcxB,aACpEY,SAAU,QACVC,QAAS,SAAUG,GAClB,GAAIF,GAAa3B,EAAE+C,UAAWlB,EAC9BF,GAAWG,KAAOO,EAAc2C,aAAanD,GAC1CF,EAAWG,MAAMJ,EAAQC,EAAYjB,EAAakB,IAEtDkC,MAAO/B,EAASgC,QAAQ9B,KAAKL,EAAWlB,EAAa2B,IACnDN,EAASiC,iBAEZhE,EAAEiE,KAAKnB,OACD,CACN,GAAInB,IACHG,KAAMpB,EAAYM,QAAQqB,EAAc6B,cAAe7B,EAAc4C,UAEtEvD,GAAQC,EAAYjB,EAAakB,OAE5B,CAEN,GAAIsD,GAAa1E,EAAc6B,EAAe3B,GAC7CoC,EAAW9C,EAAE+C,QACZnC,IAAKsE,EACLzD,SAAUY,EAAcZ,UAAY,QACpCC,QAAS,SAAUG,GAClB,GAAIF,GAAa3B,EAAE+C,UAAWlB,EAC9B,QAAOF,EAAWkD,MAClB,IAAK,OACL,IAAK,QACJlD,EAAWG,KAAO9B,EAAEmF,GAAGC,OAAOC,aAAa3E,EAAaiB,EACxD,MACD,KAAK,QACL,IAAK,OACJA,EAAWG,KAAO9B,EAAEmF,GAAGC,OAAOE,YAAY5E,EAAaiB,EACvD,MACD,SACCA,EAAWG,KAAO9B,EAAEmF,GAAGC,OAAOG,eAAe7E,EAAaiB,GAG3DD,EAAQC,EAAYjB,EAAakB,IAElCkC,MAAO/B,EAASgC,QAAQ9B,KAAKL,EAAWlB,EAAa2B,IACnDN,EAASiC,gBAEbhE,GAAEiE,KAAKnB,IAIT,QAAS0C,GAAoBtE,GAC5B,GAAc,OAAXA,EAAiB,MAAO,KAC3B,IAAIuE,GAAKC,IACT,KAAID,IAAOvE,GACC,OAARuE,IAAcC,EAAiBD,EAAIhC,eAAiBvC,EAAOuE,GAE/D,OAAOC,GA1SR1F,EAAEmF,GAAGC,OAAS,SAAUxE,EAAK+E,EAASC,GACrC7D,EAAW/B,EAAE+C,QAAO,EAAM/C,EAAEmF,GAAGC,OAAOS,SAAUF,EAChD,IAAIG,IAAgB,SAAU,WAAY,WAAY,OAAQ,UAAW,SAAU,OAAQ,SAAU,SAAU,UAAW,UAAW,WAAY,OAAQ,OAAQ,OAAQ,QAAS,aACjL,QAAS,SAAU,YAAa,SAAU,kBAAmB,aAAc,UAAW,QAAS,UAAW,SAAU,SAAU,SAAU,SAAU,UAAW,WAAY,YACzK,SAAU,UAAW,WAAY,WAAY,SAAU,aAAc,aAAc,WAAY,UAAW,QAAS,QAAS,UAAW,SAAU,gBACjJ,eAAgB,UAAW,WAAY,UAAW,SAAU,UAAW,UAAW,UAAW,SAAU,gBAAiB,UAAW,aACnI,yBAA+B,UAAW,SAAU,UAAW,QAAS,YAAa,WAAY,cAAe,cAAe,aAAc,YAC7I,QAAS,SAAU,QAAS,aAAc,QAAS,SAAU,UAAW,cAAe,eAAgB,UAAW,SAAU,UAAW,SAAU,WACjJ,cAAe,WAAY,UAAW,WAAY,UAAW,WAAY,QAAS,aAAc,aAAc,aAAc,SAAU,eAAgB,UACtJ,SAAU,gBAAiB,SAAU,UAAW,eAAgB,UAAW,UAAW,WAAY,UAAW,UAAW,cAAe,WAAY,UAAW,QAC9J,SAAU,QAAS,OAAQ,WAAY,QAAS,UAAW,WAAY,cAAe,UAAW,SAAU,UAAW,cAAe,cAAe,aACpJ,WAAY,WAAY,UAAW,SAAU,SAAU,UAAW,aAAc,SAAU,QAAS,UAAW,WAAY,UAAW,WAAY,WAAY,cAC7J,YAAa,SAAU,UAAW,aAAc,UAAW,WAAY,WAAY,OAAQ,SAAU,UAAW,QAAS,SAAU,cAAe,UAClJ,kBAAmB,SAAU,UAAW,SAAU,SAAU,QAAS,SAAU,eAAgB,aAAc,cAAe,YAAa,SAAU,QAAS,UAC5J,SAAU,SAAU,YAAa,UAAW,QAAS,aAAc,cAAe,iBAAkB,WAAY,SAAU,QAAS,QAAS,aAAc,OAAQ,SAAU,UAC5K,cAAe,oBAAqB,WAAY,eAAgB,aAAc,WAAY,QAAS,cAAe,SAAU,QAAS,QAAS,cAAe,WAC7J,SAAU,SAAU,SAAU,UAAW,cAAe,UAAW,UAAW,WAAY,YAAa,WAAY,WAAY,mBAAoB,eACnJ,WAAY,UAAW,gBAAiB,cAAe,UAAW,UAAW,aAAc,eAAgB,aAAc,WAAY,aAAc,UAAW,aAC9J,QAAS,YAAa,cAAe,YAAa,SAAU,YAAa,WAAY,SAAU,eAAgB,UAAW,QAAS,aAAc,UAAW,OAAQ,OAAQ,WAC5K,QAAS,SAAU,UAAW,SAAU,SAAU,eAAgB,cAAe,UAAW,UAAW,UAAW,cAAe,aAAc,cAAe,MAAO,QACrK,SAAU,WAAY,SAAU,UAAW,QAAS,YAAa,UAAW,WAAY,SAAU,QAAS,SAAU,WAAY,YAAa,WAC9I,iBAAkB,iBAAkB,iBAAkB,aAAc,WAAY,WAAY,eAAgB,OAAQ,UAAW,SAAU,SAAU,cAAe,SAClK,SAAU,YAAa,SAAU,YAAa,UAAW,cAAe,eAAgB,eAAgB,aAAc,aAAc,UAAW,UAC/I,qCAAsC,UAAW,aAAc,UAAW,SAAU,QAAS,UAAW,SAAU,QAAS,QAAS,SAAU,UAAW,eAAgB,UACzK,QAAS,OAAQ,SAAU,SAAU,SAAU,UAAW,UAAW,YAAa,YAAa,QAAS,SAAU,YAAa,UAAW,WAAY,WAAY,aAClK,SAAU,QAAS,QAAS,eAAgB,SAAU,UAAW,QAAS,WAAY,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAKvK,OAFiC,KAA9B9F,EAAE,iBAAiBE,QAAcF,EAAE,mCAAmC+F,SAAS,QAE3EC,KAAKC,KAAK,WAChB,GAECxF,GAFGmB,EAAY5B,EAAEgG,MACjBE,GAAetF,GAASA,EAAIG,QAAQ,YAAeH,EAAIG,QAAQ,YAAsBa,EAAU8C,KAAK,QAArB9D,CAWhF,IARGgF,EACF7D,EAASG,QAAU0D,EACT7D,EAASG,UACnBH,EAASG,QAAU,SAAUP,GAC5B3B,EAAEmF,GAAGC,OAAOe,WAAWH,KAAMjE,EAASqE,YAAazE,KAIlC,OAAhBuE,GAAwC5D,SAAhB4D,EAA2B,CAErD,IAAI,GAAIG,GAAI,EAAG/C,EAAIwC,EAAa5F,OAAYoD,EAAJ+C,EAAOA,IAAK,CACnD,GAAIC,GAAS,GAAIC,QAAO,MAAQT,EAAaO,GAAK,IAAK,IACvD,IAAiC,OAA9BH,EAAYM,MAAMF,GAAkB,CAEtC,GAAIxD,GAAW9C,EAAE+C,QAChBnC,IAAK,mCACLa,SAAU,QACVI,MACCjB,IAAKsF,EACL1E,OAAQ,QAGTE,QAAS,SAAUG,GAElBqE,EAAcrE,EAAK,YACnBpB,EAAWT,EAAEmF,GAAGC,OAAOqB,kBAAkB5E,EAAK,aAE9B,OAAbpB,GACFA,EAASS,OAASsE,EAAoBzD,EAAStB,EAAS8C,WACxD9C,EAASQ,SAAWc,EAASd,SAC7BR,EAASW,UAAYW,EAASX,UAC9BgB,EAAUR,EAAWsE,EAAazF,IAElCsB,EAAS2E,mBAAmBzE,KAAKL,EAAWsE,KAG5CnE,EAASiC,gBAIZ,OAFAhE,GAAEiE,KAAKnB,GAEAlB,GAGTnB,EAAWT,EAAEmF,GAAGC,OAAOqB,kBAAkBP,GAEzB,OAAbzF,GACFA,EAASS,OAASsE,EAAoBzD,EAAStB,EAAS8C,WACxD9C,EAASQ,SAAWc,EAASd,SAC7BR,EAASW,UAAYW,EAASX,UAC9BgB,EAAUR,EAAWsE,EAAazF,IAElCsB,EAAS2E,mBAAmBzE,KAAKL,EAAWsE,GAI9C,MAAOtE,KAMT,IAAIG,EAGJ/B,GAAEmF,GAAGC,OAAOS,UACX5E,SAAU,KACVG,UAAW,KACXuF,eAAe,EACfP,YAAa,OAEbM,mBAAoB,aACpB1E,YAAa,aACbG,WAAY,aACZD,SAAS,EACT6B,QAAS,aACTC,gBAgMDhE,EAAEmF,GAAGC,OAAOe,WAAa,SAAUvE,EAAWwE,EAAazE,GAC1D,GAAkB,OAAfA,EAGH,OAFkB,QAAfyE,GAAoD,OAA3BxE,EAAU8C,KAAK,QAAkB0B,EAAc,SACpD,QAAfA,IAAuBA,EAAc,WACtCA,GACP,IAAK,UACJxE,EAAUgF,YAAYjF,EAAWG,KACjC,MACD,KAAK,OACJF,EAAUiF,KAAKlF,EAAWG,KAC1B,MACD,KAAK,SACJF,EAAUkF,KAAK,0CACf,IAAIC,GAAkBnF,EAAUoF,QAC7BjF,GAAS4E,eACX3G,EAAE,mDAAmDiH,aAAarF,GAAWsF,MAAM,WAClF,GAAIC,GAAgBC,mBAAmBpH,EAAEgG,MAAMqB,OAC/CrH,GAAEgG,MAAMa,KAAuB,aAAjBM,EAAgC,SAAW,UACzDnH,EAAEgG,MAAMgB,SAASM,WAAWC,OAAOC,WAGrCT,EAAgBU,OAAO,QACvB,KACC9F,EAAWG,KAAK4F,QAAQ3B,SAASgB,GAChC,MAAMY,GACPZ,EAAgBU,OAAO9F,EAAWG,MAOnC,GAAGC,EAASd,SAAU,CACrB,GAAI2G,GAAab,EAAgBC,SAAS5C,OAC1C,IAAGwD,EAAa7F,EAASd,SAAU,CAClC,GAAI4G,GAAoB7H,EAAE,SAAU+G,GAAiB3C,QACjD0D,EAAqB9H,EAAE,SAAU+G,GAAiB1C,SAClD0D,EAAQF,EAAoBD,CAChC5H,GAAE,SAAU+G,GAAiB3C,MAAMyD,EAAoBE,GACvD/H,EAAE,SAAU+G,GAAiB1C,OAAOyD,EAAqBC,OAEtDhG,GAASd,UACXjB,EAAE,SAAU+G,GAAiB3C,MAAMrC,EAASd,UAE1Cc,EAASX,WACXpB,EAAE,SAAU+G,GAAiB1C,OAAOtC,EAASX,cAQlDpB,EAAEmF,GAAGC,OAAOC,aAAe,SAAUzE,EAAKe,GACzC,GAAIG,GAAMkG,EAAMrG,EAAWiC,MAAQjC,EAAWiC,MAAQ,EAGtD,IAFAoE,GAAOrG,EAAWsG,YAAc,MAAQtG,EAAWsG,YAAc,GACjED,GAAOrG,EAAWuG,cAAgB,MAAQvG,EAAWuG,cAAgB,GAClEvG,EAAWf,IACbkB,EAAO,iBAAmBlB,EAAM,iCAAmCe,EAAWf,IAAM,UAAYoH,EAAM,oBAChG,IAAGrG,EAAWwG,cAAe,CACnC,GAAIC,GAASzG,EAAWwG,cAAcnH,QAAQ,KAAM,KACpDc,GAAO,iBAAmBlB,EAAM,iCAAmCwH,EAAS,UAAYJ,EAAM,oBAE9FlG,GAAO,uCAGR,OADGH,GAAWkF,OAAM/E,GAAQ,QAAUH,EAAWkF,KAAO,UACjD/E,GAGR9B,EAAEmF,GAAGC,OAAOE,YAAc,SAAU1E,EAAKe,GACxC,GAAIG,GAAOH,EAAWkF,IACtB,OAAO/E,IAGR9B,EAAEmF,GAAGC,OAAOG,eAAiB,SAAU3E,EAAKe,GAC3C,GAAIiC,GAA8B,OAArBjC,EAAWiC,MAAkBjC,EAAWiC,MAAQhD,EAC5DkB,EAAO,EAER,OADIH,GAAWkF,OAAM/E,GAAQ,oDAAsD8B,EAAQ,gBAAkByE,OAAO1G,EAAWkF,MAAMQ,OAAOiB,UAAU,EAAE,KAAO,gBAAgB1H,EAAI,2BAC5KkB,GAGR9B,EAAEmF,GAAGC,OAAOqB,kBAAoB,SAAU7F,GACzC,IAAI,GAAID,GAAI,EAAGA,EAAIX,EAAEmF,GAAGC,OAAOmD,UAAUrI,OAAQS,IAChD,IAAI,GAAI0F,GAAI,EAAG/C,EAAItD,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAG6H,WAAWtI,OAAYoD,EAAJ+C,EAAOA,IAAK,CAC1E,GAAIC,GAAS,GAAIC,QAAOvG,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAG6H,WAAWnC,GAAI,IAChE,IAAyB,OAAtBzF,EAAI4F,MAAMF,GAAkB,MAAOtG,GAAEmF,GAAGC,OAAOmD,UAAU5H,GAG9D,MAAO,OAGRX,EAAEmF,GAAGC,OAAOqD,eAAiB,SAAUlF,EAAMsB,EAAM6D,EAAiB7H,EAAa8H,GAChF3C,KAAKzC,KAAOA,EACZyC,KAAKnB,KAAOA,EACZmB,KAAKwC,WAAaE,EAClB1C,KAAKnF,YAAcA,EACnBmF,KAAK/E,SAAW,IAChB+E,KAAK5E,UAAY,IACjBuH,EAAgBA,MAEbA,EAAcC,SAEfD,EAAclG,IADY,OAAxBkG,EAAcC,QAEf/F,MAAO,gBACPH,KAAM,MACN7B,YAAamF,KAAKnF,YAClBD,IAAK,SAAUiI,GACd,MAAO7C,MAAKnF,YAAc,mBAAqBgI,GAEhDhF,WAAY,SAAUR,GACrB,MAAOA,GAAQwD,KAAK7F,QAAQ,wBAAyB,OAAS,MAK/D0B,KAAM,OACN7B,YAAamF,KAAKnF,YAClBD,IAAK,SAAUiI,GACd,MAAO7C,MAAKnF,YAAc,oBAAsBgI,GAEjDhF,WAAY,SAAUR,GACrB,MAAwB,SAArBA,EAAQyF,KAAKjE,OAAoBxB,EAAQyF,KAAKlI,KAAOyC,EAAQyF,KAAKX,eAC7D,cAAgB9E,EAAQyF,KAAKlI,KAAOyC,EAAQyF,KAAKX,eAAiB,OAEnE9E,EAAQyF,KAAKjC,MAAQ,KAI/Bb,KAAKnF,YAAc,KAGpB,KAAI,GAAI2C,KAAYmF,GACnB3C,KAAKxC,GAAYmF,EAAcnF,EAGhCwC,MAAKxE,OAASwE,KAAKxE,QAAU,OAC7BwE,KAAK1E,kBAAoB0E,KAAK1E,mBAAqB,WACnD0E,KAAKzD,SAAWyD,KAAKzD,WACpBC,IAAK,KAaPxC,EAAEmF,GAAG4D,qBAAuB,SAAUxF,EAAMsB,EAAM6D,EAAiB7H,EAAa8H,GAC/E,IAAI,GAAIhI,GAAI,EAAGA,EAAIX,EAAEmF,GAAGC,OAAOmD,UAAUrI,OAAQS,IAChD,GAAGX,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAG4C,OAASA,IACxB,OAATsB,IACF7E,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAGkE,KAAOA,GAEV,OAApB6D,IACF1I,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAG6H,WAAaE,GAEpB,OAAhB7H,IACFb,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAGE,YAAcA,GAEnB,OAAlB8H,GAAwB,CAC1B3I,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAGgI,cAAgBA,CACzC,KAAI,GAAInF,KAAYmF,GACH,OAAbnF,GAAiD,OAA5BmF,EAAcnF,KACrCxD,EAAEmF,GAAGC,OAAOmD,UAAU5H,GAAG6C,GAAYmF,EAAcnF,MASzDxD,EAAEmF,GAAGC,OAAOmD,WAEX,GAAIvI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,mCAAoC,qBAAsB,qBAAsB,qDACnIvE,cAAe,sCACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,SAeV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,kBAAmB,sBAAuB,aAAc,kBAAmB,iCAC7HG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,SAAU,6BAA8B,6CACpFvE,cAAe,uCACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,qBAAsB,6CACxEvE,cAAe,mBACf3B,UACC6B,MAAO,MACPC,OAAQ,MACRF,UAAW,kBAGb,GAAInE,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,SAAU,qBAAsB,wJACtEvE,cAAe,sBACf3B,UACC6B,MAAO,MACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,eAAgB,SAAU,+BAAgC,sEACxFvE,cAAe,uCACf3B,UACC6B,MAAO,MACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,SAAU,8BAA+B,wDACrFvE,cAAe,gCACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRF,UAAW,YAGb,GAAInE,GAAEmF,GAAGC,OAAOqD,eAAe,iBAAkB,SAAU,+BAAgC,gGAC1FvE,cAAe,sBACf3B,UACC6B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,SAAU,2BAA4B,6CAChFvE,cAAe,4BACf3B,UACC6B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,SAAU,0CAA+C,kDACnGvE,cAAe,mDACf3B,UACC6B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,oBAAqB,uDACxEvE,cAAe,0BACf3B,UACCC,IAAK,SACL4B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,oCAAqC,+BACxFvE,cAAe,6BACf3B,UACC6B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,SAAU,wBAAyB,eAAgB,oCAC1FvE,cAAe,cACf3B,UACCC,IAAK,SACL4B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,SAAU,wBAAyB,iCAC1EvE,cAAe,cACf3B,UACCC,IAAK,SACL4B,MAAO,IACPC,OAAQ,IACRC,QAAS,KAGX,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,SAAU,4BAA6B,mDAC9EvE,cAAe,oBACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRC,QAAS,KAGX,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,SAAU,+BAAiC,mCAClFvE,cAAe,iBACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRC,QAAS,KAGX,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,4BAA6B,8DAC/EvE,cAAe,yBACf3B,UACC6B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,SAAU,gBAAiB,0BAClE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,eAAgB,SAAU,sDAAuD,0DAA2D,oCAAqC,oDAC/MG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,uBAAwB,sCAC5E,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,SAAU,uBAAwB,uCACzE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,4BAA6B,gCAChFG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,SAAU,2CAA4C,uCAChGG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,SAAU,yBAA0B,gCAC1EG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,uBAAwB,+BAC1EG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,SAAU,oCAA2C,mBAAuB,gCAAsC,gBAAmB,+BAC7K,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,SAAU,wBAAyB,8CACjF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,SAAU,uBAAwB,kCACxEG,OAAQ,QAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,gCAAiC,SAAU,oBAAqB,6CAC9FG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,MAAO,SAAU,kBAAmB,kCAClEG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,SAAU,mBAAoB,oCAC1E,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,wBAAyB,qCAC3EG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,SAAU,wCAAyC,0CACjG,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,oBAAqB,iCACzE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,MAAO,SAAU,aAAc,sCAC9D,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,SAAU,mBAAoB,8CACzE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,SAAU,gBAAiB,gDACtEG,OAAQ,SAIT,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,QAAS,kBAAmB,sCACzEG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,eAAgB,+BAClEG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,QAAS,iCAAkC,gCACxF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,wCAAyC,qCAC5F,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,iBAAkB,eAAgB,iCACrF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,mBAAoB,mCACvEG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,WAAY,YAAa,mCAC7E,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,QAAS,oBAAqB,aAAc,gCACxFjH,OAAQ,OAET,GAAIxB,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,2BAA4B,MAC/EhG,KACCI,MAAO,mDACPH,KAAM,OACNmB,WAAY,SAAUR,GACrB,MAAOA,GAAQD,KAAO,yCAA2CC,EAAQD,KAAKM,QAAU,wDAAyD,MAMpJ,GAAI1D,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,SAAU,oBAAqB,YAAa,qBAAsB,wCAC9GjH,OAAQ,UAET,GAAIxB,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,iBAAkB,MACpEhG,KACCI,MAAO,OACPH,KAAM,OACN9B,IAAK,SAAUiI,GACd,MAAO,6CAA+CA,GAEvDhF,WAAY,SAAUhC,GACrB,MAAO7B,GAAEmF,GAAGC,OAAOC,aAAaxD,EAAKiH,KAAKlI,IAAKiB,EAAKiH,UAIvD,GAAI9I,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,SAAU,kCAAmC,cAAe,qCAC1G,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,0BAA2B,qCAC7EnH,kBAAmB,iBAEpB,GAAItB,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,SAAU,wCAAyC,kCACjG,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,SAAU,6BAA8B,mCAIpF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,4BAA6B,2CAEjF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,SAAU,yBAA0B,+CAC9EvE,cAAe,qBACfc,aAAc,SAAUnD,GACvB,MAAIA,GAAKmH,iBACF,aAAenH,EAAKmH,iBAAmB,OADZ,KAIpC,GAAIhJ,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,SAAU,4BAA6B,wCACjFvE,cAAe,mBACf3B,UACCC,IAAK,OAEN8B,QAAS,IASV,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,SAAU,6BAA8B,6DACpFvE,cAAe,wBACf3B,UACCC,IAAK,OAEN8B,QAAS,IAEV,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,SAAU,+BAAgC,iCAChFG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,SAAU,eAAgB,+BAClEvE,cAAe,mBACf3B,UACCC,IAAK,OAEN8B,QAAS,IAEV,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,SAAU,oBAAqB,oCAC5EvE,cAAe,oBACf3B,UACCC,IAAK,OAEN8B,QAAS,IAEV,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,SAAU,0BAA2B,4BAChFvE,cAAe,wBACf3B,UACCC,IAAK,OAEN8B,QAAS,IAEV,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,kBAAmB,MACvEhG,KACCI,MAAO,8CACPH,KAAM,gBAGR,GAAI1C,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,SAAU,aAAc,MACjEvE,cAAe,oBACfe,SAAU,SAAUgE,EAAIC,GACvB,MAAO,wCAA0CA,EAAMC,MAAQ,6CAKjE,GAAInJ,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,kBAAmB,kDACtE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,QAAS,wBAAyB,eAAgB,+BACzF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,QAAS,wBAAyB,oCAC1E,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,QAAS,gBAAiB,gCAClE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,sCAAuC,mCAC5F,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,0BAA2B,0CAC5EG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,yBAA0B,+BAC9EG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,QAAS,sBAAuB,sCAC7EG,OAAQ,SAET,GAAI5I,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,sBAAuB,4DACzEvE,cAAe,kBACf3B,UACC6B,MAAO,IACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,QAAS,qBAAsB,6CAC3EvE,cAAe,6BACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRF,UAAW,gJAGb,GAAInE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,QAAS,gBAAiB,yCACjEvE,cAAe,sBACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRF,UAAW,0FAGb,GAAInE,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,0BAA2B,MAC/EvE,cAAe,oBACfe,SAAU,SAAUgE,EAAIG,GAIvB,MAHAC,YAAW,WACPC,YAAYA,cACb,KACI,YAAcF,EAAS,oIAGhC,GAAIpJ,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,wBAAyB,gCAC3E,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,QAAS,YAAa,iDAC5DvE,cAAe,8BACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRF,UAAW,+EAGb,GAAInE,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,yBAA0B,2FAC9EvE,cAAe,oCACfc,aAAc,SAAUnD,GACvB,IAAIA,EAAK0H,MAAO,OAAO,CACvB,IAAIlC,GAAOxF,EAAK0H,MAAY,KAAE,KAAKvI,QAAQ,gBAAiB,qCAC5D,OAAO,sEAAwEa,EAAK0H,MAAoB,aAAI,gBAAiBlB,OAAOhB,GAAMA,OAAOiB,UAAU,EAAE,KAAO,4BAGtK,GAAItI,GAAEmF,GAAGC,OAAOqD,eAAe,OAAQ,QAAS,qBAAsB,2CACrEvE,cAAe,wBACfc,aAAc,SAAUnD,GACvB,MAAIA,GAAK2H,MACF,yEAA2E3H,EAAK4H,OAAS,MAAQ5H,EAAK2H,MAAQ,SAAW3H,EAAK6H,KAAO,oBAAsB7H,EAAK8H,WAAa,eAAiB9H,EAAK+H,MAAQ,kBAAoB/H,EAAKgI,OAAS,4CAA8ChI,EAAKiI,KAAO,gBADvR,KAIzB,GAAI9J,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,QAAS,oBAAqB,8CAC3EvE,cAAe,qFACfc,aAAc,SAAUnD,GACvB,MAAIA,GAAKkI,SACF,kBAAoBlI,EAAKmI,MAAQ,8FAAgGnI,EAAKkI,SAAW,8IAAgJlI,EAAKkI,SAAW,sBAAwBlI,EAAKkI,SAAW,oBAAsBlI,EAAK0B,KAAO,UADxW,KAI5B,GAAIvD,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,QAAS,oCAAqC,8DAC1FvE,cAAe,2BACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,iBAAkB,QAAS,oCAAqC,MAC9FvE,cAAe,OACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,wBAAyB,kEAC5EvE,cAAe,oBACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,QAAS,gBAAiB,yBACjEvE,cAAe,oBACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,2BAA4B,OAC9EvE,cAAe,OACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,oBAAqB,mCACvEvE,cAAe,mBACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,SAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,uBAAwB,wGAC3EvE,cAAe,OACf3B,UACCC,IAAK,SACL4B,MAAO,QACPC,OAAQ,UAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,kCAAmC,wEACvFvE,cAAe,wBACf3B,UACC6B,MAAO,IACPC,OAAQ,IACRC,QAAS,KAGX,GAAItE,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,2BAA4B,6CAC/EvE,cAAe,gBACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,UAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,QAAS,QAAS,gBAAiB,yCACjEvE,cAAe,oBACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,UAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,0BAA2B,MAC5EhG,KACCI,MAAO,qCAGT,GAAI7C,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,sBAAuB,iCACzE,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,kCAAmC,iDACpFvE,cAAe,2BACfc,aAAc,SAAUnD,GACvB,MAAIA,GAAKA,KAAKoI,SACP,2EAA6EpI,EAAKA,KAAKqI,SAAW,iEAAmErI,EAAKA,KAAKoI,SAAW,uBAAyBpI,EAAKA,KAAKsI,SAAW,+DAAsEtI,EAAKA,KAAKoI,SAAW,sBAAwBpI,EAAKA,KAAKuI,MAAQ,8BAAgCvI,EAAKA,KAAKoI,SAAW,KAAOpI,EAAKA,KAAK0B,KAAO,yEAA2E1B,EAAKA,KAAKwI,YAAc,qDAA4DxI,EAAKA,KAAKyI,UAAY,oBADvlB,KAIjC,GAAItK,GAAEmF,GAAGC,OAAOqD,eAAe,WAAY,QAAS,+CAAgD,+CACnGvE,cAAe,sDACfc,aAAc,SAAUnD,GACvB,IAAIA,EAAK0I,GAAI,OAAO,CACpB,IAAIC,GAAM,oHAeV,OAdcA,IAAX3I,EAAKa,KAAa,oCAAsCb,EAAKa,KAAK6H,GAAK,KAAO1I,EAAKa,KAAKa,KAAO,OAC1F1B,EAAK4I,KAAa,YAAc5I,EAAK4I,KAAO,KAAO5I,EAAK0B,KAAO,OAC/D1B,EAAKkI,SAAiB,oCAAsClI,EAAKkI,SAAW,KAAOlI,EAAK0B,KAAO,OAC3F,oCAAsC1B,EAAK0I,GAAK,KAAO1I,EAAK0B,KAAO,OAC/EiH,GAAO,mEACUA,GAAd3I,EAAK6I,QAAgB,YAAc7I,EAAK4I,KAAO,eAAiB5I,EAAK6I,QAAU,SACtE,wCAA0C7I,EAAK0I,GAAK,aAC7D1I,EAAKa,OAAM8H,GAAO,YAAc3I,EAAK4I,KAAO,KAAO5I,EAAK0B,KAAO,QAC/D1B,EAAK8I,UAASH,GAAO,oBAAsB3I,EAAK8I,QAAU,iBAC1D9I,EAAK+I,WAAUJ,GAAO,qBAAuB3I,EAAK+I,SAAW,iBAC7D/I,EAAKgJ,UAASL,GAAO,6BAA+B3I,EAAKgJ,QAAU,KAAOhJ,EAAKgJ,QAAU,qBACzFhJ,EAAKiJ,SAAQN,GAAO,mBAAqB3I,EAAKiJ,OAAS,iBACvDjJ,EAAKwI,cAAaG,GAAO3I,EAAKwI,YAAc,QAC/CG,GAAO,kBAIT,GAAIxK,GAAEmF,GAAGC,OAAOqD,eAAe,gBAAiB,QAAS,sCAAuC,mEAC/FvE,cAAe,yBACfc,aAAc,SAAUnD,GACvB,IAAIA,EAAKkJ,UAAW,OAAO,CAC3B,IAAI/H,GAAInB,EAAKkJ,UAAU,GACnBC,EAAOhL,EAAEgD,EAAEgI,MAAM3D,OACjBmD,EAAM,yPAAgQxH,EAAEiI,cAAgBjI,EAAEkI,iBAAmB,mHAA0HlI,EAAEmI,aAAe,2DAA6DnI,EAAEoI,WAAa,2IAAkJpI,EAAEqI,YAAc,MAAQrI,EAAEY,MAAQ,2CAAkDoH,EAAK1C,UAAU,EAAG,KAAO,uCACvwB,KAAI3H,IAAKqC,GAAEsI,KACVd,GAAO,0FAA4FxH,EAAEsI,KAAK3K,GAAK,KAAOqC,EAAEsI,KAAK3K,GAAK,MAEnI,OADA6J,IAAO,mJAAqJxH,EAAEuI,MAAMC,QAAU,IAAMxI,EAAEuI,MAAME,aAAe,4EAAmFzI,EAAEuI,MAAMG,WAAa,yHAAgI1I,EAAEuI,MAAMC,QAAU,IAAMxI,EAAEuI,MAAME,aAAe,KAAOzI,EAAEuI,MAAME,aAAe,6EAA+EzI,EAAEuI,MAAMI,WAAa;IAItmB,GAAI3L,GAAEmF,GAAGC,OAAOqD,eAAe,YAAa,QAAS,qBAAsB,uBAAwB,sBAAuB,cAAe,qEACzI,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,eAAiB,mCACnEvE,cAAe,iBACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,gCAAiC,wEACnFvE,cAAe,iBACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,mBAAoB,uEACrEvE,cAAe,oBACf3B,UACCC,IAAK,SACL4B,MAAO,OACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,QAAS,iCAAkC,uBACxFvE,cAAe,aACf3B,UACCC,IAAK,SACL4B,MAAO,MACPC,OAAQ,OAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,SAAU,QAAS,cAAe,iCAAkC,+JAClGjE,QAAQ,EACRN,cAAe,2BACf3B,UACCC,IAAK,SACL4B,MAAO,QACPC,OAAQ,WAGV,GAAIrE,GAAEmF,GAAGC,OAAOqD,eAAe,aAAc,QAAS,kBAAoB,0CACzEjH,OAAQ,UAET,GAAIxB,GAAEmF,GAAGC,OAAOqD,eAAe,cAAe,QAAS,gCAAiC,mCACxF,GAAIzI,GAAEmF,GAAGC,OAAOqD,eAAe,UAAW,QAAS,sBAAuB,MACzEhG,KACCI,MAAO,+BACPH,KAAM,aACNmB,WAAY,SAAUR,GACrB,MAAIA,GAAQF,OACL,kCAAoCE,EAAQF,OAAS,UADjC,MAK9B,GAAInD,GAAEmF,GAAGC,OAAOqD,eAAe,gBAAiB,QAAS,+BAAgC,MACxFhG,KACCI,MAAO,aACPH,KAAM,aACNmB,WAAY,SAAUR,GACrB,MAAIA,GAAQF,OACL,sCAAwCE,EAAQF,OAAS,UADrC,QAM7BkF,QAGHuD,OAAOC,UAAU1C,IAAM,WACtB,GAAI2C,GAAI,SAAUA,EAAGC,GACpB,GAAIC,IAAS,MAAJF,IAAkB,MAAJC,GACnBE,GAAKH,GAAK,KAAOC,GAAK,KAAOC,GAAK,GACtC,OAAOC,IAAK,GAAS,MAAJD,GAEdD,EAAI,SAAUD,EAAGC,GACpB,MAAOD,IAAKC,EAAID,IAAM,GAAKC,GAExBC,EAAI,SAAUA,EAAGC,EAAGtE,EAAGuE,EAAGC,EAAGC,GAChC,MAAON,GAAEC,EAAED,EAAEA,EAAEG,EAAGD,GAAIF,EAAEI,EAAGE,IAAKD,GAAIxE,IAEjCsE,EAAI,SAAUH,EAAGC,EAAGE,EAAGtE,EAAGuE,EAAGC,EAAGC,GACnC,MAAOJ,GAAED,EAAIE,GAAKF,EAAIpE,EAAGmE,EAAGC,EAAGG,EAAGC,EAAGC,IAElCzE,EAAI,SAAUmE,EAAGC,EAAGE,EAAGtE,EAAGuE,EAAGC,EAAGC,GACnC,MAAOJ,GAAED,EAAIpE,EAAIsE,GAAKtE,EAAGmE,EAAGC,EAAGG,EAAGC,EAAGC,IAElCF,EAAI,SAAUJ,EAAGC,EAAGE,EAAGtE,EAAGuE,EAAGC,EAAGC,GACnC,MAAOJ,GAAED,EAAIE,EAAItE,EAAGmE,EAAGC,EAAGG,EAAGC,EAAGC,IAE7BD,EAAI,SAAUL,EAAGC,EAAGE,EAAGtE,EAAGuE,EAAGC,EAAGC,GACnC,MAAOJ,GAAEC,GAAKF,GAAKpE,GAAImE,EAAGC,EAAGG,EAAGC,EAAGC,IAEhCA,EAAI,SAAUL,GACjB,GAAIC,GAAGI,EAAGzL,EAAG0F,EAAGgG,EAAG/I,EAAIyI,EAAE7L,OACrBoM,EAAI,WACJC,EAAI,WACJC,EAAI,YACJC,EAAI,SACR,KAAIJ,EAAI,EAAO/I,EAAJ+I,EAAOA,GAAK,GACtBL,EAAIM,EACJF,EAAIG,EACJ5L,EAAI6L,EACJnG,EAAIoG,EACJH,EAAIL,EAAEK,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIR,EAAEQ,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,YAChCG,EAAIP,EAAEO,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,WAChCE,EAAIN,EAAEM,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,aAChCC,EAAIL,EAAEK,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIR,EAAEQ,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,YAChCG,EAAIP,EAAEO,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,aAChCE,EAAIN,EAAEM,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,WAChCC,EAAIL,EAAEK,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIR,EAAEQ,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,aAChCG,EAAIP,EAAEO,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,QACjCE,EAAIN,EAAEM,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,IAAK,GAAI,aACjCC,EAAIL,EAAEK,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,IAAK,EAAG,YAChCI,EAAIR,EAAEQ,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,IAAK,GAAI,WACjCG,EAAIP,EAAEO,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,aACjCE,EAAIN,EAAEM,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,IAAK,GAAI,YACjCC,EAAI3E,EAAE2E,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAI9E,EAAE8E,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,EAAG,aAC/BG,EAAI7E,EAAE6E,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,WACjCE,EAAI5E,EAAE4E,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,YAChCC,EAAI3E,EAAE2E,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAI9E,EAAE8E,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,IAAK,EAAG,UAChCG,EAAI7E,EAAE6E,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,YACjCE,EAAI5E,EAAE4E,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,YAChCC,EAAI3E,EAAE2E,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,WAC/BI,EAAI9E,EAAE8E,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,IAAK,EAAG,aAChCG,EAAI7E,EAAE6E,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,YAChCE,EAAI5E,EAAE4E,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,YAChCC,EAAI3E,EAAE2E,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,IAAK,EAAG,aAChCI,EAAI9E,EAAE8E,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,EAAG,WAC/BG,EAAI7E,EAAE6E,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,YAChCE,EAAI5E,EAAE4E,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,IAAK,GAAI,aACjCC,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,SAC/BI,EAAIP,EAAEO,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,aAChCG,EAAIN,EAAEM,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,YACjCE,EAAIL,EAAEK,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,IAAK,GAAI,WACjCC,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,aAC/BI,EAAIP,EAAEO,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,YAChCG,EAAIN,EAAEM,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,YAChCE,EAAIL,EAAEK,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,IAAK,GAAI,aACjCC,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,IAAK,EAAG,WAChCI,EAAIP,EAAEO,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,YAChCG,EAAIN,EAAEM,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,YAChCE,EAAIL,EAAEK,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,UAChCC,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIP,EAAEO,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,IAAK,GAAI,YACjCG,EAAIN,EAAEM,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,WACjCE,EAAIL,EAAEK,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,YAChCC,EAAIH,EAAEG,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIN,EAAEM,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,YAChCG,EAAIL,EAAEK,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,aACjCE,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,WAChCC,EAAIH,EAAEG,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,IAAK,EAAG,YAChCI,EAAIN,EAAEM,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,GAAI,GAAI,aAChCG,EAAIL,EAAEK,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,IAAK,GAAI,UACjCE,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,aAChCC,EAAIH,EAAEG,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIN,EAAEM,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,IAAK,GAAI,WACjCG,EAAIL,EAAEK,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,aAChCE,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,IAAK,GAAI,YACjCC,EAAIH,EAAEG,EAAGC,EAAGC,EAAGC,EAAGV,EAAEM,EAAI,GAAI,EAAG,YAC/BI,EAAIN,EAAEM,EAAGH,EAAGC,EAAGC,EAAGT,EAAEM,EAAI,IAAK,GAAI,aACjCG,EAAIL,EAAEK,EAAGC,EAAGH,EAAGC,EAAGR,EAAEM,EAAI,GAAI,GAAI,WAChCE,EAAIJ,EAAEI,EAAGC,EAAGC,EAAGH,EAAGP,EAAEM,EAAI,GAAI,GAAI,YAChCC,EAAIR,EAAEQ,EAAGN,GACTO,EAAIT,EAAES,EAAGH,GACTI,EAAIV,EAAEU,EAAG7L,GACT8L,EAAIX,EAAEW,EAAGpG,EAEV,QAAQiG,EAAGC,EAAGC,EAAGC,IAEd9L,EAAI,SAAUmL,GACjB,GAECG,GAFGF,EAAI,mBACPC,EAAI,GACDrE,EAAe,EAAXmE,EAAE5L,MACV,KAAI+L,EAAI,EAAOtE,EAAJsE,EAAOA,IACjBD,GAAKD,EAAE3L,OAAO0L,EAAEG,GAAK,IAAMA,EAAI,EAAI,EAAI,EAAI,IAAMF,EAAE3L,OAAO0L,EAAEG,GAAK,IAAMA,EAAI,EAAI,EAAI,GAEpF,OAAOD,IAEJ3F,EAAI,SAAUyF,GACjB,GAECG,GACAC,EAHGH,GAAKD,EAAE5L,OAAS,GAAK,GAAK,EAC1B8L,KACArE,EAAQ,GAAJoE,EACJI,EAAIL,EAAE5L,MACV,KAAI+L,EAAI,EAAOtE,EAAJsE,EAAOA,IACjBD,EAAEU,KAAK,EAER,KAAIR,EAAI,EAAOC,EAAJD,EAAOA,IACjBF,EAAEE,GAAK,KAAyB,IAAlBJ,EAAEa,WAAWT,KAAaA,EAAI,EAAI,CAIjD,OAFAF,GAAEE,GAAK,IAAM,KAAOA,EAAI,EAAI,EAC5BF,EAAM,GAAJD,EAAS,GAAS,EAAJI,EACTH,EAER,OAAOrL,GAAEyL,EAAE/F,EAAEL"} \ No newline at end of file +{"version":3,"file":"jquery.oembed.min.js","sources":["jquery.oembed.js"],"names":["$","rand","length","current","charAt","Math","floor","random","getRequestUrl","provider","externalUrl","i","url","apiendpoint","qs","indexOf","replace","maxWidth","params","maxwidth","maxHeight","maxheight","callbackparameter","escape","format","dataType","success","oembedData","container","data","code","settings","beforeEmbed","call","onEmbed","afterEmbed","embedCode","embedProvider","undefined","embedtag","tag","yql","from","query","test","xpath","ajaxopts","extend","q","env","callback","result","meta","results","l","name","property","toLowerCase","content","hasOwnProperty","title","datareturn","error","onError","ajaxOptions","ajax","templateRegex","flashvars","width","height","nocache","src","apikey","apikeys","attr","allowfullscreen","css","type","scrolling","frameborder","templateData","template","requestUrl","fn","oembed","getPhotoCode","getRichCode","getGenericCode","getNormalizedParams","key","normalizedParams","options","embedAction","defaults","shortURLList","appendTo","this","each","resourceURL","insertCode","embedMethod","j","regExp","RegExp","match","getOEmbedProvider","onProviderNotFound","includeHandle","replaceWith","html","wrap","oembedContainer","parent","insertBefore","click","encodedString","encodeURIComponent","text","children","last","toggle","append","clone","e","post_width","iframe_width_orig","iframe_height_orig","ratio","alt","author_name","provider_name","thumbnail_url","newURL","jQuery","substring","providers","urlschemes","OEmbedProvider","urlschemesarray","extraSettings","useYQL","externalurl","json","updateOEmbedProvider","image_teaser_url","wm","tourid","setTimeout","loadEmbeds","parse","Title","imdbID","Year","imdbRating","Genre","Actors","Plot","username","image","html_url","language","watchers","forks","description","pushed_at","id","out","link","picture","founded","category","website","gender","questions","body","up_vote_count","down_vote_count","answer_count","view_count","question_id","tags","owner","user_id","display_name","email_hash","reputation"],"mappings":"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"} \ No newline at end of file diff --git a/modules/editor/tpl/js/uploader.min.js b/modules/editor/tpl/js/uploader.min.js index ec564c3c9..889385e8f 100644 --- a/modules/editor/tpl/js/uploader.min.js +++ b/modules/editor/tpl/js/uploader.min.js @@ -1,2 +1,2 @@ -function previewFiles(a,b){var c,d,e,f,g,h,i=jQuery;if(!b){if(c=i(a.target).parent().addBack().filter("select").find(">option:selected"),!c.length)return;b=c.attr("value")}b&&is_def(e=uploadedFiles[b])&&(d=i("#"+e.previewAreaID).html(" "),d.length&&(f=e.download_url||"",g=f.match(/\.(?:(flv)|(swf)|(wmv|avi|mpe?g|as[fx]|mp3)|(jpe?g|png|gif))$/i),"Y"==e.direct_download&&g?g[1]?h='':g[2]?h='':g[3]?h='':g[4]&&(h=''):h='',h&&d.html(h)))}function removeUploadedFile(a){var b=uploaderSettings[a],c=b.fileListAreaID,d=get_by_id(c);if(d&&!(d.selectedIndex<0)){for(var e=[],f=0;f'):f.push(''+i.source_filename+"\n")}}if("html"==editorMode[a])f.length>0&&get_by_id("editor_textarea_"+a)&&(get_by_id("editor_textarea_"+a).value+=f.join(""));else{var j=editorGetIFrame(a);if(!j)return;f.length>0&&editorReplaceHTML(j,f.join(""))}}}}var uploadedFiles=[],uploaderSettings=[],loaded_images=[],swfUploadObjs=[],uploadSettingObj=[],uploadAutosaveChecker=!1;!function(a){function b(b){var d=b.editorSequence;is_def(d)&&(b=a.extend({sessionName:"PHPSESSID",allowedFileSize:2097152,allowedFileTypes:"*.*",allowedFileTypesDescription:"All Files",replaceButtonID:"swfUploadButton"+b.editorSequence,insertedFiles:0},b),uploadSettingObj[d]=b,a(function(){c(b)}))}function c(b){var c,d,g,h,i,j,k,l,m,n,o,p;i=b.editorSequence,j=b.replaceButtonID,c=a("#"+j).wrap(''),d=c.width(),g=c.height(),h=a('').insertAfter(c),k={flash_url:request_uri+"modules/editor/tpl/images/SWFUpload.swf",upload_url:request_uri.replace(/^https/i,"http")+"index.php",post_params:{mid:current_mid,act:"procFileUpload",editor_sequence:i,uploadTargetSrl:editorRelKeys[i].primary.value},http_success:[302],file_size_limit:Math.floor((parseInt(b.allowedFileSize,10)||1024)/1024),file_queue_limit:0,file_upload_limit:0,file_types:b.allowedFileTypes,file_types_description:b.allowedFileTypesDescription,custom_settings:{progressTarget:null,cancelButtonId:null},debug:!1,button_window_mode:"transparent",button_placeholder_id:h.attr("id"),button_text:null,button_image_url:request_uri+"common/img/blank.gif",button_width:d,button_height:g,button_text_style:null,button_text_left_padding:0,button_text_top_padding:0,button_cursor:-2,editorSequence:i,uploadTargetSrl:editorRelKeys[i].primary.value,fileListAreaID:b.fileListAreaID,previewAreaID:b.previewAreaID,uploaderStatusID:b.uploaderStatusID},"undefined"!=typeof enforce_ssl&&enforce_ssl&&(k.upload_url=request_uri+"index.php"),a("#"+b.fileListAreaID).click(previewFiles),l={file_queued:"FileQueued",file_queue_error:"FileQueueError",file_dialog_complete:"FileDialogComplete",upload_start:"UploadStart",upload_progress:"UploadProgress",upload_error:"UploadError",upload_success:"UploadSuccess",upload_complete:"UploadComplete",queue_complete:"QueueComplete"};for(m in l)l.hasOwnProperty(m)&&(n="on"+l[m],k[m+"_handler"]=b["on"+n]||f[n]);is_def(window.xeVid)&&(k.post_params.vid=xeVid),k.sessionName=b.sessionName,getCookie(b.sessionName)&&(k.post_params[b.sessionName]=getCookie(b.sessionName)),uploaderSettings[i]=k,o=new SWFUpload(k),p=a("#"+o.movieName),swfUploadObjs[i]=o.movieName,p.length&&(p.css({display:"block",cursor:"pointer",position:"absolute",left:0,top:0,width:d+"px",height:g+"px"}),(b.insertedFiles||editorRelKeys[i].primary.value)&&e(b))}function d(){return!0}function e(b){function c(){"function"==typeof _editorAutoSave&&(uploadAutosaveChecker=!0,_editorAutoSave(!0))}function d(d){var e,f,g,h,i,j,k,l,m,n,o;if(f=d.editor_sequence,g=d.files,i=d.upload_status,h=d.upload_target_srl,j=Math.floor((parseInt(d.left_size,10)||0)/1024),e=a("#"+b.fileListAreaID).empty(),h&&(editorRelKeys[f].primary.value!=h&&(editorRelKeys[f].primary.value=h,c()),editorRelKeys[f].primary.value=h,b.uploadTargetSrl=h),a("#"+b.uploaderStatusID).html(i),a("#"+b.previewAreaID).empty(),g&&g.item){for(k=g.item,a.isArray(k)||(k=[k]),l=0,m=k.length;m>l;l++)n=k[l],o=n.file_srl,uploadedFiles[o]=n,n.previewAreaID=b.previewAreaID,/\.(jpe?g|png|gif)$/i.test(n.download_url)&&(loaded_images[o]=a("").attr("src",n.download_url).get(0)),a("