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/.travis.yml b/.travis.yml
index cb2c700cf..c2eef4e9c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: php
php:
- - 5.2
- 5.3
- 5.4
- 5.5
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',
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/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 '
';
- }
- }),
//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)))
-}
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
';else if(b.thumbnail_url){var e=b.thumbnail_url.replace("_s","_b");c=''}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'
'}}),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?'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?'":!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.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='',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)
'+d.substring(0,100)+'...
"
-}}),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
';else if(b.thumbnail_url){var e=b.thumbnail_url.replace("_s","_b");c=''}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?'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?'":!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.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='',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)
'+d.substring(0,100)+'...
"
+}}),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":"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"}
\ 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/classes/context/Context.class.php b/classes/context/Context.class.php
index fd3dd69b4..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);
@@ -1277,16 +1284,11 @@ class Context
return $stack;
}
- $body = $this->_filterRequestVar($key, trim($val->body ? $val->body : ''), 0);
- if($body)
- {
- return $body;
- }
-
+ $body = $val->body;
unset($val->node_name, $val->attrs, $val->body);
if(!count(get_object_vars($val)))
{
- return NULL;
+ return $this->_filterRequestVar($key, $body, 0);
}
$stack = new stdClass();
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);
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)
{
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);
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/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) == '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');
@@ -1067,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;
}
@@ -1505,7 +1553,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 .= '| '
+ . str_repeat('-', $i) . ' ' . $cause['class'] . ': '
+ . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' '
+ . 'on line ' . $cause['line'] . ''
+ . " |
\n";
+ }
+ $html .= '| Exception trace |
' . "\n"
+ . '| # | '
+ . 'Function | '
+ . 'Location |
' . "\n";
+
+ foreach ($trace as $k => $v) {
+ $html .= '| ' . $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')
+ . ' |
' . "\n";
+ }
+ $html .= '| ' . ($k+1) . ' | '
+ . '{main} | '
+ . ' |
' . "\n"
+ . '
';
+ 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 = 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}
+
+