v1.2.5.406

This commit is contained in:
Timur Usenko 2013-09-24 23:04:44 +04:00
parent 03602d0c0f
commit 04430868b1
431 changed files with 64715 additions and 0 deletions

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
Creative Commons — Attribution-NonCommercial 3.0 Unported — CC BY-NC 3.0
(http://creativecommons.org/licenses/by-nc/3.0/)
You are free:
to Share — to copy, distribute and transmit the work
to Remix — to adapt the work
Under the following conditions:
Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
Noncommercial — You may not use this work for commercial purposes.
With the understanding that:
Waiver — Any of the above conditions can be waived if you get permission from the copyright holder.
Public Domain — Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license.
Other Rights — In no way are any of the following rights affected by the license:
Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations;
The author's moral rights;
Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights.
Notice — For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page.

1
data/VERSION Normal file
View file

@ -0,0 +1 @@
1.2.5.406

42
index.php Normal file
View file

@ -0,0 +1,42 @@
<?php
define('APP_INDEX_ROOT_PATH', rtrim(dirname(__FILE__), '\\/').'/');
define('APP_INDEX_FILE_NAME', !empty($_SERVER['PHP_SELF']) ? basename($_SERVER['PHP_SELF']) : 'index.php');
$sCustomDataPath = '';
if (file_exists(APP_INDEX_ROOT_PATH.'include.php'))
{
include_once APP_INDEX_ROOT_PATH.'include.php';
$sCustomDataPath = function_exists('__get_custom_data_full_path') ? trim(__get_custom_data_full_path()) : '';
}
define('APP_DATA_FOLDER_PATH', 0 === strlen($sCustomDataPath) ? APP_INDEX_ROOT_PATH.'data/' : $sCustomDataPath);
$sVersion = @file_get_contents(APP_DATA_FOLDER_PATH.'VERSION');
if (false !== $sVersion)
{
$sVersion = trim(preg_replace('/[\.]+/', '.', preg_replace('/[^a-zA-Z0-9\.\-_]/', '', $sVersion)));
if (0 < strlen($sVersion))
{
define('APP_VERSION', $sVersion);
if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/index.php'))
{
include APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/index.php';
}
else
{
echo 'Can\'t find startup file (Error Code: 103)';
exit(103);
}
}
else
{
echo 'Version file content error (Error Code: 102)';
exit(102);
}
}
else
{
echo 'Can\'t read version file (Error Code: 101)';
exit(101);
}

View file

@ -0,0 +1 @@
8430218614adbb81a84b63b4d4882f49d6485207

View file

@ -0,0 +1 @@
1.2.5.406

View file

@ -0,0 +1 @@
Deny from all

View file

@ -0,0 +1 @@
gmail.com,yahoo.com

View file

@ -0,0 +1,7 @@
imap_host = "imap.gmail.com"
imap_port = 993
imap_secure = "SSL"
smpt_host = "smtp.gmail.com"
smpt_port = 465
smpt_secure = "SSL"
smpt_auth = On

View file

@ -0,0 +1,7 @@
imap_host = "imap.mail.yahoo.com"
imap_port = 993
imap_secure = "SSL"
smpt_host = "smtp.mail.yahoo.com"
smpt_port = 465
smpt_secure = "SSL"
smpt_auth = On

View file

@ -0,0 +1,39 @@
<?php
namespace RainLoop;
if (!\defined('RAINLOOP_APP_ROOT_PATH'))
{
\define('RAINLOOP_APP_LIBRARIES_PATH', \rtrim(\realpath(__DIR__), '\\/').'/libraries/');
\spl_autoload_register(function ($sClassName) {
if (false !== \strpos($sClassName, '\\'))
{
foreach (array('RainLoop', 'Buzz', 'KeenIO') as $sName)
{
if (0 === \strpos($sClassName, $sName))
{
return include RAINLOOP_APP_LIBRARIES_PATH.$sName.'/'.\str_replace('\\', '/', \substr($sClassName, \strlen($sName) + 1)).'.php';
}
}
}
return false;
});
if (\class_exists('RainLoop\Service'))
{
$oException = null;
try
{
include APP_VERSION_ROOT_PATH.'app/libraries/MailSo/MailSo.php';
}
catch (\Exception $oException) {}
if (!$oException)
{
\RainLoop\Service::NewInstance()->Handle();
}
}
}

View file

@ -0,0 +1,3 @@
[LANGS_NAMES]
LANG_EN = "English"
LANG_RU = "Русский (Russian)"

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : bulgarian (bg)
// author : Krasen Borisov : https://github.com/kraz
(function(){var a={months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янрев_мар_апрай_юни_юли_авг_сеп_окт_ноеек".split("_"),weekdays:еделя_понеделник_вторник_срядаетвъртък_петък_събота".split("_"),weekdaysShort:ед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"h:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinal:function(a){return"."}};typeof module!="undefined"&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("bg",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : catalan (ca)
// author : Juan G. Hurtado : https://github.com/juanghurtado
(function(){var a={months:"Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"),monthsShort:"Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"),weekdays:"Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"),weekdaysShort:"Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(this.hours()!==1?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(this.hours()!==1?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(this.hours()!==1?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(this.hours()!==1?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(this.hours()!==1?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ca",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : chuvash (cv)
// author : Anatoly Mironov : https://github.com/mirontoli
(function(){var a={months:"кăрлач_нарăс_пуш_акаай_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),monthsShort:"кăрар_пуш_акаай_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),weekdaysShort:"вырун_ытл_юн_кĕç_эрн_шăм".split("_"),weekdaysMin:р_тн_ыт_юн_кç_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ",LLL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT",LLLL:"dddd, YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ĕнер] LT [сехетре]",nextWeek:"[Çитес] dddd LT [сехетре]",lastWeek:"[Иртнĕ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:"%sран",past:"%s каялла",s:"пĕр-ик çеккунт",m:"пĕр минут",mm:"%d минут",h:"пĕр сехет",hh:"%d сехет",d:"пĕр кун",dd:"%d кун",M:"пĕр уйăх",MM:"%d уйăх",y:"пĕр çул",yy:"%d çул"},ordinal:function(a){return"-мĕш"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("cv",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : danish (da)
// author : Ulrik Nielsen : https://github.com/mrbase
(function(){var a={months:"Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"),weekdays:"Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"),weekdaysShort:"Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"),weekdaysMin:"Sø_Ma_Ti_On_To_Fr_Lø".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd D. MMMM, YYYY h:mm A"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"minut",mm:"%d minutter",h:"time",hh:"%d timer",d:"dag",dd:"%d dage",M:"månede",MM:"%d måneder",y:"år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("da",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : german (de)
// author : lluchs : https://github.com/lluchs
(function(){var a={months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm U\\hr",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:"einer Minute",mm:"%d Minuten",h:"einer Stunde",hh:"%d Stunden",d:"einem Tag",dd:"%d Tagen",M:"einem Monat",MM:"%d Monaten",y:"einem Jahr",yy:"%d Jahren"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("de",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : canadian english (en-ca)
// author : Jonathan Abourbih : https://github.com/jonbca
(function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-ca",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : great britain english (en-gb)
// author : Chris Gedrim : https://github.com/chrisgedrim
(function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-gb",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : spanish (es)
// author : Julio Napurí : https://github.com/julionc
(function(){var a={months:"Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre".split("_"),monthsShort:"Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.".split("_"),weekdays:"Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mié._Jue._Vie._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(this.hours()!==1?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(this.hours()!==1?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(this.hours()!==1?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(this.hours()!==1?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(this.hours()!==1?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("es",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : euskara (eu)
// author : Eneko Illarramendi : https://github.com/eillarra
(function(){var a={months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYYko MMMMren D[a]",LLL:"YYYYko MMMMren D[a] LT",LLLL:"dddd, YYYYko MMMMren D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("eu",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : finnish (fi)
// author : Tarmo Aidantausta : https://github.com/bleadof
(function(){function c(a,b,c,e){var f="";switch(c){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=d(a,e)+" "+f,f}function d(c,d){return c<10?d?b[c]:a[c]:c}var a=["nolla","yksi","kaksi","kolme","neljä","viisi","kuusi","seitsemän","kahdeksan","yhdeksän"],b=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",a[7],a[8],a[9]],e={months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tam_hel_maa_huh_tou_kes_hei_elo_syy_lok_mar_jou".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMMt\\a YYYY",LLL:"Do MMMMt\\a YYYY, klo LT",LLLL:"dddd, Do MMMMt\\a YYYY, klo LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=e),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fi",e)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : canadian french (fr-ca)
// author : Jonathan Abourbih : https://github.com/jonbca
(function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr-ca",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : french (fr)
// author : John Fischer : https://github.com/jfroffice
(function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : galician (gl)
// author : Juan G. Hurtado : https://github.com/juanghurtado
(function(){var a={months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Octubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(this.hours()!==1?"ás":"a")+"] LT"},nextDay:function(){return"[mañá "+(this.hours()!==1?"ás":"a")+"] LT"},nextWeek:function(){return"dddd ["+(this.hours()!==1?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(this.hours()!==1?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(this.hours()!==1?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fai %s",s:"uns segundo",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("gl",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : hungarian (hu)
// author : Adam Brunner : https://github.com/adambrunner
(function(){function a(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":e="egy";case"mm":return e+(d||b?" perc":" perce");case"h":e="egy";case"hh":return e+(d||b?" óra":" órája");case"d":e="egy";case"dd":return e+(d||b?" nap":" napja");case"M":e="egy";case"MM":return e+(d||b?" hónap":" hónapja");case"y":e="egy";case"yy":return e+(d||b?" év":" éve");default:}return""}function b(a){var b="";switch(this.day()){case 0:b="vasárnap";break;case 1:b="hétfőn";break;case 2:b="kedden";break;case 3:b="szerdán";break;case 4:b="csütörtökön";break;case 5:b="pénteken";break;case 6:b="szombaton"}return(a?"":"múlt ")+"["+b+"] LT[-kor]"}var c={months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return b.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return b.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("hu",c)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : icelandic (is)
// author : Hinrik Örn Sigurðsson : https://github.com/hinrik
(function(){var a=function(a){return a%100==11?!0:a%10==1?!1:!0},b=function(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return a(b)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return a(b)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return a(b)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return a(b)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return a(b)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}},c={months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY kl. LT",LLLL:"dddd, D. MMMM YYYY kl. LT"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:b,m:b,mm:b,h:"klukkustund",hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("is",c)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : italian (it)
// author : Lorenzo : https://github.com/aliem
(function(){var a={months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settebre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s fa",s:"secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:function(){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("it",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : japanese (ja)
// author : LI Long : https://github.com/baryon
(function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ja",a)})();

View file

@ -0,0 +1,6 @@
// moment.js language configuration
// language : japanese (jp)
// author : LI Long : https://github.com/baryon
// This language config was incorrectly named 'jp' instead of 'ja'.
// In version 2.0.0, this will be deprecated and you should use 'ja' instead.
(function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("jp",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : korean (ko)
// author : Kyungwook, Park : https://github.com/kyungw00k
(function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ko",a)})();

View file

@ -0,0 +1,6 @@
// moment.js language configuration
// language : korean (kr)
// author : Kyungwook, Park : https://github.com/kyungw00k
// This language config was incorrectly named 'kr' instead of 'ko'.
// In version 2.0.0, this will be deprecated and you should use 'ko' instead.
(function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("kr",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : norwegian bokmål (nb)
// author : Espen Hovlandsdal : https://github.com/rexxars
(function(){var a={months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokken] LT",nextDay:"[I morgen klokken] LT",nextWeek:"dddd [klokken] LT",lastDay:"[I går klokken] LT",lastWeek:"[Forrige] dddd [klokken] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nb",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : dutch (nl)
// author : Joris Röling : https://github.com/jjupiter
(function(){var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),b="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),c={months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(c,d){return/-MMM-/.test(d)?b[c.month()]:a[c.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Vandaag om] LT",nextDay:"[Morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinal:function(a){return a===1||a===8||a>=20?"ste":"de"}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nl",c)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : polish (pl)
// author : Rafal Hirsz : https://github.com/evoL
(function(){var a=function(a){return a%10<5&&a%10>1&&~~(a/10)!==1},b=function(b,c,d){var e=b+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(a(b)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(a(b)?"godziny":"godzin");case"MM":return e+(a(b)?"miesiące":"miesięcy");case"yy":return e+(a(b)?"lata":"lat")}},c={months:"styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:"[W zeszły/łą] dddd [o] LT",sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:b,mm:b,h:b,hh:b,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:b,y:"rok",yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pl",c)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : brazilian portuguese (pt-br)
// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
(function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt-br",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : portuguese (pt)
// author : Jefferson : https://github.com/jalex79
(function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : russian (ru)
// author : Viktorminator : https://github.com/Viktorminator
(function(){var a=[function(a){return a%10===1&&a%100!==11},function(a){return a%10>=2&&a%10<=4&&a%10%1===0&&(a%100<12||a%100>14)},function(a){return a%10===0||a%10>=5&&a%10<=9&&a%10%1===0||a%100>=11&&a%100<=14&&a%100%1===0},function(a){return!0}],b=function(b,c){var d=b.split("_"),e=Math.min(a.length,d.length),f=-1;while(++f<e)if(a[f](c))return d[f];return d[e-1]},c=function(a,c,d){var e={mm:"минута_минуты_минут_минуты",hh:асасаасов_часа",dd:ень_дня_дней_дня",MM:есяц_месяцаесяцев_месяца",yy:"год_годает_года"};return d==="m"?c?"минута":"минуту":a+" "+b(e[d],+a)},d=function(a,b){var c={nominative:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),accusative:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_")},d=/D[oD]? *MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]},e=function(a,b){var c={nominative:оскресенье_понедельник_вторник_средаетверг_пятница_суббота".split("_"),accusative:оскресенье_понедельник_вторник_средуетверг_пятницу_субботу".split("_")},d=/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/.test(b)?"accusative":"nominative";return c[d][a.day()]},f={months:d,monthsShort:"янв_фев_мар_апрай_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:e,weekdaysShort:ск_пнд_втр_срд_чтв_птн_сбт".split("_"),weekdaysMin:с_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., LT",LLLL:"dddd, D MMMM YYYY г., LT"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(){return this.day()===2?"[Во] dddd [в] LT":"[В] dddd [в] LT"},lastWeek:function(){switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:c,mm:c,h:"час",hh:c,d:"день",dd:c,M:"месяц",MM:c,y:"год",yy:c},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=f),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ru",f)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : swedish (sv)
// author : Jens Alm : https://github.com/ulmus
(function(){var a={months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag klockan] LT",nextDay:"[Imorgon klockan] LT",lastDay:"[Igår klockan] LT",nextWeek:"dddd [klockan] LT",lastWeek:"[Förra] dddd[en klockan] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sen",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"e":b===1?"a":b===2?"a":b===3?"e":"e"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("sv",a)})();

View file

@ -0,0 +1,5 @@
// moment.js language configuration
// language : turkish (tr)
// authors : Erhan Gundogan : https://github.com/erhangundogan,
// Burak Yiğit Kaya: https://github.com/BYK
(function(){var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"},b={months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinal:function(b){if(b===0)return"'ıncı";var c=b%10,d=b%100-c,e=b>=100?100:null;return a[c]||a[d]||a[e]}};typeof module!="undefined"&&module.exports&&(module.exports=b),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("tr",b)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : chinese
// author : suupic : https://github.com/suupic
(function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1分钟",mm:"%d分钟",h:"1小时",hh:"%d小时",d:"1天",dd:"%d天",M:"1个月",MM:"%d个月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-cn",a)})();

View file

@ -0,0 +1,4 @@
// moment.js language configuration
// language : traditional chinese (zh-tw)
// author : Ben : https://github.com/ben-lin
(function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"一分鐘",mm:"%d分鐘",h:"一小時",hh:"%d小時",d:"一天",dd:"%d天",M:"一個月",MM:"%d個月",y:"一年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-tw",a)})();

View file

@ -0,0 +1,195 @@
<?php
namespace Buzz;
use Buzz\Client\ClientInterface;
use Buzz\Client\FileGetContents;
use Buzz\Listener\ListenerChain;
use Buzz\Listener\ListenerInterface;
use Buzz\Message\Factory\Factory;
use Buzz\Message\Factory\FactoryInterface;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Util\Url;
class Browser
{
private $client;
private $factory;
private $listener;
private $lastRequest;
private $lastResponse;
public function __construct(ClientInterface $client = null, FactoryInterface $factory = null)
{
$this->client = $client ?: new FileGetContents();
$this->factory = $factory ?: new Factory();
}
public function get($url, $headers = array())
{
return $this->call($url, RequestInterface::METHOD_GET, $headers);
}
public function post($url, $headers = array(), $content = '')
{
return $this->call($url, RequestInterface::METHOD_POST, $headers, $content);
}
public function head($url, $headers = array())
{
return $this->call($url, RequestInterface::METHOD_HEAD, $headers);
}
public function patch($url, $headers = array(), $content = '')
{
return $this->call($url, RequestInterface::METHOD_PATCH, $headers, $content);
}
public function put($url, $headers = array(), $content = '')
{
return $this->call($url, RequestInterface::METHOD_PUT, $headers, $content);
}
public function delete($url, $headers = array(), $content = '')
{
return $this->call($url, RequestInterface::METHOD_DELETE, $headers, $content);
}
/**
* Sends a request.
*
* @param string $url The URL to call
* @param string $method The request method to use
* @param array $headers An array of request headers
* @param string $content The request content
*
* @return MessageInterface The response object
*/
public function call($url, $method, $headers = array(), $content = '')
{
$request = $this->factory->createRequest($method);
if (!$url instanceof Url) {
$url = new Url($url);
}
$url->applyToRequest($request);
$request->addHeaders($headers);
$request->setContent($content);
return $this->send($request);
}
/**
* Sends a form request.
*
* @param string $url The URL to submit to
* @param array $fields An array of fields
* @param string $method The request method to use
* @param array $headers An array of request headers
*
* @return MessageInterface The response object
*/
public function submit($url, array $fields, $method = RequestInterface::METHOD_POST, $headers = array())
{
$request = $this->factory->createFormRequest();
if (!$url instanceof Url) {
$url = new Url($url);
}
$url->applyToRequest($request);
$request->addHeaders($headers);
$request->setMethod($method);
$request->setFields($fields);
return $this->send($request);
}
/**
* Sends a request.
*
* @param RequestInterface $request A request object
* @param MessageInterface $response A response object
*
* @return MessageInterface The response
*/
public function send(RequestInterface $request, MessageInterface $response = null)
{
if (null === $response) {
$response = $this->factory->createResponse();
}
if ($this->listener) {
$this->listener->preSend($request);
}
$this->client->send($request, $response);
$this->lastRequest = $request;
$this->lastResponse = $response;
if ($this->listener) {
$this->listener->postSend($request, $response);
}
return $response;
}
public function getLastRequest()
{
return $this->lastRequest;
}
public function getLastResponse()
{
return $this->lastResponse;
}
public function setClient(ClientInterface $client)
{
$this->client = $client;
}
public function getClient()
{
return $this->client;
}
public function setMessageFactory(FactoryInterface $factory)
{
$this->factory = $factory;
}
public function getMessageFactory()
{
return $this->factory;
}
public function setListener(ListenerInterface $listener)
{
$this->listener = $listener;
}
public function getListener()
{
return $this->listener;
}
public function addListener(ListenerInterface $listener)
{
if (!$this->listener) {
$this->listener = $listener;
} elseif ($this->listener instanceof ListenerChain) {
$this->listener->addListener($listener);
} else {
$this->listener = new ListenerChain(array(
$this->listener,
$listener,
));
}
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace Buzz\Client;
abstract class AbstractClient implements ClientInterface
{
protected $ignoreErrors = true;
protected $maxRedirects = 5;
protected $timeout = 5;
protected $verifyPeer = true;
protected $proxy;
public function setIgnoreErrors($ignoreErrors)
{
$this->ignoreErrors = $ignoreErrors;
}
public function getIgnoreErrors()
{
return $this->ignoreErrors;
}
public function setMaxRedirects($maxRedirects)
{
$this->maxRedirects = $maxRedirects;
}
public function getMaxRedirects()
{
return $this->maxRedirects;
}
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
public function getTimeout()
{
return $this->timeout;
}
public function setVerifyPeer($verifyPeer)
{
$this->verifyPeer = $verifyPeer;
}
public function getVerifyPeer()
{
return $this->verifyPeer;
}
public function setProxy($proxy)
{
$this->proxy = $proxy;
}
public function getProxy()
{
return $this->proxy;
}
}

View file

@ -0,0 +1,201 @@
<?php
namespace Buzz\Client;
use Buzz\Message\Form\FormRequestInterface;
use Buzz\Message\Form\FormUploadInterface;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Exception\ClientException;
/**
* Base client class with helpers for working with cURL.
*/
abstract class AbstractCurl extends AbstractClient
{
protected $options = array();
public function __construct()
{
if (defined('CURLOPT_PROTOCOLS')) {
$this->options = array(
CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
);
}
}
/**
* Creates a new cURL resource.
*
* @see curl_init()
*
* @return resource A new cURL resource
*/
protected static function createCurlHandle()
{
if (false === $curl = curl_init()) {
throw new ClientException('Unable to create a new cURL handle');
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
return $curl;
}
/**
* Populates a response object.
*
* @param resource $curl A cURL resource
* @param string $raw The raw response string
* @param MessageInterface $response The response object
*/
protected static function populateResponse($curl, $raw, MessageInterface $response)
{
$pos = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$response->setHeaders(static::getLastHeaders(rtrim(substr($raw, 0, $pos))));
$response->setContent(substr($raw, $pos));
}
/**
* Sets options on a cURL resource based on a request.
*/
private static function setOptionsFromRequest($curl, RequestInterface $request)
{
$options = array(
CURLOPT_CUSTOMREQUEST => $request->getMethod(),
CURLOPT_URL => $request->getHost().$request->getResource(),
CURLOPT_HTTPHEADER => $request->getHeaders(),
);
switch ($request->getMethod()) {
case RequestInterface::METHOD_HEAD:
$options[CURLOPT_NOBODY] = true;
break;
case RequestInterface::METHOD_GET:
$options[CURLOPT_HTTPGET] = true;
break;
case RequestInterface::METHOD_POST:
case RequestInterface::METHOD_PUT:
case RequestInterface::METHOD_DELETE:
case RequestInterface::METHOD_PATCH:
$options[CURLOPT_POSTFIELDS] = $fields = static::getPostFields($request);
// remove the content-type header
if (is_array($fields)) {
$options[CURLOPT_HTTPHEADER] = array_filter($options[CURLOPT_HTTPHEADER], function($header) {
return 0 !== stripos($header, 'Content-Type: ');
});
}
break;
}
curl_setopt_array($curl, $options);
}
/**
* Returns a value for the CURLOPT_POSTFIELDS option.
*
* @return string|array A post fields value
*/
private static function getPostFields(RequestInterface $request)
{
if (!$request instanceof FormRequestInterface) {
return $request->getContent();
}
$fields = $request->getFields();
$multipart = false;
foreach ($fields as $name => $value) {
if ($value instanceof FormUploadInterface) {
$multipart = true;
if ($file = $value->getFile()) {
// replace value with upload string
$fields[$name] = '@'.$file;
if ($contentType = $value->getContentType()) {
$fields[$name] .= ';type='.$contentType;
}
} else {
return $request->getContent();
}
}
}
return $multipart ? $fields : http_build_query($fields);
}
/**
* A helper for getting the last set of headers.
*
* @param string $raw A string of many header chunks
*
* @return array An array of header lines
*/
private static function getLastHeaders($raw)
{
$headers = array();
foreach (preg_split('/(\\r?\\n)/', $raw) as $header) {
if ($header) {
$headers[] = $header;
} else {
$headers = array();
}
}
return $headers;
}
/**
* Stashes a cURL option to be set on send, when the resource is created.
*
* If the supplied value it set to null the option will be removed.
*
* @param integer $option The option
* @param mixed $value The value
*
* @see curl_setopt()
*/
public function setOption($option, $value)
{
if (null === $value) {
unset($this->options[$option]);
} else {
$this->options[$option] = $value;
}
}
/**
* Prepares a cURL resource to send a request.
*/
protected function prepare($curl, RequestInterface $request, array $options = array())
{
static::setOptionsFromRequest($curl, $request);
// apply settings from client
if ($this->getTimeout() < 1) {
curl_setopt($curl, CURLOPT_TIMEOUT_MS, $this->getTimeout() * 1000);
} else {
curl_setopt($curl, CURLOPT_TIMEOUT, $this->getTimeout());
}
if ($this->proxy) {
curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
}
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0 < $this->getMaxRedirects());
curl_setopt($curl, CURLOPT_MAXREDIRS, $this->getMaxRedirects());
curl_setopt($curl, CURLOPT_FAILONERROR, !$this->getIgnoreErrors());
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->getVerifyPeer());
// apply additional options
curl_setopt_array($curl, $options + $this->options);
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Buzz\Client;
use Buzz\Message\RequestInterface;
abstract class AbstractStream extends AbstractClient
{
/**
* Converts a request into an array for stream_context_create().
*
* @param RequestInterface $request A request object
*
* @return array An array for stream_context_create()
*/
public function getStreamContextArray(RequestInterface $request)
{
$options = array(
'http' => array(
// values from the request
'method' => $request->getMethod(),
'header' => implode("\r\n", $request->getHeaders()),
'content' => $request->getContent(),
'protocol_version' => $request->getProtocolVersion(),
// values from the current client
'ignore_errors' => $this->getIgnoreErrors(),
'max_redirects' => $this->getMaxRedirects(),
'timeout' => $this->getTimeout(),
),
'ssl' => array(
'verify_peer' => $this->getVerifyPeer(),
),
);
if ($this->proxy) {
$options['http']['proxy'] = $this->proxy;
$options['http']['request_fulluri'] = true;
}
return $options;
}
}

View file

@ -0,0 +1,11 @@
<?php
namespace Buzz\Client;
interface BatchClientInterface extends ClientInterface
{
/**
* Processes the queued requests.
*/
public function flush();
}

View file

@ -0,0 +1,17 @@
<?php
namespace Buzz\Client;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
interface ClientInterface
{
/**
* Populates the supplied response with the response for the supplied request.
*
* @param RequestInterface $request A request object
* @param MessageInterface $response A response object
*/
public function send(RequestInterface $request, MessageInterface $response);
}

View file

@ -0,0 +1,55 @@
<?php
namespace Buzz\Client;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Exception\ClientException;
use Buzz\Exception\LogicException;
class Curl extends AbstractCurl
{
private $lastCurl;
public function send(RequestInterface $request, MessageInterface $response, array $options = array())
{
if (is_resource($this->lastCurl)) {
curl_close($this->lastCurl);
}
$this->lastCurl = static::createCurlHandle();
$this->prepare($this->lastCurl, $request, $options);
$data = curl_exec($this->lastCurl);
if (false === $data) {
$errorMsg = curl_error($this->lastCurl);
$errorNo = curl_errno($this->lastCurl);
throw new ClientException($errorMsg, $errorNo);
}
static::populateResponse($this->lastCurl, $data, $response);
}
/**
* Introspects the last cURL request.
*
* @see curl_getinfo()
*/
public function getInfo($opt = 0)
{
if (!is_resource($this->lastCurl)) {
throw new LogicException('There is no cURL resource');
}
return curl_getinfo($this->lastCurl, $opt);
}
public function __destruct()
{
if (is_resource($this->lastCurl)) {
curl_close($this->lastCurl);
}
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace Buzz\Client;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Util\CookieJar;
use Buzz\Exception\ClientException;
class FileGetContents extends AbstractStream
{
/**
* @var CookieJar
*/
protected $cookieJar;
/**
* @param CookieJar|null $cookieJar
*/
public function __construct(CookieJar $cookieJar = null)
{
if ($cookieJar) {
$this->setCookieJar($cookieJar);
}
}
/**
* @param CookieJar $cookieJar
*/
public function setCookieJar(CookieJar $cookieJar)
{
$this->cookieJar = $cookieJar;
}
/**
* @return CookieJar
*/
public function getCookieJar()
{
return $this->cookieJar;
}
/**
* @see ClientInterface
*
* @throws ClientException If file_get_contents() fires an error
*/
public function send(RequestInterface $request, MessageInterface $response)
{
if ($cookieJar = $this->getCookieJar()) {
$cookieJar->clearExpiredCookies();
$cookieJar->addCookieHeaders($request);
}
$context = stream_context_create($this->getStreamContextArray($request));
$url = $request->getHost().$request->getResource();
$level = error_reporting(0);
$content = file_get_contents($url, 0, $context);
error_reporting($level);
if (false === $content) {
$error = error_get_last();
throw new ClientException($error['message']);
}
$response->setHeaders($this->filterHeaders((array) $http_response_header));
$response->setContent($content);
if ($cookieJar) {
$cookieJar->processSetCookieHeaders($request, $response);
}
}
private function filterHeaders(array $headers)
{
$filtered = array();
foreach ($headers as $header) {
if (0 === stripos($header, 'http/')) {
$filtered = array();
}
$filtered[] = $header;
}
return $filtered;
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace Buzz\Client;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Exception\ClientException;
class MultiCurl extends AbstractCurl implements BatchClientInterface
{
private $queue = array();
public function send(RequestInterface $request, MessageInterface $response, array $options = array())
{
$this->queue[] = array($request, $response, $options);
}
public function flush()
{
if (false === $curlm = curl_multi_init()) {
throw new ClientException('Unable to create a new cURL multi handle');
}
// prepare a cURL handle for each entry in the queue
foreach ($this->queue as $i => &$queue) {
list($request, $response, $options) = $queue;
$curl = $queue[] = static::createCurlHandle();
$this->prepare($curl, $request, $options);
curl_multi_add_handle($curlm, $curl);
}
$active = null;
do {
$mrc = curl_multi_exec($curlm, $active);
} while (CURLM_CALL_MULTI_PERFORM == $mrc);
while ($active && CURLM_OK == $mrc) {
if (-1 != curl_multi_select($curlm)) {
do {
$mrc = curl_multi_exec($curlm, $active);
} while (CURLM_CALL_MULTI_PERFORM == $mrc);
}
}
// populate the responses
while (list($request, $response, $options, $curl) = array_shift($this->queue)) {
static::populateResponse($curl, curl_multi_getcontent($curl), $response);
curl_multi_remove_handle($curlm, $curl);
}
curl_multi_close($curlm);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace Buzz\Exception;
/**
* Thrown whenever a client process fails.
*/
class ClientException extends RuntimeException
{
}

View file

@ -0,0 +1,10 @@
<?php
namespace Buzz\Exception;
/**
* Marker interface to denote exceptions thrown from the Buzz context.
*/
interface ExceptionInterface
{
}

View file

@ -0,0 +1,10 @@
<?php
namespace Buzz\Exception;
/**
* Thrown when an invalid argument is provided.
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View file

@ -0,0 +1,10 @@
<?php
namespace Buzz\Exception;
/**
* Thrown whenever a required call-flow is not respected.
*/
class LogicException extends \LogicException implements ExceptionInterface
{
}

View file

@ -0,0 +1,7 @@
<?php
namespace Buzz\Exception;
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View file

@ -0,0 +1,27 @@
<?php
namespace Buzz\Listener;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
class BasicAuthListener implements ListenerInterface
{
private $username;
private $password;
public function __construct($username, $password)
{
$this->username = $username;
$this->password = $password;
}
public function preSend(RequestInterface $request)
{
$request->addHeader('Authorization: Basic '.base64_encode($this->username.':'.$this->password));
}
public function postSend(RequestInterface $request, MessageInterface $response)
{
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Buzz\Listener;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Exception\InvalidArgumentException;
class CallbackListener implements ListenerInterface
{
private $callable;
/**
* Constructor.
*
* The callback should expect either one or two arguments, depending on
* whether it is receiving a pre or post send notification.
*
* $listener = new CallbackListener(function($request, $response = null) {
* if ($response) {
* // postSend
* } else {
* // preSend
* }
* });
*
* @param mixed $callable A PHP callable
*
* @throws InvalidArgumentException If the argument is not callable
*/
public function __construct($callable)
{
if (!is_callable($callable)) {
throw new InvalidArgumentException('The argument is not callable.');
}
$this->callable = $callable;
}
public function preSend(RequestInterface $request)
{
call_user_func($this->callable, $request);
}
public function postSend(RequestInterface $request, MessageInterface $response)
{
call_user_func($this->callable, $request, $response);
}
}

View file

@ -0,0 +1,42 @@
<?php
namespace Buzz\Listener\History;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
class Entry
{
private $request;
private $response;
private $duration;
/**
* Constructor.
*
* @param RequestInterface $request The request
* @param MessageInterface $response The response
* @param integer $duration The duration in seconds
*/
public function __construct(RequestInterface $request, MessageInterface $response, $duration = null)
{
$this->request = $request;
$this->response = $response;
$this->duration = $duration;
}
public function getRequest()
{
return $this->request;
}
public function getResponse()
{
return $this->response;
}
public function getDuration()
{
return $this->duration;
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace Buzz\Listener\History;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
class Journal implements \Countable, \IteratorAggregate
{
private $entries = array();
private $limit = 10;
/**
* Records an entry in the journal.
*
* @param RequestInterface $request The request
* @param MessageInterface $response The response
* @param integer $duration The duration in seconds
*/
public function record(RequestInterface $request, MessageInterface $response, $duration = null)
{
$this->addEntry(new Entry($request, $response, $duration));
}
public function addEntry(Entry $entry)
{
array_push($this->entries, $entry);
$this->entries = array_slice($this->entries, $this->getLimit() * -1);
end($this->entries);
}
public function getEntries()
{
return $this->entries;
}
public function getLast()
{
return end($this->entries);
}
public function getLastRequest()
{
return $this->getLast()->getRequest();
}
public function getLastResponse()
{
return $this->getLast()->getResponse();
}
public function clear()
{
$this->entries = array();
}
public function count()
{
return count($this->entries);
}
public function setLimit($limit)
{
$this->limit = $limit;
}
public function getLimit()
{
return $this->limit;
}
public function getIterator()
{
return new \ArrayIterator(array_reverse($this->entries));
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace Buzz\Listener;
use Buzz\Listener\History\Journal;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
class HistoryListener implements ListenerInterface
{
private $journal;
private $startTime;
public function __construct(Journal $journal)
{
$this->journal = $journal;
}
public function getJournal()
{
return $this->journal;
}
public function preSend(RequestInterface $request)
{
$this->startTime = microtime(true);
}
public function postSend(RequestInterface $request, MessageInterface $response)
{
$this->journal->record($request, $response, microtime(true) - $this->startTime);
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace Buzz\Listener;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
class ListenerChain implements ListenerInterface
{
private $listeners;
public function __construct(array $listeners = array())
{
$this->listeners = $listeners;
}
public function addListener(ListenerInterface $listener)
{
$this->listeners[] = $listener;
}
public function getListeners()
{
return $this->listeners;
}
public function preSend(RequestInterface $request)
{
foreach ($this->listeners as $listener) {
$listener->preSend($request);
}
}
public function postSend(RequestInterface $request, MessageInterface $response)
{
foreach ($this->listeners as $listener) {
$listener->postSend($request, $response);
}
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace Buzz\Listener;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
interface ListenerInterface
{
public function preSend(RequestInterface $request);
public function postSend(RequestInterface $request, MessageInterface $response);
}

View file

@ -0,0 +1,36 @@
<?php
namespace Buzz\Listener;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
use Buzz\Exception\InvalidArgumentException;
class LoggerListener implements ListenerInterface
{
private $logger;
private $prefix;
private $startTime;
public function __construct($logger, $prefix = null)
{
if (!is_callable($logger)) {
throw new InvalidArgumentException('The logger must be a callable.');
}
$this->logger = $logger;
$this->prefix = $prefix;
}
public function preSend(RequestInterface $request)
{
$this->startTime = microtime(true);
}
public function postSend(RequestInterface $request, MessageInterface $response)
{
$seconds = microtime(true) - $this->startTime;
call_user_func($this->logger, sprintf('%sSent "%s %s%s" in %dms', $this->prefix, $request->getMethod(), $request->getHost(), $request->getResource(), round($seconds * 1000)));
}
}

View file

@ -0,0 +1,154 @@
<?php
namespace Buzz\Message;
abstract class AbstractMessage implements MessageInterface
{
private $headers = array();
private $content;
/**
* Returns the value of a header.
*
* @param string $name
* @param string|boolean $glue Glue for implode, or false to return an array
*
* @return string|array|null
*/
public function getHeader($name, $glue = "\r\n")
{
$needle = $name.':';
$values = array();
foreach ($this->getHeaders() as $header) {
if (0 === stripos($header, $needle)) {
$values[] = trim(substr($header, strlen($needle)));
}
}
if (false === $glue) {
return $values;
} else {
return count($values) ? implode($glue, $values) : null;
}
}
/**
* Returns a header's attributes.
*
* @param string $name A header name
*
* @return array An associative array of attributes
*/
public function getHeaderAttributes($name)
{
$attributes = array();
foreach ($this->getHeader($name, false) as $header) {
if (false !== strpos($header, ';')) {
// remove header value
list(, $header) = explode(';', $header, 2);
// loop through attribute key=value pairs
foreach (array_map('trim', explode(';', trim($header))) as $pair) {
list($key, $value) = explode('=', $pair);
$attributes[$key] = $value;
}
}
}
return $attributes;
}
/**
* Returns the value of a particular header attribute.
*
* @param string $header A header name
* @param string $attribute An attribute name
*
* @return string|null The value of the attribute or null if it isn't set
*/
public function getHeaderAttribute($header, $attribute)
{
$attributes = $this->getHeaderAttributes($header);
if (isset($attributes[$attribute])) {
return $attributes[$attribute];
}
}
/**
* Returns the current message as a DOMDocument.
*
* @return \DOMDocument
*/
public function toDomDocument()
{
$revert = libxml_use_internal_errors(true);
$document = new \DOMDocument('1.0', $this->getHeaderAttribute('Content-Type', 'charset') ?: 'UTF-8');
if (0 === strpos($this->getHeader('Content-Type'), 'text/xml')) {
$document->loadXML($this->getContent());
} else {
$document->loadHTML($this->getContent());
}
libxml_use_internal_errors($revert);
return $document;
}
public function setHeaders(array $headers)
{
$this->headers = $this->flattenHeaders($headers);
}
public function addHeader($header)
{
$this->headers[] = $header;
}
public function addHeaders(array $headers)
{
$this->headers = array_merge($this->headers, $this->flattenHeaders($headers));
}
public function getHeaders()
{
return $this->headers;
}
public function setContent($content)
{
$this->content = $content;
}
public function getContent()
{
return $this->content;
}
public function __toString()
{
$string = implode("\r\n", $this->getHeaders())."\r\n";
if ($content = $this->getContent()) {
$string .= "\r\n$content\r\n";
}
return $string;
}
protected function flattenHeaders(array $headers)
{
$flattened = array();
foreach ($headers as $key => $header) {
if (is_int($key)) {
$flattened[] = $header;
} else {
$flattened[] = $key.': '.$header;
}
}
return $flattened;
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace Buzz\Message\Factory;
use Buzz\Message\Form\FormRequest;
use Buzz\Message\Request;
use Buzz\Message\RequestInterface;
use Buzz\Message\Response;
class Factory implements FactoryInterface
{
public function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null)
{
return new Request($method, $resource, $host);
}
public function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null)
{
return new FormRequest($method, $resource, $host);
}
public function createResponse()
{
return new Response();
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace Buzz\Message\Factory;
use Buzz\Message\RequestInterface;
interface FactoryInterface
{
public function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null);
public function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null);
public function createResponse();
}

View file

@ -0,0 +1,187 @@
<?php
namespace Buzz\Message\Form;
use Buzz\Message\Request;
use Buzz\Exception\LogicException;
/**
* FormRequest.
*
* $request = new FormRequest();
* $request->setField('user[name]', 'Kris Wallsmith');
* $request->setField('user[image]', new FormUpload('/path/to/image.jpg'));
*
* @author Marc Weistroff <marc.weistroff@sensio.com>
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
*/
class FormRequest extends Request implements FormRequestInterface
{
private $fields = array();
private $boundary;
/**
* Constructor.
*
* Defaults to POST rather than GET.
*/
public function __construct($method = self::METHOD_POST, $resource = '/', $host = null)
{
parent::__construct($method, $resource, $host);
}
/**
* Sets the value of a form field.
*
* If the value is an array it will be flattened and one field value will
* be added for each leaf.
*/
public function setField($name, $value)
{
if (is_array($value)) {
$this->addFields(array($name => $value));
return;
}
if ('[]' == substr($name, -2)) {
$this->fields[substr($name, 0, -2)][] = $value;
} else {
$this->fields[$name] = $value;
}
}
public function addFields(array $fields)
{
foreach ($this->flattenArray($fields) as $name => $value) {
$this->setField($name, $value);
}
}
public function setFields(array $fields)
{
$this->fields = array();
$this->addFields($fields);
}
public function getFields()
{
return $this->fields;
}
public function getResource()
{
$resource = parent::getResource();
if (!$this->isSafe() || !$this->fields) {
return $resource;
}
// append the query string
$resource .= false === strpos($resource, '?') ? '?' : '&';
$resource .= http_build_query($this->fields);
return $resource;
}
public function setContent($content)
{
throw new \BadMethodCallException('It is not permitted to set the content.');
}
public function getHeaders()
{
$headers = parent::getHeaders();
if ($this->isSafe()) {
return $headers;
}
if ($this->isMultipart()) {
$headers[] = 'Content-Type: multipart/form-data; boundary='.$this->getBoundary();
} else {
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
}
return $headers;
}
public function getContent()
{
if ($this->isSafe()) {
return;
}
if (!$this->isMultipart()) {
return http_build_query($this->fields);
}
$content = '';
foreach ($this->fields as $name => $values) {
$content .= '--'.$this->getBoundary()."\r\n";
if ($values instanceof FormUploadInterface) {
if (!$values->getFilename()) {
throw new LogicException(sprintf('Form upload at "%s" does not include a filename.', $name));
}
$values->setName($name);
$content .= (string) $values;
} else {
foreach (is_array($values) ? $values : array($values) as $value) {
$content .= "Content-Disposition: form-data; name=\"$name\"\r\n";
$content .= "\r\n";
$content .= $value."\r\n";
}
}
}
$content .= '--'.$this->getBoundary().'--';
return $content;
}
// private
private function flattenArray(array $values, $prefix = '', $format = '%s')
{
$flat = array();
foreach ($values as $name => $value) {
$flatName = $prefix.sprintf($format, $name);
if (is_array($value)) {
$flat += $this->flattenArray($value, $flatName, '[%s]');
} else {
$flat[$flatName] = $value;
}
}
return $flat;
}
private function isSafe()
{
return in_array($this->getMethod(), array(self::METHOD_GET, self::METHOD_HEAD));
}
private function isMultipart()
{
foreach ($this->fields as $name => $value) {
if (is_object($value) && $value instanceof FormUploadInterface) {
return true;
}
}
return false;
}
private function getBoundary()
{
if (!$this->boundary) {
$this->boundary = sha1(rand(11111, 99999).time().uniqid());
}
return $this->boundary;
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace Buzz\Message\Form;
use Buzz\Message\RequestInterface;
/**
* An HTTP request message sent by a web form.
*
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
*/
interface FormRequestInterface extends RequestInterface
{
/**
* Returns an array of field names and values.
*
* @return array A array of names and values
*/
public function getFields();
/**
* Sets the form fields for the current request.
*
* @param array $fields An array of field names and values
*/
public function setFields(array $fields);
}

View file

@ -0,0 +1,118 @@
<?php
namespace Buzz\Message\Form;
use Buzz\Message\AbstractMessage;
class FormUpload extends AbstractMessage implements FormUploadInterface
{
private $name;
private $filename;
private $contentType;
private $file;
public function __construct($file = null, $contentType = null)
{
if ($file) {
$this->loadContent($file);
}
$this->contentType = $contentType;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function getFilename()
{
if ($this->filename) {
return $this->filename;
} elseif ($this->file) {
return basename($this->file);
}
}
public function setFilename($filename)
{
$this->filename = $filename;
}
public function getContentType()
{
return $this->contentType ?: $this->detectContentType() ?: 'application/octet-stream';
}
public function setContentType($contentType)
{
$this->contentType = $contentType;
}
/**
* Prepends Content-Disposition and Content-Type headers.
*/
public function getHeaders()
{
$headers = array('Content-Disposition: form-data');
if ($name = $this->getName()) {
$headers[0] .= sprintf('; name="%s"', $name);
}
if ($filename = $this->getFilename()) {
$headers[0] .= sprintf('; filename="%s"', $filename);
}
if ($contentType = $this->getContentType()) {
$headers[] = 'Content-Type: '.$contentType;
}
return array_merge($headers, parent::getHeaders());
}
/**
* Loads the content from a file.
*/
public function loadContent($file)
{
$this->file = $file;
parent::setContent(null);
}
public function setContent($content)
{
parent::setContent($content);
$this->file = null;
}
public function getFile()
{
return $this->file;
}
public function getContent()
{
return $this->file ? file_get_contents($this->file) : parent::getContent();
}
// private
private function detectContentType()
{
if (!class_exists('finfo', false)) {
return false;
}
$finfo = new \finfo(FILEINFO_MIME_TYPE);
return $this->file ? $finfo->file($this->file) : $finfo->buffer(parent::getContent());
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace Buzz\Message\Form;
use Buzz\Message\MessageInterface;
interface FormUploadInterface extends MessageInterface
{
public function setName($name);
public function getFile();
public function getFilename();
public function getContentType();
}

View file

@ -0,0 +1,74 @@
<?php
namespace Buzz\Message;
/**
* An HTTP message.
*
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
*/
interface MessageInterface
{
/**
* Returns a header value.
*
* @param string $name A header name
* @param string|boolean $glue Glue for implode, or false to return an array
*
* @return string|array|null The header value(s)
*/
public function getHeader($name, $glue = "\r\n");
/**
* Returns an array of header lines.
*
* @return array An array of header lines (integer indexes, e.g. ["Header: value"])
*/
public function getHeaders();
/**
* Sets all headers on the current message.
*
* Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"]
*
* @param array $headers An array of header lines
*/
public function setHeaders(array $headers);
/**
* Adds a header to this message.
*
* @param string $header A header line
*/
public function addHeader($header);
/**
* Adds a set of headers to this message.
*
* Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"]
*
* @param array $headers Headers
*/
public function addHeaders(array $headers);
/**
* Returns the content of the message.
*
* @return string The message content
*/
public function getContent();
/**
* Sets the content of the message.
*
* @param string $content The message content
*/
public function setContent($content);
/**
* Returns the message document.
*
* @return string The message
*/
public function __toString();
}

View file

@ -0,0 +1,174 @@
<?php
namespace Buzz\Message;
use Buzz\Util\Url;
class Request extends AbstractMessage implements RequestInterface
{
private $method;
private $resource;
private $host;
private $protocolVersion = 1.0;
/**
* Constructor.
*
* @param string $method
* @param string $resource
* @param string $host
*/
public function __construct($method = self::METHOD_GET, $resource = '/', $host = null)
{
$this->method = strtoupper($method);
$this->resource = $resource;
$this->host = $host;
}
public function setHeaders(array $headers)
{
parent::setHeaders(array());
foreach ($this->flattenHeaders($headers) as $header) {
$this->addHeader($header);
}
}
public function addHeader($header)
{
if (0 === stripos(substr($header, -8), 'HTTP/1.') && 3 == count($parts = explode(' ', $header))) {
list($method, $resource, $protocolVersion) = $parts;
$this->setMethod($method);
$this->setResource($resource);
$this->setProtocolVersion((float) substr($protocolVersion, 5));
} else {
parent::addHeader($header);
}
}
public function setMethod($method)
{
$this->method = strtoupper($method);
}
public function getMethod()
{
return $this->method;
}
public function setResource($resource)
{
$this->resource = $resource;
}
public function getResource()
{
return $this->resource;
}
public function setHost($host)
{
$this->host = $host;
}
public function getHost()
{
return $this->host;
}
public function setProtocolVersion($protocolVersion)
{
$this->protocolVersion = $protocolVersion;
}
public function getProtocolVersion()
{
return $this->protocolVersion;
}
/**
* A convenience method for getting the full URL of the current request.
*
* @return string
*/
public function getUrl()
{
return $this->getHost().$this->getResource();
}
/**
* A convenience method for populating the current request from a URL.
*
* @param Url|string $url An URL
*/
public function fromUrl($url)
{
if (!$url instanceof Url) {
$url = new Url($url);
}
$url->applyToRequest($this);
}
/**
* Returns true if the current request is secure.
*
* @return boolean
*/
public function isSecure()
{
return 'https' == parse_url($this->getHost(), PHP_URL_SCHEME);
}
/**
* Merges cookie headers on the way out.
*/
public function getHeaders()
{
return $this->mergeCookieHeaders(parent::getHeaders());
}
/**
* Returns a string representation of the current request.
*
* @return string
*/
public function __toString()
{
$string = sprintf("%s %s HTTP/%.1f\r\n", $this->getMethod(), $this->getResource(), $this->getProtocolVersion());
if ($host = $this->getHost()) {
$string .= 'Host: '.$host."\r\n";
}
if ($parent = trim(parent::__toString())) {
$string .= $parent."\r\n";
}
return $string;
}
// private
private function mergeCookieHeaders(array $headers)
{
$cookieHeader = null;
$needle = 'Cookie:';
foreach ($headers as $i => $header) {
if (0 !== stripos($header, $needle)) {
continue;
}
if (null === $cookieHeader) {
$cookieHeader = $i;
} else {
$headers[$cookieHeader] .= '; '.trim(substr($header, strlen($needle)));
unset($headers[$i]);
}
}
return array_values($headers);
}
}

View file

@ -0,0 +1,75 @@
<?php
namespace Buzz\Message;
/**
* An HTTP request message.
*
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
*/
interface RequestInterface extends MessageInterface
{
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_PATCH = 'PATCH';
/**
* Returns the HTTP method of the current request.
*
* @return string An HTTP method
*/
public function getMethod();
/**
* Sets the HTTP method of the current request.
*
* @param string $method The request method
*/
public function setMethod($method);
/**
* Returns the resource portion of the request line.
*
* @return string The resource requested
*/
public function getResource();
/**
* Sets the resource for the current request.
*
* @param string $resource The resource being requested
*/
public function setResource($resource);
/**
* Returns the protocol version of the current request.
*
* @return float The protocol version
*/
public function getProtocolVersion();
/**
* Returns the value of the host header.
*
* @return string|null The host
*/
public function getHost();
/**
* Sets the host for the current request.
*
* @param string $host The host
*/
public function setHost($host);
/**
* Checks if the current request is secure.
*
* @return Boolean True if the request is secure
*/
public function isSecure();
}

View file

@ -0,0 +1,193 @@
<?php
namespace Buzz\Message;
class Response extends AbstractMessage
{
private $protocolVersion;
private $statusCode;
private $reasonPhrase;
/**
* Returns the protocol version of the current response.
*
* @return float
*/
public function getProtocolVersion()
{
if (null === $this->protocolVersion) {
$this->parseStatusLine();
}
return $this->protocolVersion ?: null;
}
/**
* Returns the status code of the current response.
*
* @return integer
*/
public function getStatusCode()
{
if (null === $this->statusCode) {
$this->parseStatusLine();
}
return $this->statusCode ?: null;
}
/**
* Returns the reason phrase for the current response.
*
* @return string
*/
public function getReasonPhrase()
{
if (null === $this->reasonPhrase) {
$this->parseStatusLine();
}
return $this->reasonPhrase ?: null;
}
public function setHeaders(array $headers)
{
parent::setHeaders($headers);
$this->resetStatusLine();
}
public function addHeader($header)
{
parent::addHeader($header);
$this->resetStatusLine();
}
public function addHeaders(array $headers)
{
parent::addHeaders($headers);
$this->resetStatusLine();
}
/**
* Is response invalid?
*
* @return Boolean
*/
public function isInvalid()
{
return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600;
}
/**
* Is response informative?
*
* @return Boolean
*/
public function isInformational()
{
return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
}
/**
* Is response successful?
*
* @return Boolean
*/
public function isSuccessful()
{
return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
}
/**
* Is the response a redirect?
*
* @return Boolean
*/
public function isRedirection()
{
return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
}
/**
* Is there a client error?
*
* @return Boolean
*/
public function isClientError()
{
return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
}
/**
* Was there a server side error?
*
* @return Boolean
*/
public function isServerError()
{
return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
}
/**
* Is the response OK?
*
* @return Boolean
*/
public function isOk()
{
return 200 === $this->getStatusCode();
}
/**
* Is the reponse forbidden?
*
* @return Boolean
*/
public function isForbidden()
{
return 403 === $this->getStatusCode();
}
/**
* Is the response a not found error?
*
* @return Boolean
*/
public function isNotFound()
{
return 404 === $this->getStatusCode();
}
/**
* Is the response empty?
*
* @return Boolean
*/
public function isEmpty()
{
return in_array($this->getStatusCode(), array(201, 204, 304));
}
// private
private function parseStatusLine()
{
$headers = $this->getHeaders();
if (isset($headers[0]) && 3 == count($parts = explode(' ', $headers[0], 3))) {
$this->protocolVersion = (float) $parts[0];
$this->statusCode = (integer) $parts[1];
$this->reasonPhrase = $parts[2];
} else {
$this->protocolVersion = $this->statusCode = $this->reasonPhrase = false;
}
}
private function resetStatusLine()
{
$this->protocolVersion = $this->statusCode = $this->reasonPhrase = null;
}
}

View file

@ -0,0 +1,216 @@
<?php
namespace Buzz\Util;
use Buzz\Message\RequestInterface;
class Cookie
{
const ATTR_DOMAIN = 'domain';
const ATTR_PATH = 'path';
const ATTR_SECURE = 'secure';
const ATTR_MAX_AGE = 'max-age';
const ATTR_EXPIRES = 'expires';
protected $name;
protected $value;
protected $attributes = array();
protected $createdAt;
/**
* Constructor.
*/
public function __construct()
{
$this->createdAt = time();
}
/**
* Returns true if the current cookie matches the supplied request.
*
* @return boolean
*/
public function matchesRequest(RequestInterface $request)
{
// domain
if (!$this->matchesDomain(parse_url($request->getHost(), PHP_URL_HOST))) {
return false;
}
// path
if (!$this->matchesPath($request->getResource())) {
return false;
}
// secure
if ($this->hasAttribute(static::ATTR_SECURE) && !$request->isSecure()) {
return false;
}
return true;
}
/**
* Returns true of the current cookie has expired.
*
* Checks the max-age and expires attributes.
*
* @return boolean Whether the current cookie has expired
*/
public function isExpired()
{
$maxAge = $this->getAttribute(static::ATTR_MAX_AGE);
if ($maxAge && time() - $this->getCreatedAt() > $maxAge) {
return true;
}
$expires = $this->getAttribute(static::ATTR_EXPIRES);
if ($expires && strtotime($expires) < time()) {
return true;
}
return false;
}
/**
* Returns true if the current cookie matches the supplied domain.
*
* @param string $domain A domain hostname
*
* @return boolean
*/
public function matchesDomain($domain)
{
$cookieDomain = $this->getAttribute(static::ATTR_DOMAIN);
if (0 === strpos($cookieDomain, '.')) {
$pattern = '/\b'.preg_quote(substr($cookieDomain, 1), '/').'$/i';
return (boolean) preg_match($pattern, $domain);
} else {
return 0 == strcasecmp($cookieDomain, $domain);
}
}
/**
* Returns true if the current cookie matches the supplied path.
*
* @param string $path A path
*
* @return boolean
*/
public function matchesPath($path)
{
$needle = $this->getAttribute(static::ATTR_PATH);
return null === $needle || 0 === strpos($path, $needle);
}
/**
* Populates the current cookie with data from the supplied Set-Cookie header.
*
* @param string $header A Set-Cookie header
* @param string $issuingDomain The domain that issued the header
*/
public function fromSetCookieHeader($header, $issuingDomain)
{
list($this->name, $header) = explode('=', $header, 2);
if (false === strpos($header, ';')) {
$this->value = $header;
$header = null;
} else {
list($this->value, $header) = explode(';', $header, 2);
}
$this->clearAttributes();
foreach (array_map('trim', explode(';', trim($header))) as $pair) {
if (false === strpos($pair, '=')) {
$name = $pair;
$value = null;
} else {
list($name, $value) = explode('=', $pair);
}
$this->setAttribute($name, $value);
}
if (!$this->getAttribute(static::ATTR_DOMAIN)) {
$this->setAttribute(static::ATTR_DOMAIN, $issuingDomain);
}
}
/**
* Formats a Cookie header for the current cookie.
*
* @return string An HTTP request Cookie header
*/
public function toCookieHeader()
{
return 'Cookie: '.$this->getName().'='.$this->getValue();
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setValue($value)
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setAttributes(array $attributes)
{
// attributes are case insensitive
$this->attributes = array_change_key_case($attributes);
}
public function setAttribute($name, $value)
{
$this->attributes[strtolower($name)] = $value;
}
public function getAttributes()
{
return $this->attributes;
}
public function getAttribute($name)
{
$name = strtolower($name);
if (isset($this->attributes[$name])) {
return $this->attributes[$name];
}
}
public function hasAttribute($name)
{
return array_key_exists($name, $this->attributes);
}
public function clearAttributes()
{
$this->setAttributes(array());
}
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
}
public function getCreatedAt()
{
return $this->createdAt;
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Buzz\Util;
use Buzz\Message\MessageInterface;
use Buzz\Message\RequestInterface;
class CookieJar
{
protected $cookies = array();
public function setCookies($cookies)
{
$this->cookies = array();
foreach ($cookies as $cookie) {
$this->addCookie($cookie);
}
}
public function getCookies()
{
return $this->cookies;
}
/**
* Adds a cookie to the current cookie jar.
*
* @param Cookie $cookie A cookie object
*/
public function addCookie(Cookie $cookie)
{
$this->cookies[] = $cookie;
}
/**
* Adds Cookie headers to the supplied request.
*
* @param RequestInterface $request A request object
*/
public function addCookieHeaders(RequestInterface $request)
{
foreach ($this->cookies as $cookie) {
if ($cookie->matchesRequest($request)) {
$request->addHeader($cookie->toCookieHeader());
}
}
}
/**
* Processes Set-Cookie headers from a request/response pair.
*
* @param RequestInterface $request A request object
* @param MessageInterface $response A response object
*/
public function processSetCookieHeaders(RequestInterface $request, MessageInterface $response)
{
foreach ($response->getHeader('Set-Cookie', false) as $header) {
$cookie = new Cookie();
$cookie->fromSetCookieHeader($header, parse_url($request->getHost(), PHP_URL_HOST));
$this->addCookie($cookie);
}
}
/**
* Removes expired cookies.
*/
public function clearExpiredCookies()
{
foreach ($this->cookies as $i => $cookie) {
if ($cookie->isExpired()) {
unset($this->cookies[$i]);
}
}
// reset array keys
$this->cookies = array_values($this->cookies);
}
}

View file

@ -0,0 +1,190 @@
<?php
namespace Buzz\Util;
use Buzz\Message\RequestInterface;
use Buzz\Exception\InvalidArgumentException;
class Url
{
private static $defaultPorts = array(
'http' => 80,
'https' => 443,
);
private $url;
private $components;
/**
* Constructor.
*
* @param string $url The URL
*
* @throws InvalidArgumentException If the URL is invalid
*/
public function __construct($url)
{
$components = parse_url($url);
if (false === $components) {
throw new InvalidArgumentException(sprintf('The URL "%s" is invalid.', $url));
}
// support scheme-less URLs
if (!isset($components['host']) && isset($components['path'])) {
$pos = strpos($components['path'], '/');
if (false === $pos) {
$components['host'] = $components['path'];
unset($components['path']);
} elseif (0 !== $pos) {
list($host, $path) = explode('/', $components['path'], 2);
$components['host'] = $host;
$components['path'] = '/'.$path;
}
}
// default port
if (isset($components['scheme']) && !isset($components['port']) && isset(self::$defaultPorts[$components['scheme']])) {
$components['port'] = self::$defaultPorts[$components['scheme']];
}
$this->url = $url;
$this->components = $components;
}
public function getScheme()
{
return $this->parseUrl('scheme');
}
public function getHostname()
{
return $this->parseUrl('host');
}
public function getPort()
{
return $this->parseUrl('port');
}
public function getUser()
{
return $this->parseUrl('user');
}
public function getPassword()
{
return $this->parseUrl('pass');
}
public function getPath()
{
return $this->parseUrl('path');
}
public function getQueryString()
{
return $this->parseUrl('query');
}
public function getFragment()
{
return $this->parseUrl('fragment');
}
/**
* Returns a host string that combines scheme, hostname and port.
*
* @return string A host value for an HTTP message
*/
public function getHost()
{
if ($hostname = $this->parseUrl('host')) {
$host = $scheme = $this->parseUrl('scheme', 'http');
$host .= '://';
$host .= $hostname;
$port = $this->parseUrl('port');
if ($port && (!isset(self::$defaultPorts[$scheme]) || self::$defaultPorts[$scheme] != $port)) {
$host .= ':'.$port;
}
return $host;
}
}
/**
* Returns a resource string that combines path and query string.
*
* @return string A resource value for an HTTP message
*/
public function getResource()
{
$resource = $this->parseUrl('path', '/');
if ($query = $this->parseUrl('query')) {
$resource .= '?'.$query;
}
return $resource;
}
/**
* Returns a formatted URL.
*/
public function format($pattern)
{
static $map = array(
's' => 'getScheme',
'u' => 'getUser',
'a' => 'getPassword',
'h' => 'getHostname',
'o' => 'getPort',
'p' => 'getPath',
'q' => 'getQueryString',
'f' => 'getFragment',
'H' => 'getHost',
'R' => 'getResource',
);
$url = '';
$parts = str_split($pattern);
while ($part = current($parts)) {
if (isset($map[$part])) {
$method = $map[$part];
$url .= $this->$method();
} elseif ('\\' == $part) {
$url .= next($parts);
} elseif (!ctype_alpha($part)) {
$url .= $part;
} else {
throw new InvalidArgumentException(sprintf('The format character "%s" is invalid.', $part));
}
next($parts);
}
return $url;
}
/**
* Applies the current URL to the supplied request.
*/
public function applyToRequest(RequestInterface $request)
{
$request->setResource($this->getResource());
$request->setHost($this->getHost());
}
private function parseUrl($component = null, $default = null)
{
if (null === $component) {
return $this->components;
} elseif (isset($this->components[$component])) {
return $this->components[$component];
} else {
return $default;
}
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace KeenIO\Http\Adaptor;
/**
* Class AdaptorInterface
*
* @package KeenIO\Http\Adaptor
*/
interface AdaptorInterface
{
/**
* post to the KeenIO API
*
* @param $url
* @param array $parameters
* @return mixed
*/
public function doPost($url, array $parameters);
}

View file

@ -0,0 +1,49 @@
<?php
namespace KeenIO\Http\Adaptor;
use Buzz\Browser;
use Buzz\Client\Curl;
/**
* Class Buzz
* @package KeenIO\Http\Adaptor
*/
final class Buzz implements AdaptorInterface
{
private $apiKey;
private $browser;
/**
* @param $apiKey
* @param null $client
*/
public function __construct($apiKey)
{
$this->apiKey = $apiKey;
$this->browser = new Browser(new Curl());
$this->browser->getClient()->setVerifyPeer(false);
}
/**
* post to the KeenIO API
*
* @param $url
* @param array $parameters
* @return mixed
*/
public function doPost($url, array $parameters)
{
$headers = array(
// 'Authorization' => $this->apiKey,
'Content-Type' => 'application/json'
);
$content = json_encode($parameters);
$response = $this->browser->post($url, $headers, $content);
return $response->getContent();
}
}

View file

@ -0,0 +1,215 @@
<?php
namespace KeenIO\Service;
use KeenIO\Http\Adaptor\AdaptorInterface
, KeenIO\Http\Adaptor\Buzz as BuzzHttpAdaptor
;
/**
* Class KeenIO
*
* @package KeenIO\Service
*/
final class KeenIO
{
private static $projectId;
private static $apiKey;
private static $httpAdaptor;
public static function getApiKey()
{
return self::$apiKey;
}
/**
* @param $value
* @throws \Exception
*/
public static function setApiKey($value)
{
if (!ctype_alnum($value)) {
throw new \Exception(sprintf("API Key '%s' contains invalid characters or spaces.", $value));
}
self::$apiKey = $value;
}
public static function getProjectId()
{
return self::$projectId;
}
/**
* @param $value
* @throws \Exception
*/
public static function setProjectId($value)
{
// Validate collection name
if (!ctype_alnum($value)) {
throw new \Exception(
"Project ID '" . $value . "' contains invalid characters or spaces."
);
}
self::$projectId = $value;
}
/**
* @return BuzzHttpAdaptor
*/
public static function getHttpAdaptor()
{
if (!self::$httpAdaptor) {
self::$httpAdaptor = new BuzzHttpAdaptor(self::getApiKey());
}
return self::$httpAdaptor;
}
/**
* @param AdaptorInterface $httpAdaptor
*/
public static function setHttpAdaptor(AdaptorInterface $httpAdaptor)
{
self::$httpAdaptor = $httpAdaptor;
}
/**
* @param $projectId
* @param $apiKey
*/
public static function configure($projectId, $apiKey)
{
self::setProjectId($projectId);
self::setApiKey($apiKey);
}
/**
* add an event to KeenIO
*
* @param $collectionName
* @param $parameters
* @return mixed
* @throws \Exception
*/
public static function addEvent($collectionName, $parameters = array())
{
self::validateConfiguration();
if (!ctype_alnum($collectionName)) {
throw new \Exception(
sprintf("Collection name '%s' contains invalid characters or spaces.", $collectionName)
);
}
$url = sprintf(
'https://api.keen.io/3.0/projects/%s/events/%s',
self::getProjectId(),
$collectionName
);
$response = self::getHttpAdaptor()->doPost($url, $parameters);
$json = json_decode($response);
return $json->created;
}
/**
* get a scoped key for an array of filters
*
* @param $filters
* @return string
*/
public static function getScopedKey($filters)
{
self::validateConfiguration();
$filterArray = array('filters' => $filters);
$filterJson = self::padString(json_encode($filterArray));
$ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($ivLength);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::getApiKey(), $filterJson, MCRYPT_MODE_CBC, $iv);
$ivHex = bin2hex($iv);
$encryptedHex = bin2hex($encrypted);
$scopedKey = $ivHex . $encryptedHex;
return $scopedKey;
}
/**
* decrypt a scoped key (primarily used for testing)
*
* @param $scopedKey
* @return mixed
*/
public static function decryptScopedKey($scopedKey)
{
$ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC) * 2;
$ivHex = substr($scopedKey, 0, $ivLength);
$encryptedHex = substr($scopedKey, $ivLength);
$resultPadded = mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
self::getApiKey(),
pack('H*', $encryptedHex),
MCRYPT_MODE_CBC,
pack('H*', $ivHex)
);
$result = self::unpadString($resultPadded);
$filterArray = json_decode($result, true);
return $filterArray['filters'];
}
/**
* implement PKCS7 padding
*
* @param $string
* @param int $blockSize
* @return string
*/
protected static function padString($string, $blockSize = 32)
{
$paddingSize = $blockSize - (strlen($string) % $blockSize);
$string .= str_repeat(chr($paddingSize), $paddingSize);
return $string;
}
/**
* remove padding for a PKCS7-padded string
*
* @param $string
* @return string
*/
protected static function unpadString($string)
{
$len = strlen($string);
$pad = ord($string[$len - 1]);
return substr($string, 0, $len - $pad);
}
protected static function validateConfiguration()
{
// Validate configuration
if (!self::getProjectId()) {
throw new \Exception('Keen IO has not been configured');
}
// if (!self::getProjectId() or !self::getApiKey()) {
// throw new \Exception('Keen IO has not been configured');
// }
}
}

View file

@ -0,0 +1,183 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
abstract class Collection
{
/**
* @var array
*/
protected $aItems;
/**
* @access protected
*/
protected function __construct()
{
$this->aItems = array();
}
/**
* @param mixed $mItem
* @param bool $bToTop = false
* @return self
*/
public function Add($mItem, $bToTop = false)
{
if ($bToTop)
{
\array_unshift($this->aItems, $mItem);
}
else
{
\array_push($this->aItems, $mItem);
}
return $this;
}
/**
* @param array $aItems
* @return self
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function AddArray($aItems)
{
if (!\is_array($aItems))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
foreach ($aItems as $mItem)
{
$this->Add($mItem);
}
return $this;
}
/**
* @return self
*/
public function Clear()
{
$this->aItems = array();
return $this;
}
/**
* @return array
*/
public function CloneAsArray()
{
return $this->aItems;
}
/**
* @return int
*/
public function Count()
{
return \count($this->aItems);
}
/**
* @return array
*/
public function &GetAsArray()
{
return $this->aItems;
}
/**
* @param mixed $mCallback
*/
public function MapList($mCallback)
{
$aResult = array();
if (\is_callable($mCallback))
{
foreach ($this->aItems as $oItem)
{
$aResult[] = \call_user_func($mCallback, $oItem);
}
}
return $aResult;
}
/**
* @param mixed $mCallback
* @return array
*/
public function FilterList($mCallback)
{
$aResult = array();
if (\is_callable($mCallback))
{
foreach ($this->aItems as $oItem)
{
if (\call_user_func($mCallback, $oItem))
{
$aResult[] = $oItem;
}
}
}
return $aResult;
}
/**
* @param mixed $mCallback
* @return void
*/
public function ForeachList($mCallback)
{
if (\is_callable($mCallback))
{
foreach ($this->aItems as $oItem)
{
\call_user_func($mCallback, $oItem);
}
}
}
/**
* @return mixed | null
* @return mixed
*/
public function &GetByIndex($iIndex)
{
$mResult = null;
if (\key_exists($iIndex, $this->aItems))
{
$mResult = $this->aItems[$iIndex];
}
return $mResult;
}
/**
* @param array $aItems
* @return self
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function SetAsArray($aItems)
{
if (!\is_array($aItems))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$this->aItems = $aItems;
return $this;
}
}

View file

@ -0,0 +1,180 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Crypt {
/**
*
* @param string $sString
* @param string $sKey
*
* @return string
*/
public static function XxteaEncrypt($sString, $sKey)
{
if (0 === \strlen($sString))
{
return '';
}
$aV = self::str2long($sString, true);
$aK = self::str2long($sKey, false);
if (\count($aK) < 4)
{
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++)
{
$aK[$iIndex] = 0;
}
}
$iN = \count($aV) - 1;
$iZ = $aV[$iN];
$iY = $aV[0];
$iDelta = 0x9E3779B9;
$iQ = \floor(6 + 52 / ($iN + 1));
$iSum = 0;
while (0 < $iQ--)
{
$iSum = self::int32($iSum + $iDelta);
$iE = $iSum >> 2 & 3;
for ($iPIndex = 0; $iPIndex < $iN; $iPIndex++)
{
$iY = $aV[$iPIndex + 1];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iZ = $aV[$iPIndex] = self::int32($aV[$iPIndex] + $iMx);
}
$iY = $aV[0];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iZ = $aV[$iN] = self::int32($aV[$iN] + $iMx);
}
return self::long2str($aV, false);
}
/**
* @param string $sEncriptedString
* @param string $sKey
*
* @return string
*/
public static function XxteaDecrypt($sEncriptedString, $sKey)
{
if (0 === \strlen($sEncriptedString))
{
return '';
}
$aV = self::str2long($sEncriptedString, false);
$aK = self::str2long($sKey, false);
if (\count($aK) < 4)
{
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++)
{
$aK[$iIndex] = 0;
}
}
$iN = \count($aV) - 1;
$iZ = $aV[$iN];
$iY = $aV[0];
$iDelta = 0x9E3779B9;
$iQ = \floor(6 + 52 / ($iN + 1));
$iSum = self::int32($iQ * $iDelta);
while ($iSum != 0)
{
$iE = $iSum >> 2 & 3;
for ($iPIndex = $iN; $iPIndex > 0; $iPIndex--)
{
$iZ = $aV[$iPIndex - 1];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iY = $aV[$iPIndex] = self::int32($aV[$iPIndex] - $iMx);
}
$iZ = $aV[$iN];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iY = $aV[0] = self::int32($aV[0] - $iMx);
$iSum = self::int32($iSum - $iDelta);
}
return self::long2str($aV, true);
}
/**
* @param array $aV
* @param array $aW
*
* @return string
*/
private static function long2str($aV, $aW)
{
$iLen = \count($aV);
$iN = ($iLen - 1) << 2;
if ($aW)
{
$iM = $aV[$iLen - 1];
if (($iM < $iN - 3) || ($iM > $iN))
{
return false;
}
$iN = $iM;
}
$aS = array();
for ($iIndex = 0; $iIndex < $iLen; $iIndex++)
{
$aS[$iIndex] = \pack('V', $aV[$iIndex]);
}
if ($aW)
{
return \substr(\join('', $aS), 0, $iN);
}
else
{
return \join('', $aS);
}
}
/**
* @param string $sS
* @param string $sW
*
* @return array
*/
private static function str2long($sS, $sW)
{
$aV = \unpack('V*', $sS . \str_repeat("\0", (4 - \strlen($sS) % 4) & 3));
$aV = \array_values($aV);
if ($sW)
{
$aV[\count($aV)] = \strlen($sS);
}
return $aV;
}
/**
* @param int $iN
*
* @return int
*/
private static function int32($iN)
{
while ($iN >= 2147483648)
{
$iN -= 4294967296;
}
while ($iN <= -2147483649)
{
$iN += 4294967296;
}
return (int) $iN;
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class DateTimeHelper
{
/**
* @access private
*/
private function __construct()
{
}
/**
* @staticvar \DateTimeZone $oDateTimeZone
*
* @return \DateTimeZone
*/
public static function GetUtcTimeZoneObject()
{
static $oDateTimeZone = null;
if (null === $oDateTimeZone)
{
$oDateTimeZone = new \DateTimeZone('UTC');
}
return $oDateTimeZone;
}
/**
* Parse date string formated as "Thu, 10 Jun 2010 08:58:33 -0700 (PDT)"
* RFC2822
*
* @param string $sDateTime
*
* @return int
*/
public static function ParseRFC2822DateString($sDateTime)
{
$sDateTime = \trim(\preg_replace('/ \([a-zA-Z0-9]+\)$/', '', \trim($sDateTime)));
$oDateTime = \DateTime::createFromFormat('D, d M Y H:i:s O', $sDateTime, \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject());
return $oDateTime ? $oDateTime->getTimestamp() : 0;
}
/**
* Parse date string formated as "10-Jan-2012 01:58:17 -0800"
* IMAP INTERNALDATE Format
*
* @param string $sDateTime
*
* @return int
*/
public static function ParseInternalDateString($sDateTime)
{
$oDateTime = \DateTime::createFromFormat('d-M-Y H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject());
return $oDateTime ? $oDateTime->getTimestamp() : 0;
}
/**
* Parse date string formated as "2011-06-14 23:59:59 +0400"
*
* @param string $sDateTime
*
* @return int
*/
public static function ParseDateStringType1($sDateTime)
{
$oDateTime = \DateTime::createFromFormat('Y-m-d H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject());
return $oDateTime ? $oDateTime->getTimestamp() : 0;
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace MailSo\Base\Enumerations;
/**
* @category MailSo
* @package Base
* @subpackage Enumerations
*/
class Charset
{
const UTF_8 = 'utf-8';
const UTF_7 = 'utf-7';
const UTF_7_IMAP = 'utf7-imap';
const WIN_1250 = 'windows-1250';
const WIN_1251 = 'windows-1251';
const WIN_1252 = 'windows-1252';
const WIN_1253 = 'windows-1253';
const WIN_1254 = 'windows-1254';
const WIN_1255 = 'windows-1255';
const WIN_1256 = 'windows-1256';
const WIN_1257 = 'windows-1257';
const WIN_1258 = 'windows-1258';
const ISO_8859_1 = 'iso-8859-1';
const ISO_8859_8 = 'iso-8859-8';
const ISO_8859_8_I = 'iso-8859-8-i';
}

View file

@ -0,0 +1,24 @@
<?php
namespace MailSo\Base\Enumerations;
/**
* @category MailSo
* @package Base
* @subpackage Enumerations
*/
class Encoding
{
const QUOTED_PRINTABLE = 'Quoted-Printable';
const QUOTED_PRINTABLE_LOWER = 'quoted-printable';
const QUOTED_PRINTABLE_SHORT = 'Q';
const BASE64 = 'Base64';
const BASE64_LOWER = 'base64';
const BASE64_SHORT = 'B';
const SEVEN_BIT = '7bit';
const _7_BIT = '7bit';
const EIGHT_BIT = '8bit';
const _8_BIT = '8bit';
}

View file

@ -0,0 +1,24 @@
<?php
namespace MailSo\Base\Exceptions;
/**
* @category MailSo
* @package Base
* @subpackage Exceptions
*/
class Exception extends \Exception
{
/**
* @param string $sMessage
* @param int $iCode
* @param \Exception|null $oPrevious
*/
public function __construct($sMessage = '', $iCode = 0, $oPrevious = null)
{
$sMessage = 0 === strlen($sMessage) ? str_replace('\\', '-', get_class($this)).' ('.
basename($this->getFile()).' ~ '.$this->getLine().')' : $sMessage;
parent::__construct($sMessage, $iCode, $oPrevious);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Base\Exceptions;
/**
* @category MailSo
* @package Base
* @subpackage Exceptions
*/
class InvalidArgumentException extends \MailSo\Base\Exceptions\Exception {}

View file

@ -0,0 +1,666 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class HtmlUtils
{
/**
* @access private
*/
private function __construct()
{
}
/**
* @param string $sText
*
* @return \DOMDocument | bool
*/
public static function GetDomFromText($sText)
{
static $bOnce = true;
if ($bOnce)
{
$bOnce = false;
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('libxml_use_internal_errors'))
{
@\libxml_use_internal_errors(true);
}
}
$oDom = new \DOMDocument('1.0', 'utf-8');
@$oDom->loadHTML('<'.'?xml version="1.0" encoding="utf-8"?'.'>'.
'<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>'.$sText.'</body></html>');
return $oDom;
}
/**
* @param string $sHtml
*
* @return string
*/
public static function ClearBodyAndHtmlTag($sHtml)
{
$sHtml = \preg_replace('/<body([^>]*)>/im', '<div\\1>', $sHtml);
$sHtml = \preg_replace('/<\/body>/im', '</div>', $sHtml);
$sHtml = \preg_replace('/<html([^>]*)>/im', '<div\\1>', $sHtml);
$sHtml = \preg_replace('/<\/html>/im', '</div>', $sHtml);
return $sHtml;
}
/**
* @param string $sHtml
*
* @return string
*/
public static function ClearTags($sHtml)
{
$aRemoveTags = array(
'head', 'link', 'base', 'meta', 'title', 'style', 'script', 'bgsound',
'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset'
);
$aToRemove = array(
'/<!doctype[^>]*>/msi',
'/<\?xml [^>]*\?>/msi'
);
foreach ($aRemoveTags as $sTag)
{
$aToRemove[] = '\'<'.$sTag.'[^>]*>.*?</[\s]*'.$sTag.'>\'msi';
$aToRemove[] = '\'<'.$sTag.'[^>]*>\'msi';
$aToRemove[] = '\'</[\s]*'.$sTag.'[^>]*>\'msi';
}
return \preg_replace($aToRemove, '', $sHtml);
}
/**
* @param string $sHtml
*
* @return string
*/
public static function ClearOn($sHtml)
{
$aToReplace = array(
'/on(Blur)/si',
'/on(Change)/si',
'/on(Click)/si',
'/on(DblClick)/si',
'/on(Error)/si',
'/on(Focus)/si',
'/on(KeyDown)/si',
'/on(KeyPress)/si',
'/on(KeyUp)/si',
'/on(Load)/si',
'/on(MouseDown)/si',
'/on(MouseEnter)/si',
'/on(MouseLeave)/si',
'/on(MouseMove)/si',
'/on(MouseOut)/si',
'/on(MouseOver)/si',
'/on(MouseUp)/si',
'/on(Move)/si',
'/on(Resize)/si',
'/on(ResizeEnd)/si',
'/on(ResizeStart)/si',
'/on(Scroll)/si',
'/on(Select)/si',
'/on(Submit)/si',
'/on(Unload)/si'
);
return \preg_replace($aToReplace, 'оn\\1', $sHtml);
}
/**
*
* @param string $sStyle
* @param \DOMElement $oElement
* @param bool $bHasExternals
* @param array $aFoundCIDs
*
* @return string
*/
public static function ClearStyle($sStyle, $oElement, &$bHasExternals, &$aFoundCIDs)
{
$sStyle = \trim($sStyle);
$aOutStyles = array();
$aStyles = \explode(';', $sStyle);
$aMatch = array();
foreach ($aStyles as $sStyleItem)
{
$aStyleValue = \explode(':', $sStyleItem, 2);
$sName = \trim(\strtolower($aStyleValue[0]));
$sValue = isset($aStyleValue[1]) ? \trim($aStyleValue[1]) : '';
if ('position' === $sName && 'fixed' === \strtolower($sValue))
{
$sValue = 'absolute';
}
if (0 === \strlen($sName) || 0 === \strlen($sValue))
{
continue;
}
$sStyleItem = $sName.': '.$sValue;
$aStyleValue = array($sName, $sValue);
/*if (\in_array($sName, array('position', 'left', 'right', 'top', 'bottom', 'behavior', 'cursor')))
{
// skip
}
else */if (\in_array($sName, array('behavior', 'cursor')) ||
('display' === $sName && 'none' === \strtolower($sValue)) ||
\preg_match('/expression/i', $sValue) ||
('text-indent' === $sName && '-' === \substr(trim($sValue), 0, 1))
)
{
// skip
}
else if (\in_array($sName, array('background-image', 'background', 'list-style-image', 'content'))
&& \preg_match('/url[\s]?\(([^)]+)\)/im', $sValue, $aMatch) && !empty($aMatch[1]))
{
$sFullUrl = \trim($aMatch[0], '"\' ');
$sUrl = \trim($aMatch[1], '"\' ');
$sStyleValue = \trim(\preg_replace('/[\s]+/', ' ', \str_replace($sFullUrl, '', $sValue)));
$sStyleItem = empty($sStyleValue) ? '' : $sName.': '.$sStyleValue;
if ('cid:' === \strtolower(\substr($sUrl, 0, 4)))
{
if ($oElement)
{
$oElement->setAttribute('data-x-style-cid-name',
'background' === $sName ? 'background-image' : $sName);
$oElement->setAttribute('data-x-style-cid', \substr($sUrl, 4));
$aFoundCIDs[] = \substr($sUrl, 4);
}
}
else
{
if ($oElement)
{
if (\preg_match('/http[s]?:\/\//i', $sUrl))
{
$bHasExternals = true;
if (\in_array($sName, array('background-image', 'list-style-image', 'content')))
{
$sStyleItem = '';
}
$sTemp = '';
if ($oElement->hasAttribute('data-x-style-url'))
{
$sTemp = \trim($oElement->getAttribute('data-x-style-url'));
}
$sTemp = empty($sTemp) ? '' : (';' === \substr($sTemp, -1) ? $sTemp.' ' : $sTemp.'; ');
$oElement->setAttribute('data-x-style-url', \trim($sTemp.
('background' === $sName ? 'background-image' : $sName).': '.$sFullUrl, ' ;'));
}
else if ('data:image/' !== \strtolower(\substr(\trim($sUrl), 0, 11)))
{
$oElement->setAttribute('data-x-broken-style-src', $sFullUrl);
}
}
}
if (!empty($sStyleItem))
{
$aOutStyles[] = $sStyleItem;
}
}
else if ('height' === $sName)
{
// $aOutStyles[] = 'min-'.ltrim($sStyleItem);
$aOutStyles[] = $sStyleItem;
}
else
{
$aOutStyles[] = $sStyleItem;
}
}
return \implode(';', $aOutStyles);
}
/**
* @param string $sHtml
* @param bool $bHasExternals
* @param array $aFoundCIDs
*
* @return string
*/
public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array())
{
$sHtml = null === $sHtml ? '' : (string) $sHtml;
$sHtml = \trim($sHtml);
if (0 === \strlen($sHtml))
{
return '';
}
$bHasExternals = false;
$sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml);
$sHtml = \MailSo\Base\HtmlUtils::ClearOn($sHtml);
$sHtml = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sHtml);
// Dom Part
$oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml);
unset($sHtml);
if ($oDom)
{
$aNodes = $oDom->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{
$sTagNameLower = \strtolower($oElement->tagName);
if ('iframe' === $sTagNameLower || 'frame' === $sTagNameLower)
{
$oElement->setAttribute('src', 'javascript:false');
}
if (\in_array($sTagNameLower, array('a', 'form', 'area')))
{
$oElement->setAttribute('target', '_blank');
}
if (\in_array($sTagNameLower, array('a', 'form', 'area', 'input', 'button', 'textarea')))
{
$oElement->setAttribute('tabindex', '-1');
}
// if ('blockquote' === $sTagNameLower)
// {
// $oElement->removeAttribute('style');
// }
@$oElement->removeAttribute('id');
@$oElement->removeAttribute('class');
@$oElement->removeAttribute('contenteditable');
@$oElement->removeAttribute('designmode');
@$oElement->removeAttribute('data-bind');
if ($oElement->hasAttribute('src'))
{
$sSrc = \trim($oElement->getAttribute('src'));
$oElement->removeAttribute('src');
if ('cid:' === \strtolower(\substr($sSrc, 0, 4)))
{
$oElement->setAttribute('data-x-src-cid', \substr($sSrc, 4));
$aFoundCIDs[] = \substr($sSrc, 4);
}
else
{
if (\preg_match('/http[s]?:\/\//i', $sSrc))
{
$oElement->setAttribute('data-x-src', $sSrc);
$bHasExternals = true;
}
else if ('data:image/' === \strtolower(\substr(\trim($sSrc), 0, 11)))
{
$oElement->setAttribute('src', $sSrc);
}
else
{
$oElement->setAttribute('data-x-broken-src', $sSrc);
}
}
}
$sBackground = $oElement->hasAttribute('background')
? \trim($oElement->getAttribute('background')) : '';
$sBackgroundColor = $oElement->hasAttribute('bgcolor')
? \trim($oElement->getAttribute('bgcolor')) : '';
if (!empty($sBackground) || !empty($sBackgroundColor))
{
$aStyles = array();
$sStyles = $oElement->hasAttribute('style')
? $oElement->getAttribute('style') : '';
if (!empty($sBackground))
{
$aStyles[] = 'background-image: url(\''.$sBackground.'\')';
$oElement->removeAttribute('background');
}
if (!empty($sBackgroundColor))
{
$aStyles[] = 'background-color: '.$sBackgroundColor;
$oElement->removeAttribute('bgcolor');
}
$oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').\implode('; ', $aStyles));
}
if ($oElement->hasAttribute('style'))
{
$oElement->setAttribute('style',
\MailSo\Base\HtmlUtils::ClearStyle($oElement->getAttribute('style'), $oElement, $bHasExternals, $aFoundCIDs));
}
}
$sResult = $oDom->saveHTML();
}
unset($oDom);
$sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult);
$sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult);
return \trim($sResult);
}
/**
* @param string $sHtml
* @param array $aFoundCids = array()
*
* @return string
*/
public static function BuildHtml($sHtml, &$aFoundCids = array())
{
$oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml);
unset($sHtml);
$aNodes = $oDom->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{
if ($oElement->hasAttribute('data-x-src-cid'))
{
$sCid = $oElement->getAttribute('data-x-src-cid');
$oElement->removeAttribute('data-x-src-cid');
if (!empty($sCid))
{
$aFoundCids[] = $sCid;
@$oElement->removeAttribute('src');
$oElement->setAttribute('src', 'cid:'.$sCid);
}
}
if ($oElement->hasAttribute('data-x-broken-src'))
{
$oElement->setAttribute('src', $oElement->getAttribute('data-x-broken-src'));
$oElement->removeAttribute('data-x-broken-src');
}
if ($oElement->hasAttribute('data-x-src'))
{
$oElement->setAttribute('src', $oElement->getAttribute('data-x-src'));
$oElement->removeAttribute('data-x-src');
}
if ($oElement->hasAttribute('data-x-href'))
{
$oElement->setAttribute('href', $oElement->getAttribute('data-x-href'));
$oElement->removeAttribute('data-x-href');
}
if ($oElement->hasAttribute('data-x-style-cid-name') && $oElement->hasAttribute('data-x-style-cid'))
{
$sCidName = $oElement->getAttribute('data-x-style-cid-name');
$sCid = $oElement->getAttribute('data-x-style-cid');
$oElement->removeAttribute('data-x-style-cid-name');
$oElement->removeAttribute('data-x-style-cid');
if (!empty($sCidName) && !empty($sCid) && \in_array($sCidName,
array('background-image', 'background', 'list-style-image', 'content')))
{
$sStyles = '';
if ($oElement->hasAttribute('style'))
{
$sStyles = \trim(\trim($oElement->getAttribute('style')), ';');
}
$sBack = $sCidName.': url(cid:'.$sCid.')';
$sStyles = \preg_replace('/'.\preg_quote($sCidName, '/').':\s?[^;]+/i', $sBack, $sStyles);
if (false === \strpos($sStyles, $sBack))
{
$sStyles .= empty($sStyles) ? '': '; ';
$sStyles .= $sBack;
}
$oElement->setAttribute('style', $sStyles);
$aFoundCids[] = $sCid;
}
}
if ($oElement->hasAttribute('data-x-style-url'))
{
$sAddStyles = $oElement->getAttribute('data-x-style-url');
$oElement->removeAttribute('data-x-style-url');
if (!empty($sAddStyles))
{
$sStyles = '';
if ($oElement->hasAttribute('style'))
{
$sStyles = \trim(\trim($oElement->getAttribute('style')), ';');
}
$oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').$sAddStyles);
}
}
}
$sResult = $oDom->saveHTML();
unset($oDom);
$sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult);
$sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult);
return '<!DOCTYPE html><html'.(\MailSo\Base\Utils::IsRTL($sResult) ? ' dir="rtl"' : ' dir="ltr"').'><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><head>'.
'<body>'.\trim($sResult).'</body></html>';
}
/**
* @param string $sText
* @param bool $bLinksWithTargetBlank = true
*
* @return string
*/
public static function ConvertPlainToHtml($sText, $bLinksWithTargetBlank = true)
{
$sText = \trim($sText);
if (0 === \strlen($sText))
{
return '';
}
$sText = \MailSo\Base\LinkFinder::NewInstance()
->Text($sText)
->UseDefaultWrappers($bLinksWithTargetBlank)
// ->CompileText(true, false);
->CompileText(true, true);
$sText = \str_replace("\r", '', $sText);
$aText = \explode("\n", $sText);
unset($sText);
$bIn = false;
$bDo = true;
do
{
$bDo = false;
$aNextText = array();
foreach ($aText as $sTextLine)
{
$bStart = 0 === \strpos(\ltrim($sTextLine), '&gt;');
if ($bStart && !$bIn)
{
$bDo = true;
$bIn = true;
$aNextText[] = '<blockquote>';
$aNextText[] = \substr(\ltrim($sTextLine), 4);
}
else if (!$bStart && $bIn)
{
$bIn = false;
$aNextText[] = '</blockquote>';
$aNextText[] = $sTextLine;
}
else if ($bStart && $bIn)
{
$aNextText[] = \substr(\ltrim($sTextLine), 4);
}
else
{
$aNextText[] = $sTextLine;
}
}
if ($bIn)
{
$bIn = false;
$aNextText[] = '</blockquote>';
}
$aText = $aNextText;
}
while ($bDo);
$sText = \join("\n", $aText);
unset($aText);
$sText = \preg_replace('/[\n][ ]+/', "\n", $sText);
// $sText = \preg_replace('/[\s]+([\s])/', '\\1', $sText);
$sText = \preg_replace('/<blockquote>[\s]+/i', '<blockquote>', $sText);
$sText = \preg_replace('/[\s]+<\/blockquote>/i', '</blockquote>', $sText);
$sText = \preg_replace('/<\/blockquote>([\n]{0,2})<blockquote>/i', '\\1', $sText);
$sText = \preg_replace('/[\n]{3,}/', "\n\n", $sText);
$sText = \strtr($sText, array(
"\n" => "<br />",
"\t" => '&nbsp;&nbsp;&nbsp;',
' ' => '&nbsp;&nbsp;'
));
return $sText;
}
/**
* @param string $sText
*
* @return string
*/
public static function ConvertHtmlToPlain($sText)
{
$sText = trim(stripslashes($sText));
$sText = preg_replace('/[\s]+/', ' ', $sText);
$sText = preg_replace(array(
"/\r/",
"/[\n\t]+/",
'/<script[^>]*>.*?<\/script>/i',
'/<style[^>]*>.*?<\/style>/i',
'/<title[^>]*>.*?<\/title>/i',
'/<h[123][^>]*>(.+?)<\/h[123]>/i',
'/<h[456][^>]*>(.+?)<\/h[456]>/i',
'/<p[^>]*>/i',
'/<br[^>]*>/i',
'/<b[^>]*>(.+?)<\/b>/i',
'/<i[^>]*>(.+?)<\/i>/i',
'/(<ul[^>]*>|<\/ul>)/i',
'/(<ol[^>]*>|<\/ol>)/i',
'/<li[^>]*>/i',
'/<a[^>]*href="([^"]+)"[^>]*>(.+?)<\/a>/i',
'/<hr[^>]*>/i',
'/(<table[^>]*>|<\/table>)/i',
'/(<tr[^>]*>|<\/tr>)/i',
'/<td[^>]*>(.+?)<\/td>/i',
'/<th[^>]*>(.+?)<\/th>/i',
'/&nbsp;/i',
'/&quot;/i',
'/&gt;/i',
'/&lt;/i',
'/&amp;/i',
'/&copy;/i',
'/&trade;/i',
'/&#8220;/',
'/&#8221;/',
'/&#8211;/',
'/&#8217;/',
'/&#38;/',
'/&#169;/',
'/&#8482;/',
'/&#151;/',
'/&#147;/',
'/&#148;/',
'/&#149;/',
'/&reg;/i',
'/&bull;/i',
'/&[&;]+;/i',
'/&#39;/',
'/&#160;/'
), array(
'',
' ',
'',
'',
'',
"\n\n\\1\n\n",
"\n\n\\1\n\n",
"\n\n\t",
"\n",
'\\1',
'\\1',
"\n\n",
"\n\n",
"\n\t* ",
'\\2 (\\1)',
"\n------------------------------------\n",
"\n",
"\n",
"\t\\1\n",
"\t\\1\n",
' ',
'"',
'>',
'<',
'&',
'(c)',
'(tm)',
'"',
'"',
'-',
"'",
'&',
'(c)',
'(tm)',
'--',
'"',
'"',
'*',
'(R)',
'*',
'',
'\'',
''
), $sText);
$sText = str_ireplace('<div>',"\n<div>", $sText);
$sText = strip_tags($sText, '');
$sText = preg_replace("/\n\\s+\n/", "\n", $sText);
$sText = preg_replace("/[\n]{3,}/", "\n\n", $sText);
return trim($sText);
}
}

View file

@ -0,0 +1,583 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Http
{
/**
* @var bool
*/
private $bIsMagicQuotesOn;
/**
* @access private
*/
private function __construct()
{
$this->bIsMagicQuotesOn = (bool) @\ini_get('magic_quotes_gpc');
}
/**
* @return \MailSo\Base\Http
*/
public static function NewInstance()
{
return new self();
}
/**
* @staticvar \MailSo\Base\Http $oInstance;
*
* @return \MailSo\Base\Http
*/
public static function SingletonInstance()
{
static $oInstance = null;
if (null === $oInstance)
{
$oInstance = self::NewInstance();
}
return $oInstance;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasQuery($sKey)
{
return isset($_GET[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
* @param bool $bClearPercZeroZero = true
*
* @return mixed
*/
public function GetQuery($sKey, $mDefault = null, $bClearPercZeroZero = true)
{
return isset($_GET[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_GET[$sKey], $bClearPercZeroZero) : $mDefault;
}
/**
* @return array|null
*/
public function GetQueryAsArray()
{
return isset($_GET) && \is_array($_GET) ? \MailSo\Base\Utils::StripSlashesValue($_GET, true) : null;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasPost($sKey)
{
return isset($_POST[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
* @param bool $bClearPercZeroZero = false
*
* @return mixed
*/
public function GetPost($sKey, $mDefault = null, $bClearPercZeroZero = false)
{
return isset($_POST[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_POST[$sKey], $bClearPercZeroZero) : $mDefault;
}
/**
* @return array|null
*/
public function GetPostAsArray()
{
return isset($_POST) && \is_array($_POST) ? \MailSo\Base\Utils::StripSlashesValue($_POST, false) : null;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasRequest($sKey)
{
return isset($_REQUEST[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
*
* @return mixed
*/
public function GetRequest($sKey, $mDefault = null)
{
return isset($_REQUEST[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_REQUEST[$sKey]) : $mDefault;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasServer($sKey)
{
return isset($_SERVER[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
*
* @return mixed
*/
public function GetServer($sKey, $mDefault = null)
{
return isset($_SERVER[$sKey]) ? $_SERVER[$sKey] : $mDefault;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasEnv($sKey)
{
return isset($_ENV[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
*
* @return mixed
*/
public function GetEnv($sKey, $mDefault = null)
{
return isset($_ENV[$sKey]) ? $_ENV[$sKey] : $mDefault;
}
/**
* @return string
*/
public function ServerProtocol()
{
return $this->GetServer('SERVER_PROTOCOL', 'HTTP/1.0');
}
/**
* @return string
*/
public function GetMethod()
{
return $this->GetServer('REQUEST_METHOD', '');
}
/**
* @return bool
*/
public function IsPost()
{
return ('POST' === $this->GetMethod());
}
/**
* @return bool
*/
public function IsGet()
{
return ('GET' === $this->GetMethod());
}
/**
* @return string
*/
public function GetQueryString()
{
return $this->GetServer('QUERY_STRING', '');
}
/**
* @return bool
*/
public function CheckLocalhost($sServer)
{
return \in_array(\strtolower(\trim($sServer)), array(
'localhost', '127.0.0.1', '::1', '::1/128', '0:0:0:0:0:0:0:1'
));
}
/**
* @return bool
*/
public function IsLocalhost()
{
return $this->CheckLocalhost($this->GetServer('REMOTE_ADDR', ''));
}
/**
* @return string
*/
public function GetRawBody()
{
static $sRawBody = null;
if (null === $sRawBody)
{
$sBody = @\file_get_contents('php://input');
$sRawBody = (false !== $sBody) ? $sBody : '';
}
return $sRawBody;
}
/**
* @param string $sHeader
*
* @return string
*/
public function GetHeader($sHeader)
{
$sResultHeader = '';
$sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
$sResultHeader = $this->GetServer($sServerKey, '');
if (0 === \strlen($sResultHeader) &&
\MailSo\Base\Utils::FunctionExistsAndEnabled('apache_request_headers'))
{
$sHeaders = \apache_request_headers();
if (isset($sHeaders[$sHeader]))
{
$sResultHeader = $sHeaders[$sHeader];
}
}
return $sResultHeader;
}
/**
* @return string
*/
public function GetScheme()
{
return ('on' === \strtolower($this->GetServer('HTTPS'))) ? 'https' : 'http';
}
/**
* @return bool
*/
public function IsSecure()
{
return ('https' === $this->GetScheme());
}
/**
* @param bool $bWithRemoteUserData = false
* @param bool $bRemoveWWW = true
*
* @return string
*/
public function GetHost($bWithRemoteUserData = false, $bRemoveWWW = true)
{
$sHost = $this->GetServer('HTTP_HOST', '');
if (0 === \strlen($sHost))
{
$sScheme = $this->GetScheme();
$sName = $this->GetServer('SERVER_NAME');
$iPort = (int) $this->GetServer('SERVER_PORT');
$sHost = (('http' === $sScheme && 80 === $iPort) || ('https' === $sScheme && 443 === $iPort))
? $sName : $sName.':'.$iPort;
}
if ($bRemoveWWW)
{
$sHost = 'www.' === \substr(\strtolower($sHost), 0, 4) ? \substr($sHost, 0, 4) : $sHost;
}
if ($bWithRemoteUserData)
{
$sUser = \trim($this->HasServer('REMOTE_USER') ? $this->GetServer('REMOTE_USER', '') : '');
$sHost = (0 < \strlen($sUser) ? $sUser.'@' : '').$sHost;
}
return $sHost;
}
/**
* @param bool $bCheckProxy = true
*
* @return string
*/
public function GetClientIp($bCheckProxy = true)
{
$sIp = '';
if ($bCheckProxy && null !== $this->GetServer('HTTP_CLIENT_IP', null))
{
$sIp = $this->GetServer('HTTP_CLIENT_IP', '');
}
else if ($bCheckProxy && null !== $this->GetServer('HTTP_X_FORWARDED_FOR', null))
{
$sIp = $this->GetServer('HTTP_X_FORWARDED_FOR', '');
}
else
{
$sIp = $this->GetServer('REMOTE_ADDR', '');
}
return $sIp;
}
/**
* @param string $sUrl
* @param array $aPost = array()
* @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)'
* @param int $iCode = 0
* @param \MailSo\Log\Logger $oLogger = null
*
* @return string|bool
*/
public function SendPostRequest($sUrl, $aPost = array(), $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$iCode = 0, $oLogger = null)
{
$aOptions = array(
CURLOPT_URL => $sUrl,
CURLOPT_HEADER => false,
CURLOPT_FAILONERROR => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $aPost,
CURLOPT_TIMEOUT => 20
);
if (0 < \strlen($sCustomUserAgent))
{
$aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent;
}
$oCurl = \curl_init();
\curl_setopt_array($oCurl, $aOptions);
if ($oLogger)
{
$oLogger->Write('cURL: Send post request: '.$sUrl);
}
$mResult = \curl_exec($oCurl);
$iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE);
$sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE);
if ($oLogger)
{
$oLogger->Write('cURL: Post request result: (Status: '.$iCode.', ContentType: '.$sContentType.')');
if (false === $mResult || 200 !== $iCode)
{
$oLogger->Write('cURL: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING);
}
}
if (\is_resource($oCurl))
{
\curl_close($oCurl);
}
return $mResult;
}
/**
* @param string $sUrl
* @param resource $rFile
* @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)'
* @param string $sContentType = ''
* @param int $iCode = 0
* @param \MailSo\Log\Logger $oLogger = null
*
* @return bool
*/
public function SaveUrlToFile($sUrl, $rFile, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null)
{
if (!is_resource($rFile))
{
if ($oLogger)
{
$oLogger->Write('cURL: input resource invalid.', \MailSo\Log\Enumerations\Type::WARNING);
}
return false;
}
$aOptions = array(
CURLOPT_URL => $sUrl,
CURLOPT_HEADER => false,
CURLOPT_FAILONERROR => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FILE => $rFile,
CURLOPT_TIMEOUT => 10
);
if (0 < \strlen($sCustomUserAgent))
{
$aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent;
}
$oCurl = \curl_init();
\curl_setopt_array($oCurl, $aOptions);
if ($oLogger)
{
$oLogger->Write('cURL: Send request: '.$sUrl);
}
$bResult = \curl_exec($oCurl);
$iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE);
$sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE);
if ($oLogger)
{
$oLogger->Write('cURL: Request result: '.($bResult ? 'true' : 'false').' (Status: '.$iCode.', ContentType: '.$sContentType.')');
if (!$bResult || 200 !== $iCode)
{
$oLogger->Write('cURL: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING);
}
}
if (\is_resource($oCurl))
{
\curl_close($oCurl);
}
return $bResult;
}
/**
* @param string $sUrl
* @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)'
* @param string $sContentType = ''
* @param int $iCode = 0
* @param \MailSo\Log\Logger $oLogger = null
*
* @return string|bool
*/
public function GetUrlAsString($sUrl, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null)
{
$rMemFile = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
if ($this->SaveUrlToFile($sUrl, $rMemFile, $sCustomUserAgent, $sContentType, $iCode, $oLogger) && \is_resource($rMemFile))
{
\rewind($rMemFile);
return \stream_get_contents($rMemFile);
}
return false;
}
/**
* @param int $iExpireTime
* @param bool $bSetCacheHeader = true
* @param string $sEtag = ''
*
* @return bool
*/
public function ServerNotModifiedCache($iExpireTime, $bSetCacheHeader = true, $sEtag = '')
{
$bResult = false;
if (0 < $iExpireTime)
{
$iUtcTimeStamp = \time();
$sIfModifiedSince = $this->GetHeader('If-Modified-Since', '');
if (0 === \strlen($sIfModifiedSince))
{
if ($bSetCacheHeader)
{
\header('Cache-Control: public', true);
\header('Pragma: public', true);
\header('Last-Modified: '.\gmdate('D, d M Y H:i:s', $iUtcTimeStamp - $iExpireTime).' UTC', true);
\header('Expires: '.\gmdate('D, j M Y H:i:s', $iUtcTimeStamp + $iExpireTime).' UTC', true);
if (0 < strlen($sEtag))
{
\header('Etag: '.$sEtag, true);
}
}
}
else
{
$this->StatusHeader(304);
$bResult = true;
}
}
return $bResult;
}
/**
* @param int $iStatus
*
* @return void
*/
public function StatusHeader($iStatus, $sCustomStatusText = '')
{
switch ($iStatus)
{
default:
\header('Status: '.$iStatus, true, $iStatus);
break;
case 304:
\header($this->ServerProtocol().' 304 '.(0 === \strlen($sCustomStatusText) ? 'Not Modified' : $sCustomStatusText), true, $iStatus);
break;
case 200:
\header($this->ServerProtocol().' 200 '.(0 === \strlen($sCustomStatusText) ? 'OK' : $sCustomStatusText), true, $iStatus);
break;
case 401:
\header($this->ServerProtocol().' 401 '.(0 === \strlen($sCustomStatusText) ? 'Please sign in' : $sCustomStatusText), true, $iStatus);
break;
case 404:
\header($this->ServerProtocol().' 404 '.(0 === \strlen($sCustomStatusText) ? 'Not Found' : $sCustomStatusText), true, $iStatus);
break;
}
}
/**
* @return string
*/
public function GetPath()
{
$sUrl = \ltrim(\substr($this->GetServer('SCRIPT_NAME', ''), 0, \strrpos($this->GetServer('SCRIPT_NAME', ''), '/')), '/');
return '' === $sUrl ? '/' : '/'.$sUrl.'/';
}
/**
* @return string
*/
public function GetUrl()
{
return '/'.$this->GetServer('REQUEST_URI', '');
}
/**
* @return string
*/
public function GetFullUrl()
{
return $this->GetScheme().'://'.$this->GetHost(true, false).$this->GetPath();
}
/**
* @return string
*/
public function GetFullUrlWithQuery()
{
return $this->GetScheme().'://'.$this->GetHost(true, false).$this->GetUrl();
}
}

View file

@ -0,0 +1,323 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class LinkFinder
{
/**
* @const
*/
const OPEN_LINK = '@#@link{';
const CLOSE_LINK = '}link@#@';
/**
* @var array
*/
private $aPrepearPlainStringUrls;
/**
* @var string
*/
private $sText;
/**
* @var mixed
*/
private $fLinkWrapper;
/**
* @var int
*/
private $iHtmlSpecialCharsFlags;
/**
* @var mixed
*/
private $fMailWrapper;
/**
* @access private
*/
private function __construct()
{
$this->iHtmlSpecialCharsFlags = (\defined('ENT_QUOTES') && \defined('ENT_SUBSTITUTE') && \defined('ENT_HTML401'))
? ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 : ENT_QUOTES;
if (\defined('ENT_IGNORE'))
{
$this->iHtmlSpecialCharsFlags |= ENT_IGNORE;
}
$this->Clear();
}
/**
* @return \MailSo\Base\LinkFinder
*/
public static function NewInstance()
{
return new self();
}
/**
* @return \MailSo\Base\LinkFinder
*/
public function Clear()
{
$this->aPrepearPlainStringUrls = array();
$this->fLinkWrapper = null;
$this->fMailWrapper = null;
$this->sText = '';
return $this;
}
/**
* @param string $sText
*
* @return \MailSo\Base\LinkFinder
*/
public function Text($sText)
{
$this->sText = $sText;
return $this;
}
/**
* @param mixed $fLinkWrapper
*
* @return \MailSo\Base\LinkFinder
*/
public function LinkWrapper($fLinkWrapper)
{
$this->fLinkWrapper = $fLinkWrapper;
return $this;
}
/**
* @param mixed $fMailWrapper
*
* @return \MailSo\Base\LinkFinder
*/
public function MailWrapper($fMailWrapper)
{
$this->fMailWrapper = $fMailWrapper;
return $this;
}
/**
* @param bool $bAddTargetBlank = false
*
* @return \MailSo\Base\LinkFinder
*/
public function UseDefaultWrappers($bAddTargetBlank = false)
{
$this->fLinkWrapper = function ($sLink, $bShortLink = false) use ($bAddTargetBlank) {
if ($bShortLink && \in_array(\strtolower($sLink), array('asp.net', 'vb.net', 'mailbee.net')))
{
return $sLink;
}
$sNameLink = $sLink;
if (!\preg_match('/^[a-z]{3,5}\:\/\//i', \ltrim($sLink)))
{
$sLink = 'http://'.\ltrim($sLink);
}
return '<a '.($bAddTargetBlank ? 'target="_blank" ': '').'href="'.$sLink.'">'.$sNameLink.'</a>';
};
$this->fMailWrapper = function ($sEmail) use ($bAddTargetBlank) {
return '<a '.($bAddTargetBlank ? 'target="_blank" ': '').'href="mailto:'.$sEmail.'">'.$sEmail.'</a>';
};
return $this;
}
/**
* @param bool $bUseHtmlSpecialChars = true
* @param bool $bFindShortLinks = true
*
* @return string
*/
public function CompileText($bUseHtmlSpecialChars = true, $bFindShortLinks = true)
{
$sText = $this->sText;
$this->aPrepearPlainStringUrls = array();
if (null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper))
{
$sText = $this->findLinks($sText, $this->fLinkWrapper);
}
if (null !== $this->fMailWrapper && \is_callable($this->fMailWrapper))
{
$sText = $this->findMails($sText, $this->fMailWrapper);
}
if ($bFindShortLinks && null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper))
{
$sText = $this->findShortLinks($sText, $this->fLinkWrapper);
}
if ($bUseHtmlSpecialChars)
{
$sText = @\htmlentities($sText, $this->iHtmlSpecialCharsFlags, 'UTF-8');
}
if (0 < \count($this->aPrepearPlainStringUrls))
{
for ($iIndex = 0, $iLen = \count($this->aPrepearPlainStringUrls); $iIndex < $iLen; $iIndex++)
{
$sText = \str_replace(\MailSo\Base\LinkFinder::OPEN_LINK.$iIndex.
\MailSo\Base\LinkFinder::CLOSE_LINK, $this->aPrepearPlainStringUrls[$iIndex], $sText);
}
$this->aPrepearPlainStringUrls = array();
}
return $sText;
}
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findLinks($sText, $fWrapper)
{
$sPattern = '/([\W]|^)((?:https?:\/\/)|(?:svn:\/\/)|(?:git:\/\/)|(?:s?ftps?:\/\/)|(?:www\.))'.
'((\S+?)(\\/)?)((?:&gt;)?|[^\w\=\\/;\(\)\[\]]*?)(?=<|\s|$)/imu';
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
if (\is_array($aMatch) && 6 < \count($aMatch))
{
while (\in_array($sChar = \substr($aMatch[3], -1), array(']', ')')))
{
if (\substr_count($aMatch[3], ']' === $sChar ? '[': '(') - \substr_count($aMatch[3], $sChar) < 0)
{
$aMatch[3] = \substr($aMatch[3], 0, -1);
$aMatch[6] = (']' === $sChar ? ']': ')').$aMatch[6];
}
else
{
break;
}
}
$sLinkWithWrap = \call_user_func($fWrapper, $aMatch[2].$aMatch[3]);
if (\is_string($sLinkWithWrap) && 0 < \strlen($sLinkWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap);
return $aMatch[1].
\MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK.
$aMatch[6];
}
return $aMatch[0];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findShortLinks($sText, $fWrapper)
{
$sPattern = '/([a-z0-9-\.]+\.(?:com|org|net|ru))([^a-z0-9-\.])/i';
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
if (\is_array($aMatch) && 2 < \count($aMatch) && isset($aMatch[1]) && 0 < \strlen($aMatch[1]))
{
$sLinkWithWrap = \call_user_func_array($fWrapper, array($aMatch[1], true));
if (\is_string($sLinkWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap);
return \MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK.
$aMatch[2];
}
return $aMatch[0];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findMails($sText, $fWrapper)
{
$sPattern = '/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/';
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
if (\is_array($aMatch) && isset($aMatch[1]))
{
$sMailWithWrap = \call_user_func($fWrapper, $aMatch[1]);
if (\is_string($sMailWithWrap) && 0 < \strlen($sMailWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sMailWithWrap);
return \MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK;
}
return $aMatch[1];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Loader
{
/**
* @var bool
*/
public static $StoreStatistic = true;
/**
* @var array
*/
private static $aIncStatistic = array();
/**
* @var array
*/
private static $aSetStatistic = array();
/**
* @staticvar bool $bIsInited
*
* @return void
*/
public static function Init()
{
static $bIsInited = false;
if (!$bIsInited)
{
$bIsInited = true;
self::SetStatistic('Inited', \microtime(true));
}
}
/**
* @param string $sName
* @param int $iIncSize = 1
*
* @return void
*/
public static function IncStatistic($sName, $iIncSize = 1)
{
if (self::$StoreStatistic)
{
self::$aIncStatistic[$sName] = isset(self::$aIncStatistic[$sName])
? self::$aIncStatistic[$sName] + $iIncSize : $iIncSize;
}
}
/**
* @param string $sName
* @param mixed $mValue
*
* @return void
*/
public static function SetStatistic($sName, $mValue)
{
if (self::$StoreStatistic)
{
self::$aSetStatistic[$sName] = $mValue;
}
}
/**
* @param string $sName
*
* @return mixed
*/
public static function GetStatistic($sName)
{
return self::$StoreStatistic && isset(self::$aSetStatistic[$sName]) ? self::$aSetStatistic[$sName] : null;
}
/**
* @return array|null
*/
public static function Statistic()
{
$aResult = null;
if (self::$StoreStatistic)
{
$aResult = array(
'php' => array(
'phpversion' => \phpversion(),
'ssl' => (int) \function_exists('openssl_open'),
'iconv' => (int) \function_exists('iconv')
));
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('memory_get_usage') &&
\MailSo\Base\Utils::FunctionExistsAndEnabled('memory_get_peak_usage'))
{
$aResult['php']['memory_get_usage'] =
Utils::FormatFileSize(\memory_get_usage(true), 2);
$aResult['php']['memory_get_peak_usage'] =
Utils::FormatFileSize(\memory_get_peak_usage(true), 2);
}
self::SetStatistic('TimeDelta', \microtime(true) - self::GetStatistic('Inited'));
$aResult['statistic'] = self::$aSetStatistic;
$aResult['counts'] = self::$aIncStatistic;
}
return $aResult;
}
}

View file

@ -0,0 +1,116 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class ResourceRegistry
{
/**
* @var array
*/
public static $Resources = array();
/**
* @access private
*/
private function __construct()
{
}
/**
* @staticvar bool $bInited
*
* @return void
*/
private static function regResourcesShutdownFunc()
{
static $bInited = false;
if (!$bInited)
{
$bInited = true;
\register_shutdown_function(function () {
if (\is_array(\MailSo\Base\ResourceRegistry::$Resources))
{
foreach (\array_keys(\MailSo\Base\ResourceRegistry::$Resources) as $sKey)
{
if (\is_resource(\MailSo\Base\ResourceRegistry::$Resources[$sKey]))
{
\MailSo\Base\Loader::IncStatistic('CloseMemoryResource');
\fclose(\MailSo\Base\ResourceRegistry::$Resources[$sKey]);
}
\MailSo\Base\ResourceRegistry::$Resources[$sKey] = null;
}
}
\MailSo\Base\ResourceRegistry::$Resources = array();
});
}
}
/**
* @param int $iMemoryMaxInMb = 5
*
* @return resource | bool
*/
public static function CreateMemoryResource($iMemoryMaxInMb = 5)
{
self::regResourcesShutdownFunc();
$oResult = @\fopen('php://temp/maxmemory:'.($iMemoryMaxInMb * 1024 * 1024), 'r+b');
if (\is_resource($oResult))
{
\MailSo\Base\Loader::IncStatistic('CreateMemoryResource');
\MailSo\Base\ResourceRegistry::$Resources[(string) $oResult] = $oResult;
return $oResult;
}
return false;
}
/**
* @param string $sString
*
* @return resource | bool
*/
public static function CreateMemoryResourceFromString($sString)
{
$oResult = self::CreateMemoryResource();
if (\is_resource($oResult))
{
\fwrite($oResult, $sString);
\rewind($oResult);
}
return $oResult;
}
/**
* @param resource $rResource
*
* @return void
*/
public static function CloseMemoryResource(&$rResource)
{
if (\is_resource($rResource))
{
$sKey = (string) $rResource;
if (isset(\MailSo\Base\ResourceRegistry::$Resources[$sKey]))
{
\fclose(\MailSo\Base\ResourceRegistry::$Resources[$sKey]);
\MailSo\Base\ResourceRegistry::$Resources[$sKey] = null;
unset(\MailSo\Base\ResourceRegistry::$Resources[$sKey]);
\MailSo\Base\Loader::IncStatistic('CloseMemoryResource');
}
if (\is_resource($rResource))
{
\fclose($rResource);
}
$rResource = null;
}
}
}

View file

@ -0,0 +1,368 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class Binary
{
/**
* @var string
*/
const STREAM_NAME = 'mailsobinary';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var resource
*/
private $rStream;
/**
* @var string
*/
private $sFromEncoding;
/**
* @var string
*/
private $sToEncoding;
/**
* @var string
*/
private $sFunctionName;
/**
* @var int
*/
private $iPos;
/**
* @var string
*/
private $sBuffer;
/**
* @var string
*/
private $sReadEndBuffer;
/**
* @param string $sContentTransferEncoding
* @param bool $bDecode = true
*
* @return string
*/
public static function GetInlineDecodeOrEncodeFunctionName($sContentTransferEncoding, $bDecode = true)
{
$sFunctionName = '';
switch (strtolower($sContentTransferEncoding))
{
case \MailSo\Base\Enumerations\Encoding::BASE64_LOWER:
// InlineBase64Decode
$sFunctionName = $bDecode ? 'InlineBase64Decode' : 'convert.base64-encode';
break;
case \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_LOWER:
// InlineQuotedPrintableDecode
$sFunctionName = $bDecode ? 'convert.quoted-printable-decode' : 'convert.quoted-printable-encode';
break;
}
return $sFunctionName;
}
/**
* @param string $sBodyString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineNullDecode($sBodyString, &$sEndBuffer)
{
$sEndBuffer = '';
return $sBodyString;
}
/**
* @param string $sBaseString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineBase64Decode($sBaseString, &$sEndBuffer)
{
$sEndBuffer = '';
$sBaseString = str_replace(array("\r", "\n", "\t"), '', $sBaseString);
$iBaseStringLen = strlen($sBaseString);
$iBaseStringNormFloorLen = floor($iBaseStringLen / 4) * 4;
if ($iBaseStringNormFloorLen < $iBaseStringLen)
{
$sEndBuffer = substr($sBaseString, $iBaseStringNormFloorLen);
$sBaseString = substr($sBaseString, 0, $iBaseStringNormFloorLen);
}
return \MailSo\Base\Utils::Base64Decode($sBaseString);
}
/**
* @param string $sQuotedPrintableString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineQuotedPrintableDecode($sQuotedPrintableString, &$sEndBuffer)
{
$sEndBuffer = '';
$sQuotedPrintableLen = strlen($sQuotedPrintableString);
$iLastSpace = strrpos($sQuotedPrintableString, ' ');
if (false !== $iLastSpace && $iLastSpace + 1 < $sQuotedPrintableLen)
{
$sEndBuffer = substr($sQuotedPrintableString, $iLastSpace + 1);
$sQuotedPrintableString = substr($sQuotedPrintableString, 0, $iLastSpace + 1);
}
return quoted_printable_decode($sQuotedPrintableString);
}
/**
* @param string $sEncodedString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineConvertDecode($sEncodedString, &$sEndBuffer, $sFromEncoding, $sToEncoding)
{
$sEndBuffer = '';
$sQuotedPrintableLen = strlen($sEncodedString);
$iLastSpace = strrpos($sEncodedString, ' ');
if (false !== $iLastSpace && $iLastSpace + 1 < $sQuotedPrintableLen)
{
$sEndBuffer = substr($sEncodedString, $iLastSpace + 1);
$sEncodedString = substr($sEncodedString, 0, $iLastSpace + 1);
}
return \MailSo\Base\Utils::ConvertEncoding($sEncodedString, $sFromEncoding, $sToEncoding);
}
/**
* @param resource $rStream
* @param string $sUtilsDecodeOrEncodeFunctionName = null
* @param string $sFromEncoding = null
* @param string $sToEncoding = null
*
* @return resource|bool
*/
public static function CreateStream($rStream,
$sUtilsDecodeOrEncodeFunctionName = null, $sFromEncoding = null, $sToEncoding = null)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\Binary');
}
if (null === $sUtilsDecodeOrEncodeFunctionName || 0 === strlen($sUtilsDecodeOrEncodeFunctionName))
{
$sUtilsDecodeOrEncodeFunctionName = 'InlineNullDecode';
}
$sHashName = md5(microtime(true).mt_rand(1000, 9999));
if (null !== $sFromEncoding && null !== $sToEncoding && $sFromEncoding !== $sToEncoding)
{
$rStream = self::CreateStream($rStream, $sUtilsDecodeOrEncodeFunctionName);
$sUtilsDecodeOrEncodeFunctionName = 'InlineConvertDecode';
}
if (in_array($sUtilsDecodeOrEncodeFunctionName, array(
'convert.base64-decode', 'convert.base64-encode',
'convert.quoted-printable-decode', 'convert.quoted-printable-encode'
)))
{
$rFilter = \stream_filter_append($rStream, $sUtilsDecodeOrEncodeFunctionName,
STREAM_FILTER_READ, array(
'line-length' => \MailSo\Mime\Enumerations\Constants::LINE_LENGTH,
'line-break-chars' => \MailSo\Mime\Enumerations\Constants::CRLF
));
return \is_resource($rFilter) ? $rStream : false;
}
self::$aStreams[$sHashName] =
array($rStream, $sUtilsDecodeOrEncodeFunctionName, $sFromEncoding, $sToEncoding);
\MailSo\Base\Loader::IncStatistic('CreateStream/Binary');
return \fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$this->iPos = 0;
$this->sBuffer = '';
$this->sReadEndBuffer = '';
$this->rStream = false;
$this->sFromEncoding = null;
$this->sToEncoding = null;
$this->sFunctionName = null;
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_array(self::$aStreams[$sHashName]) &&
4 === count(self::$aStreams[$sHashName]))
{
$this->rStream = self::$aStreams[$sHashName][0];
$this->sFunctionName = self::$aStreams[$sHashName][1];
$this->sFromEncoding = self::$aStreams[$sHashName][2];
$this->sToEncoding = self::$aStreams[$sHashName][3];
}
$bResult = is_resource($this->rStream);
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
$sReturn = '';
$sFunctionName = $this->sFunctionName;
if ($iCount > 0)
{
if ($iCount < strlen($this->sBuffer))
{
$sReturn = substr($this->sBuffer, 0, $iCount);
$this->sBuffer = substr($this->sBuffer, $iCount);
}
else
{
$sReturn = $this->sBuffer;
while ($iCount > 0)
{
if (feof($this->rStream))
{
if (0 === strlen($this->sBuffer.$sReturn))
{
return false;
}
if (0 < strlen($this->sReadEndBuffer))
{
$sReturn .= self::$sFunctionName($this->sReadEndBuffer,
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
$iDecodeLen = strlen($sReturn);
}
$iCount = 0;
$this->sBuffer = '';
}
else
{
$sReadResult = fread($this->rStream, 8192);
if (false === $sReadResult)
{
return false;
}
$sReturn .= self::$sFunctionName($this->sReadEndBuffer.$sReadResult,
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
$iDecodeLen = strlen($sReturn);
if ($iCount < $iDecodeLen)
{
$this->sBuffer = substr($sReturn, $iCount);
$sReturn = substr($sReturn, 0, $iCount);
$iCount = 0;
}
else
{
$iCount -= $iDecodeLen;
}
}
}
}
$this->iPos += strlen($sReturn);
return $sReturn;
}
return false;
}
/**
* @return int
*/
public function stream_write()
{
return 0;
}
/**
* @return int
*/
public function stream_tell()
{
return $this->iPos;
}
/**
* @return bool
*/
public function stream_eof()
{
return 0 === strlen($this->sBuffer) && feof($this->rStream);
}
/**
*
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 2,
'ino' => 0,
'mode' => 33206,
'nlink' => 1,
'uid' => 0,
'gid' => 0,
'rdev' => 2,
'size' => 0,
'atime' => 1061067181,
'mtime' => 1056136526,
'ctime' => 1056136526,
'blksize' => -1,
'blocks' => -1
);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

View file

@ -0,0 +1,185 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class Literal
{
/**
* @var string
*/
const STREAM_NAME = 'mailsoliteral';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var resource
*/
private $rStream;
/**
* @var int
*/
private $iSize;
/**
* @var int
*/
private $iPos;
/**
* @param resource $rStream
* @param int $iLiteralLen
*
* @return resource|bool
*/
public static function CreateStream($rStream, $iLiteralLen)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\Literal');
}
$sHashName = md5(microtime(true).mt_rand(1000, 9999));
self::$aStreams[$sHashName] = array($rStream, $iLiteralLen);
\MailSo\Base\Loader::IncStatistic('CreateStream/Literal');
return fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$this->iPos = 0;
$this->iSize = 0;
$this->rStream = false;
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_array(self::$aStreams[$sHashName]) &&
2 === count(self::$aStreams[$sHashName]))
{
$this->rStream = self::$aStreams[$sHashName][0];
$this->iSize = self::$aStreams[$sHashName][1];
}
$bResult = is_resource($this->rStream);
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
$sResult = false;
if ($this->iSize < $this->iPos + $iCount)
{
$iCount = $this->iSize - $this->iPos;
}
if ($iCount > 0)
{
$sReadResult = '';
$iRead = $iCount;
while (0 < $iRead)
{
$sAddRead = @fread($this->rStream, $iRead);
if (false === $sAddRead)
{
$sReadResult = false;
break;
}
$sReadResult .= $sAddRead;
$iRead -= strlen($sAddRead);
$this->iPos += strlen($sAddRead);
}
if (false !== $sReadResult)
{
$sResult = $sReadResult;
}
}
return $sResult;
}
/**
* @return int
*/
public function stream_write()
{
return 0;
}
/**
* @return int
*/
public function stream_tell()
{
return $this->iPos;
}
/**
* @return bool
*/
public function stream_eof()
{
return $this->iPos >= $this->iSize;
}
/**
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 2,
'ino' => 0,
'mode' => 33206,
'nlink' => 1,
'uid' => 0,
'gid' => 0,
'rdev' => 2,
'size' => $this->iSize,
'atime' => 1061067181,
'mtime' => 1056136526,
'ctime' => 1056136526,
'blksize' => -1,
'blocks' => -1
);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

View file

@ -0,0 +1,257 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class SubStreams
{
/**
* @var string
*/
const STREAM_NAME = 'mailsosubstreams';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var array
*/
private $aSubStreams;
/**
* @var int
*/
private $iIndex;
/**
* @var string
*/
private $sBuffer;
/**
* @var bool
*/
private $bIsEnd;
/**
* @var int
*/
private $iPos;
/**
* @param array $aSubStreams
*
* @return resource|bool
*/
public static function CreateStream($aSubStreams)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\SubStreams');
}
$sHashName = md5(microtime(true).mt_rand(1000, 9999));
self::$aStreams[$sHashName] = $aSubStreams;
\MailSo\Base\Loader::IncStatistic('CreateStream/SubStreams');
return fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
}
/**
* @return resource|null
*/
protected function &getPart()
{
$nNull = null;
if (isset($this->aSubStreams[$this->iIndex]));
{
return $this->aSubStreams[$this->iIndex];
}
return $nNull;
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$this->aSubStreams = array();
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_array(self::$aStreams[$sHashName]) &&
0 < count(self::$aStreams[$sHashName]))
{
$this->iIndex = 0;
$this->iPos = 0;
$this->bIsEnd = false;
$this->sBuffer = '';
$this->aSubStreams = self::$aStreams[$sHashName];
}
$bResult = 0 < count($this->aSubStreams);
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
$sReturn = '';
$mCurrentPart = null;
if ($iCount > 0)
{
if ($iCount < strlen($this->sBuffer))
{
$sReturn = substr($this->sBuffer, 0, $iCount);
$this->sBuffer = substr($this->sBuffer, $iCount);
}
else
{
$sReturn = $this->sBuffer;
while ($iCount > 0)
{
$mCurrentPart =& $this->getPart();
if (null === $mCurrentPart)
{
$this->bIsEnd = true;
$this->sBuffer = '';
$iCount = 0;
break;
}
if (is_resource($mCurrentPart))
{
if (!feof($mCurrentPart))
{
$sReadResult = fread($mCurrentPart, 8192);
if (false === $sReadResult)
{
return false;
}
$sReturn .= $sReadResult;
$iLen = strlen($sReturn);
if ($iCount < $iLen)
{
$this->sBuffer = substr($sReturn, $iCount);
$sReturn = substr($sReturn, 0, $iCount);
$iCount = 0;
}
else
{
$iCount -= $iLen;
}
}
else
{
$this->iIndex++;
}
}
else if (is_string($mCurrentPart))
{
$sReadResult = substr($mCurrentPart, 0, $iCount);
$sReturn .= $sReadResult;
$iLen = strlen($sReadResult);
if ($iCount < $iLen)
{
$this->sBuffer = substr($sReturn, $iCount);
$sReturn = substr($sReturn, 0, $iCount);
$iCount = 0;
}
else
{
$iCount -= $iLen;
}
$this->iIndex++;
}
}
}
$this->iPos += strlen($sReturn);
return $sReturn;
}
return false;
}
/**
* @return int
*/
public function stream_write()
{
return 0;
}
/**
* @return int
*/
public function stream_tell()
{
return $this->iPos;
}
/**
* @return bool
*/
public function stream_eof()
{
return $this->bIsEnd;
}
/**
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 2,
'ino' => 0,
'mode' => 33206,
'nlink' => 1,
'uid' => 0,
'gid' => 0,
'rdev' => 2,
'size' => 0,
'atime' => 1061067181,
'mtime' => 1056136526,
'ctime' => 1056136526,
'blksize' => -1,
'blocks' => -1
);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class Test
{
/**
* @var string
*/
const STREAM_NAME = 'mailsotest';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var resource
*/
private $rReadSream;
/**
* @param string $sRawResponse
*
* @return resource|bool
*/
public static function CreateStream($sRawResponse)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\Test');
}
$sHashName = md5(microtime(true).mt_rand(1000, 9999));
$rConnect = fopen('php://memory', 'r+b');
fwrite($rConnect, $sRawResponse);
fseek($rConnect, 0);
self::$aStreams[$sHashName] = $rConnect;
\MailSo\Base\Loader::IncStatistic('CreateStream/Test');
return fopen(self::STREAM_NAME.'://'.$sHashName, 'r+b');
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_resource(self::$aStreams[$sHashName]))
{
$this->rReadSream = self::$aStreams[$sHashName];
$bResult = true;
}
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
return fread($this->rReadSream, $iCount);
}
/**
* @param string $sInputString
*
* @return int
*/
public function stream_write($sInputString)
{
return strlen($sInputString);
}
/**
* @return int
*/
public function stream_tell()
{
return ftell($this->rReadSream);
}
/**
* @return bool
*/
public function stream_eof()
{
return feof($this->rReadSream);
}
/**
* @return array
*/
public function stream_stat()
{
return fstat($this->rReadSream);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,95 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Validator
{
/**
* @param string $sEmail
*
* @return bool
*/
public static function EmailString($sEmail)
{
$bResult = false;
if (self::NotEmptyString($sEmail))
{
$bResult = (bool) \preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\.\+\-_]*@[a-zA-Z0-9][a-zA-Z0-9\.\+\-_]*$/', $sEmail);
}
return $bResult;
}
/**
* @param string $sString
* @param bool $bTrim = false
*
* @return bool
*/
public static function NotEmptyString($sString, $bTrim = false)
{
$bResult = false;
if (\is_string($sString))
{
if ($bTrim)
{
$sString = \trim($sString);
}
$bResult = 0 < \strlen($sString);
}
return $bResult;
}
/**
* @param array $aList
*
* @return bool
*/
public static function NotEmptyArray($aList)
{
return \is_array($aList) && 0 < \count($aList);
}
/**
* @param int $iNumber
* @param int $iMin = null
* @param int $iMax = null
*
* @return bool
*/
public static function RangeInt($iNumber, $iMin = null, $iMax = null)
{
$bResult = false;
if (\is_int($iNumber))
{
$bResult = true;
if ($bResult && null !== $iMin)
{
$bResult = $iNumber >= $iMin;
}
if ($bResult && null !== $iMax)
{
$bResult = $iNumber <= $iMax;
}
}
return $bResult;
}
/**
* @param int $iPort
*
* @return bool
*/
public static function PortInt($iPort)
{
return self::RangeInt($iPort, 0, 65535);
}
}

View file

@ -0,0 +1,149 @@
<?php
namespace MailSo\Cache;
/**
* @category MailSo
* @package Cache
*/
class CacheClient
{
/**
* @var \MailSo\Cache\DriverInterface
*/
private $oDriver;
/**
* @var string
*/
private $sCacheIndex;
/**
* @access private
*/
private function __construct()
{
$this->oDriver = null;
$this->sCacheIndex = '';
}
/**
* @return \MailSo\Cache\CacheClient
*/
public static function NewInstance()
{
return new self();
}
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue)
{
return $this->oDriver ? $this->oDriver->Set($sKey.$this->sCacheIndex, $sValue) : false;
}
/**
* @param string $sKey
*
* @return bool
*/
public function SetTimer($sKey)
{
return $this->Set($sKey.'/TIMER', time());
}
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey)
{
$sValue = '';
if ($this->oDriver)
{
$sValue = $this->oDriver->Get($sKey.$this->sCacheIndex);
}
return $sValue;
}
/**
* @param string $sKey
*
* @return int
*/
public function GetTimer($sKey)
{
$iTimer = 0;
$sValue = $this->Get($sKey.'/TIMER');
if (0 < strlen($sValue) && is_numeric($sValue))
{
$iTimer = (int) $sValue;
}
return $iTimer;
}
/**
* @param string $sKey
*
* @return \MailSo\Cache\CacheClient
*/
public function Delete($sKey)
{
if ($this->oDriver)
{
$this->oDriver->Delete($sKey.$this->sCacheIndex);
}
return $this;
}
/**
* @param \MailSo\Cache\DriverInterface $oDriver
*
* @return \MailSo\Cache\CacheClient
*/
public function SetDriver(\MailSo\Cache\DriverInterface $oDriver)
{
$this->oDriver = $oDriver;
return $this;
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false;
}
/**
* @return bool
*/
public function IsInited()
{
return $this->oDriver instanceof \MailSo\Cache\DriverInterface;
}
/**
* @param string $sCacheIndex
*
* @return \MailSo\Cache\CacheClient
*/
public function SetCacheIndex($sCacheIndex)
{
$this->sCacheIndex = 0 < \strlen($sCacheIndex) ? "\x0".$sCacheIndex : '';
return $this;
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace MailSo\Cache;
/**
* @category MailSo
* @package Cache
*/
interface DriverInterface
{
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue);
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey);
/**
* @param string $sKey
*
* @return void
*/
public function Delete($sKey);
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24);
}

Some files were not shown because too many files have changed in this diff Show more