diff --git a/.gitignore b/.gitignore index 1fc5e393..e75c5ae8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -src/.idea/workspace.xml src/mibew/install/package src/absent_* src/release* @@ -15,3 +14,10 @@ src/mibew/plugins/* src/mibew/locales/* !src/mibew/locales/en/ !src/mibew/locales/names/ + +# Do not index composer files +src/composer.phar +src/composer.lock + +# Do not index third-party libraries +src/mibew/vendor diff --git a/src/.idea/.name b/src/.idea/.name deleted file mode 100644 index 4c926610..00000000 --- a/src/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -messenger \ No newline at end of file diff --git a/src/.idea/codeStyleSettings.xml b/src/.idea/codeStyleSettings.xml deleted file mode 100644 index de6382eb..00000000 --- a/src/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - diff --git a/src/.idea/encodings.xml b/src/.idea/encodings.xml deleted file mode 100644 index 0b99745d..00000000 --- a/src/.idea/encodings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/.idea/inspectionProfiles/Project_Default.xml b/src/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index c66df003..00000000 --- a/src/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/.idea/inspectionProfiles/profiles_settings.xml b/src/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b312839..00000000 --- a/src/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/.idea/messenger.iml b/src/.idea/messenger.iml deleted file mode 100644 index 54192b37..00000000 --- a/src/.idea/messenger.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/.idea/misc.xml b/src/.idea/misc.xml deleted file mode 100644 index 11e74ae4..00000000 --- a/src/.idea/misc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - http://www.w3.org/1999/xhtml - - - - diff --git a/src/.idea/modules.xml b/src/.idea/modules.xml deleted file mode 100644 index 3160e9b9..00000000 --- a/src/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/.idea/projectCodeStyle.xml b/src/.idea/projectCodeStyle.xml deleted file mode 100644 index 596456e4..00000000 --- a/src/.idea/projectCodeStyle.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - diff --git a/src/.idea/scopes/scope_settings.xml b/src/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b8..00000000 --- a/src/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/.idea/vcs.xml b/src/.idea/vcs.xml deleted file mode 100644 index 9ab281ac..00000000 --- a/src/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/build.xml b/src/build.xml index 55e2c4b8..0b73a386 100644 --- a/src/build.xml +++ b/src/build.xml @@ -5,11 +5,12 @@ + - + Flatten templates directory structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Done + + + + + + Handlebars templates from all styles are built. + + @@ -156,7 +224,7 @@ - Dialogs styles built. + Styles built. @@ -192,7 +260,7 @@ - + Build "${app_name}" JavaScript application @@ -200,9 +268,6 @@ - - - @@ -353,74 +418,6 @@ - - - Compile Handlebars templates of the Core - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Done - - - Mibew Messenger built. diff --git a/src/composer.json b/src/composer.json new file mode 100644 index 00000000..a85f70a8 --- /dev/null +++ b/src/composer.json @@ -0,0 +1,8 @@ +{ + "require": { + "xamin/handlebars.php": "dev-master#5b188ce19e9b07170238c82bd34051a31bdeebbf" + }, + "config": { + "vendor-dir": "mibew/vendor" + } +} \ No newline at end of file diff --git a/src/mibew/b.php b/src/mibew/b.php index a5536140..f364917a 100644 --- a/src/mibew/b.php +++ b/src/mibew/b.php @@ -33,7 +33,8 @@ if ($referer && isset($_SESSION['threadid'])) { $msg = getstring2_( "chat.client.visited.page", array($referer), - $thread->locale + $thread->locale, + true ); $thread->postMessage(Thread::KIND_FOR_AGENT, $msg); } diff --git a/src/mibew/install/index.php b/src/mibew/install/index.php index eff567b1..8bae8eab 100644 --- a/src/mibew/install/index.php +++ b/src/mibew/install/index.php @@ -34,6 +34,9 @@ require_once(MIBEW_FS_ROOT.'/libs/config.php'); */ define('MIBEW_CONFIG_WEB_ROOT', $mibewroot); +// Initialize external dependencies +require_once(MIBEW_FS_ROOT . '/vendor/autoload.php'); + // Try to get actual base URL of the Mibew $requestUri = $_SERVER["REQUEST_URI"]; if (!preg_match('/^(.*)\\/install(\\/[^\\/\\\\]*)?$/', $requestUri, $matches)) { @@ -55,8 +58,9 @@ require_once(MIBEW_FS_ROOT.'/libs/common/misc.php'); require_once(MIBEW_FS_ROOT.'/libs/common/response.php'); require_once(MIBEW_FS_ROOT.'/libs/common/string.php'); require_once(MIBEW_FS_ROOT.'/libs/classes/Mibew/Style/StyleInterface.php'); -require_once(MIBEW_FS_ROOT.'/libs/classes/Mibew/Style/Style.php'); +require_once(MIBEW_FS_ROOT.'/libs/classes/Mibew/Style/AbstractStyle.php'); require_once(MIBEW_FS_ROOT.'/libs/classes/Mibew/Style/PageStyle.php'); +require_once(MIBEW_FS_ROOT.'/libs/classes/Mibew/Handlebars/HelpersSet.php'); // Include database structure require_once(MIBEW_FS_ROOT.'/install/dbinfo.php'); diff --git a/src/mibew/js/compiled/default_app.js b/src/mibew/js/compiled/default_app.js index 1f7cf1f2..08d08445 100644 --- a/src/mibew/js/compiled/default_app.js +++ b/src/mibew/js/compiled/default_app.js @@ -1,13 +1,3 @@ -/* - Copyright 2005-2013 the original author or authors. - Licensed under the Apache License, Version 2.0 (the "License"). - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -*/ -(function(){var k=Handlebars.template,l=Handlebars.templates=Handlebars.templates||{};l.default_control=k(function(a,b,e,h,f){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,a.helpers);f=f||{};h=this.escapeExpression;a="";(e=e.title)?e=e.call(b,{hash:{},data:f}):(e=b.title,e="function"===typeof e?e.apply(b):e);return a+=h(e)+""});l.message=k(function(a,b,e,h,f){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,a.helpers);f=f||{};var c,g=this.escapeExpression,j=e.helperMissing;a={hash:{}, -data:f};a=""+(g((c=e.formatTime||b.formatTime,c?c.call(b,b.created,a):j.call(b,"formatTime",b.created,a)))+"\n");if((c=e["if"].call(b,b.name,{hash:{},inverse:this.noop,fn:this.program(1,function(a,c){var b,d;b="";(d=e.name)?d=d.call(a,{hash:{},data:c}):(d=a.name,d="function"===typeof d?d.apply(a):d);return b+=g(d)+": "},f),data:f}))||0===c)a+=c;a+="\n";if((c=e["if"].call(b,b.allowFormatting,{hash:{},inverse:this.program(5,function(a,b){var c,d;d={hash:{},data:b};return g((c=e.apply||a.apply,c?c.call(a,a.message,"urlReplace, nl2br",d):j.call(a,"apply",a.message,"urlReplace, nl2br",d)))},f),fn:this.program(3,function(a,c){var b,d;d={hash:{},data:c};return g((b=e.apply||a.apply,b?b.call(a,a.message,"urlReplace, nl2br, allowTags",d):j.call(a, -"apply",a.message,"urlReplace, nl2br, allowTags",d)))},f),data:f}))||0===c)a+=c;return a+="
"})})(); /* Copyright 2005-2013 the original author or authors. Licensed under the Apache License, Version 2.0 (the "License"). diff --git a/src/mibew/js/compiled/users_app.js b/src/mibew/js/compiled/users_app.js index eb5c4637..a86fb390 100644 --- a/src/mibew/js/compiled/users_app.js +++ b/src/mibew/js/compiled/users_app.js @@ -1,37 +1,3 @@ -/* - Copyright 2005-2013 the original author or authors. - Licensed under the Apache License, Version 2.0 (the "License"). - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -*/ -(function(){var l=Handlebars.template,m=Handlebars.templates=Handlebars.templates||{};m.agent=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f=e.helperMissing,h=this.escapeExpression;c='';(a=e.name)?a=a.call(b,{hash:{},data:d}):(a=b.name,a="function"===typeof a?a.apply(b):a);c+=h(a);if((a=e.unless.call(b,b.isLast,{hash:{},inverse:this.noop, -fn:this.program(9,function(){return","},d),data:d}))||0===a)c+=a;return c});m.no_threads=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f;c=e.helperMissing;a=this.escapeExpression;d={hash:{},data:d};return b=''+(a((f=e.L10n||b.L10n,f?f.call(b,"clients.no_clients",d):c.call(b,"L10n","clients.no_clients",d)))+"")});m.no_visitors=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d|| -{};var f;c=e.helperMissing;a=this.escapeExpression;d={hash:{},data:d};return b=''+(a((f=e.L10n||b.L10n,f?f.call(b,"visitors.no_visitors",d):c.call(b,"L10n","visitors.no_visitors",d)))+"")});m.queued_thread=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f=e.helperMissing,h=this.escapeExpression;c='\n \n ";if((a=e["if"].call(b,b.firstMessage,{hash:{},inverse:this.noop,fn:this.program(7,function(a,b){var c,g;c='"},d),data:d}))||0===a)c+=a;c+='\n\n\n
\n ';if((a=e["if"].call(b,b.canOpen,{hash:{},inverse:this.noop,fn:this.program(9,function(a,c){var b,g;b={hash:{},data:c};return b='\n
\n ')},d),data:d}))||0===a)c+=a;c+="\n ";if((a=e["if"].call(b,b.canView,{hash:{},inverse:this.noop,fn:this.program(11,function(a,b){var c,g;c={hash:{},data:b};return c='\n
\n ')},d),data:d}))||0=== -a)c+=a;c+="\n ";if((a=e["if"].call(b,b.tracked,{hash:{},inverse:this.noop,fn:this.program(13,function(a,c){var b,g;b={hash:{},data:c};return b='\n
\n ')},d),data:d}))||0===a)c+=a;c+="\n ";if((a=e["if"].call(b,b.canBan,{hash:{},inverse:this.noop,fn:this.program(15,function(a,b){var c,g;c={hash:{},data:b}; -return c='\n
\n ')},d),data:d}))||0===a)c+=a;c+='\n
\n
\n\n';if((a=e["if"].call(b,b.userIp,{hash:{},inverse:this.program(19,function(a,c){var b;(b=e.remote)?b=b.call(a,{hash:{},data:c}):(b=a.remote,b="function"===typeof b?b.apply(a):b);return h(b)}, -d),fn:this.program(17,function(a,b){var c,g;c='';(g=e.remote)?g=g.call(a,{hash:{},data:b}):(g=a.remote,g="function"===typeof g?g.apply(a):g);return c+=h(g)+""},d),data:d}))||0===a)c+=a;c+='\n';(a=e.stateDesc)?a=a.call(b,{hash:{},data:d}):(a=b.stateDesc,a="function"===typeof a?a.apply(b):a);c+=h(a)+'\n';(a=e.agentName)?a=a.call(b,{hash:{},data:d}):(a=b.agentName,a="function"===typeof a? -a.apply(b):a);c+=h(a)+'\n\n';if((a=e.unless.call(b,b.chatting,{hash:{},inverse:this.program(23,function(){return"-"},d),fn:this.program(21,function(a,b){var c,g;c=''},d),data:d}))||0===a)c+=a;c+='\n';if((a=e["if"].call(b,b.ban,{hash:{},inverse:this.program(27,function(a,b){var c;(c=e.userAgent)?c=c.call(a,{hash:{},data:b}):(c=a.userAgent,c="function"===typeof c?c.apply(a):c);return h(c)},d),fn:this.program(25,function(a){var c;return h((c=(c=a.ban,null==c||!1===c?c:c.reason),"function"===typeof c?c.apply(a):c))},d),data:d}))||0===a)c+=a;return c+""});m.status_panel=l(function(c,b,e,a,d){this.compilerInfo= -[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f,h=e.helperMissing,j=this.escapeExpression;c='
';(a=e.message)?a=a.call(b,{hash:{},data:d}):(a=b.message,a="function"===typeof a?a.apply(b):a);c+=j(a);if((f=e["if"].call(b,(a=b.agent,null==a||!1===a?a:a.away),{hash:{},inverse:this.program(3,function(a,c){var b,d;d={hash:{},data:c};return j((b=e.L10n||a.L10n,b?b.call(a,"pending.status.online",d):h.call(a,"L10n","pending.status.online",d)))},d),fn:this.program(1,function(a,c){var b, -d;d={hash:{},data:c};return j((b=e.L10n||a.L10n,b?b.call(a,"pending.status.away",d):h.call(a,"L10n","pending.status.away",d)))},d),data:d}))||0===f)c+=f;c+='
"});m.threads_collection=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f,h=e.helperMissing,j=this.escapeExpression;a={hash:{},data:d};c='\n\n\n \n \n \n \n \n \n \n \n\n\n\n\n\n
'+(j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.name", -a):h.call(b,"L10n","pending.table.head.name",a)))+"");a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.actions",a):h.call(b,"L10n","pending.table.head.actions",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.contactid",a):h.call(b,"L10n","pending.table.head.contactid",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.state",a):h.call(b,"L10n","pending.table.head.state", -a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.operator",a):h.call(b,"L10n","pending.table.head.operator",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.total",a):h.call(b,"L10n","pending.table.head.total",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.waittime",a):h.call(b,"L10n","pending.table.head.waittime",a)))+"";a={hash:{},data:d}; -return c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.etc",a):h.call(b,"L10n","pending.table.head.etc",a)))+'
'});m.visitor=l(function(c,b,e,a,d){function f(){return"-"}this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var h,j=e.helperMissing,k=this.escapeExpression;c='\n ';if((a=e.unless.call(b,b.invitationInfo,{hash:{},inverse:this.program(3,function(a,c){var b;(b=e.userName)? -b=b.call(a,{hash:{},data:c}):(b=a.userName,b="function"===typeof b?b.apply(a):b);return k(b)},d),fn:this.program(1,function(a,b){var c,d;c={hash:{},data:b};c='');(d=e.userName)?d=d.call(a,{hash:{},data:b}):(d=a.userName,d="function"===typeof d?d.apply(a):d);return c+=k(d)+""},d),data:d}))||0===a)c+=a;h={hash:{},data:d};c=c+'\n\n\n
\n
\n
\n
\n\n');if((a=e["if"].call(b,b.userIp,{hash:{},inverse:this.program(7,function(a,c){var b;(b=e.remote)?b=b.call(a,{hash:{},data:c}):(b=a.remote,b="function"===typeof b?b.apply(a):b);return k(b)},d),fn:this.program(5,function(a,b){var c,d;c=''; -(d=e.remote)?d=d.call(a,{hash:{},data:b}):(d=a.remote,d="function"===typeof d?d.apply(a):d);return c+=k(d)+""},d),data:d}))||0===a)c+=a;c+='\n\n\n';if((a=e["if"].call(b,b.invitationInfo,{hash:{},inverse:this.program(11,f,d),fn:this.program(9,function(a){var b;return k((b=(b=a.invitationInfo,null==b||!1===b?b:b.agentName),"function"===typeof b?b.apply(a):b))},d),data:d}))||0===a)c+=a;c+='\n';if((a=e["if"].call(b,b.invitationInfo,{hash:{},inverse:this.program(11,f,d),fn:this.program(13,function(a){var b;return a=""+('')},d),data:d}))||0===a)c+=a;c+='\n';(a=e.invitations)?a=a.call(b,{hash:{},data:d}):(a=b.invitations,a="function"===typeof a?a.apply(b):a);c+=k(a)+" / ";(a=e.chats)?a=a.call(b,{hash:{},data:d}):(a=b.chats,a="function"===typeof a?a.apply(b):a);c+=k(a)+'\n';(a=e.userAgent)?a=a.call(b,{hash:{},data:d}):(a=b.userAgent,a="function"===typeof a?a.apply(b):a);return c+=k(a)+""}); -m.visitors_collection=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f,h=e.helperMissing,j=this.escapeExpression;a={hash:{},data:d};c='\n\n\n \n \n \n \n \n \n \n \n \n\n\n\n\n
'+(j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.name",a):h.call(b,"L10n","visitors.table.head.name",a)))+"");a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.actions",a):h.call(b,"L10n", -"visitors.table.head.actions",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.contactid",a):h.call(b,"L10n","visitors.table.head.contactid",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.firsttimeonsite",a):h.call(b,"L10n","visitors.table.head.firsttimeonsite",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.lasttimeonsite",a):h.call(b,"L10n","visitors.table.head.lasttimeonsite", -a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.invited.by",a):h.call(b,"L10n","visitors.table.head.invited.by",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.invitationtime",a):h.call(b,"L10n","visitors.table.head.invitationtime",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.invitations",a):h.call(b,"L10n","visitors.table.head.invitations",a)))+""; -a={hash:{},data:d};return c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.etc",a):h.call(b,"L10n","visitors.table.head.etc",a)))+'
'})})(); /* Copyright 2005-2013 the original author or authors. Licensed under the Apache License, Version 2.0 (the "License"). diff --git a/src/mibew/js/templates/compiled/users_app.tpl.js b/src/mibew/js/templates/compiled/users_app.tpl.js deleted file mode 100644 index 8b6ca101..00000000 --- a/src/mibew/js/templates/compiled/users_app.tpl.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright 2005-2013 the original author or authors. - Licensed under the Apache License, Version 2.0 (the "License"). - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -*/ -(function(){var l=Handlebars.template,m=Handlebars.templates=Handlebars.templates||{};m.agent=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f=e.helperMissing,h=this.escapeExpression;c='';(a=e.name)?a=a.call(b,{hash:{},data:d}):(a=b.name,a="function"===typeof a?a.apply(b):a);c+=h(a);if((a=e.unless.call(b,b.isLast,{hash:{},inverse:this.noop, -fn:this.program(9,function(){return","},d),data:d}))||0===a)c+=a;return c});m.no_threads=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f;c=e.helperMissing;a=this.escapeExpression;d={hash:{},data:d};return b=''+(a((f=e.L10n||b.L10n,f?f.call(b,"clients.no_clients",d):c.call(b,"L10n","clients.no_clients",d)))+"")});m.no_visitors=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d|| -{};var f;c=e.helperMissing;a=this.escapeExpression;d={hash:{},data:d};return b=''+(a((f=e.L10n||b.L10n,f?f.call(b,"visitors.no_visitors",d):c.call(b,"L10n","visitors.no_visitors",d)))+"")});m.queued_thread=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f=e.helperMissing,h=this.escapeExpression;c='\n \n ";if((a=e["if"].call(b,b.firstMessage,{hash:{},inverse:this.noop,fn:this.program(7,function(a,b){var c,g;c='"},d),data:d}))||0===a)c+=a;c+='\n\n\n
\n ';if((a=e["if"].call(b,b.canOpen,{hash:{},inverse:this.noop,fn:this.program(9,function(a,c){var b,g;b={hash:{},data:c};return b='\n
\n ')},d),data:d}))||0===a)c+=a;c+="\n ";if((a=e["if"].call(b,b.canView,{hash:{},inverse:this.noop,fn:this.program(11,function(a,b){var c,g;c={hash:{},data:b};return c='\n
\n ')},d),data:d}))||0=== -a)c+=a;c+="\n ";if((a=e["if"].call(b,b.tracked,{hash:{},inverse:this.noop,fn:this.program(13,function(a,c){var b,g;b={hash:{},data:c};return b='\n
\n ')},d),data:d}))||0===a)c+=a;c+="\n ";if((a=e["if"].call(b,b.canBan,{hash:{},inverse:this.noop,fn:this.program(15,function(a,b){var c,g;c={hash:{},data:b}; -return c='\n
\n ')},d),data:d}))||0===a)c+=a;c+='\n
\n
\n\n';if((a=e["if"].call(b,b.userIp,{hash:{},inverse:this.program(19,function(a,c){var b;(b=e.remote)?b=b.call(a,{hash:{},data:c}):(b=a.remote,b="function"===typeof b?b.apply(a):b);return h(b)}, -d),fn:this.program(17,function(a,b){var c,g;c='';(g=e.remote)?g=g.call(a,{hash:{},data:b}):(g=a.remote,g="function"===typeof g?g.apply(a):g);return c+=h(g)+""},d),data:d}))||0===a)c+=a;c+='\n';(a=e.stateDesc)?a=a.call(b,{hash:{},data:d}):(a=b.stateDesc,a="function"===typeof a?a.apply(b):a);c+=h(a)+'\n';(a=e.agentName)?a=a.call(b,{hash:{},data:d}):(a=b.agentName,a="function"===typeof a? -a.apply(b):a);c+=h(a)+'\n\n';if((a=e.unless.call(b,b.chatting,{hash:{},inverse:this.program(23,function(){return"-"},d),fn:this.program(21,function(a,b){var c,g;c=''},d),data:d}))||0===a)c+=a;c+='\n';if((a=e["if"].call(b,b.ban,{hash:{},inverse:this.program(27,function(a,b){var c;(c=e.userAgent)?c=c.call(a,{hash:{},data:b}):(c=a.userAgent,c="function"===typeof c?c.apply(a):c);return h(c)},d),fn:this.program(25,function(a){var c;return h((c=(c=a.ban,null==c||!1===c?c:c.reason),"function"===typeof c?c.apply(a):c))},d),data:d}))||0===a)c+=a;return c+""});m.status_panel=l(function(c,b,e,a,d){this.compilerInfo= -[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f,h=e.helperMissing,j=this.escapeExpression;c='
';(a=e.message)?a=a.call(b,{hash:{},data:d}):(a=b.message,a="function"===typeof a?a.apply(b):a);c+=j(a);if((f=e["if"].call(b,(a=b.agent,null==a||!1===a?a:a.away),{hash:{},inverse:this.program(3,function(a,c){var b,d;d={hash:{},data:c};return j((b=e.L10n||a.L10n,b?b.call(a,"pending.status.online",d):h.call(a,"L10n","pending.status.online",d)))},d),fn:this.program(1,function(a,c){var b, -d;d={hash:{},data:c};return j((b=e.L10n||a.L10n,b?b.call(a,"pending.status.away",d):h.call(a,"L10n","pending.status.away",d)))},d),data:d}))||0===f)c+=f;c+='
"});m.threads_collection=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f,h=e.helperMissing,j=this.escapeExpression;a={hash:{},data:d};c='\n\n\n \n \n \n \n \n \n \n \n\n\n\n\n\n
'+(j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.name", -a):h.call(b,"L10n","pending.table.head.name",a)))+"");a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.actions",a):h.call(b,"L10n","pending.table.head.actions",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.contactid",a):h.call(b,"L10n","pending.table.head.contactid",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.state",a):h.call(b,"L10n","pending.table.head.state", -a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.operator",a):h.call(b,"L10n","pending.table.head.operator",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.total",a):h.call(b,"L10n","pending.table.head.total",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.waittime",a):h.call(b,"L10n","pending.table.head.waittime",a)))+"";a={hash:{},data:d}; -return c+=j((f=e.L10n||b.L10n,f?f.call(b,"pending.table.head.etc",a):h.call(b,"L10n","pending.table.head.etc",a)))+'
'});m.visitor=l(function(c,b,e,a,d){function f(){return"-"}this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var h,j=e.helperMissing,k=this.escapeExpression;c='\n ';if((a=e.unless.call(b,b.invitationInfo,{hash:{},inverse:this.program(3,function(a,c){var b;(b=e.userName)? -b=b.call(a,{hash:{},data:c}):(b=a.userName,b="function"===typeof b?b.apply(a):b);return k(b)},d),fn:this.program(1,function(a,b){var c,d;c={hash:{},data:b};c='');(d=e.userName)?d=d.call(a,{hash:{},data:b}):(d=a.userName,d="function"===typeof d?d.apply(a):d);return c+=k(d)+""},d),data:d}))||0===a)c+=a;h={hash:{},data:d};c=c+'\n\n\n
\n
\n
\n
\n\n');if((a=e["if"].call(b,b.userIp,{hash:{},inverse:this.program(7,function(a,c){var b;(b=e.remote)?b=b.call(a,{hash:{},data:c}):(b=a.remote,b="function"===typeof b?b.apply(a):b);return k(b)},d),fn:this.program(5,function(a,b){var c,d;c=''; -(d=e.remote)?d=d.call(a,{hash:{},data:b}):(d=a.remote,d="function"===typeof d?d.apply(a):d);return c+=k(d)+""},d),data:d}))||0===a)c+=a;c+='\n\n\n';if((a=e["if"].call(b,b.invitationInfo,{hash:{},inverse:this.program(11,f,d),fn:this.program(9,function(a){var b;return k((b=(b=a.invitationInfo,null==b||!1===b?b:b.agentName),"function"===typeof b?b.apply(a):b))},d),data:d}))||0===a)c+=a;c+='\n';if((a=e["if"].call(b,b.invitationInfo,{hash:{},inverse:this.program(11,f,d),fn:this.program(13,function(a){var b;return a=""+('')},d),data:d}))||0===a)c+=a;c+='\n';(a=e.invitations)?a=a.call(b,{hash:{},data:d}):(a=b.invitations,a="function"===typeof a?a.apply(b):a);c+=k(a)+" / ";(a=e.chats)?a=a.call(b,{hash:{},data:d}):(a=b.chats,a="function"===typeof a?a.apply(b):a);c+=k(a)+'\n';(a=e.userAgent)?a=a.call(b,{hash:{},data:d}):(a=b.userAgent,a="function"===typeof a?a.apply(b):a);return c+=k(a)+""}); -m.visitors_collection=l(function(c,b,e,a,d){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,c.helpers);d=d||{};var f,h=e.helperMissing,j=this.escapeExpression;a={hash:{},data:d};c='\n\n\n \n \n \n \n \n \n \n \n \n\n\n\n\n
'+(j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.name",a):h.call(b,"L10n","visitors.table.head.name",a)))+"");a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.actions",a):h.call(b,"L10n", -"visitors.table.head.actions",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.contactid",a):h.call(b,"L10n","visitors.table.head.contactid",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.firsttimeonsite",a):h.call(b,"L10n","visitors.table.head.firsttimeonsite",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.lasttimeonsite",a):h.call(b,"L10n","visitors.table.head.lasttimeonsite", -a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.invited.by",a):h.call(b,"L10n","visitors.table.head.invited.by",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.invitationtime",a):h.call(b,"L10n","visitors.table.head.invitationtime",a)))+"";a={hash:{},data:d};c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.invitations",a):h.call(b,"L10n","visitors.table.head.invitations",a)))+""; -a={hash:{},data:d};return c+=j((f=e.L10n||b.L10n,f?f.call(b,"visitors.table.head.etc",a):h.call(b,"L10n","visitors.table.head.etc",a)))+'
'})})(); diff --git a/src/mibew/libs/chat.php b/src/mibew/libs/chat.php index a5a6457a..47d73e69 100644 --- a/src/mibew/libs/chat.php +++ b/src/mibew/libs/chat.php @@ -723,14 +723,15 @@ function chat_start_for_user( Thread::KIND_FOR_AGENT, getstring2( 'chat.visitor.invitation.accepted', - array($operator_name) + array($operator_name), + true ) ); } else { if ($referrer) { $thread->postMessage( Thread::KIND_FOR_AGENT, - getstring2('chat.came.from', array($referrer)) + getstring2('chat.came.from', array($referrer), true) ); } if ($requested_operator && !$requested_operator_online) { @@ -738,11 +739,12 @@ function chat_start_for_user( Thread::KIND_INFO, getstring2( 'chat.requested_operator.offline', - array(get_operator_name($requested_operator)) + array(get_operator_name($requested_operator)), + true ) ); } else { - $thread->postMessage(Thread::KIND_INFO, getstring('chat.wait')); + $thread->postMessage(Thread::KIND_INFO, getstring('chat.wait', true)); } } @@ -750,7 +752,7 @@ function chat_start_for_user( if ($info) { $thread->postMessage( Thread::KIND_FOR_AGENT, - getstring2('chat.visitor.info', array($info)) + getstring2('chat.visitor.info', array($info), true) ); } diff --git a/src/mibew/libs/classes/Mibew/Handlebars/HelpersSet.php b/src/mibew/libs/classes/Mibew/Handlebars/HelpersSet.php new file mode 100644 index 00000000..5f4df721 --- /dev/null +++ b/src/mibew/libs/classes/Mibew/Handlebars/HelpersSet.php @@ -0,0 +1,573 @@ +helpersList(); + } + + /** + * A helper for string localization. + * + * Example of usage: + * + * {{l10n "localization.string" arg1 arg2 arg3}} + * + * where: + * - "localization.string" is localization constant. + * - arg* are arguments that will be passed to getlocal2 function. There + * can be arbitrary number of such arguments. + */ + public function localizationHelper($template, $context, $args, $source) + { + // Check if there is at least one argument + $parsed_arguments = $template->parseArguments($args); + if (empty($parsed_arguments)) { + return ''; + } + + $text = $context->get(array_shift($parsed_arguments)); + + // We need to escape extra arguments passed to the helper. Thus we need + // to get escape function and its arguments from the template engine. + $escape_func = $template->getEngine()->getEscape(); + $escape_args = $template->getEngine()->getEscapeArgs(); + + // Check if there are any other arguments passed into helper and escape + // them. + $local_args = array(); + foreach ($parsed_arguments as $parsed_argument) { + // Get locale argument string and add it to escape function + // arguments. + array_unshift($escape_args, $context->get($parsed_argument)); + + // Escape locale argument's value + $local_args[] = call_user_func_array( + $escape_func, + array_values($escape_args) + ); + + // Remove locale argument's value from escape function argument + array_shift($escape_args); + } + + if (empty($local_args)) { + $result = getlocal($text); + } else { + $result = getlocal2($text, $local_args); + } + + return new \Handlebars\SafeString($result); + } + + /** + * Conditional helper that checks if two values are equal or not. + * + * Example of usage: + * + * {{#ifEqual first second}} + * The first argument is equal to the second one. + * {{else}} + * The arguments are not equal. + * {{/ifEqual}} + * + */ + public function ifEqualHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args) || count($parsed_args) < 2) { + return ''; + } + + $condition = ($context->get($parsed_args[0]) == $context->get($parsed_args[1])); + + if ($condition) { + $template->setStopToken('else'); + $buffer = $template->render($context); + $template->setStopToken(false); + } else { + $template->setStopToken('else'); + $template->discard(); + $template->setStopToken(false); + $buffer = $template->render($context); + } + + return $buffer; + } + + /** + * Conditional helper that checks if at least one argumet can be treated as + * "true" value. + * + * Example of usage: + * + * {{#ifAny first second third}} + * At least one of argument can be threated as "true". + * {{else}} + * All values are "falsy" + * {{/ifAny}} + * + */ + public function ifAnyHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + + $condition = false; + foreach ($parsed_args as $parsed_arg) { + $value = $context->get($parsed_arg); + + if ($value instanceof \Handlebars\String) { + // We need to get internal string. Casting any object of + // \Handlebars\String will have positive result even for those + // with empty internal strings. + $value = $value->getString(); + } + + if ($value) { + $condition = true; + break; + } + } + + if ($condition) { + $template->setStopToken('else'); + $buffer = $template->render($context); + $template->setStopToken(false); + } else { + $template->setStopToken('else'); + $template->discard(); + $template->setStopToken(false); + $buffer = $template->render($context); + } + + return $buffer; + } + + /** + * A helper for templates inheritance. + * + * Example of usage: + * + * {{#extends "parentTemplateName"}} + * {{#override "blockName"}} + * Overridden first block + * {{/override}} + * + * {{#override "anotherBlockName"}} + * Overridden second block + * {{/override}} + * {{/extends}} + * + */ + public function extendsHelper($template, $context, $args, $source) + { + // Get name of the parent template + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + $parent_template = $context->get(array_shift($parsed_args)); + + // Render content inside "extends" block to override blocks + $template->render($context); + + // We need to another instance of \Handlebars\Template to render parent + // template. It can be got from Handlebars engine, so get the latter. + $handlebars = $template->getEngine(); + + // Render the parent template + return $handlebars->render($parent_template, $context); + } + + /** + * A helper for defining default content of a block. + * + * Example of usage: + * + * {{#block "blockName"}} + * Default content for the block + * {{/block}} + * + */ + public function blockHelper($template, $context, $args, $source) + { + // Get block name + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + $block_name = $context->get(array_shift($parsed_args)); + + // If the block is not overridden render and show the default value + if (!isset($this->blocksStorage[$block_name])) { + return $template->render($context); + } + + // Show overridden content + return $this->blocksStorage[$block_name]; + } + + /** + * A helper for overriding content of a block. + * + * Example of usage: + * + * {{#extends "parentTemplateName"}} + * {{#override "blockName"}} + * Overridden first block + * {{/override}} + * + * {{#override "anotherBlockName"}} + * Overridden second block + * {{/override}} + * {{/extends}} + * + */ + public function overrideHelper($template, $context, $args, $source) + { + // Get block name + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + $block_name = $context->get(array_shift($parsed_args)); + + // We need to provide unlimited inheritence level. Rendering is started + // from the deepest level template. If the content is in the block + // storage it is related with the deepest level template. Thus we do not + // need to override it. + if (!isset($this->blocksStorage[$block_name])) { + $this->blocksStorage[$block_name] = $template->render($context); + } + } + + /** + * Conditional helper that checks if block overridden or not. + * + * Example of usage: + * + * {{#ifOverridden "blockName"}} + * The block was overridden + * {{else}} + * The block was not overridden + * {{/ifOverriden}} + * + */ + public function ifOverriddenHelper($template, $context, $args, $source) + { + // Get block name + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + $block_name = $context->get(array_shift($parsed_args)); + + // Check condition and render blocks + if (isset($this->blocksStorage[$block_name])) { + $template->setStopToken('else'); + $buffer = $template->render($context); + $template->setStopToken(false); + } else { + $template->setStopToken('else'); + $template->discard(); + $template->setStopToken(false); + $buffer = $template->render($context); + } + + return $buffer; + } + + /** + * Conditional helper that checks if block overridden or not. + * + * Example of usage: + * + * {{#unlessOverridden "blockName"}} + * The block was not overridden + * {{else}} + * The block was overridden + * {{/unlessOverriden}} + * + */ + public function unlessOverriddenHelper($template, $context, $args, $source) + { + // Get block name + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + $block_name = $context->get(array_shift($parsed_args)); + + // Check condition and render blocks + if (!isset($this->blocksStorage[$block_name])) { + $template->setStopToken('else'); + $buffer = $template->render($context); + $template->setStopToken(false); + } else { + $template->setStopToken('else'); + $template->discard(); + $template->setStopToken(false); + $buffer = $template->render($context); + } + + return $buffer; + } + + /** + * Generates markup with hidden input tag for CSRF token. + * + * Example of usage: + * + * {{csrfTokenInput}} + * + */ + public function csrfTokenInputHelper() + { + return new \Handlebars\SafeString(get_csrf_token_input()); + } + + /** + * Generates CSRF taken formated prepared to insert in URLs. + * + * Example of usage: + * + * {{csrfTokenInUrl}} + * + */ + public function csrfTokenInUrlHelper() + { + return new \Handlebars\SafeString(get_csrf_token_in_url()); + } + + /** + * Generates pagination block. + * + * Example of usage: + * + * {{generatePagination stylePath paginationInfo bottom}} + * + * where: + * - "stylePath" is expression for path to current style. + * - "paginationInfo" is 'info' key from the result of setup_pagination + * function. + * - "bottom": optional argument that indicate if pagination block shoud + * be generated for a page bottom or not. If specified and equal to + * string "false" then boolean false will be passed into + * generate_pagination. In all other cases boolean true will be used. + */ + public function generatePaginationHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args) || count($parsed_args) < 2) { + return ''; + } + + $stylePath = $context->get($parsed_args[0]); + $pagination_info = $context->get($parsed_args[1]); + $bottom = empty($parsed_args[2]) ? true : $context->get($parsed_args[2]); + + $pagination = generate_pagination( + $stylePath, + $pagination_info, + ($bottom === "false") ? false : true + ); + + return new \Handlebars\SafeString($pagination); + } + + /** + * Escapes special characters to use result as a valid JavaScript string + * enclosed with single quotes (') or duouble quotes ("). + * + * Example of usage: + * + * var a = "{{#jsString}}some string to escape{{/jsString}}"; + * + */ + public function jsStringHelper($template, $context, $args, $source) + { + return str_replace("\n", "\\n", addslashes($template->render($context))); + } + + /** + * Helper for repeating content. + * + * Example of usage: + * + * {{#repeat times}}content to repeat{{/repeat}} + * + */ + public function repeatHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + + $times = intval($context->get($parsed_args[0])); + $string = $template->render($context); + + return str_repeat($string, $times); + } + + /** + * Helper for replacing substrings. + * + * Example of usage: + * + * {{#replace search replacement}}target content{{/replace}} + * + */ + public function replaceHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args) || count($parsed_args) < 2) { + return ''; + } + + $search = $context->get($parsed_args[0]); + $replacement = $context->get($parsed_args[1]); + $subject = $template->render($context); + + return str_replace($search, $replacement, $subject); + } + + /** + * Format date using internal format. + * + * Example of usage: + * + * {{formatDate unixTimestamp}} + * + */ + public function formatDateHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + + $timestamp = intval($context->get($parsed_args[0])); + + return date_to_text($timestamp); + } + + /** + * Format date difference using internal format. + * + * Example of usage: + * + * {{formatDateDiff seconds}} + * + */ + public function formatDateDiffHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args)) { + return ''; + } + + $seconds = intval($context->get($parsed_args[0])); + + return date_diff_to_text($seconds); + } + + /** + * Cut string if it exceeds specified length. + * + * Example of usage: + * + * {{cutString string length}} + * + */ + public function cutStringHelper($template, $context, $args, $source) + { + $parsed_args = $template->parseArguments($args); + if (empty($parsed_args) || count($parsed_args) < 2) { + return ''; + } + + $string = $context->get($parsed_args[0]); + $length = intval($context->get($parsed_args[1])); + + return substr($string, 0, $length); + } + + /** + * Actually builds helpers list. + * + * @return array List of helpers + */ + protected function helpersList() + { + return array( + 'l10n' => array($this, 'localizationHelper'), + 'extends' => array($this, 'extendsHelper'), + 'block' => array($this, 'blockHelper'), + 'override' => array($this, 'overrideHelper'), + 'ifOverridden' => array($this, 'ifOverriddenHelper'), + 'unlessOverridden' => array($this, 'unlessOverriddenHelper'), + 'ifEqual' => array($this, 'ifEqualHelper'), + 'ifAny' => array($this, 'ifAnyHelper'), + 'generatePagination' => array($this, 'generatePaginationHelper'), + 'jsString' => array($this, 'jsStringHelper'), + 'repeat' => array($this, 'repeatHelper'), + 'replace' => array($this, 'replaceHelper'), + 'formatDate' => array($this, 'formatDateHelper'), + 'formatDateDiff' => array($this, 'formatDateDiffHelper'), + 'cutString' => array($this, 'cutStringHelper'), + 'csrfTokenInput' => array($this, 'csrfTokenInputHelper'), + 'csrfTokenInUrl' => array($this, 'csrfTokenInUrlHelper'), + ); + } +} diff --git a/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php b/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php index afdd3962..3adeaba7 100644 --- a/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php +++ b/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php @@ -533,7 +533,7 @@ class ThreadProcessor extends ClientSideProcessor if ($email) { $thread->postMessage( Thread::KIND_FOR_AGENT, - getstring2('chat.visitor.email', array($email)) + getstring2('chat.visitor.email', array($email), true) ); } @@ -647,19 +647,19 @@ class ThreadProcessor extends ClientSideProcessor if ($referrer) { $thread->postMessage( Thread::KIND_FOR_AGENT, - getstring2('chat.came.from', array($referrer)) + getstring2('chat.came.from', array($referrer), true) ); } if ($email) { $thread->postMessage( Thread::KIND_FOR_AGENT, - getstring2('chat.visitor.email', array($email)) + getstring2('chat.visitor.email', array($email), true) ); } if ($info) { $thread->postMessage( Thread::KIND_FOR_AGENT, - getstring2('chat.visitor.info', array($info)) + getstring2('chat.visitor.info', array($info), true) ); } $thread->postMessage(Thread::KIND_USER, $message, array('name' => $name)); diff --git a/src/mibew/libs/classes/Mibew/Style/PageStyle.php b/src/mibew/libs/classes/Mibew/Style/PageStyle.php index 32673528..42196964 100644 --- a/src/mibew/libs/classes/Mibew/Style/PageStyle.php +++ b/src/mibew/libs/classes/Mibew/Style/PageStyle.php @@ -19,12 +19,44 @@ namespace Mibew\Style; // Import namespaces and classes of the core use Mibew\Settings; +use Mibew\Handlebars\HelpersSet; /** * Represents a style for operator pages */ class PageStyle extends AbstractStyle implements StyleInterface { + /** + * Template engine for chat templates. + * + * @var \Handlebars\Handlebars + */ + protected $templateEngine; + + /** + * Object constructor + * + * @param string $style_name Name of the style + */ + public function __construct($style_name) + { + parent::__construct($style_name); + + $templates_loader = new \Handlebars\Loader\FilesystemLoader( + MIBEW_FS_ROOT . '/' . $this->filesPath() . '/templates_src/server_side/' + ); + + $this->templateEngine = new \Handlebars\Handlebars(array( + 'loader' => $templates_loader, + 'partials_loader' => $templates_loader, + 'helpers' => new \Handlebars\Helpers(HelpersSet::getHelpers()) + )); + + // Use custom function to escape strings + $this->templateEngine->setEscape('safe_htmlspecialchars'); + $this->templateEngine->setEscapeArgs(array()); + } + /** * Builds base path for style files. This path is relative Mibew root and * does not contain neither leading nor trailing slash. @@ -49,20 +81,18 @@ class PageStyle extends AbstractStyle implements StyleInterface // Prepare to output html start_html_output(); - // Build full view name. Remove '\' and '/' characters form the - // specified view name - $full_view_name = MIBEW_FS_ROOT . '/' . $this->filesPath() . '/views/' - . str_replace("/\\", '', $template_name) . '.php'; - // $page variable is used in included views files, so we need to create // it as an alias of $data argument. $page = $data; - // Add template root value to page variables - $page['stylepath'] = MIBEW_WEB_ROOT . '/' . $this->filesPath(); + // Pass additional variables to template + $page['mibewRoot'] = MIBEW_WEB_ROOT; + $page['mibewVersion'] = MIBEW_VERSION; + $page['currentLocale'] = CURRENT_LOCALE; + $page['rtl'] = (getlocal("localedirection") == 'rtl'); + $page['stylePath'] = MIBEW_WEB_ROOT . '/' . $this->filesPath(); - // Load and execute the view - require($full_view_name); + echo($this->templateEngine->render($template_name, $page)); } /** diff --git a/src/mibew/libs/classes/Mibew/Thread.php b/src/mibew/libs/classes/Mibew/Thread.php index 6ccb5df7..e4057353 100644 --- a/src/mibew/libs/classes/Mibew/Thread.php +++ b/src/mibew/libs/classes/Mibew/Thread.php @@ -364,7 +364,7 @@ class Thread // Send message $thread->postMessage( self::KIND_EVENTS, - getstring_("chat.status.user.reopenedthread", $thread->locale) + getstring_("chat.status.user.reopenedthread", $thread->locale, true) ); return $thread; @@ -602,7 +602,8 @@ class Thread // Send message to user $message_to_post = getstring_( "chat.status.operator.dead", - $this->locale + $this->locale, + true ); $this->postMessage( self::KIND_CONN, @@ -626,7 +627,8 @@ class Thread // And send a message to operator $message_to_post = getstring_( "chat.status.user.dead", - $this->locale + $this->locale, + true ); $this->postMessage( self::KIND_FOR_AGENT, @@ -708,13 +710,15 @@ class Thread $message_to_post = getstring2_( "chat.status.operator.changed", array($operator_name, $this->agentName), - $this->locale + $this->locale, + true ); } else { $message_to_post = getstring2_( "chat.status.operator.returned", array($operator_name), - $this->locale + $this->locale, + true ); } @@ -867,7 +871,8 @@ class Thread getstring2_( "chat.status.user.left", array($this->userName), - $this->locale + $this->locale, + true ) ); } else { @@ -876,7 +881,8 @@ class Thread self::KIND_FOR_AGENT, getstring_( "chat.visitor.invitation.canceled", - $this->locale + $this->locale, + true ) ); } else { @@ -885,7 +891,8 @@ class Thread getstring2_( "chat.status.operator.left", array($this->agentName), - $this->locale + $this->locale, + true ) ); } @@ -942,20 +949,23 @@ class Thread $message = getstring2_( "chat.status.operator.changed", array($operator_name, $this->agentName), - $this->locale + $this->locale, + true ); } else { $message = getstring2_( "chat.status.operator.returned", array($operator_name), - $this->locale + $this->locale, + true ); } } else { $message = getstring2_( "chat.status.operator.joined", array($operator_name), - $this->locale + $this->locale, + true ); } } elseif ($this->state == self::STATE_CHATTING) { @@ -965,7 +975,8 @@ class Thread $message = getstring2_( "chat.status.operator.changed", array($operator_name, $this->agentName), - $this->locale + $this->locale, + true ); } } else { @@ -1015,7 +1026,8 @@ class Thread $message = getstring2_( "chat.status.user.changedname", array($old_name, $new_name), - $this->locale + $this->locale, + true ); $this->postMessage(self::KIND_EVENTS, $message); } diff --git a/src/mibew/libs/common/csrf.php b/src/mibew/libs/common/csrf.php index 50057a03..c51176a1 100644 --- a/src/mibew/libs/common/csrf.php +++ b/src/mibew/libs/common/csrf.php @@ -33,20 +33,18 @@ function csrf_check_token() } } -/* print csrf token as a hidden field */ -function print_csrf_token_input() +function get_csrf_token_input() { set_csrf_token(); - echo ""; + return ''; } -/* print csrf token in url format */ -function print_csrf_token_in_url() +function get_csrf_token_in_url() { set_csrf_token(); - echo "&csrf_token=" . $_SESSION['csrf_token']; + return "&csrf_token=" . $_SESSION['csrf_token']; } /* set csrf token */ diff --git a/src/mibew/libs/common/locale.php b/src/mibew/libs/common/locale.php index ee3689eb..0adf3f4c 100644 --- a/src/mibew/libs/common/locale.php +++ b/src/mibew/libs/common/locale.php @@ -287,7 +287,7 @@ function getoutputenc() : MIBEW_ENCODING; } -function getstring_($text, $locale) +function getstring_($text, $locale, $raw = false) { global $messages; if (!isset($messages[$locale])) { @@ -296,53 +296,66 @@ function getstring_($text, $locale) $localized = $messages[$locale]; if (isset($localized[$text])) { - return $localized[$text]; + return $raw + ? $localized[$text] + : sanitize_string($localized[$text], 'low', 'moderate'); } if ($locale != 'en') { - return getstring_($text, 'en'); + return getstring_($text, 'en', $raw); } - return "!" . $text; + return "!" . ($raw ? $text : sanitize_string($text, 'low', 'moderate')); } -function getstring($text) +function getstring($text, $raw = false) { - return getstring_($text, CURRENT_LOCALE); + return getstring_($text, CURRENT_LOCALE, $raw); } -function getlocal($text) +function getlocal($text, $raw = false) { - return myiconv(MIBEW_ENCODING, getoutputenc(), getstring_($text, CURRENT_LOCALE)); + return getlocal_($text, CURRENT_LOCALE, $raw); } -function getlocal_($text, $locale) +function getlocal_($text, $locale, $raw = false) { - return myiconv(MIBEW_ENCODING, getoutputenc(), getstring_($text, $locale)); + $string = myiconv( + MIBEW_ENCODING, + getoutputenc(), + getstring_($text, $locale, true) + ); + + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } -function getstring2_($text, $params, $locale) +function getstring2_($text, $params, $locale, $raw = false) { - $string = getstring_($text, $locale); + $string = getstring_($text, $locale, true); for ($i = 0; $i < count($params); $i++) { $string = str_replace("{" . $i . "}", $params[$i], $string); } - return $string; + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } -function getstring2($text, $params) +function getstring2($text, $params, $raw = false) { - return getstring2_($text, $params, CURRENT_LOCALE); + return getstring2_($text, $params, CURRENT_LOCALE, $raw); } -function getlocal2($text, $params) +function getlocal2($text, $params, $raw = false) { - $string = myiconv(MIBEW_ENCODING, getoutputenc(), getstring_($text, CURRENT_LOCALE)); + $string = myiconv( + MIBEW_ENCODING, + getoutputenc(), + getstring_($text, CURRENT_LOCALE, true) + ); + for ($i = 0; $i < count($params); $i++) { $string = str_replace("{" . $i . "}", $params[$i], $string); } - return $string; + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } /* prepares for Javascript string */ @@ -354,7 +367,7 @@ function get_local_for_js($text, $params) $string = str_replace("{" . $i . "}", $params[$i], $string); } - return $string; + return sanitize_string($string, 'low', 'moderate'); } function locale_load_id_list($name) diff --git a/src/mibew/libs/common/string.php b/src/mibew/libs/common/string.php index db3feeab..490bd78d 100644 --- a/src/mibew/libs/common/string.php +++ b/src/mibew/libs/common/string.php @@ -54,3 +54,116 @@ function escape_with_cdata($text) { return "", "]]>]]>"; } + +/** + * Simple HTML sanitation. + * + * Includes some code from the PHP StripAttributes Class For XML and HTML. + * + * @param string $string Target string + * @param string $tags_level Sanitation level for tags. Available values are + * "high", "moderate" and "low". + * @param string $attr_level Sanitation level for attributes. Available values + * are "high", "moderate" and "low". + * @return string Sanitized string with stripped dangerous tags and attributes. + * + * @author David (semlabs.co.uk) + * @copyright (c) 2009, David (semlabs.co.uk) + * @license MIT + * @link http://semlabs.co.uk/journal/php-strip-attributes-class-for-xml-and-html + */ +function sanitize_string($string, $tags_level = 'high', $attr_level = 'high') +{ + $sanitize_tags = array( + 'high' => '', + 'moderate' => '
', + 'low' => '