Compare commits

..

806 Commits

Author SHA1 Message Date
320d814df4 Bump version 2023-05-30 21:51:49 +03:00
8953017b9d Update copyright notice 2023-05-30 21:49:59 +03:00
874e896178 Fix post-installation sound check for a case with disabled mod_rewrite 2023-05-24 17:37:34 +03:00
973632b4ae Switch to a newer version of some Symfony components 2023-05-24 16:47:30 +03:00
5fa9663d99 Add check for null values for incoming params 2023-05-24 16:46:14 +03:00
1ed31ad638 Bump version 2022-10-22 01:06:02 +03:00
da94f781b3 Improve outlook for chat history items related to leaved messages 2022-10-21 01:43:23 +03:00
d4640219a6 Fix bug with invalid groups list setup for chat dialogs 2022-10-21 01:02:16 +03:00
1fc048fec9 Save correct number of a visitor's messages for threads related to offline messages 2022-10-15 01:26:11 +03:00
d6d5477022 Bump version 2022-06-28 18:56:47 +03:00
691bcfa061 Add button to show tracked path of a visitor into operator's chat window 2022-06-28 02:58:00 +03:00
3148db54b5 Fix typo in the comment 2022-06-28 02:56:45 +03:00
Fedor A. Fetisov
58ee240c80 Fix warning in login controller when checking non-existent login 2022-06-24 01:43:22 +03:00
ca090638da Fix PHP 8.1 compatibility issue with the inherited static variable 2022-06-17 01:59:30 +03:00
4f05231b04 Bump version 2022-05-06 23:55:36 +03:00
730577b4a4 Update copyright notices
Actualize the years
2022-05-06 23:54:45 +03:00
51f2c41b31
Merge pull request #264 from BFallert/temp_viewport_mobile
add viewport meta tag to control layout on mobile browsers
2022-01-25 17:01:20 +03:00
BFallert
2de3ac9044 viewport meta tag for mobile view for backend added 2022-01-17 12:07:50 +01:00
BFallert
09f632cc6d add viewport meta tag to control layout on mobile browsers 2022-01-17 10:53:36 +01:00
339da62a23 Bump version 2021-12-14 13:54:38 +03:00
5a4d3d420f Fix potential problem with some absent HTTP request headers 2021-12-03 20:25:25 +03:00
cd1e8adce3
Merge pull request #263 from jmechnich/check-user-agent
Check if HTTP_USER_AGENT is set, use empty string otherwise
2021-12-03 19:32:56 +03:00
jmechnich
e676ca47dc Check if HTTP_USER_AGENT is set, use empty string otherwise 2021-12-01 20:39:20 +01:00
637758c13e Bump version 2021-12-01 16:43:58 +03:00
6a0c067cef Fix issue with client-side detection of valid cookie domain
See https://mibew.org/forums/index.php/topic,192324.msg200169.html
2021-12-01 16:41:38 +03:00
a956f85fc7 Bump version 2021-11-04 17:11:32 +03:00
1a137bb683 Fix calculation of visitor's messages for old threads 2021-11-02 18:33:23 +03:00
57eacfb953 Remove redundant blank lines 2021-11-01 21:14:07 +03:00
88247f0de3 Switch to a new version of PHP_CodeSniffer 2021-11-01 21:13:52 +03:00
eb0bc9ae5c Bump version 2021-09-03 16:31:58 +03:00
7f133f17f7 Fix bug with tracking new visitors 2021-09-03 16:31:15 +03:00
944b0fe6c5 Bump version 2021-09-01 01:31:33 +03:00
eae2b3df81 Update i18n submodule 2021-09-01 01:28:19 +03:00
3b3abe615d Fix default value for samesite cookies property 2021-08-30 19:06:57 +03:00
756014d568 Add invitation sound check into the installation process 2021-08-29 23:36:35 +03:00
6d4c438d62 Add unique sound for invitations 2021-08-29 23:34:21 +03:00
5c2743c01a Add ogg/vorbis option for audio files 2021-08-29 23:02:41 +03:00
eeb660293c Style copy code button 2021-08-28 03:46:11 +03:00
01261f8c92 Implement simple button code copying 2021-08-28 03:40:34 +03:00
06078cc8e7 Implement sound notification on invitation to chat 2021-08-28 03:09:23 +03:00
a37ea34670 Merge branch 'cookies' into test 2021-08-28 01:13:07 +03:00
56418b1551 Mark all necessary cookies as SameSite=None if possible 2021-08-28 01:12:40 +03:00
dc9f128b79 Fix code style 2021-08-28 00:40:29 +03:00
2533b362ab Fallback to window-based chat in case of blocked third parties cookies
Also affects #261.
2021-08-27 23:10:41 +03:00
0c416c7d7c Add handler for exceptions on thread update related to cookies block (see also #258) 2021-08-27 15:00:22 +03:00
fd94b0108c Remove redundant legacy code 2021-08-27 13:04:57 +03:00
99fb30b0ec Remove redundant legacy code 2021-08-27 13:04:34 +03:00
81e2e345a7 Fix invalid behavior of invitations in case of blocked cookies 2021-08-27 03:24:06 +03:00
ce5071c3e3 Fix typo 2021-08-27 03:00:13 +03:00
1210561448 Implement prototype for invitation sound playback 2021-08-27 02:29:37 +03:00
9294697d58 Fix type 2021-08-27 02:21:58 +03:00
3a92a54cd5 Fix some real-world issues with invitation styles 2021-08-26 00:15:28 +03:00
b6a70659b1 Fix issue with invalid management of session cookies in some browsers leading to "attack of clones" 2021-08-24 22:41:20 +03:00
cd22f3e9d8 Fix damned cookies behaviour in modern chrome 2021-08-24 22:39:35 +03:00
8aba48a1d2 Remove obsolete code from init 2021-08-24 19:09:22 +03:00
Fedor A. Fetisov
423ef8d36f Set cookies on the client side as secure and safe to set as third party if possible 2021-08-24 17:26:28 +03:00
098abccde7 Fix code style 2021-08-24 17:21:09 +03:00
Fedor A. Fetisov
75aaaf21b7 Bump version 2021-07-13 14:07:10 +03:00
622027302f Switch to own PHP8 compatible fork of CanteenHTML5 2021-07-09 23:38:03 +03:00
5b999eff2d Fix warning in PHP 8.0 2021-07-09 01:39:50 +03:00
562eeceac2 Bump version 2021-07-08 23:52:07 +03:00
f9e0755b23 Fix typo in chat user model property 2021-06-15 01:09:18 +03:00
74b9faf7af
Merge pull request #259 from jmechnich/fix-ssl-icon-link
fix SSL lock icon link in chat
2021-06-15 01:07:04 +03:00
jmechnich
9978074fbc fix SSL lock icon link in chat 2021-06-11 21:42:17 +02:00
2df50d9096 Bump version 2021-05-18 18:00:17 +03:00
14aba49194 Update i18n submodule 2021-05-18 18:00:05 +03:00
17df9c8dbc Implement CAPTCHA for the form to send chat to email (fixes #255) 2021-05-18 15:28:44 +03:00
6dae66540d Make possible to disable sending a chat to email 2021-05-16 02:40:51 +03:00
0317979c92 Update i18n submodule 2021-04-23 13:49:22 +03:00
a4b3824a42 Fix typo in standard mail template 2021-04-15 22:01:23 +03:00
f1200c4999 Fix installer crash in absence of PDO and/or pdo_mysql extensions 2021-04-14 13:40:50 +03:00
d7365d719f Update i18n submodule 2021-04-14 12:32:43 +03:00
42f5c1a20a Fix issue with invitation to chat from inaccessible operator 2021-04-13 19:11:03 +03:00
74e69aa520 Fix issue with notices about non well formed numeric values 2021-04-09 16:45:46 +03:00
20da5d2f36 Fix possible type mismatch in track_visit_page func 2021-04-09 16:34:29 +03:00
fe951ad050 Update system requirements 2021-04-09 15:48:19 +03:00
Tsvetan Koshutanski
8edcc7e57f Update dependencies and routing.yml for PHP 7.4 2021-04-09 15:47:15 +03:00
Tsvetan Koshutanski
62ad932aa7 Properly check if variable is set before referencing it
For PHP 7.4
2021-04-09 15:24:01 +03:00
33fb35bd34 Fix returning value in get_group_email func 2021-04-09 15:05:16 +03:00
Tsvetan Koshutanski
003f98b18c Check if group is set
The actual value is possible to be null,
thus leading to PHP notice without the check.

For PHP7.4
2021-04-09 15:05:02 +03:00
6e3720f8e4 Bump version 2021-04-02 18:31:03 +03:00
Tsvetan Koshutanski
4f3d0a57f9 Change return type to empty string on bad incoming value 2021-03-29 17:24:50 +03:00
Tsvetan Koshutanski
f28659a025 Check variable is of type array before using it
For PHP 7.4
2021-03-29 17:24:29 +03:00
Tsvetan Koshutanski
026b463fb7 Ignore intellij folder 2021-03-29 17:22:46 +03:00
bfe0065f1c Bump version 2021-03-22 22:41:40 +03:00
91a1b1872c Fix style of generated operator code field 2021-03-22 22:41:35 +03:00
cf67b11295 Fix issue with double widget code in generated button 2021-03-22 22:41:26 +03:00
dd4169f815 Fix check of system requirements 2021-03-22 22:41:12 +03:00
dbe04bb342 Update system requirements 2021-03-18 18:42:33 +03:00
98f2b68560 Bump version 2021-03-18 16:53:01 +03:00
805bb610a5 Improve handle of network connection errors (fix #203) 2021-03-18 15:50:49 +03:00
3148d0eb2a Update i18n submodule 2021-03-18 02:45:19 +03:00
67439317c4 Make possible to switch tracking for each type of button (also, fix #239) 2021-03-18 02:38:19 +03:00
5e90541918 Fix minor style issue with survey button 2021-03-18 01:43:42 +03:00
704862faad Remove redundant required mark for avatar field 2021-03-17 15:50:49 +03:00
c8df65baee Add dark styles 2021-03-17 15:50:15 +03:00
49d86a55be Skip versioning for _all_ styles 2021-03-17 15:00:50 +03:00
de3db5527b Update copyright notices
Actualize the years
2021-01-29 21:39:18 +03:00
d115befab9 Improve cli tool for bulk update of headers 2021-01-29 21:38:39 +03:00
6b20d0c8b6 Upgrade several vulnerable build tools 2021-01-29 21:37:53 +03:00
b296525e39 Disable versioning for package-lock.json 2021-01-29 21:36:51 +03:00
7a16536341 Fix js code style 2021-01-29 19:55:51 +03:00
aa94e21602 Switch to a newer handlebars.js 2021-01-29 19:55:09 +03:00
bb932e5b9c Migrate build system to Gulp 4 2021-01-29 19:54:44 +03:00
a9ca845c80 Bump version 2020-12-25 23:59:54 +03:00
b8bad36510 Fix XSS in error message (thanks to Sharif aka Vincent Pentester) 2020-12-25 23:44:33 +03:00
1c3d9c98b4 Update i18n submodule 2020-10-25 16:01:08 +03:00
dc9577ff6a Bump version 2020-07-09 12:45:27 +03:00
2336e406f4 Fix XSS in vex messages 2020-07-09 12:45:04 +03:00
84f5bca0a9 Fix multiple XSS (thanks to adsec2s) 2020-07-09 11:16:53 +03:00
fb35d4fff9 Fix comment 2020-07-09 11:12:10 +03:00
ace1423a13 Bump version 2020-03-21 17:31:19 +03:00
3b9a8e5456
Merge pull request #247 from Mibew/debian_fix2
Remove possible tilda from a string of installed dependency.
2020-03-21 17:28:13 +03:00
c60b247ef7 Update copyright notices
Actualize the years
2020-03-21 17:01:34 +03:00
89f0f5c688 Remove possible tilda from a string of installed dependency.
Fix #246.
2020-03-19 18:56:12 +03:00
7bdf01d344 Bump version 2019-12-03 19:31:50 +03:00
c0d9a461af Switch to symfony/http-foundation ~2.8.52 (fix CVE-2019-18888) 2019-12-03 19:30:19 +03:00
1844d91893 Fix security issue in the build environment 2019-06-21 01:55:51 +03:00
1a3594311b Bump version 2019-06-02 22:56:17 +03:00
8b6dcf4db0 Fix typo in cookie name for minified popup state
Fixes #245
2019-05-27 18:23:07 +03:00
9d8e057410 Bump version 2019-04-19 13:38:16 +03:00
8a2586d01b Make possible to support PHP 7.3
Due to abandoned state of XaminProject/handlebars.php one had to switched to private repositories for stuff related to PHP implementation of Handlebars template engine
2019-04-17 18:36:50 +03:00
be5d5d182b Bump version 2019-02-19 16:22:34 +03:00
38b653d075 Fix bug with immutable group description in dialog forms
See https://mibew.org/forums/index.php/topic,192246.msg199920.html for details
2019-02-19 02:31:25 +03:00
88a1b978ce
Merge pull request #241 from Mibew/semver_fix
Loose down semantic versioning expressions
2019-01-23 10:34:07 +03:00
a2946bd67d Loose down semantic versioning expressions
See https://github.com/Mibew/geo-ip-plugin/issues/6 for details
2019-01-22 10:52:25 +03:00
410b925b8d Fix potential issue with incoming visitor name 2019-01-13 19:24:26 +03:00
4f9b48135c Update copyright notices
Actualize the years
2019-01-13 19:17:33 +03:00
5bc4698520 Get rid of get_get_param() function 2019-01-13 17:51:30 +03:00
0f64ad3674 Fix security issue in the build environment 2018-11-27 18:19:07 +03:00
93f949d914 Fix typo in comment 2018-11-26 22:00:13 +03:00
b971d2d85c Update i18n submodule 2018-11-19 19:48:41 +03:00
edd279ca8e Restore ability to reopen iframe with a standard style 2018-11-19 19:13:51 +03:00
525b7de7e2 Make possible to reopen iframe with a custom styled chat
Fixes #238
2018-11-19 19:02:48 +03:00
b6bfc39cbf Bump version 2018-11-19 16:46:52 +03:00
3f4420181c
Update list of official stable plugins in README 2018-11-17 00:49:16 +03:00
94eaed0b2c Update lodash dependency 2018-10-30 03:21:01 +03:00
Fedor A. Fetisov
d747568575 Update i18n submodule 2018-10-30 03:13:59 +03:00
2cda0cbb66 Update i18n submodule 2018-10-17 21:44:25 +03:00
d41db57211 Add link to privacy policy into the leaving message form 2018-10-17 21:41:02 +03:00
bc99761b7a Update i18n submodule 2018-10-17 19:46:20 +03:00
fc2c9d791a Add warnings about need for button regeneration 2018-10-17 19:35:51 +03:00
f9b6eeb92c Fix bug with misinterpretation of 0 as an operator code 2018-08-20 23:10:44 +03:00
2d60df2417 Bump version 2018-08-17 23:24:06 +03:00
6dc0bc8d34 Update i18n submodule 2018-08-17 19:27:23 +03:00
110322ab47 Fix invalid comment 2018-08-17 18:56:07 +03:00
e40be770c3
Merge pull request #235 from Mibew/gdpr
Add optional privacy link to pre-chat survey
2018-08-17 18:48:30 +03:00
d32f9c02ce Add optional privacy link to pre-chat survey
Fixes #227
2018-08-16 19:10:57 +03:00
83185a6b32 Fix invalid comment 2018-08-16 16:38:12 +03:00
a9644ddec1 Prepare database update for the next release 2018-08-16 16:37:08 +03:00
e9b29737c9
Merge pull request #234 from Mibew/mysql_fix
Add support for MySQL 8 (fixes #232)
2018-08-16 12:25:39 +03:00
4f03a73f9a Add support for MySQL 8 (fixes #232) 2018-08-09 16:04:31 +03:00
647bd84995 Update i18n submodule 2018-05-28 18:03:21 +03:00
eb60d6b39f Update i18n submodule 2018-05-28 17:54:28 +03:00
4d038b0777 Bump version 2018-05-25 13:19:55 +03:00
67b0a6005e
Add Mibew Open Street Map plugin to the list of official plugins 2018-05-23 18:25:11 +03:00
d605c80332 Update i18n submodule 2018-05-10 03:56:51 +03:00
98954281d5 Promote usage of Mibew:OpenStreetMap plugin instead of Mibew:GoogleMaps 2018-05-10 03:49:27 +03:00
58e0ddc952 Bump version 2018-04-19 22:30:33 +03:00
f1030c0298 Fix bug with the misbehaviour of the chat toggle
After minimizing the chat it was impossible to use it while browsing the site
2018-04-19 22:20:50 +03:00
9cb71e62c1 Bump version 2018-04-10 19:17:01 +03:00
60ff2c853c Update i18n submodule 2018-04-10 19:15:45 +03:00
6c4e883a8a Fix localization constant 2018-04-10 19:13:23 +03:00
25a4a3db40 Fix code style 2018-03-20 02:20:16 +03:00
5f2aab1501 Fix attempt to restore closed chat in popup 2018-03-20 02:17:14 +03:00
8a2fbc6f38 Fix coding style 2018-02-06 02:18:53 +03:00
2b6779af8f Fix handling of information on updates for absent plugins 2018-02-06 02:11:36 +03:00
efa1372cdc Fix handling of obsolete information on updates 2018-02-06 01:28:48 +03:00
Fedor A. Fetisov
64e902c5a1 Fix version number in VERSION.txt 2018-02-05 17:27:12 +03:00
ee97a2f932 Merge branch 'master' of github.com:Mibew/mibew 2018-02-05 16:42:14 +03:00
4960397655 Fix position of widget toggle element 2018-02-05 16:41:43 +03:00
da03edb665 Change all project related URLs to secure ones 2018-02-02 19:45:40 +03:00
712117dfc4 Update i18n submodule 2018-02-02 19:32:43 +03:00
048e2dd3f0 Update copyright notices
Actualize the years
2018-02-02 19:20:04 +03:00
3beed6b2ec
Merge pull request #221 from Mibew/responsive
Implement responsive design for mobile devices
2018-02-02 17:54:22 +03:00
c62a98b22a Make invitations to chat responsive 2018-01-27 00:57:10 +03:00
20d97e5bce Improve media query logic for responsive design
Fix footer width for mobile devices
2018-01-26 13:08:32 +03:00
2581119295 Restrict responsive design by media query 2018-01-24 18:18:57 +03:00
95c55aa931 Implement responsive design
See https://mibew.org/forums/index.php/topic,191515.msg199759.html for details
2018-01-23 17:45:48 +03:00
059bc5ac39 Update i18n submodule 2018-01-16 19:11:20 +03:00
324a85fb7f
Merge pull request #219 from Mibew/new_perms
New permissions
2018-01-16 18:33:46 +03:00
28e968b15f
Merge pull request #220 from Mibew/cluster_fix
Cluster fix
2018-01-16 18:32:56 +03:00
9d2c4404c0 Remove redundant blank line 2018-01-16 18:13:21 +03:00
d61b142e40 Add missed ids for all textareas 2018-01-16 17:26:28 +03:00
d1a1f51bf0 Wrap chat iframe into a div
This could help make the design responsive
2018-01-16 17:11:23 +03:00
0cf963ac5e Add primary key to revision database table
Fixes #218
2018-01-12 01:07:44 +03:00
5921115af0 Bump version 2018-01-12 01:07:03 +03:00
87d7478864 Fix min PHP version in installer 2018-01-12 01:00:09 +03:00
3179d5b669 Disable management of canned messages for all but admins 2018-01-12 00:32:18 +03:00
8ced21fe86 Hide system information from anyone but admins 2018-01-11 23:35:13 +03:00
84e4de1e7a Add new permission to control access to system statistics 2018-01-11 23:26:13 +03:00
39309d1914 Bump version 2017-11-29 16:46:58 +03:00
194b396788 Remove duplicate license headers from compiled js files 2017-11-28 17:14:46 +03:00
7dd32257d1 Add missed localization for installation steps list 2017-11-22 14:30:49 +03:00
6de62a6929 Don't attach translation.js when in the maintenance mode
Also not sure but maybe it has something to do with #207.
2017-11-22 14:28:37 +03:00
1c6433eb73 Switch to actual handlebars.js library 2017-11-22 14:22:06 +03:00
762998cd4b Update i18n submodule 2017-11-14 22:45:51 +03:00
73abafebac Fix typo in the message 2017-11-14 22:39:24 +03:00
81cd6f75fe Update i18n submodule 2017-11-14 22:24:31 +03:00
42f28a72da Update i18n submodule 2017-11-13 00:20:05 +03:00
69916d8f6d Update i18n submodule 2017-11-12 21:18:14 +03:00
ec2e29083b Bump version 2017-11-12 18:38:53 +03:00
98a5570ef6 Notify operator of potentially irreversible permissions change 2017-11-12 18:36:24 +03:00
3ec1610fff Make possible to remove first user (Fixes #210) 2017-11-12 17:59:50 +03:00
bc39c22c29 Disable versioning for CDN files 2017-11-12 04:39:03 +03:00
2e3b718fe2 Merge branch 'master' of github.com:Mibew/mibew 2017-11-12 04:11:07 +03:00
be8182ffcc Improve gulpfile
Add and fix comments, improve organization and code style
2017-11-12 03:59:14 +03:00
dfaaffcff4 Add new gulp tasks
New tasks intends to automate the process of release uploading to CDN
2017-11-12 02:21:02 +03:00
de782c7fea Automate i18n archives creation via gulp 2017-11-11 02:44:40 +03:00
3ea37e0e11 Create release archives with top-level dir 2017-11-10 18:17:12 +03:00
0f1407682e Fix bug in handle of dirs in gulp 2017-11-10 18:15:59 +03:00
e40e821b5f Add i18n repo as a submodule 2017-11-10 17:05:04 +03:00
31ad9138ef Fix typo in the default config 2017-11-06 02:28:52 +03:00
9cd07fe829 Merge branch 'master' of github.com:Mibew/mibew 2017-11-01 04:26:24 +03:00
4dec01bdaa Correct a bunch of incomplete names of Mibew Messenger 2017-11-01 04:26:08 +03:00
e64670e5aa Fix code style 2017-10-28 01:52:16 +03:00
7c07d7f3e2
Merge pull request #214 from Mibew/fs_fix
Make possible to force secure URLs for iframe styles
2017-10-27 23:23:44 +03:00
f9c5d4dbaf
Merge pull request #213 from Mibew/stats
Make statistics compatible with the default MySQL 5.7 settings
2017-10-27 23:23:26 +03:00
52f203b43d Fix typo in comment 2017-10-18 16:17:46 +03:00
35d80bdcee Fix code style 2017-10-13 19:44:23 +03:00
a6b7367002 Make possible to force secure URLs for iframe styles (Fixes #206) 2017-10-13 19:41:00 +03:00
75c04cae38 Fix potential issue with fallback front page 2017-10-11 16:27:16 +03:00
915b6786d9 Fix erroneous confirmation message 2017-10-11 15:26:18 +03:00
b561f7eec8 Make statistics compatible with the default MySQL 5.7 settings
See
https://mibew.org/forums/index.php/topic,192176.msg199690 for details
2017-10-05 11:38:43 +03:00
89556ae68f Create template for PRs 2017-10-03 19:34:22 +03:00
33149aafb9 Create template for issues 2017-10-03 19:28:35 +03:00
edf8850952 Make symbolic link to license relative 2017-10-03 18:47:56 +03:00
393bf21f30 Add license in Github-compatible way 2017-10-03 18:45:20 +03:00
03a2051ad7 Fix bug with disappearing toggle control (Fixes #209) 2017-10-03 01:41:57 +03:00
51ad3e70d3 Fix unhandled error in plugins list discovering 2017-09-22 17:27:34 +03:00
9417960281 Update the server requirements in README 2017-07-17 19:38:45 +03:00
a312bc5e8f Bump version 2017-07-06 16:10:15 +03:00
a617eebeec Prevent unauthorized access to chat history 2017-07-06 16:00:06 +03:00
38e53aaa6a Bump version 2017-06-27 14:50:02 +03:00
8b6d411d58 Merge pull request #204 from Mibew/styles_fix
Styles fix
2017-06-15 19:34:14 +03:00
1b436f9535 Fix setting of the invitation style 2017-06-15 19:28:47 +03:00
64fccc272c Fix typo in comment 2017-06-09 01:01:51 +03:00
ead790853e Fix setting of the chat style 2017-06-05 18:34:13 +03:00
Fedor A. Fetisov
47e7a81f6f Update year in visible copyright notices 2017-05-26 22:23:30 +03:00
Fedor A. Fetisov
73b11b48af Fix code style 2017-05-26 16:07:26 +03:00
Fedor A. Fetisov
5bb282b3bd Bump version 2017-05-26 16:03:08 +03:00
Fedor A. Fetisov
9608c5a83d Update copyright notice 2017-05-26 16:02:42 +03:00
568e539e49 Merge branch 'ipv6' 2017-05-26 15:42:18 +03:00
Fedor A. Fetisov
8c99b13e12 Improve algorithm in setting the value for a visitor's IP 2017-05-25 12:01:11 +03:00
35bbb22c56 Fix a typo 2017-05-24 16:52:30 +03:00
Fedor A. Fetisov
169b8d3b76 Fix clean task of Gulp
Task 'clean' now compatible with multiple styles (Fixes #200)
2017-05-23 17:12:42 +03:00
d8a63bc2cd Fix invalid algorithm in setting the value for a visitor's IP 2017-05-23 16:16:00 +03:00
f105a0b5d2 Fix inline doc for get_remote_host() 2017-05-22 02:03:29 +03:00
843a6e11ae Define correct remote IP for a visitor (with IPv6 support)
See #197
2017-05-22 02:02:31 +03:00
a5320b07d7 Add Mibew Operator Status to the list of official plugins 2017-03-21 15:31:49 +03:00
3eafe870bc Add Mibew Slack to the list of official plugins 2017-03-18 01:00:59 +03:00
82704cfbd6 Improve instruction for update (Fixes #189) 2017-03-18 00:57:05 +03:00
88ba0f148e Merge pull request #199 from Mibew/gulp_promise
Use promises to build all the styles
2017-03-18 00:49:54 +03:00
Dmitriy Simushev
19376e7f6c More promises to gulpfile.js! 2017-03-16 23:46:01 +03:00
Dmitriy Simushev
3ae6e5cdb4 Use promises to build all the styles 2017-03-13 14:29:16 +03:00
29c9d8dc7d Specify minimal version of Node.js in package.json 2017-03-10 18:07:17 +03:00
7c822661e6 Merge pull request #195 from Mibew/styles
Improve gulp file
2017-03-10 01:56:57 +03:00
3a85c9060b Add watch task (see #179) 2017-03-10 01:45:23 +03:00
834e75cdd6 Compile all styles (see #179) 2017-03-10 01:44:53 +03:00
6ea5f5af11 Merge pull request #194 from Mibew/trusted_proxies
Add "trusted_proxy" option
2017-03-10 00:00:18 +03:00
e2099735e1 Make existing configs backwards compatible with the trusted_proxies option 2017-03-09 23:58:13 +03:00
Dmitriy Simushev
8b1e218862 Add "trusted_proxy" option
Fixes #188
2017-03-09 13:34:57 +00:00
e718518698 Fix permissions for release archives 2017-02-08 10:41:35 +03:00
cc55a13151 Make handlebars cache adapter compatible with the new version of handlebars.php 2016-12-29 18:23:41 +03:00
0fc11b3885 Merge pull request #185 from Mibew/x 2016-12-29 17:50:08 +03:00
16b7297d19 Merge pull request #184 from Mibew/fix_143 2016-12-29 17:49:37 +03:00
1683b7c72a Fix invalid comment 2016-12-29 17:42:11 +03:00
f4ad0a2351 Prevent unnecessary increment of thread revision value
Fixes #149
2016-12-29 17:37:40 +03:00
7f6b193656 Clear routes from cache when a plugin becomes initialized or non-initialized for the first time
Fixes #143
2016-12-29 02:56:50 +03:00
15dbe153f5 Implement cache for Plugin Manager 2016-12-28 19:51:11 +03:00
547efb38e4 Load plugins after the cache initialization 2016-12-28 19:31:22 +03:00
f44ccdc4e1 Remove irrelevant comment 2016-12-28 19:19:44 +03:00
1549125665 Fix bug with failed initialization of plugins that does not need config at all 2016-12-28 19:18:46 +03:00
cf76dd744d Store plugin initialization status in the database 2016-12-28 17:30:33 +03:00
57afba72e8 Update database schema
Add into the plugins table a column to store last known initialization status
2016-12-28 03:55:18 +03:00
3f97ad09df Bump version 2016-12-28 03:53:39 +03:00
00213f806c Implement minification of the chat iframe
Fixes #153
2016-12-28 03:30:02 +03:00
d0f1c50f51 Implement toggle method for iframe-based chat popup 2016-12-27 19:39:11 +03:00
bc16b7c25f Update list of repos in README 2016-12-27 17:56:18 +03:00
5424424eaf Remove duplicate init for isOnline 2016-12-26 18:26:22 +03:00
7aed881f08 Fix naming for the new template variable 2016-12-26 18:22:51 +03:00
ca169c5bc7 Make possible to determine whether an operator is online at any page of the administrative interface
Fixes #181
2016-12-24 03:33:49 +03:00
7041adcdfb Remove built-in (and broken) geo location feature from the core
Fixes #173
2016-12-23 17:35:42 +03:00
ffcdb223cc Fix typos in comments 2016-12-23 15:33:49 +03:00
c70bdfcd90 Prevent system from using uninitialized values when configuration doesn't exists 2016-12-23 15:32:14 +03:00
d512573af8 Make sure that configuration file exist
Fixes #105
2016-12-23 15:21:13 +03:00
0527a9def1 Remove double escape of values in the tracked path of a visitor.
Fixes #137
2016-12-23 14:43:19 +03:00
09ef31e750 Update versions requirements for Gulp 2016-12-08 18:10:19 +03:00
9213453bc3 Merge pull request #176 from J-Fricke/php7
Implement PHP7 compatibility
2016-11-18 14:07:35 +03:00
Joshua Fricke
8c3cbf0489 feat: set min version for xamin/handlebars.php to ~0.10.3 2016-11-02 14:55:13 -07:00
Joshua Fricke
45ac4ec1ee feat: update justblackbird/handlebars.php-helpers dependency to v1
* update .../String namespace to .../Text in Handlebars/Helpers.php
2016-09-22 13:42:12 -07:00
e3123d7c45 Update forgotten version number 2016-08-10 18:02:42 +03:00
680059dece Fix code styling in the contributed code 2016-08-09 18:21:25 +03:00
e9526daf1c Bump version 2016-08-09 18:07:11 +03:00
a2774b8fb9 Merge pull request #171 from Mibew/nav666-patch-1
Try to initialize session only once
2016-08-09 18:01:02 +03:00
5618a334d9 Merge pull request #170 from Mibew/Silron88-patch-2
Fix possible duplicate messages on submit
2016-08-09 17:54:17 +03:00
Silron88
8b32bebdc2 fix: if click send and before message is sended click send again then message will be duplicated 2016-08-08 18:51:54 +03:00
788a18f7f1 Merge branch 'patch-1' of https://github.com/nav666/mibew into nav666-patch-1 2016-08-08 18:40:57 +03:00
ad186da482 Update copyright notices 2016-08-08 18:31:45 +03:00
345cb1748a Merge pull request #167 from candido1212/patch-1
Add missing localization constant
2016-08-08 17:25:12 +03:00
e8f07d27ef Merge pull request #168 from nav666/patch-2
Fix issue with invalid default weight for memcached server in config
2016-08-08 17:24:08 +03:00
e64fe1eb17 Bump version 2016-06-28 16:20:12 +03:00
Dmitriy Simushev
e6dfd1dfec Fix unused vars in JS code 2016-06-09 20:55:59 +00:00
Dmitriy Simushev
a56e775ab9 Make ES lint stop nagging about unused argument of catch statement 2016-06-08 18:20:00 +00:00
Dmitriy Simushev
ce3a59b13c Remove unreachable js code 2016-06-04 14:03:37 +00:00
Dmitriy Simushev
85d1acad5e Refer to jQuery as 'jQuery' and not '$' 2016-06-04 14:02:05 +00:00
Dmitriy Simushev
13dd999158 Add all missed semicolons to JS app
Yes, I know about ASI and that the simicolons are not actually
needed in most cases, but I belive the code looks better when
semicolons are in places.
2016-06-03 14:23:17 +00:00
Dmitriy Simushev
cb3bd91b76 Fix indent in JS app 2016-06-03 13:34:55 +00:00
Dmitriy Simushev
d5130ed655 Make sure all for-in loops works as expected 2016-06-02 23:20:24 +00:00
Dmitriy Simushev
199438285c Merge branch 'stweil-typos' 2016-06-02 12:09:21 +00:00
Stefan Weil
a149731c46 Fix some typos in variable names and strings
Most of them were found by codespell.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
2016-05-30 23:00:08 +02:00
Dmitriy Simushev
2e629df611 Add gulp task for JavaScript files linting 2016-05-30 13:15:50 +00:00
Dmitriy Simushev
fcdc1021af Merge branch 'stweil-typos' 2016-05-28 10:11:03 +00:00
Stefan Weil
ce5cbaa850 Fix some typos in comments (most of them found by codespell)
Fix also an error string in Updater.php.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
2016-05-28 12:02:30 +02:00
dcd243505d Merge pull request #155 from aburakovskiy/master
Add ability to ban forever
2016-05-04 20:05:11 +03:00
Alexander Burakovskiy
4d32e942a3 Add ability to ban forever 2016-05-04 13:14:10 +03:00
nav666
95909d7ed4 Update default_config.yml 2016-04-07 02:41:19 +03:00
nav666
fad8ca5854 Update init.php 2016-04-07 02:24:01 +03:00
Candido
cd3778ca0d Add translate to string "cannot load avatar" 2016-03-07 11:27:35 -03:00
Dmitriy Simushev
8fe1498847 Merge pull request #151 from aburakovskiy/master
Fix thread ban
2016-03-01 13:59:40 +03:00
Alexander Burakovskiy
0edc9657b4 Fix thread ban 2016-02-25 14:53:15 +02:00
9fe423db62 Fix syntax errors 2015-08-23 22:15:10 +03:00
Dmitriy Simushev
a9e7114375 Reduce duplication in get_operators_from_adjacent_groups function 2015-08-05 14:38:49 +00:00
Dmitriy Simushev
e150bd1d26 Mark get_all_groups_for_operator function as deprecated 2015-08-05 14:35:13 +00:00
Dmitriy Simushev
4c9f963aa7 Fix groups isolation
See #131 for details
2015-08-05 14:22:56 +00:00
Dmitriy Simushev
9d81661cfe Fix history for operator without colleagues whose threads he can view
Fixes #132
2015-08-05 13:48:42 +00:00
fcd3cacfbc Add brief update instruction into README 2015-07-24 13:23:42 +03:00
Dmitriy Simushev
3edc959096 Bump version 2015-07-14 11:38:49 +00:00
Dmitriy Simushev
d656d8fe38 Update PHPCode Sniffer 2015-07-08 10:07:11 +00:00
Dmitriy Simushev
eccbb59bcc Require PHP's mbstring extension
Fixes #125
2015-06-19 11:26:03 +00:00
Dmitriy Simushev
8457e51717 Add THREAD_USER_IS_READY event 2015-06-19 11:15:07 +00:00
Dmitriy Simushev
227c7a9410 Localize message about no available updates at the "About" page 2015-06-10 13:02:01 +00:00
Dmitriy Simushev
9c92fda11b Localize "Download" link caption at the "About" page 2015-06-10 12:54:34 +00:00
Dmitriy Simushev
896f090aba Show history for group's related threads when isolation is on 2015-06-10 08:37:54 +00:00
Dmitriy Simushev
5363698020 Make sure appropriate defaults for omitted configs are used 2015-06-08 14:20:45 +00:00
Dmitriy Simushev
aa0c213cc3 Deny access for another's history in groups isolation mode 2015-06-08 14:18:39 +00:00
Dmitriy Simushev
5009f51342 Deny access to history for operators without CAN_VIEWTHREADS permission 2015-06-08 10:08:27 +00:00
Dmitriy Simushev
b340206d3a Merge branch 'auto_update' 2015-06-05 14:47:12 +00:00
Dmitriy Simushev
2cbb0c4134 Set correct instance ID when checking updates manually 2015-06-05 14:38:18 +00:00
Dmitriy Simushev
8c574ec88c Update Updates Server URL one more time 2015-06-05 14:28:12 +00:00
Dmitriy Simushev
5af9f92102 Send instance ID to the updates server 2015-06-05 11:53:39 +00:00
Dmitriy Simushev
6bf331b355 Rename "available_update" table to "availableupdate"
This is needed to follow naming convention
2015-06-05 11:39:44 +00:00
Dmitriy Simushev
4b74ceb854 Fix "available_update" table schema 2015-06-05 11:34:13 +00:00
Dmitriy Simushev
25054c4e0f Add "_instance_id" setting 2015-06-05 11:33:19 +00:00
Dmitriy Simushev
fbe53e3b29 Create getter for update checker inside the cron worker 2015-06-05 09:45:25 +00:00
Dmitriy Simushev
5397f7014a Fix default URL of updates server 2015-06-04 10:16:51 +00:00
Dmitriy Simushev
ebb3cf8ab1 Use the latest version of JSON2 from Douglas Crockford's repository 2015-06-01 13:35:58 +00:00
Dmitriy Simushev
55e7dbe704 Update Bower dependencies
Backbone.js and Underscrore.js left untouched because of versions
conflict with Marionette.js
2015-06-01 13:28:07 +00:00
Dmitriy Simushev
f13d938bde Update build dependencies 2015-06-01 13:08:15 +00:00
Dmitriy Simushev
0ff5c7c28a Fix localization constant at locale edit page 2015-05-28 14:42:10 +00:00
Dmitriy Simushev
fc789e6ef9 Improve statistics aggregation algorithm a little 2015-05-28 13:49:42 +00:00
Dmitriy Simushev
9f3ce28877 Remove unused "use" statement 2015-05-28 13:22:46 +00:00
Dmitriy Simushev
4e7f9eac50 Provide a way to disable automatical updates checking 2015-05-26 14:45:34 +00:00
Dmitriy Simushev
2fc85b1068 Add "check for updates" button to "about" page 2015-05-26 14:19:09 +00:00
Dmitriy Simushev
930ea9a6ac Show info about cURL extension at "About" page 2015-05-26 13:54:39 +00:00
Dmitriy Simushev
d4ebd68052 Show list of available updates at "About" page 2015-05-26 13:53:22 +00:00
Dmitriy Simushev
e9d41c4869 Fix name of "available_update" table 2015-05-26 13:34:58 +00:00
Dmitriy Simushev
577c2be622 Create a way to automatically get info about available updates 2015-05-26 13:19:13 +00:00
Dmitriy Simushev
8e7fe6bcd7 Remove debug statements from CronWorker 2015-05-26 12:17:32 +00:00
Dmitriy Simushev
973cc5746e Remove unused "use" statement 2015-05-22 12:55:49 +00:00
Dmitriy Simushev
8326eb3ebf Merge branch 'editable_locales'
This allows to edit locales meta info using UI
2015-05-22 12:22:27 +00:00
Dmitriy Simushev
e9baceb039 Add an ability to change locale setting using UI
Fixes #99
2015-05-22 11:26:48 +00:00
Dmitriy Simushev
720b72f8e4 Use the latest version of PHPCS from the repository 2015-05-22 10:59:46 +00:00
a3ebe57f1f Bump version 2015-05-22 13:40:33 +03:00
Dmitriy Simushev
d9dc5e0ed7 Fix password form disapearing on installation 2015-05-21 14:09:28 +00:00
Dmitriy Simushev
bc024c3253 Fix layout for install and login pages 2015-05-21 13:58:54 +00:00
Dmitriy Simushev
137d92624e Store locales' meta info in the database 2015-05-21 12:39:36 +00:00
Dmitriy Simushev
5d13afd8f6 Make sure visitor name is not empty in prechat survey 2015-05-08 14:54:53 +00:00
Dmitriy Simushev
5628f42782 Make sure Thread::groupId is always integer
See https://mibew.org/forums/index.php/topic,191756.0.html for details
about why it's needed.
2015-05-08 12:46:50 +00:00
Dmitriy Simushev
eae5b8bb06 Make rewrite rules work with old Apache
See https://mibew.org/forums/index.php/topic,191761.0.html
2015-05-07 14:17:14 +00:00
Dmitriy Simushev
40fef4e360 Fix "replace" Handlebars.js helper 2015-05-07 13:23:53 +00:00
Dmitriy Simushev
ab35143e18 Add gulp "rebuild" task 2015-04-17 14:18:59 +00:00
Dmitriy Simushev
f176ac628b Use clean inside "default" gulp task 2015-04-17 13:07:25 +00:00
Dmitriy Simushev
7a09546198 Fix docs for EventDispatcher\Events::BUTTON_GENERATE const 2015-04-15 14:30:44 +00:00
Dmitriy Simushev
47672a5eb6 Fix gulp clean task 2015-04-14 11:43:56 +00:00
Dmitriy Simushev
3307ba01dc Fix bug with race condition on build 2015-04-14 11:39:33 +00:00
7d3558460b Bump version 2015-04-14 13:47:23 +03:00
Dmitriy Simushev
2fdb7e4525 Update copyrights in the default page style CSS file 2015-04-08 09:46:10 +00:00
Dmitriy Simushev
48d8805605 Add "Show menu" link at awaiting users page
Fixes #95
2015-04-08 09:44:05 +00:00
Dmitriy Simushev
e4a104f52e Add CLI cron worker 2015-04-01 15:28:10 +00:00
Dmitriy Simushev
ff09ea09cc Extract CronWorker from CronController 2015-04-01 15:24:51 +00:00
Dmitriy Simushev
a4ce7ffea7 Clean up before release preparation 2015-03-31 10:54:34 +00:00
0f8b5da18a Bump version 2015-03-30 14:10:55 +03:00
Dmitriy Simushev
1a358c2f09 Don't call set_csrf_token() function in controllers 2015-03-27 15:19:10 +00:00
Dmitriy Simushev
b56881bf01 Mark Database::throwExeptions method as deprecated
This is done because the method has a typo in the name.
2015-03-27 15:05:17 +00:00
Dmitriy Simushev
59de37a12b Automatically reject invitation when visitor goes to another page 2015-03-27 14:34:53 +00:00
Dmitriy Simushev
2a819b1b98 Allow using "?" and "*" wildcards for history search 2015-03-27 13:29:12 +00:00
Dmitriy Simushev
a9eb9f8cf2 Mark thread as chatting right after an invitation is accepted 2015-03-27 12:31:11 +00:00
Dmitriy Simushev
70f630d125 Rewrite Thread::take method to simplify it 2015-03-27 12:29:54 +00:00
Dmitriy Simushev
0075e2169c Add a function that loads online operators 2015-03-26 10:46:50 +00:00
Dmitriy Simushev
f47a67fd57 Notify operators only about threads that are waiting for the answer 2015-03-25 14:41:42 +00:00
Dmitriy Simushev
b2bb9cfb92 Do not show alert if another one is already shown 2015-03-25 14:28:03 +00:00
Dmitriy Simushev
a3f68852ce Fix broken avatar URL in invitation 2015-03-24 15:29:18 +00:00
Dmitriy Simushev
2031d82600 Bump version 2015-03-24 15:05:05 +00:00
Dmitriy Simushev
31b09570f9 Allow to use multiple memcached servers for caching 2015-03-24 15:01:39 +00:00
Dmitriy Simushev
b18aef404a Use bower for managing client side dependencies
Fixes #117
2015-03-23 16:42:32 +00:00
Dmitriy Simushev
6fb71835bf Update Handlebars.js to v3.0.0 2015-03-23 10:05:40 +00:00
Dmitriy Simushev
22aaedd3be Add support of memcached storage for caching 2015-03-20 15:26:15 +00:00
Dmitriy Simushev
758203b6d3 Encapsulate cache pool instantiation in CacheFactory 2015-03-20 14:59:11 +00:00
Dmitriy Simushev
57182b0589 Forbid access to cache files 2015-03-20 13:24:34 +00:00
Dmitriy Simushev
0f44076e48 Use unexpired cache for routes by default 2015-03-20 13:15:32 +00:00
Dmitriy Simushev
094139dead Add routes caching 2015-03-20 13:08:04 +00:00
Dmitriy Simushev
30fd4bad7c Add HTTP caching headers to translations.js
Fixes #70
2015-03-19 12:04:42 +00:00
Dmitriy Simushev
9fef4b2871 Simplify working with Asset Manager in Handlebars helpers 2015-03-19 09:55:58 +00:00
Dmitriy Simushev
db702e43c9 Simplify working with Router in Handlebars helpers 2015-03-19 09:34:16 +00:00
Dmitriy Simushev
93c5cb995a Update Vex.js to v2.3.2 2015-03-18 13:15:41 +00:00
Dmitriy Simushev
5fada43676 Update Marionette.js to v2.4.1 2015-03-18 13:07:26 +00:00
Dmitriy Simushev
adac8fb3fd Update Underscore.js to v1.8.2 2015-03-18 12:57:56 +00:00
Dmitriy Simushev
0eef94a164 Update composer dependencies 2015-03-18 12:50:09 +00:00
Dmitriy Simushev
3c0c880661 Add CSRF protection for password recovery forms 2015-03-17 14:41:31 +00:00
Dmitriy Simushev
e122d020eb Add CSRF protection to login form 2015-03-17 14:22:32 +00:00
Dmitriy Simushev
a8629df5ec Use "encodeURIComponent" instead of "escape" in popup windows JS
This also fixes passing client's URL for IDN domains to the server.
2015-03-17 13:47:23 +00:00
Dmitriy Simushev
415005e2f6 Fix validation for empty emails 2015-03-17 13:25:00 +00:00
Dmitriy Simushev
6e78c45c67 Allow using email with IDN domains at the server side 2015-03-17 12:25:25 +00:00
Dmitriy Simushev
6ac77e629a Improve email validation at the client side 2015-03-17 12:24:21 +00:00
Dmitriy Simushev
313e854723 Move email validation function to Mibew\Mail\Utils class 2015-03-17 10:36:45 +00:00
Dmitriy Simushev
4332d9c205 Use third-party library to validate email at client side 2015-03-17 10:31:37 +00:00
Dmitriy Simushev
833d2a9096 Use PHP's filter_var function for email validation 2015-03-16 15:58:34 +00:00
Dmitriy Simushev
6e71f0542b Store relative avatar path in database
Also it fixes #114
2015-03-16 12:56:36 +00:00
f6fe379a54 Add information on cron job into README 2015-03-10 18:18:22 +03:00
Dmitriy Simushev
cc5adc17b2 Use correct field to pass operator's requests frequency to client side
Fixes #112
2015-03-04 09:56:37 +00:00
284318a287 Update version 2015-02-24 18:21:20 +03:00
Dmitriy Simushev
edcd348bca Fix bug with single popup window openning 2015-02-20 14:22:59 +00:00
Dmitriy Simushev
21ae86958d Remove unused AbstractGenerator::getChatUrlForJs method 2015-02-03 16:20:39 +00:00
Dmitriy Simushev
0dca0bb57d Build correct URLs for chat popups 2015-02-03 16:19:01 +00:00
Dmitriy Simushev
933ced4575 Do not use HTML entities inside script tag
Fixes #107
2015-02-03 16:17:52 +00:00
Dmitriy Simushev
232d69cf72 Use Vex.js for alert, confirm and prompt 2015-02-03 14:23:32 +00:00
Dmitriy Simushev
c1850f0bb3 Use async notice for alert, confirm and prompt functions 2015-02-03 14:08:52 +00:00
Dmitriy Simushev
ebd6684d4a Switch to PHPCS 2.x 2015-02-03 09:49:00 +00:00
Dmitriy Simushev
62f958622c Use stable version of UA parser 2015-02-03 09:46:07 +00:00
Dmitriy Simushev
626145340e Fix setting current database version in the Updater 2015-01-26 12:17:52 +00:00
Dmitriy Simushev
84b0d891e0 Update dependencies of the build system 2015-01-23 11:47:12 +00:00
Dmitriy Simushev
ef98d5056a Make the project buildable on windows 2015-01-23 11:34:24 +00:00
Dmitriy Simushev
ea0b6a0cd5 Add "widgetResponseAlter" event 2015-01-22 12:58:53 +00:00
Dmitriy Simushev
f015b5b820 Pass an instance of Request Processor to *_FUNCTION_CALL events 2015-01-22 11:41:35 +00:00
Dmitriy Simushev
6d3810b7ba Improve Mibew.Utils.toDashFormat JS function 2015-01-21 11:49:27 +00:00
Dmitriy Simushev
e273b04dab Remove unneded condition from profile controller 2015-01-21 11:48:40 +00:00
Dmitriy Simushev
9799fb5e3f Fix "empty password" notification 2015-01-21 11:28:13 +00:00
Dmitriy Simushev
c27a0e1aea Use correct login to generate password hash when it is changed 2015-01-21 11:22:12 +00:00
47ee6edaad Update copyright notices 2015-01-21 14:04:29 +03:00
b8d2af4c67 Update version 2015-01-21 13:05:41 +03:00
Dmitriy Simushev
8faa0d9f4e Hide iframe popup while its real styles are loading 2015-01-21 09:49:50 +00:00
Dmitriy Simushev
9ef0739b80 Show ajax loader while chat iframe is loading 2015-01-20 14:45:41 +00:00
Dmitriy Simushev
ad7f3d6167 Do not define widget code twice 2015-01-20 14:44:21 +00:00
Dmitriy S. Simushev
78dfb230ed Merge pull request #102 from Mibew/dashboard
Dashboard
2015-01-20 16:58:05 +03:00
Dmitriy Simushev
854a4ca010 Switch to dev version of UAParser 2015-01-20 13:55:50 +00:00
Dmitriy Simushev
7fde2eb9cd Add ability to use mibew in an iframe
Fixes #63
2015-01-20 13:48:28 +00:00
8c6d98ddbd Remove useless attribute 2015-01-19 13:39:12 +03:00
c2229a6c79 Improve dashboard look'n'feel 2015-01-17 15:16:10 +03:00
Dmitriy Simushev
120abce028 Fix invitation window params 2015-01-16 10:40:06 +00:00
Dmitriy Simushev
a6d6f2bea2 Add Mibew.Utils.deleteCookie function to widget.js 2015-01-15 13:31:50 +00:00
Dmitriy Simushev
3f6a95f7a6 Use human-readable way to define visitor track window params 2015-01-14 14:37:30 +00:00
Dmitriy Simushev
090f650ac1 Use human-readable way to define user track window params 2015-01-14 14:25:51 +00:00
Dmitriy Simushev
06109eb0c4 Use human-readable way to define ban window params 2015-01-14 14:20:15 +00:00
Dmitriy Simushev
f6938b2f13 Remove unused configs from default page style 2015-01-14 14:12:57 +00:00
Dmitriy Simushev
9467525dac Remove unneeded default configs from ChatStyle 2015-01-14 13:50:32 +00:00
Dmitriy Simushev
1914b23c74 Use human-readable way to define history window params 2015-01-14 13:38:39 +00:00
Dmitriy Simushev
e333ff3d27 Rename Mibew.Utils.buildWindowOptions to buildWindowParams 2015-01-14 12:56:24 +00:00
Dmitriy Simushev
a5b7002239 Use human-readable way to define send mail window params 2015-01-14 12:51:38 +00:00
Dmitriy Simushev
9faf346634 Use human-readable way to define chat window params 2015-01-14 12:25:25 +00:00
Dmitriy Simushev
67a0db5349 Add JS "buildWindowOptions" utility method 2015-01-14 12:14:49 +00:00
Dmitriy Simushev
e5b8c84736 Allow plugins depend on environment
Fixes #98
2015-01-13 11:32:33 +00:00
Dmitriy Simushev
090383bc95 Use UA Parser from packagist.org instead of GitHub repo 2015-01-12 11:21:27 +00:00
Dmitriy S. Simushev
52107afc1a Merge pull request #100 from Mibew/invitations_fix
Prevent use of undefined values on display of chat invitation
2015-01-12 11:46:15 +03:00
Dmitriy S. Simushev
3b9ded0b29 Merge pull request #101 from Mibew/missed_constant
Replace old localization constant with a valid string
2015-01-06 21:58:56 +03:00
c51a3ee5a1 Replace old localization constant with a valid string 2015-01-06 20:32:31 +03:00
ba9c01b82c Prevent use of undefined values on display of chat invitation 2015-01-03 03:13:19 +03:00
Dmitriy Simushev
132ca02cdf Allow to use any browser for chat
There are too many browsers in the world thus we cannot really say
is the current browser is fully supported or not. Give a chance to
all browsers.
2014-12-29 15:39:13 +00:00
Dmitriy Simushev
9cd082b878 Use third party library to detect user's browser 2014-12-29 15:04:24 +00:00
Dmitriy Simushev
efbf92b012 Use multi-level style configs 2014-12-29 11:30:33 +00:00
Dmitriy Simushev
ff1940cdc5 Mibew does not use "iconv" library anymore 2014-12-29 09:29:13 +00:00
Dmitriy Simushev
6a17db4e04 Operators can post messages only to own threads 2014-12-25 15:28:47 +00:00
Dmitriy Simushev
5a2e48eeef Fix ID style in operator's code field 2014-12-25 13:36:11 +00:00
Dmitriy Simushev
b9fd28f20f Do not show "visitor navigate" message if the page is not changed 2014-12-25 12:42:03 +00:00
Dmitriy Simushev
1a8f50adb0 Move "about" link to "Others" section 2014-12-24 16:00:50 +00:00
Dmitriy Simushev
31d602986e Move link to profile to operator's name in the top right corner
Fixes #93
2014-12-24 15:31:13 +00:00
Dmitriy Simushev
fb83027a1e Truncate operator's avatar in invitation
Fixes #96
2014-12-24 13:44:27 +00:00
Dmitriy Simushev
19edc91dfd Add warning sign to "run update wizard" notice 2014-12-24 12:59:26 +00:00
Dmitriy Simushev
27a23f68c0 Remove unneeded versions
Fixes #97
2014-12-24 12:50:27 +00:00
Dmitriy Simushev
1306efd380 Move header logo's styles to css 2014-12-24 12:08:53 +00:00
Dmitriy Simushev
b19473f658 Add link to dashboard to mibew logo
Fixes #94
2014-12-24 12:03:41 +00:00
Dmitriy Simushev
53c60eed76 Exclude JS sources from release package 2014-12-23 14:48:26 +00:00
Dmitriy Simushev
1fae58c350 Remove separate license page 2014-12-23 14:45:14 +00:00
Dmitriy Simushev
0c00a697ec Update build dependencies 2014-12-23 14:36:59 +00:00
Dmitriy Simushev
7e8ea1cdbf Update copyright notice at the about page 2014-12-23 14:32:46 +00:00
Dmitriy Simushev
a39d0fa6cf Fix typo at the about page 2014-12-23 13:55:36 +00:00
Dmitriy Simushev
b40e1deb89 Remove latest version placeholder from about page 2014-12-23 13:52:11 +00:00
Dmitriy Simushev
ee751b471d Use new gateway for latest version info 2014-12-23 13:46:43 +00:00
Dmitriy Simushev
782e9895e5 Show another info on the about page 2014-12-23 13:33:27 +00:00
Dmitriy Simushev
8552881f7d Move system info to about page 2014-12-23 12:51:40 +00:00
Dmitriy Simushev
9bfd6a29fb Use new icon for add group, operator, etc. buttons. 2014-12-23 10:48:53 +00:00
Dmitriy Simushev
f5c80e7b5c Add about page
Fixes #53
2014-12-23 10:22:22 +00:00
Dmitriy Simushev
d7a5c1d9c1 Use new dashboard icons
The icons are taken from http://www.icojam.com/blog/?p=259
2014-12-22 15:44:57 +00:00
Dmitriy Simushev
e66e0c1452 Update jQuery to v1.11.2 2014-12-22 10:16:59 +00:00
Dmitriy Simushev
21daf749f0 Allow markup in leave message page description 2014-12-19 13:50:40 +00:00
Dmitriy Simushev
1e46d6fabd Add notice about statistics aggregation 2014-12-19 13:24:07 +00:00
Dmitriy Simushev
8b34ca34c7 Remove statistics_aggregation_interval setting 2014-12-19 12:36:41 +00:00
Dmitriy Simushev
964e917f4a Provide easy way to override views in JS application 2014-12-18 14:42:11 +00:00
Dmitriy Simushev
210e82e798 Use correct ID for dynamically loaded scripts 2014-12-18 14:05:32 +00:00
Dmitriy Simushev
243fa1a1d9 Remane "mibewAgentButton" id to "mibew-agent-button" 2014-12-18 13:54:46 +00:00
Dmitriy Simushev
506425a9e1 Clean up JS in the default page style 2014-12-18 13:20:35 +00:00
Dmitriy Simushev
a72a602120 Update Marionette.js to v2.3.0 2014-12-18 12:57:44 +00:00
Dmitriy S. Simushev
bcd2bb9242 Merge pull request #89 from Mibew/remove_link
Remove useless link from popup window with a thread history
2014-12-17 20:35:10 +03:00
Dmitriy S. Simushev
a6e6993a65 Merge pull request #88 from Mibew/layout_fix
Fix layout on plugins page
2014-12-17 20:34:40 +03:00
054133e013 Remove useless link from popup window with a thread history 2014-12-17 19:31:28 +03:00
2d875ba623 Fix layout on plugins page 2014-12-17 19:15:25 +03:00
Dmitriy S. Simushev
e6f6fd7d38 Merge pull request #87 from Mibew/issue73
Beautify stylesheets and fix #73
2014-12-17 16:50:46 +03:00
792acd7b17 Beautify stylesheets and fix #73 2014-12-17 15:38:52 +03:00
Dmitriy Simushev
30d884b699 Use static file for license during installation 2014-12-17 11:42:05 +00:00
Dmitriy Simushev
bc14d1f0ef Let the system work without mailer configs 2014-12-17 10:46:42 +00:00
Dmitriy S. Simushev
062a4c1090 Merge pull request #86 from Mibew/fix_typo
Fix typo in string constant
2014-12-17 13:09:26 +03:00
134bbb9984 Fix typo in string constant 2014-12-17 00:04:01 +03:00
Dmitriy Simushev
a441bed2a2 Move common helpers to a separate composer package 2014-12-16 16:00:20 +00:00
Dmitriy Simushev
f5ee6448e4 Store project meta info only in composer.json 2014-12-11 14:21:20 +00:00
Dmitriy Simushev
3e77eddb33 Exclude vendor binaries from release package 2014-12-11 14:06:15 +00:00
Dmitriy Simushev
ad8c815b3c Use SESSION_PREFIX everywhere 2014-12-11 13:56:22 +00:00
Dmitriy Simushev
96724464e2 Create missed templates at "operator/mail-template" page 2014-12-11 13:20:20 +00:00
Dmitriy Simushev
8f346ae0b7 Do not die if "leave_message" mail template cannot be loaded 2014-12-11 13:07:17 +00:00
Dmitriy Simushev
8a47afef58 Do not die if "user_history" mail template cannot be loaded 2014-12-11 13:04:25 +00:00
Dmitriy Simushev
6768fe96c2 Use "en" locale as a fallback for MailTemplate 2014-12-11 12:48:53 +00:00
Dmitriy Simushev
c4a47928a8 Add warning about uncaught exception to AbstractProcessor 2014-12-11 11:57:57 +00:00
Dmitriy Simushev
ec06357535 Use stable version of Handlebars.php 2014-12-11 11:26:29 +00:00
Dmitriy Simushev
bb1b6c377c Log error when "Internal Server Error" page is shown 2014-12-11 10:48:00 +00:00
Dmitriy Simushev
9c87fadb7d Clean up ImageGenerator::getWidgetCode method 2014-12-11 10:18:24 +00:00
Dmitriy S. Simushev
db7aa3d12a Merge pull request #84 from Mibew/button_fix
Fix button generation with disabled visitors tracking
2014-12-11 13:14:40 +03:00
304de4ab71 Fix button generation with disabled visitors tracking 2014-12-10 19:48:34 +03:00
Dmitriy S. Simushev
3e5f589972 Merge pull request #83 from Mibew/connection_timeout
Fixes #65
2014-12-10 19:32:15 +03:00
Dmitriy Simushev
6fbee71173 Add an ability to use SMTP mail transport 2014-12-10 16:21:59 +00:00
07c015856e Fixes #65 2014-12-10 19:09:04 +03:00
Dmitriy Simushev
17b7bf6757 Use Object-Oriented approach for mail templates 2014-12-10 11:50:57 +00:00
Dmitriy Simushev
e0716bbeb2 Fix bug with "plugin" table fields sizes 2014-12-10 11:15:23 +00:00
Dmitriy Simushev
4e4f0adfd6 Use SwiftMailer to send emails 2014-12-09 14:40:16 +00:00
Dmitriy Simushev
a66e23fe9b Remove unneeded TODO from HomeController 2014-12-09 11:55:35 +00:00
80565efefb Update README 2014-12-08 16:18:34 +03:00
3a325ecc6c Update info on system requirements 2014-12-08 15:12:24 +03:00
Dmitriy Simushev
aa28272dbd Update Symfony Components 2014-12-05 15:53:18 +00:00
Dmitriy Simushev
097ec6ef1a Add info about current plugin state 2014-11-28 15:18:48 +00:00
Dmitriy Simushev
2bdfebc428 Add PluginManager::hasPlugin method 2014-11-28 15:02:16 +00:00
Dmitriy Simushev
5282e789ba Use PluginInfo::needsUpdate instead of checking versions directly 2014-11-28 14:38:54 +00:00
Dmitriy Simushev
b0aa66c7cf Fix issue with sprintf arguments in PluginManager 2014-11-28 14:25:07 +00:00
Dmitriy Simushev
772aa904d9 Add plugins update stuff 2014-11-28 14:20:47 +00:00
Dmitriy Simushev
459f75727a Provide an ability to use static methods as updates 2014-11-28 13:34:37 +00:00
Dmitriy Simushev
e2d4ab3715 Recognize alpha and rc versions in updates names 2014-11-28 11:46:27 +00:00
Dmitriy Simushev
80f5873d9a Move getUpdates to Maintenance\Utils class 2014-11-28 11:02:55 +00:00
Dmitriy Simushev
abdfa54f36 Update Handlebars.php 2014-11-27 15:42:30 +00:00
Dmitriy Simushev
361e424acd Merge two localization constants in plugins template 2014-11-27 15:08:52 +00:00
Dmitriy Simushev
7ac85ac412 Check that all needed PHP extensions are loaded before install 2014-11-27 13:01:25 +00:00
Dmitriy Simushev
80077be185 Implement new plugin management system 2014-11-27 11:42:23 +00:00
014a7fabcb Merge pull request #80 from Mibew/issue61
Fix setting of tracking cookie for TLDs
2014-11-27 13:37:26 +03:00
a2fee28bba Fix setting of tracking cookie for TLDs
Fixes #61
2014-11-26 20:02:15 +03:00
Dmitriy Simushev
f7434502b7 Add PluginInfo::getInstance method 2014-11-25 12:22:49 +00:00
Dmitriy Simushev
a4361fe8ce Create plugin info wrapper 2014-11-24 10:37:08 +00:00
Dmitriy Simushev
48978fb060 Add a function to check if a plugin exists or it does not. 2014-11-24 10:13:51 +00:00
Dmitriy Simushev
03a8eab3d1 Fix undefined index in ThreadProcessor::processFunction 2014-11-21 15:49:03 +00:00
Dmitriy Simushev
428c592139 Statically cache results of Plugin\Utils::discoverPlugins 2014-11-21 13:06:44 +00:00
Dmitriy Simushev
dca7c2c520 Fix comments in Mibew\Ban class 2014-11-21 13:00:30 +00:00
Dmitriy Simushev
c9c1ffca4e Remove unused "use" statement 2014-11-20 10:06:30 +00:00
Dmitriy Simushev
ad5554bb52 Fix coding style in Mibew\Plugin\Utils 2014-11-20 09:50:32 +00:00
Dmitriy Simushev
bf7642dab3 Run plugins only after all libs are loaded 2014-11-20 09:26:03 +00:00
Dmitriy Simushev
a63f4ced3d Create a method for plugin class name building 2014-11-19 14:19:01 +00:00
Dmitriy Simushev
b896d43db7 Use more strict policy for plugin names 2014-11-19 14:06:19 +00:00
Dmitriy Simushev
f4b08ff0a3 Add plugins discovery means 2014-11-19 13:15:41 +00:00
Dmitriy Simushev
c70764dab2 Use regular singleton in Mibew\Plugin\PluginManager 2014-11-19 12:50:08 +00:00
Dmitriy Simushev
542b830577 Return false from PluginManager::getPlugin for unregistered plugins 2014-11-19 11:58:50 +00:00
Dmitriy Simushev
bfe902e062 Rename Mibew\Plugin\Manager to Mibew\Plugin\PluginManager 2014-11-19 11:55:16 +00:00
Dmitriy Simushev
c205c9ff94 Use versions range in plugin dependencies 2014-11-19 10:17:15 +00:00
Dmitriy Simushev
2d702f5542 Add versions check to plugins 2014-11-18 12:06:22 +00:00
Dmitriy Simushev
d68b0bdb0c Flush cache on update 2014-11-17 14:30:15 +00:00
Dmitriy Simushev
07b25a2fc3 Create Updater 2014-11-17 14:19:07 +00:00
Dmitriy Simushev
a43d46f5f5 Extract SessionAuthenticationManager 2014-11-13 11:19:53 +00:00
Dmitriy Simushev
47851c9ed2 Move "format_version_id" func to Maintenance\Utils class 2014-11-12 15:14:13 +00:00
Dmitriy Simushev
f82d42e729 Add "buttonGenerate" event 2014-11-12 10:58:21 +00:00
Dmitriy Simushev
c43fccf297 Use CanteenHTML5 for buttons generation 2014-11-12 10:24:40 +00:00
Dmitriy Simushev
d446b9a78f Replace INSTALLATION_IN_PROGRESS const with MAINTENANCE_MODE 2014-11-11 13:31:38 +00:00
Dmitriy Simushev
1deebaff20 Move Installer to a separated namespace 2014-11-11 13:14:37 +00:00
Dmitriy Simushev
df66227729 Remove unused "escape_with_cdata" function 2014-11-11 12:21:02 +00:00
Dmitriy Simushev
bcbb02f52f Fix trailing slash removing on installation 2014-11-11 10:49:13 +00:00
Dmitriy Simushev
f5470239e4 Use Symfony-compatible router 2014-11-11 10:34:04 +00:00
Dmitriy Simushev
f8909d5e8c Move Stash cache to separated directory 2014-11-11 10:31:51 +00:00
d27633fc28 Increase Mibew version 2014-11-10 21:41:12 +03:00
Dmitriy Simushev
6066b9312e Remove "is_secure_request" function 2014-11-07 12:39:19 +00:00
Dmitriy Simushev
fe0d2f2760 Check directories permissions on install
Fixes #76
2014-11-07 12:09:18 +00:00
Dmitriy Simushev
2c0d88c4d5 Use ephemeral cache during installation 2014-11-07 11:40:36 +00:00
Dmitriy Simushev
2c9a6830c8 Use lazy objects creation in Application class 2014-11-07 11:10:19 +00:00
Dmitriy Simushev
6b3b5d6fec Forbid users to post to closed threads
Fixes #72
2014-11-06 13:13:29 +00:00
Dmitriy Simushev
b4ab5d8cd1 Use "once" method instead of "on"/"off" in JS message form 2014-11-06 11:02:57 +00:00
Dmitriy Simushev
bffc2fd799 Restrict access to a thread for third-party users
Fixes #71
2014-11-06 10:45:38 +00:00
Dmitriy Simushev
3f36afc285 Fix comments for AbstractProcessor::processFunction method 2014-11-06 10:08:12 +00:00
Dmitriy Simushev
18e9cf7039 Remove "get_logged_in" function 2014-11-05 15:52:25 +00:00
Dmitriy Simushev
43f7df6c76 Remove Thread::setupAvatar method 2014-11-05 15:29:23 +00:00
Dmitriy Simushev
03328b9293 Use valid types for Thread fields 2014-11-05 14:40:19 +00:00
Dmitriy Simushev
3dd80070c7 Add "userId" and "agentId" fields to thread at client side 2014-11-05 14:25:02 +00:00
Dmitriy Simushev
3984c260b0 Use the correct backpath to redirect operator after login 2014-11-05 10:46:56 +00:00
Dmitriy Simushev
82a4d7a2a2 Use composer's autoloader
Funny, but it fixes #75 without classes changing
2014-10-31 14:13:49 +00:00
Dmitriy Simushev
3b43090bda Add "visitorDeleteOld" event 2014-10-31 11:51:08 +00:00
Dmitriy Simushev
f0c4299ba3 Remove old visitors in single process 2014-10-31 11:26:53 +00:00
Dmitriy Simushev
f10079497c Add "groupUpdateOperators" event 2014-10-31 09:59:44 +00:00
Dmitriy Simushev
07fc4a3666 Fix broken links at "operator/group/<id>/members" page 2014-10-30 13:53:47 +00:00
Dmitriy Simushev
38bc096444 Return IDs set from "get_operator_group_ids" function 2014-10-30 13:49:16 +00:00
Dmitriy Simushev
146c4b7ac1 Return IDs set from "get_group_members" function 2014-10-30 13:27:23 +00:00
Dmitriy Simushev
9d854e9642 Use regular "Thread::save" to close old invitations 2014-10-30 13:07:54 +00:00
Dmitriy Simushev
6e200bf956 Fix race condition in old invitation closing 2014-10-30 12:33:21 +00:00
Dmitriy Simushev
b3c9a02660 Encapsulate locks mechanics in "ProcessLock" class 2014-10-30 12:25:48 +00:00
Dmitriy Simushev
22699f1ed5 Add "threadGetMessagesAlter" event 2014-10-30 10:19:08 +00:00
Dmitriy Simushev
c0232e6fce Use regular tread save in "Thread::closeOldThreads" method 2014-10-29 16:03:38 +00:00
Dmitriy Simushev
96c9bf2a93 Prevent race condition in old threads closing 2014-10-29 15:12:05 +00:00
Dmitriy Simushev
b5020645be Remove Settings::update method
It was too slow
2014-10-29 15:02:55 +00:00
Dmitriy Simushev
bf483e4abc Fix bug with "Settings::update" method. 2014-10-29 14:35:40 +00:00
Dmitriy Simushev
a37018aab6 Add "default" argument to "Settings::get" method 2014-10-29 13:48:30 +00:00
Dmitriy Simushev
be7d49c0f5 Use Events class constant instead of raw event name in track.php 2014-10-29 12:39:59 +00:00
Dmitriy Simushev
336d8c1faa Add "threadCreate" event 2014-10-29 10:50:09 +00:00
Dmitriy Simushev
ab942731e6 Refactor Thread class 2014-10-29 10:45:35 +00:00
Dmitriy Simushev
168336a20b Document "threadFunctionCall" event 2014-10-28 13:04:31 +00:00
Dmitriy Simushev
297377b0fd Add "operatorUpdate" event 2014-10-28 12:43:40 +00:00
Dmitriy Simushev
65d7cb3823 Use "update_operator" func for operator modification everywhere 2014-10-28 12:26:14 +00:00
Dmitriy Simushev
1d9a837e37 Make operator's login unchangeable 2014-10-28 12:06:07 +00:00
Dmitriy Simushev
05f5a606d1 Refactor update_operator function 2014-10-28 11:45:36 +00:00
Dmitriy Simushev
614f02a108 Refactor "check_group_fields" function 2014-10-28 10:40:26 +00:00
Dmitriy Simushev
32a134f31a Remove unused class alias from libs/chat.php 2014-10-27 14:20:59 +00:00
Dmitriy Simushev
4ae850d529 Remove invalid link from Thread::postMessage docs 2014-10-27 14:19:08 +00:00
Dmitriy Simushev
3f27aea2ea Add "threadPostMessage" event 2014-10-27 13:18:12 +00:00
Dmitriy Simushev
30da4ae75e Add notice about triggering event to "update_group" function 2014-10-27 12:07:52 +00:00
Dmitriy Simushev
b7bf41a191 Create separate function for enable/disable operators 2014-10-27 11:55:29 +00:00
Dmitriy Simushev
38769615ac Fix notice about undefined variable in BanController 2014-10-27 10:57:43 +00:00
Dmitriy Simushev
6cc94bcb33 Reduce duplication in Ban class 2014-10-27 10:57:03 +00:00
Dmitriy Simushev
7f6a9c6513 Add "banUpdate" event 2014-10-27 10:40:45 +00:00
Dmitriy Simushev
7e371a20d9 Fix wrong group key in "update_group" function 2014-10-27 10:30:25 +00:00
Dmitriy Simushev
28270d7d18 Use named placeholders in "update_group" function 2014-10-27 10:27:37 +00:00
Dmitriy Simushev
d6084f035f Pass regular group array to "create_group" and "update_group" functions 2014-10-27 10:19:21 +00:00
Dmitriy Simushev
816323a154 Add one more group parameter to check 2014-10-27 10:01:40 +00:00
Dmitriy Simushev
0a3207e879 Add "groupUpdate" event 2014-10-27 10:00:27 +00:00
Dmitriy Simushev
7af300b8f5 Move group related functions to libs/groups.php 2014-10-23 11:41:35 +00:00
Dmitriy Simushev
9753081407 Sent "Visitor closed chat window" message only if there was a chat 2014-10-22 14:34:06 +00:00
Dmitriy Simushev
c83fd59763 Remove unused "blockedcount" field of ban table 2014-10-22 14:17:38 +00:00
Dmitriy Simushev
445a5866ad Add "invitationIgnore" event 2014-10-22 14:15:05 +00:00
Dmitriy Simushev
f070a121fe Fix typo in widget.js code 2014-10-21 12:54:07 +00:00
Dmitriy Simushev
c2f0fb24c3 Describe "routesAlter" event in Events class 2014-10-21 12:37:07 +00:00
Dmitriy Simushev
7eea7c09d4 Add "banDelete" event 2014-10-21 11:51:19 +00:00
Dmitriy Simushev
6263f3a2f4 Add "banCreate" event 2014-10-21 11:43:10 +00:00
Dmitriy Simushev
ada83c629a Encapsulate work with bans in Ban class 2014-10-21 11:33:13 +00:00
Dmitriy Simushev
1dea407037 Add "invitationReject" event 2014-10-20 12:44:44 +00:00
Dmitriy Simushev
b83cb193f1 Add "invitationAccept" event 2014-10-20 12:36:44 +00:00
Dmitriy Simushev
5ad1044dc0 Add "invitationCreate" event 2014-10-20 12:27:10 +00:00
Dmitriy Simushev
09b3d77b19 Add "groupDelete" action 2014-10-20 12:21:59 +00:00
Dmitriy Simushev
7ce1add5dc Create delete_group function 2014-10-20 12:10:31 +00:00
Dmitriy Simushev
34341ef01c Refactor create_group function a little 2014-10-20 11:50:45 +00:00
Dmitriy Simushev
1aec37b6f6 Add "groupCreate" event 2014-10-20 11:17:56 +00:00
Dmitriy Simushev
9b05509ec4 Add "threadClose" event 2014-10-20 11:07:50 +00:00
Dmitriy Simushev
53450ea9d6 Create "threadDelete" event 2014-10-20 10:55:22 +00:00
Dmitriy Simushev
60bd21bf42 Move "threadUpdate" event to Events class 2014-10-20 10:17:34 +00:00
Dmitriy Simushev
d05fe335b8 Describe all "users" app related events in Events class 2014-10-20 10:12:55 +00:00
Dmitriy Simushev
55b1476139 Describe "cronRun" event in Events class 2014-10-17 14:42:39 +00:00
Dmitriy Simushev
de1d5d6d51 Create "visitorCreate" event 2014-10-17 14:37:01 +00:00
Dmitriy Simushev
e61b91dd5e Describe "visitorTrack" event in Events class 2014-10-17 14:10:20 +00:00
Dmitriy Simushev
1814298f4f Create "Resource not found" event 2014-10-17 13:47:57 +00:00
Dmitriy Simushev
5c52ec61da Describe "accessDenied" event in Events class 2014-10-17 13:36:20 +00:00
Dmitriy Simushev
86f6d6429e Move "pageAdd*" events description to Events class 2014-10-17 13:15:53 +00:00
Dmitriy Simushev
31c4afe751 Remove jabber operator field 2014-10-17 12:48:28 +00:00
Dmitriy Simushev
a34cb53e91 Add event on operator create 2014-10-17 11:09:10 +00:00
Dmitriy Simushev
2dca8f236e Describe operators' events in one place 2014-10-17 10:54:04 +00:00
Dmitriy Simushev
55b7b28eb1 Move EventDispatcher class to a separate namespace 2014-10-17 09:47:03 +00:00
Dmitriy Simushev
919c71a1c1 Fix misssed semicolon in js test 2014-10-14 14:39:52 +00:00
Dmitriy Simushev
2d5d4b0e46 Remove unused "append_query" function 2014-10-14 14:38:54 +00:00
Dmitriy Simushev
2703f72de8 Fix localization of unknown strings on client 2014-10-14 12:36:23 +00:00
Dmitriy Simushev
7f071cbe80 Increase Mibew version 2014-10-14 11:19:24 +00:00
Dmitriy Simushev
55587f67fe Remove unused "jsString" Handlebars.php helper 2014-10-14 11:18:39 +00:00
Dmitriy Simushev
ae7ee06031 Increase cache ttl for handlebars templates 2014-10-14 11:16:55 +00:00
Dmitriy Simushev
3fbc5fa262 Always set focus on message input after message sent
Fixes #66
2014-10-14 11:03:20 +00:00
Dmitriy Simushev
397786991d Simplify plugins' assets attachment 2014-10-14 10:57:01 +00:00
Dmitriy Simushev
1a82e11b5e Use 500 as default weight for plugins assets 2014-10-14 10:23:40 +00:00
Dmitriy Simushev
71d2b234c6 Create Asset/Package class to reduce code duplication 2014-10-14 09:36:55 +00:00
Dmitriy Simushev
f8d4d074d5 Rename "styles/dialogs" to "styles/chats" 2014-10-13 13:52:17 +00:00
Dmitriy Simushev
6ac121bc01 Remove unused value 2014-10-13 13:34:28 +00:00
Dmitriy Simushev
452446a375 Initialize chat js application from controller 2014-10-13 13:30:07 +00:00
Dmitriy Simushev
dcd17ed01c Attach js files to chat page in "_layout" template 2014-10-13 12:41:11 +00:00
Dmitriy Simushev
8eaf93a916 Remove unused templates from the default chat style 2014-10-13 11:34:44 +00:00
Dmitriy Simushev
0d1efa5a87 Use cache for Handlebars AST 2014-10-13 11:20:05 +00:00
Dmitriy Simushev
d92b88b65a Initialize "thread_log" client side app from controller 2014-10-13 09:52:06 +00:00
Dmitriy Simushev
aee1aa6904 Initialize "users" client side app from controller 2014-10-13 09:23:43 +00:00
Dmitriy Simushev
5dafbd2997 Add weights to asset manager 2014-10-13 09:07:07 +00:00
Dmitriy Simushev
54b4814389 Attach js on updates page via controller 2014-10-10 12:38:00 +00:00
Dmitriy Simushev
d01bd8a080 Move thread log app initialization to controller 2014-10-10 12:25:53 +00:00
Dmitriy Simushev
3081dcc8db Remove js working with features fields from style files 2014-10-10 12:14:37 +00:00
Dmitriy Simushev
c86d7569f3 Remove js working with group fields from style files 2014-10-10 11:59:23 +00:00
Dmitriy Simushev
e8b35a6971 Move js attaching from install_done template to controller 2014-10-10 11:44:13 +00:00
Dmitriy Simushev
3339153ad3 Remove js with operator delete comfirm from style files 2014-10-10 11:24:54 +00:00
Dmitriy Simushev
ed6252bb38 Remove js with group delete comfirm from style files 2014-10-10 11:10:28 +00:00
Dmitriy Simushev
01e2d8f2a7 Remove js with ban delete comfirm from style files 2014-10-10 10:57:00 +00:00
Dmitriy Simushev
dd71e6bc70 Attach js and css assets to every operator's page 2014-10-10 10:33:08 +00:00
Dmitriy Simushev
46ee9df63a Use relative URL for assets as default 2014-10-10 10:17:41 +00:00
Dmitriy Simushev
922edc96d7 Replace inline js in the default page style with files 2014-10-10 09:15:50 +00:00
Dmitriy Simushev
a671caeb79 Move js code which auto close a window in a sepate file 2014-10-10 09:01:15 +00:00
Dmitriy Simushev
3088481d6d Remove unused "brws.js" lib 2014-10-10 08:38:37 +00:00
Dmitriy Simushev
00bba6c05a Create a base class for jsAssets and cssAssets helpers 2014-10-10 08:17:36 +00:00
Dmitriy Simushev
5b09b3e52c Rename "additionalJs" helper to "jsAssets" 2014-10-09 14:31:26 +00:00
Dmitriy Simushev
3772274ca3 Rename "additionalCss" helper to "cssAssets" 2014-10-09 14:27:35 +00:00
Dmitriy Simushev
7ce4d812bd Rename "AssetManager::add*Asset" methods to "attach*" 2014-10-09 14:20:40 +00:00
Dmitriy Simushev
2ed44e874c Clean up docs for Assetmanager::triggerJsEvent a little 2014-10-09 14:01:38 +00:00
Dmitriy Simushev
9898fb0cbe Create "additionalCss" HBS helper 2014-10-09 13:51:37 +00:00
Dmitriy Simushev
bc45a6d3be Create "additionalJs" HBS helper 2014-10-09 13:25:17 +00:00
Dmitriy Simushev
e320dcd1bb Create AssetManager class 2014-10-08 14:14:43 +00:00
Dmitriy Simushev
54840e96ad Move default js libraries to _layout.hbs in pages style 2014-10-07 11:02:31 +00:00
Dmitriy Simushev
406e11a38e Simplify client side templates structure of pages style 2014-10-06 10:38:33 +00:00
Dmitriy Simushev
a61b48252c Move request preparation and finalization to special methods 2014-10-06 09:06:11 +00:00
Dmitriy Simushev
952ebf8b9d Remove unneeded files from release archive
Fixes #67
2014-09-26 13:18:42 +00:00
Dmitriy Simushev
b6d472d62f Fix some typos in js 2014-09-26 09:24:49 +00:00
Dmitriy Simushev
0cd01e2c03 Remove unneeded "pageAddLocalizedStrings" event 2014-09-25 12:40:46 +00:00
Dmitriy Simushev
c3956be558 Move send shortcut string generation to the client side 2014-09-25 12:33:30 +00:00
Dmitriy Simushev
6e6920851d Remove almost all pseudo-localization strings 2014-09-25 11:51:04 +00:00
Dmitriy Simushev
022fe7d6f4 Purge cache on cron 2014-09-25 10:38:31 +00:00
Dmitriy Simushev
ba103d5636 Pass all localized string to a client side application 2014-09-25 10:30:19 +00:00
Dmitriy Simushev
a2e2f1b194 Use Stash as a cache system 2014-09-24 13:04:37 +00:00
Dmitriy Simushev
e514b1590b Pass AssetUrlGenerator via constructor to ControllerResolver 2014-09-23 13:10:35 +00:00
Dmitriy Simushev
2bb6899c33 Move translation logic from js helper to localization object 2014-09-19 13:51:59 +00:00
Dmitriy Simushev
cb4bd3acaa Add inheritance helpers to Handlebars.js 2014-09-18 15:00:57 +00:00
Dmitriy Simushev
fa615bc2e0 Add placeholders to HBS.js "l10n" helper 2014-09-18 10:35:08 +00:00
Dmitriy Simushev
957e67686a Refactor HelpersSet class 2014-09-18 09:42:50 +00:00
Dmitriy Simushev
911487871d Generate offline message in the template 2014-09-18 08:32:16 +00:00
Dmitriy Simushev
c397a953a1 Update Handlebars.php version 2014-09-17 14:54:04 +00:00
Dmitriy Simushev
e7b0201e0a Update Handlebars.js to v2.0.0 2014-09-15 14:32:34 +00:00
Dmitriy Simushev
340c0f9213 Update jQuery to v1.11.1 2014-09-12 13:14:20 +00:00
Dmitriy Simushev
db4e8ee0db Update Underscore.js to v1.7.0 2014-09-12 12:50:49 +00:00
Dmitriy Simushev
95caad6b59 Use "replace" helper instead of "nl2br" in HBS.js templates 2014-09-12 11:12:34 +00:00
Dmitriy Simushev
ae9de7aa92 Sanitize messages at server side 2014-09-12 10:59:56 +00:00
Dmitriy Simushev
ce6761755e Enforce HTML sanitization 2014-09-11 14:53:03 +00:00
Dmitriy Simushev
6154992f4f Remove "apply" Handlebars.js helper 2014-09-11 12:30:11 +00:00
Dmitriy Simushev
0b9fdeceb8 Fix number arguments in "allowTags" Handlebars.js helper 2014-09-11 12:15:19 +00:00
Dmitriy Simushev
34017d54db Fix number arguments in "urlReplace" Handlebars.js helper 2014-09-11 11:24:33 +00:00
Dmitriy Simushev
aa12eceeea Fix number arguments in "nl2br" Handlebars.js helper 2014-09-11 11:23:02 +00:00
Dmitriy Simushev
9805b4bb18 Add "replace" Handlebars.js helper 2014-09-11 11:08:34 +00:00
Dmitriy Simushev
333f769a16 Add "cutString" Handlebars.js helper 2014-09-11 10:09:14 +00:00
Dmitriy Simushev
75276ab2da Add "repeat" Handlebars.js helper 2014-09-11 10:06:30 +00:00
Dmitriy Simushev
814869ec77 Add tests for "ifEven" and "ifOdd" Handlebars.js helpers 2014-09-11 09:36:33 +00:00
Dmitriy Simushev
3f3abb4255 Add "ifEqual" Handlebars.js helper 2014-09-11 09:29:36 +00:00
Dmitriy Simushev
55a33cf012 Add "ifAny" Handlebars.js helper 2014-09-11 09:19:51 +00:00
Dmitriy Simushev
accfbe0acd Merge branch 'fix_comment' 2014-09-10 15:04:20 +00:00
94c1859a01 Fix comment for generated text link 2014-09-10 18:59:43 +04:00
Dmitriy Simushev
bbf1cec98c Remove unused "use" statement in the "ifOdd" helper 2014-09-10 14:15:14 +00:00
Dmitriy Simushev
ff72960382 Throw an exception if a HBS helper receives wrong arguments set 2014-09-10 14:13:16 +00:00
Dmitriy Simushev
61ee2d0af6 Fix invitation popup 2014-09-10 11:26:09 +00:00
Dmitriy Simushev
933d03e45a Increase Mibew version 2014-09-10 11:07:54 +00:00
Dmitriy Simushev
86085a0c31 Force Mibew to work without mod_rewrite 2014-09-10 10:56:06 +00:00
Dmitriy Simushev
7c969e495e Add RTL support to the default chat style
Fixes #64
2014-09-10 10:16:30 +00:00
Dmitriy Simushev
97ab17ce7a Update Symfony components version 2014-09-10 09:40:27 +00:00
Dmitriy Simushev
58959cf866 Fix problems with installation script 2014-09-09 10:07:43 +00:00
Dmitriy Simushev
7201dfd113 Remove MIBEW_WEB_ROOT constant 2014-09-08 14:08:44 +00:00
Dmitriy Simushev
a314bca69b Move "go online link" generation to Controller 2014-09-08 14:01:41 +00:00
Dmitriy Simushev
cb98a6fc94 Fix typo in comment 2014-09-08 12:39:09 +00:00
Dmitriy Simushev
f107ae4556 Configure plugins data with a request instead of a page name 2014-09-08 12:29:30 +00:00
Dmitriy Simushev
3a3b7f362b Add "asset" helper to the repository. 2014-09-08 09:54:53 +00:00
Dmitriy Simushev
ff917b25ad Do not use MIBEW_WEB_ROOT in Style classes 2014-09-05 10:59:48 +00:00
Dmitriy Simushev
dfbbc11cfb Apply asset helper to chat templates 2014-09-05 10:50:36 +00:00
Dmitriy Simushev
7c1e123ad6 Do not use style path for pagination generation 2014-09-05 10:26:47 +00:00
Dmitriy Simushev
84094ad38b Use divs instead of images for pagination arrows 2014-09-05 10:06:26 +00:00
Dmitriy Simushev
5a3a4d959f Use asset helper in pages style 2014-09-05 09:13:11 +00:00
Dmitriy Simushev
83f6c31dd6 Fix styles screeenshots 2014-09-04 15:11:52 +00:00
Dmitriy Simushev
e5031f9987 Use "mibewRoot" only in file paths 2014-09-04 12:53:13 +00:00
Dmitriy Simushev
0253f8e67e Remove unused use statement 2014-09-04 12:43:08 +00:00
Dmitriy Simushev
c207f0507d Use "route" helper to generate URLs in chat style 2014-09-04 12:26:18 +00:00
Dmitriy Simushev
6ceecb42aa Generate links for Users JS App in the controller 2014-09-04 12:12:30 +00:00
Dmitriy Simushev
f8bd639f39 Use stylePath variable instead of tplRoot in chat templates 2014-09-04 10:52:57 +00:00
Dmitriy Simushev
cf6e7f625a Fix URL for ban edit page 2014-09-04 10:38:17 +00:00
Dmitriy Simushev
cbc119382b Create a helper to generatate URLs with CSRF protection 2014-09-04 10:23:38 +00:00
Dmitriy Simushev
c08ab3a456 Use "route" helper in pages style 2014-09-03 15:19:27 +00:00
Dmitriy Simushev
09c7b15656 Move protected AbstractController::getStyle method to the end of the class 2014-09-03 11:56:53 +00:00
Dmitriy Simushev
5ee217accb Create "route" Handlebars.php helper 2014-09-03 11:52:37 +00:00
Dmitriy Simushev
eba2eadaca Reduce code duplication in Handlebars powered styles 2014-09-03 11:27:43 +00:00
Dmitriy Simushev
7021cb983e Move takeover confirmation page template to chat style 2014-08-29 12:55:41 +00:00
Dmitriy Simushev
37cc5cb178 Move Handlebars.php helpers to separate classes 2014-08-29 11:42:15 +00:00
Dmitriy Simushev
a5d7c6ccd4 Don't use MIBEW_WEB_ROOT in get_current_locale func 2014-08-28 12:15:59 +00:00
Dmitriy Simushev
766be1f051 Remove unused function "get_app_location" 2014-08-28 10:23:58 +00:00
Dmitriy Simushev
f61ef23e3f Don't use global environment in "setup_chatview_for_user" func 2014-08-28 10:22:17 +00:00
Dmitriy Simushev
896e0d924b Don't rely on internal Router structure 2014-08-28 09:52:48 +00:00
Dmitriy Simushev
1c1d479474 Don't use global environment in "setup_chatview_for_operator" func 2014-08-28 09:39:14 +00:00
Dmitriy Simushev
ee492a0c23 Extract release preparation stuff from default gulp task
Fixes #62
2014-08-28 08:40:08 +00:00
Dmitriy Simushev
da54de32b9 Remove unused "is_agent_opera95" function 2014-08-27 15:34:56 +00:00
Dmitriy Simushev
4ba7804b88 Make *Processor::handleRequest returns a Response 2014-08-27 13:44:01 +00:00
Dmitriy Simushev
928328f2b0 Set default value for Thread's agent ID when a thread is created 2014-08-27 13:28:01 +00:00
Dmitriy Simushev
730dd2f2df Make *Processor handles Symfony requests 2014-08-27 13:22:43 +00:00
Dmitriy Simushev
8b1b38dddc Set default operator's avatar
Fixes #60
2014-08-27 10:33:35 +00:00
Dmitriy Simushev
57770e76cf Remove unused needs_frame_src function 2014-08-26 14:53:21 +00:00
Dmitriy Simushev
aad2f6a34f Move button generating logic to separate classes 2014-08-26 12:03:58 +00:00
Dmitriy Simushev
3802e1bf0f Update Handlebars.php version 2014-08-26 09:39:14 +00:00
Dmitriy Simushev
c9e7971c41 Fix button size determination 2014-08-26 09:33:10 +00:00
Dmitriy Simushev
e97f3d1fbf Add secure URL generation for assets 2014-08-25 11:21:18 +00:00
Dmitriy Simushev
21c0ee9134 Move secure URL generation to the Router 2014-08-22 13:11:17 +00:00
Dmitriy Simushev
96df4dc857 Declare method visibility in ButtonCodeController 2014-08-21 11:38:45 +00:00
Dmitriy Simushev
c32628e2b2 Generate URLs from routes in HomeController 2014-08-21 11:37:17 +00:00
Dmitriy Simushev
df4b6f214e Add an easy way to generate assets URL 2014-08-21 11:33:38 +00:00
Dmitriy Simushev
f0f41cbfb6 Move all button generation logic to ButtonCodeController 2014-08-20 14:40:30 +00:00
Dmitriy Simushev
e9f480e3ef Add an ability to generate https routes 2014-08-20 13:00:03 +00:00
Dmitriy Simushev
82a3cb7dd5 Remove unused "verifyparam_groupid" function 2014-08-20 10:04:19 +00:00
Dmitriy Simushev
34a8a2eee4 Do not use MIBEW_WEB_ROOT in AvatarController 2014-08-20 09:50:39 +00:00
Dmitriy Simushev
e6b9635e22 Add project name to .pot file 2014-08-19 12:49:54 +00:00
Dmitriy Simushev
154e891cb4 Update Handlebars.php version 2014-08-18 14:40:24 +00:00
4fc223a6a6 Improve headers 2014-08-18 15:42:27 +04:00
Dmitriy Simushev
22a34c3315 Localize some strings related with files uploading 2014-08-18 09:46:26 +00:00
Dmitriy Simushev
51e076aafc Add more PHP's localization functions 2014-08-18 09:42:08 +00:00
Dmitriy Simushev
46a8345de2 Extract localization strings from js files 2014-08-18 09:23:15 +00:00
Dmitriy Simushev
17d7014da9 Rename Localization.get method on the client side 2014-08-18 09:11:40 +00:00
Dmitriy Simushev
7128870ef6 Fix notice about undefined "visitorid" in UserChatController 2014-08-13 14:09:35 +00:00
Dmitriy Simushev
48408c6547 Remove unused console scripts 2014-08-13 12:51:17 +00:00
Dmitriy Simushev
3ca9395d69 Search localization strings in .handlebars files 2014-08-13 12:14:35 +00:00
Dmitriy Simushev
95d2593b28 Update version of gulp-phpcs plugin 2014-08-13 11:03:03 +00:00
Dmitriy Simushev
02874adbd0 Do not include GIT repos of third-party libs to build 2014-08-13 09:04:44 +00:00
Dmitriy Simushev
f583aa6439 Add gulp task for .pot file generation 2014-08-13 08:40:42 +00:00
742 changed files with 28058 additions and 8798 deletions

24
.gitignore vendored
View File

@ -1,6 +1,11 @@
# IDE folders
.idea
src/mibew/install/package
src/absent_*
src/release*
src/upload*
src/*.po
# Do not index actual configuration files
src/mibew/configs/config.yml
@ -10,6 +15,11 @@ src/tests/server_side/mibew/libs/config.php
src/mibew/files/avatar/*
!src/mibew/files/avatar/.keep
# Do not index cache files
src/mibew/cache/*
!src/mibew/cache/.keep
!src/mibew/cache/.htaccess
# Do not index plugins
src/mibew/plugins/*
!src/mibew/plugins/.keep
@ -24,20 +34,22 @@ src/composer.lock
# Do not index third-party libraries
src/mibew/vendor
src/mibew/js/vendor
# Do not index node.js modules that are used for building
src/node_modules
src/package-lock.json
# Do not index compiled js files of the core
src/mibew/js/compiled/*
!src/mibew/js/compiled/.keep
# Do not index compiled files of chat styles
src/mibew/styles/dialogs/default/templates_compiled/client_side/*
!src/mibew/styles/dialogs/default/templates_compiled/client_side/.keep
src/mibew/styles/dialogs/default/js/compiled/*
!src/mibew/styles/dialogs/default/js/compiled/.keep
src/mibew/styles/chats/*/templates_compiled/client_side/*
!src/mibew/styles/chats/*/templates_compiled/client_side/.keep
src/mibew/styles/chats/*/js/compiled/*
!src/mibew/styles/chats/*/js/compiled/.keep
# Do not index compiled files of page styles
src/mibew/styles/pages/default/templates_compiled/client_side/*
!src/mibew/styles/pages/default/templates_compiled/client_side/.keep
src/mibew/styles/pages/*/templates_compiled/client_side/*
!src/mibew/styles/pages/*/templates_compiled/client_side/.keep

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "src/i18n"]
path = src/i18n
url = git@github.com:Mibew/i18n.git

12
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,12 @@
### Environment
* Mibew Messenger version:
* OS:
* Web server:
* PHP:
* PHP extensions:
* MySQL:
### Expected behavior
### Actual behavior
### Steps to reproduce the behavior

1
LICENSE Symbolic link
View File

@ -0,0 +1 @@
./src/mibew/LICENSE.txt

8
PULL_REQUEST_TEMPLATE.md Normal file
View File

@ -0,0 +1,8 @@
Fixes # .
Changes proposed in this pull request:
-
-
-
@Mibew/core-developers

View File

@ -11,7 +11,7 @@ This repository contains the core of Mibew Messenger application.
## Server requirements
1. A webserver or web hosting account running on any major Operating System
2. PHP (5.3.3 and above) with MySQL support
2. PHP (7.2.5 and above) with PDO, pdo_mysql, cURL, mbstring and gd extensions
3. MySQL 5.0 and above
## Build from sources
@ -33,7 +33,39 @@ Mibew Messenger is licensed under the terms of [Apache License, Version 2.0](htt
## Other repositories of the Mibew project
### Actual
1. [Mibew Messenger i18n repository](https://github.com/Mibew/i18n)
2. [Mibew Messenger design repository](https://github.com/Mibew/design)
3. [Mibew Java applications repository](https://github.com/Mibew/java)
4. [Mibew Tray repository](https://github.com/Mibew/tray)
3. [Mibew documentation repository](https://github.com/Mibew/docs.mibew.org)
### Obsolete
1. [Mibew Java applications repository](https://github.com/Mibew/java)
2. [Mibew Tray repository](https://github.com/Mibew/tray)
### Plugins
1. [Mibew Boilerplate plugin](https://github.com/Mibew/boilerplate-plugin) - a template for a real plugin
#### Ready for production use
1. [Mibew Advanced Button plugin](https://github.com/Mibew/advanced-button-plugin)
2. [Mibew Auto Invite plugin](https://github.com/Mibew/auto-invite-plugin)
3. [Mibew Auto Reply plugin](https://github.com/Mibew/auto-reply-plugin)
4. [Mibew Broadcast plugin](https://github.com/Mibew/broadcast-plugin)
5. [Mibew Bulk Logs Operations plugin](https://github.com/Mibew/bulk-logs-operations-plugin)
6. [Mibew Button Refresh plugin](https://github.com/Mibew/button-refresh-plugin)
7. [Mibew Emoji plugin](https://github.com/Mibew/emoji-plugin)
8. [Mibew Filter Visitors By Operator Code plugin](https://github.com/Mibew/filter-visitors-by-operator-code-plugin)
9. [Mibew First Message plugin](https://github.com/Mibew/first-message-plugin)
10. [Mibew Geo IP plugin](https://github.com/Mibew/geo-ip-plugin)
11. [Mibew Google Maps plugin](https://github.com/Mibew/google-maps-plugin)
12. [Mibew Open Street Map plugin](https://github.com/Mibew/open-street-map-plugin)
13. [Mibew Operator Status plugin](https://github.com/Mibew/mibew-operator-status-plugin)
14. [Mibew Purge History plugin](https://github.com/Mibew/purge-history-plugin)
15. [Mibew Real Ban plugin](https://github.com/Mibew/real-ban-plugin)
16. [Mibew Slack plugin](https://github.com/Mibew/mibew_slack)
17. [Mibew Title Notification plugin](https://github.com/Mibew/title-notification-plugin)
#### Not ready for production use (not stable, broken, obsolete, etc.)
1. [Mibew External API plugin](https://github.com/Mibew/external-api-plugin)

4
src/.bowerrc Normal file
View File

@ -0,0 +1,4 @@
{
"directory": "./mibew/js/vendor",
"analytics": false
}

27
src/.eslintrc Normal file
View File

@ -0,0 +1,27 @@
{
"extends": "eslint:recommended",
"rules": {
"indent": ["error", 4, {"SwitchCase": 1}],
"no-trailing-spaces": "error",
"semi": ["error", "always"],
"guard-for-in": "error",
"no-unused-vars": ["error", {"caughtErrors": "none", "args": "none"}]
},
"globals": {
"Mibew": true,
"MibewAPI": true,
"MibewAPIInteraction": true,
"MibewAPIChatInteraction": true,
"MibewAPIUsersInteraction": true,
"MibewAPIExecutionContext": true,
"Handlebars": true,
"_": true,
"Backbone": true,
"jQuery": true,
"vex": true,
"validator": true
},
"env":{
"browser": true
}
}

17
src/bower.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "mibew",
"private": true,
"dependencies": {
"underscore": "1.8.2",
"json": "https://github.com/douglascrockford/JSON-js.git#c98948ae1944a28e2e8ebc3717894e580aeaaa05",
"jquery": "1.11.3",
"backbone": "1.1.2",
"marionette": "2.4.1",
"handlebars": "4.3.0",
"vex": "2.3.2",
"validator-js": "3.40.0"
},
"resolutions": {
"underscore": "1.8.2"
}
}

View File

@ -1,56 +0,0 @@
#!/usr/bin/perl
sub read_transl($) {
my($from) = @_;
my %translation = ();
open(IN, "mibew/locales/$from/properties");
while(<IN>) {
chomp;
if(/^([\w\.]+)=(.*)$/) {
if($1 ne "encoding" && $1 ne "output_charset" && $1 ne "output_encoding") {
$translation{$1} = $2;
}
} else {
die "wrong line in $from: $_\n";
}
}
close(IN);
return %translation;
}
%tr_en = read_transl("en");
@all_keys = keys %tr_en;
sub check_transl($%) {
my($name,%tr) = @_;
print "checking $name...\n";
my @totransl = ();
for $key (@all_keys) {
unless(exists $tr{$key}) {
push @totransl, "$key=".$tr_en{$key};
}
}
for $key(keys %tr) {
unless(exists $tr_en{$key}) {
print "unknown key in $name: $key\n";
}
}
if($#totransl >= 0) {
print "@{[$#totransl+1]} lines absent in locales/$name/properties\n";
open(OUT, "> absent_$name");
for(sort @totransl) {
print OUT "$_\n";
}
close(OUT);
}
}
check_transl("ru", read_transl("ru"));
check_transl("fr", read_transl("fr"));
check_transl("de", read_transl("de"));
check_transl("sp", read_transl("sp"));
check_transl("it", read_transl("it"));
check_transl("pl", read_transl("pl"));
check_transl("zh-tw", read_transl("zh-tw"));

View File

@ -1,32 +1,49 @@
{
"name": "mibew/mibew",
"version": "2.0-dev",
"version": "3.6.0",
"description": "Mibew Messenger - open-source live support application",
"type": "project",
"homepage": "http://mibew.org",
"homepage": "https://mibew.org",
"license": "Apache-2.0",
"authors": [
{
"name": "Mibew Messenger Project",
"homepage": "http://mibew.org/credits"
"homepage": "https://mibew.org/credits"
}
],
"support": {
"email": "support@mibew.org",
"issues": "https://github.com/mibew/mibew/issues",
"forum": "http://mibew.org/forums",
"forum": "https://mibew.org/forums",
"source": "https://github.com/mibew/mibew"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/mibew/handlebars.php"
},
{
"type": "vcs",
"url": "https://github.com/mibew/handlebars.php-helpers"
}
],
"require": {
"xamin/handlebars.php": "dev-master#cd8cec42a048ba0d8c7dd0bfde39b973b6a14b3f",
"symfony/http-foundation": "2.4.*",
"symfony/routing": "2.4.*",
"symfony/config": "2.4.*",
"symfony/yaml": "2.4.*",
"symfony/translation": "2.4.*"
"mibew/handlebars.php": "~0.10.5",
"mibew/handlebars.php-helpers": "1.*",
"symfony/http-foundation": "4.4.*",
"symfony/routing": "4.4.*",
"symfony/config": "4.4.*",
"symfony/yaml": "^5.2",
"symfony/translation": "2.6.*",
"tedivm/stash": "0.12.*",
"mibew/html5": "1.1.*",
"vierbergenlars/php-semver": "3.0.*",
"swiftmailer/swiftmailer": "~5.4.0",
"ua-parser/uap-php": "^3.9",
"true/punycode": "~1.1"
},
"require-dev": {
"squizlabs/php_codesniffer": "1.*"
"squizlabs/php_codesniffer": "3.*"
},
"config": {
"vendor-dir": "mibew/vendor"

View File

@ -1,245 +0,0 @@
#!/usr/bin/perl
use Digest::MD5 qw(md5 md5_hex md5_base64);
@rules = (
["redirect(ed)?\\.tpl", 1],
["\\.tpl", 0],
["view/license.php", 0],
["view/themes.php", 2],
["view/translate.php", 2],
["view/translatelist.php", 2],
["view/settings.php", 2],
["view/updates.php", 2],
["view/features.php", 2],
["view/performance.php", 2],
["view/avatar.php", 2],
["view/permissions.php", 2],
["view/agent.php", 2],
["view/agents.php", 2],
["view/group.php", 2],
["view/groupmembers.php", 2],
["view/groups.php", 2],
["view/operator_groups.php", 2],
["view/gen_button.php", 2],
["view/install_err.php", 2],
["view/install_index.php", 2],
["view/.*\\.php", 1],
["install/.*\\.php", 2],
["operator/themes.php", 2],
["operator/translate.php", 2],
["operator/settings.php", 2],
["operator/updates.php", 2],
["operator/features.php", 2],
["operator/performance.php", 2],
["operator/avatar.php", 2],
["operator/permissions.php", 2],
["operator/operator.php", 2],
["operator/operators.php", 2],
["operator/group.php", 2],
["operator/groupmembers.php", 2],
["operator/groups.php", 2],
["operator/opgroups.php", 2],
["operator/getcode.php", 2],
["operator/.*\\.php", 1],
["mibew/client.php", 0],
["mibew/leavemessage.php", 0],
["mibew/captcha.php", 0],
["mibew/license.php", 0],
["mibew/mail.php", 0],
["libs/operator_settings.php", 2],
["mibew/libs/chat.php", 0],
["libs/pagination.php", 1],
["libs/settings.php", 2],
["libs/groups.php", 2],
["libs/demothread.php", 2],
["mibew/thread.php", 0],
["mibew/b.php", 0],
["mibew/button.php", 0],
["mibew/index.php", 0],
["mibew/libs/.*\\.php", 1],
);
%messagekeys = (
"localeid" => 0,
"output_charset" => 0,
"output_encoding" => 0,
"harderrors.header" => 0,
"errors.required" => 0,
"errors.wrong_field" => 0,
"errors.file.move.error" => 2,
"errors.invalid.file.type" => 2,
"errors.file.size.exceeded" => 2,
"permission.admin" => 1,
"permission.takeover" => 1,
"permission.viewthreads" => 1,
"chat.thread.state_chatting_with_agent" => 1,
"chat.thread.state_closed" => 1,
"chat.thread.state_loading" => 1,
"chat.thread.state_wait" => 1,
"chat.thread.state_wait_for_another_agent" => 1,
"clients.queue.chat" => 1,
"clients.queue.prio" => 1,
"clients.queue.wait" => 1,
);
$mibewPath = "mibew";
%urls = ();
%usermessages = ();
%operatormessages = ();
$current_level = 0;
sub usemsg($) {
my ($m) = @_;
$messagekeys{$m} = exists $messagekeys{$m} && $messagekeys{$m} < $current_level ? $messagekeys{$m} : $current_level;
if($current_level == -1) {
print " .. $m\n";
}
}
sub file_content($) {
my $input = $_[0];
open( IN1, "< $input" ) or die "cannot find file $input";
my $oldslash = $/;
$/ = EOI;
$content = <IN1>;
close( IN1 );
if($content =~ s/\r//g) {
open( OUT1, "> $input") or die "cannot fix $input";
print OUT1 $content;
close(OUT1);
}
$/ = $oldslash;
return $content;
}
sub process_tpl($) {
my ($filename) = @_;
my $m = file_content($filename);
while( $m =~ /\${msg:([\w\.]+)(,[\w\.]+)?}/g ) {
usemsg($1);
}
while( $m =~ /\${url:([\w\.]+)(,[\w\.]+)?}/g ) {
usemsg($1);
$urls{"%$1"} = 1;
}
}
sub process_php($) {
my ($source) = @_;
my $content = file_content($source);
$content =~ s/<\?xml version=\\"1\.0\\" encoding=\\"UTF-8\\"\?>//;
while( $content =~ s/<\?(?!xml)(.*?)\?>//s ) {
my $inner = $1;
while($inner =~ s/(getlocal|no_field)2?_?\((.*?)[,\)]//s) {
my $firstarg = $2;
if( $firstarg =~ /^["']([\w\.]+)['"]$/) {
usemsg($1);
} elsif($firstarg =~ /^\$\w+$/ || $firstarg eq '"$var.header"' || $firstarg eq '"permission.$permid"' || $firstarg eq '$threadstate_key[$thread[\'istate\']]') {
# skip
} else {
print "> unknown: $firstarg\n";
}
}
}
}
sub file_checksum($) {
my ($source) = @_;
if($source =~ /\.(png|gif|jpg|ico|wav)$/ || $source =~ /config\.php$/) {
return "-";
}
my $content = file_content($source);
return md5_hex($content);
}
@allsources = ();
sub process_one($) {
my($source) = @_;
push @allsources, $source unless $source =~ /$mibewPath\/locales/ && $source !~ /$mibewPath\/locales\/(en|names)/ || $source =~ /\/package$/;
if($source !~ /\.(php|tpl)$/) {
return;
}
$current_level = -1;
A: foreach $rule (@rules) {
my $key = $$rule[0];
if($source =~ /$key/) {
$current_level = $$rule[1];
last A;
}
}
if($current_level < 0 || $current_level > 2) {
print "not detected for: $source\n";
$current_level = 0;
}
if($source =~ /\.php$/) {
# print "$source ($current_level)\n";
process_php($source);
} elsif($source =~ /\.tpl$/) {
process_tpl($source);
} else {
#print ". $source\n";
}
}
sub process_files($) {
my($from) = @_;
opendir(DIR, $from) || die "can't opendir $from: $!";
my @content = readdir(DIR);
closedir DIR;
for(grep { -f "$from/$_" && ($_ !~ /^\./ || $_ eq ".htaccess") } @content) {
process_one("$from/$_");
}
for(grep { -d "$from/$_" && $_ !~ /^\./ } @content) {
process_files("$from/$_");
}
}
process_files($mibewPath);
# fix
$messagekeys{'page.analysis.userhistory.title'} = 1;
$messagekeys{'errors.failed.uploading.file'} = 2;
open( OUT, "> $mibewPath/locales/names/level1") or die "cannot write file, $!";
for $key(sort grep { $messagekeys{$_} == 0 } keys %messagekeys) {
print OUT "$key\n";
}
close( OUT );
open( OUT, "> $mibewPath/locales/names/level2") or die "cannot write file, $!";
for $key(sort grep { $messagekeys{$_} == 1 } keys %messagekeys) {
print OUT "$key\n";
}
close( OUT );
open( OUT, "> $mibewPath/install/package") or die "cannot write file, $!";
for $key(sort @allsources) {
$digest = file_checksum($key);
$key =~ s/$mibewPath\///;
print OUT "$key $digest\n";
}
close( OUT );

View File

@ -1,60 +1,124 @@
// Initialize requirements
var fs = require('fs'),
https = require('https'),
exec = require('child_process').exec,
eventStream = require('event-stream'),
runSequence = require('run-sequence'),
runSequence = require('gulp4-run-sequence'),
through = require('through2'),
lodash = require('lodash'),
PoFile = require('pofile'),
strftime = require('strftime'),
del = require('del'),
bower = require('bower'),
gulp = require('gulp'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
phpcs = require('gulp-phpcs'),
order = require('gulp-order'),
handlebars = require('gulp-handlebars'),
handlebarsEngine = require('handlebars'),
defineModule = require('gulp-define-module'),
header = require('gulp-header'),
zip = require('gulp-zip'),
tar = require('gulp-tar'),
gzip = require('gulp-gzip'),
chmod = require('gulp-chmod');
chmod = require('gulp-chmod'),
xgettext = require('gulp-xgettext'),
concatPo = require('gulp-concat-po'),
rename = require('gulp-rename'),
eslint = require('gulp-eslint'),
removeDuplicateHeaders = require('mibew-gulp-greh'),
mkdirp = require('mkdirp');
// Set global configs.
// Set global configuration
var config = {
mibewPath: 'mibew',
configsPath: 'mibew/configs',
phpVendorPath: 'mibew/vendor',
jsVendorPath: 'mibew/js/vendor',
pluginsPath: 'mibew/plugins',
avatarsPath: 'mibew/files/avatar',
cachePath: 'mibew/cache',
jsPath: 'mibew/js',
chatStylesPath: 'mibew/styles/dialogs',
chatStylesPath: 'mibew/styles/chats',
pageStylesPath: 'mibew/styles/pages',
i18nPath: 'i18n',
i18nPrefix: 'mibew-i18n-',
releasePath: 'release',
uploadPath: 'upload',
compiledTemplatesHeader: fs.readFileSync('tools/compiled_templates_header.txt'),
getComposerUrl: 'https://getcomposer.org/installer',
phpBin: 'php -d "suhosin.executor.include.whitelist = phar"',
package: require('./package.json')
phpBin: 'php -d "suhosin.executor.include.whitelist = phar" -d "memory_limit=512M"',
package: require('./composer.json'),
msginit: 'msginit',
msgcat: 'msgcat'
}
config.i18nSuffix = '-' + config.package.version + '-' + strftime('%Y%m%d');
// Tasks for cleaning //////////////////
// Checks all PHP files with PHP Code Sniffer.
gulp.task('phpcs', ['composer-install-dev'], function() {
return gulp.src([
config.mibewPath + '/**/*.php',
'!' + config.phpVendorPath + '/**/*.*',
'!' + config.pluginsPath + '/**/*.*'
])
.pipe(phpcs({
bin: config.phpVendorPath + '/bin/phpcs',
standard: 'PSR2',
warningSeverity: 0
}));
// Cleans all built files
gulp.task('clean', function(callback) {
return del([
config.releasePath,
'composer.lock',
config.phpVendorPath,
config.jsVendorPath,
config.jsPath + '/compiled/**/*',
'!' + config.jsPath + '/compiled/.keep',
config.chatStylesPath + '/*/templates_compiled/client_side/*.js',
config.chatStylesPath + '/*/js/compiled/*.js',
config.pageStylesPath + '/*/templates_compiled/client_side/*.js'
], callback);
});
// Cleans temporary English translation in the release dir
gulp.task('clean-tmp-po', function(callback) {
return del([config.releasePath + '/translation.po'], callback);
});
// Cleans temporary files of translations in the release dir
gulp.task('clean-tmp-i18n-files', function(callback) {
return del([
config.releasePath + '/**/*',
'!' + config.releasePath + '/*.zip',
'!' + config.releasePath + '/*.tar.gz',
'!' + config.releasePath + '/*.pot'
], callback);
});
// Cleans all files prepared for uploading to CDN
gulp.task('clean-upload', function(callback) {
return del([config.uploadPath], callback);
});
// Cleans everything
gulp.task('clean-all', function(callback) {
runSequence( ['clean', 'clean-upload'],
callback );
});
// Watcher tasks ///////////////////////
// Watch styles
gulp.task('watch', function() {
gulp.watch(config.pageStylesPath + '/**/*.handlebars', gulp.series('page-styles'));
gulp.watch(config.chatStylesPath + '/**/js/source/**/*.js', gulp.series('chat-styles-js'));
gulp.watch(config.chatStylesPath + '/**/*.handlebars', gulp.series('chat-styles-handlebars'));
});
// Service tasks //////////////////
// Get and install PHP Composer
gulp.task('get-composer', function(callback) {
// Check if Composer already in place
// Check whether Composer is already in place
if (fs.existsSync('./composer.phar')) {
callback(null);
return;
}
// Get installer from the internet
// Get installer from the Internet
https.get(config.getComposerUrl, function(response) {
// Run PHP to install Composer
var php = exec(config.phpBin, function(error, stdout, stderr) {
@ -66,20 +130,107 @@ gulp.task('get-composer', function(callback) {
});
// Install Composer dependencies excluding development ones
gulp.task('composer-install', ['get-composer'], function(callback) {
exec(config.phpBin + ' composer.phar install --no-dev', function(error, stdout, stderr) {
callback(error ? stderr : null);
});
});
gulp.task('composer-install', gulp.series('get-composer', function(callback) {
exec(config.phpBin + ' composer.phar install --no-dev',
function(error, stdout, stderr) {
callback(error ? stderr : null);
});
}));
// Install all Composer dependencies
gulp.task('composer-install-dev', ['get-composer'], function(callback) {
exec(config.phpBin + ' composer.phar install', function(error, stdout, stderr) {
callback(error ? stderr : null);
});
gulp.task('composer-install-dev', gulp.series('get-composer', function(callback) {
exec(config.phpBin + ' composer.phar install',
function(error, stdout, stderr) {
callback(error ? stderr : null);
});
}));
// Installs bower dependencies
gulp.task('bower-install', function(callback) {
bower.commands.install([], {}, {})
.on('error', function(error) {
callback(error);
})
.on('end', function() {
// We should manually minify JavaScript files that was not minified
// by bower packages' authors
// TODO: This is a temproary workaround and should be removed once
// the packages will be fixed
var stream = eventStream.merge(
gulp.src(config.jsVendorPath + '/backbone/backbone.js',
{base: config.jsVendorPath})
.pipe(uglify({preserveComments: 'some'}))
// There are neither "@license" tag nor "!preserve" in the
// header. Add the header manually
.pipe(header(
"// Backbone.js 1.1.2\n"
+ "// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n"
+ "// Backbone may be freely distributed under the MIT license.\n"
+ "// For all details and documentation:\n"
+ "// http://backbonejs.org\n"
))
.pipe(rename('backbone/backbone-min.js')),
gulp.src(config.jsVendorPath + '/json/json2.js',
{base: config.jsVendorPath})
.pipe(uglify({preserveComments: 'some'}))
// There are neither "@license" tag nor "!preserve" in the
// header, add the header manually
.pipe(header("// json2.js. Public Domain. See http://www.JSON.org/js.html\n"))
.pipe(rename('json/json2.min.js'))
)
.pipe(gulp.dest(config.jsVendorPath));
stream
.on('error', callback)
.on('end', callback);
});
});
// Compile all JavaScript files of the Mibew Core
// Tasks for checking //////////////////
// Checks all PHP files with PHP Code Sniffer
gulp.task('phpcs', gulp.series('composer-install-dev', function() {
return gulp.src([
config.mibewPath + '/**/*.php',
'!' + config.phpVendorPath + '/**/*.*',
'!' + config.pluginsPath + '/**/*.*',
'!' + config.cachePath + '/**/*.*'
], {
// Content of the cache directory is readable only for webserver.
// Thus we must to set "strict" option to false to prevent "EACCES"
// errors. At the same we need to see all errors that take place.
strict: false,
silent: false
})
.pipe(phpcs({
bin: config.phpVendorPath + '/bin/phpcs',
standard: 'PSR2',
warningSeverity: 0
}))
.pipe(phpcs.reporter('log'))
.pipe(phpcs.reporter('fail'));
}));
// Checks all JavaScript Source files with ESLint
gulp.task('eslint', function() {
return gulp.src(config.jsPath + '/source/**/*.js')
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
// Restore empty English translation in the source code
gulp.task('post-pack-cleanup', function(callback) {
gulp.src('translation.po')
.pipe(gulp.dest(config.mibewPath + '/locales/en/'));
del(['translation.po', config.releasePath + '/translation.po'], callback);
});
// Tasks of compiling //////////////////
// Compile all JavaScript files of the Mibew Messenger Core
gulp.task('js', function() {
return eventStream.merge(
getClientSideApp('default'),
@ -89,91 +240,376 @@ gulp.task('js', function() {
gulp.src(config.jsPath + '/source/**/*.js')
)
.pipe(uglify({preserveComments: 'some'}))
.pipe(removeDuplicateHeaders())
.pipe(gulp.dest(config.jsPath + '/compiled'));
});
// Performs all job related with chat styles.
gulp.task('chat-styles', ['chat-styles-handlebars', 'chat-styles-js'], function() {
// This task is just a combination of other tasks. That is why there is no
// real code.
});
// Compile and concatenate handlebars files for all chat styles.
// Compile and concatenate Handlebars templates for all chat styles
gulp.task('chat-styles-handlebars', function() {
// TODO: Process all available styles, not only the default one.
var stylePath = config.chatStylesPath + '/default';
return gulp.src(stylePath + '/templates_src/client_side/**/*.handlebars')
.pipe(handlebars())
.pipe(wrapHandlebarsTemplate())
.pipe(concat('templates.js'))
.pipe(uglify({preserveComments: 'some'}))
.pipe(header(config.compiledTemplatesHeader))
.pipe(gulp.dest(stylePath + '/templates_compiled/client_side'));
return getChildDirs(config.chatStylesPath)
.then(function (dirs) {
return Promise.all(dirs.map(function (dir) {
return new Promise(function(resolve, reject) {
gulp.src(config.chatStylesPath + '/' + dir
+ '/templates_src/client_side/**/*.handlebars')
.pipe(handlebars({
// Use specific version of Handlebars.js
handlebars: handlebarsEngine
}))
.pipe(wrapHandlebarsTemplate())
.pipe(concat('templates.js'))
.pipe(uglify({preserveComments: 'some'}))
.pipe(header(config.compiledTemplatesHeader))
.pipe(gulp.dest(config.chatStylesPath + '/' + dir
+ '/templates_compiled/client_side'))
.on('end', resolve)
.on('error', reject);
});
}));
});
});
// Compile and concatenate js files for all chat styles.
// Compile and concatenate js files for all chat styles
gulp.task('chat-styles-js', function() {
// TODO: Process all available styles, not only the default one.
var stylePath = config.chatStylesPath + '/default';
return gulp.src(stylePath + '/js/source/**/*.js')
.pipe(concat('scripts.js'))
.pipe(uglify({preserveComments: 'some'}))
.pipe(gulp.dest(stylePath + '/js/compiled'));
return getChildDirs(config.chatStylesPath)
.then(function (dirs) {
return Promise.all(dirs.map(function (dir) {
return new Promise(function(resolve, reject) {
gulp.src(config.chatStylesPath + '/' + dir
+ '/js/source/**/*.js')
.pipe(concat('scripts.js'))
.pipe(uglify({preserveComments: 'some'}))
.pipe(gulp.dest(config.chatStylesPath + '/' + dir
+ '/js/compiled'))
.on('end', resolve)
.on('error', reject);
});
}));
});
});
// Performs all job related with pages styles.
// Performs all job related to pages styles
gulp.task('page-styles', function() {
// TODO: Process all available styles, not only the default one.
var stylePath = config.pageStylesPath + '/default';
return eventStream.merge(
gulp.src(stylePath + '/templates_src/client_side/default/**/*.handlebars')
.pipe(handlebars())
.pipe(wrapHandlebarsTemplate())
.pipe(concat('default_app.tpl.js')),
gulp.src(stylePath + '/templates_src/client_side/users/**/*.handlebars')
.pipe(handlebars())
.pipe(wrapHandlebarsTemplate())
.pipe(concat('users_app.tpl.js'))
)
.pipe(uglify({preserveComments: 'some'}))
.pipe(header(config.compiledTemplatesHeader))
.pipe(gulp.dest(stylePath + '/templates_compiled/client_side'));
return getChildDirs(config.pageStylesPath)
.then(function (dirs) {
return Promise.all(dirs.map(function (dir) {
return new Promise(function(resolve, reject){
gulp.src(config.pageStylesPath + '/' + dir
+ '/templates_src/client_side/**/*.handlebars')
.pipe(handlebars({
// Use specific version of Handlebars.js
handlebars: handlebarsEngine
}))
.pipe(wrapHandlebarsTemplate())
.pipe(concat('templates.js'))
.pipe(uglify({preserveComments: 'some'}))
.pipe(header(config.compiledTemplatesHeader))
.pipe(gulp.dest(config.pageStylesPath + '/' + dir
+ '/templates_compiled/client_side'))
.on('end', resolve)
.on('error', reject);
});
}));
});
});
// Pack sources to .zip and .tar.gz archives.
gulp.task('pack-sources', ['composer-install'], function() {
var sources = config.mibewPath + '/**/*',
version = config.package.version;
// Performs all job related to chat styles
gulp.task('chat-styles', gulp.series('chat-styles-handlebars', 'chat-styles-js'));
return eventStream.merge(
gulp.src(sources, {dot: true})
.pipe(zip('mibew-' + version + '.zip')),
gulp.src(sources, {dot: true})
.pipe(tar('mibew-' + version + '.tar'))
.pipe(gzip())
)
.pipe(chmod(0644))
.pipe(gulp.dest('release'));
});
// Builds all the sources
gulp.task('default', function(callback) {
// Prepares ready to use development version of Mibew Messenger without
// packing or validating it
gulp.task('rebuild', function(callback) {
runSequence(
['phpcs', 'js', 'chat-styles', 'page-styles'],
'pack-sources',
'clean',
['js', 'chat-styles', 'page-styles', 'composer-install',
'bower-install'],
callback
);
});
// Tasks for localization issues ///////
// Generate POT-file based upon the source code
gulp.task('generate-pot', function() {
return eventStream.merge(
gulp.src([
config.mibewPath + '/**/*.php',
'!' + config.phpVendorPath + '/**/*.*',
'!' + config.pluginsPath + '/**/*.*',
'!' + config.cachePath + '/**/*.*'
], {
// Content of the cache directory is readable only for
// webserver. Thus we must to set "strict" option to false
// to prevent "EACCES" errors. At the same we need to see all
// errors that take place.
strict: false,
silent: false
})
.pipe(xgettext({
language: 'PHP',
keywords: [
{name: 'getlocal'},
{name: 'no_field'},
{name: 'wrong_field'},
{name: 'failed_uploading_file', singular: 2}
]
})),
gulp.src(config.jsPath + '/source/**/*.js', {base: config.mibewPath})
.pipe(xgettext({
language: 'JavaScript',
keywords: [
{name: 'trans'}
]
})),
gulp.src([
config.chatStylesPath + '/default/templates_src/**/*.handlebars',
config.pageStylesPath + '/default/templates_src/**/*.handlebars'
], {base: config.mibewPath})
.pipe(xgettextHandlebars())
)
.pipe(concatPo(config.i18nPrefix + 'translation'
+ config.i18nSuffix + '.pot',
{
headers: {
'Project-Id-Version': 'Mibew Messenger '
+ config.package.version,
'Report-Msgid-Bugs-To': config.package.support.email,
'POT-Creation-Date': strftime('%Y-%m-%d %H:%M%z'),
'PO-Revision-Date': '',
'Last-Translator': '',
'Language-Team': '',
'Content-Type': 'text/plain; charset=UTF-8'
}
})
)
.pipe(gulp.dest(config.releasePath));
});
// Generate temporary English translation to be used in the release
gulp.task('generate-tmp-po', gulp.series('generate-pot', function(callback) {
return exec(config.msginit + ' --no-translator --no-wrap -i '
+ config.releasePath + '/' + config.i18nPrefix + 'translation'
+ config.i18nSuffix + '.pot' + ' -l en -o '
+ config.releasePath + '/translation.po',
function(error, stdout, stderr) {
callback(error ? stderr : null);
});
}));
// Generate complete translations (that includes missed strings) to be used
// in the release
gulp.task('generate-pos', gulp.series('generate-tmp-po', function(callback) {
return getChildDirs(config.i18nPath + '/translations')
.then(function (dirs) {
return Promise.all(dirs.map(function (dir) {
return new Promise(function(resolve, reject) {
mkdirp(config.releasePath + '/' + dir, function (error) {
if (error) {
reject(error);
}
});
exec(config.msgcat + ' ' + config.i18nPath + '/translations/'
+ dir + '/translation.po ' + config.releasePath
+ '/translation.po --no-location --no-wrap --use-first'
+ ' -o ' + config.releasePath + '/' + dir
+ '/translation.po',
function(error, stdout, stderr) {
if (error) {
reject(error);
}
});
var sources = [
config.i18nPath + '/translations/' + dir + '/**/*',
'!' + config.i18nPath + '/translations/' + dir
+ '/translation.po'
];
gulp.src(sources)
.pipe(gulp.dest(config.releasePath + '/' + dir))
.on('error', reject)
.on('end', resolve);
});
}));
});
}));
// Packaging tasks /////////////////////
// Pack sources for release as .zip and .tar.gz archives
gulp.task('pack-sources', gulp.series('composer-install', 'bower-install', function() {
gulp.src(config.mibewPath + '/locales/en/translation.po')
.pipe(gulp.dest('.'));
gulp.src(config.releasePath + '/translation.po')
.pipe(gulp.dest(config.mibewPath + '/locales/en/'));
var sources = [
config.mibewPath + '/**/*',
// Exclude user's config
'!' + config.configsPath + '/config.yml',
// Exclude cache files but not the ".keep" file.
'!' + config.cachePath + '/**/!(.keep)',
// Exclude avatars but not the ".keep" file.
'!' + config.avatarsPath + '/!(.keep)',
// Exclude plugins but not the ".keep" file.
'!' + config.pluginsPath + '/!(.keep)',
'!' + config.pluginsPath + '/*/**/*',
// Exclude Git repositories that can be shipped with third-party libs
'!' + config.phpVendorPath + '/**/.git',
'!' + config.phpVendorPath + '/**/.git/**/*',
// Exclude vendors binaries
'!' + config.phpVendorPath + '/bin/**/*',
// Exclude JavaScript sources
'!' + config.jsPath + '/source/**/*',
// Actually we does not need backbone.babysitter and backbone.wreqr
// dependencies because they embed into marionette.js. So we exclude
// "backbone.babysitter" and "backbone.wreqr" directories and all their
// contents.
'!' + config.jsVendorPath + '/backbone.babysitter{,/**}',
'!' + config.jsVendorPath + '/backbone.wreqr{,/**}',
// Exclude dot files within third-party JS libraries.
'!' + config.jsVendorPath + '/**/.*',
// Exclude config files of various package systems
'!' + config.jsVendorPath + '/**/{bower,component,package,composer}.json',
// Exclude config files of various build systems
'!' + config.jsVendorPath + '/**/Gruntfile.*',
'!' + config.jsVendorPath + '/**/gulpfile.*',
'!' + config.jsVendorPath + '/**/Makefile',
// Exclude HTML files from third-party JS libraries. Such files can be
// used for docs or for tests, we need none of them.
'!' + config.jsVendorPath + '/**/*.html',
// There are too many useless files in Vex.js library. Exclude them.
'!' + config.jsVendorPath + '/vex/sass{,/**}',
'!' + config.jsVendorPath + '/vex/docs{,/**}',
'!' + config.jsVendorPath + '/vex/docs{,/**}',
'!' + config.jsVendorPath + '/vex/coffee{,/**}'
];
var srcOptions = {
// Dot files (.htaccess, .keep, etc.) must be included in the package
dot: true,
// Content of the cache directory is readable only for webserver. Thus
// we must to set "strict" option to false to prevent "EACCES" errors.
// At the same we need to see all errors that take place.
strict: false,
silent: false,
// Preserve root directory name (i.e. 'mibew/')
base: '.'
}
var version = config.package.version;
return eventStream.merge(
gulp.src(sources, srcOptions)
.pipe(zip('mibew-' + version + '.zip')),
gulp.src(sources, srcOptions)
.pipe(tar('mibew-' + version + '.tar'))
.pipe(gzip())
)
.pipe(chmod(644))
.pipe(gulp.dest(config.releasePath));
}));
// Pack translations for release as .zip and .tar.gz archives
gulp.task('pack-i18n', function(callback) {
return getChildDirs(config.i18nPath + '/translations')
.then(function (dirs) {
return Promise.all(dirs.map(function (dir) {
return new Promise(function(resolve, reject) {
var srcOptions = {
base: config.releasePath
};
eventStream.merge(
gulp.src(config.releasePath + '/' + dir
+ '/**/*', srcOptions)
.pipe(zip(config.i18nPrefix + dir
+ config.i18nSuffix + '.zip')),
gulp.src(config.releasePath + '/' + dir
+ '/**/*', srcOptions)
.pipe(tar(config.i18nPrefix + dir
+ config.i18nSuffix + '.tar'))
.pipe(gzip())
)
.pipe(chmod(644))
.pipe(gulp.dest(config.releasePath))
.on('error', reject)
.on('end', resolve);
});
}));
});
});
// Tasks of releasing //////////////////
// Prepare release of Mibew Messenger
gulp.task('prepare-release', function(callback) {
runSequence(
'clean',
['phpcs', 'js', 'chat-styles', 'page-styles', 'generate-pot',
'generate-tmp-po'],
'pack-sources',
'post-pack-cleanup',
callback
);
});
// Prepare releases of translations for Mibew Messenger
gulp.task('prepare-i18n-release', function(callback) {
runSequence( 'clean-tmp-po',
'generate-pos',
'pack-i18n',
'clean-tmp-i18n-files',
callback
);
});
// Mirror prepared releases of Mibew Messenger and its translations in a form
// intended for uploading into the CDN
gulp.task('prepare-for-upload', function(callback) {
gulp.src(config.releasePath + '/mibew-' + config.package.version + '.*')
.pipe(gulp.dest(config.uploadPath + '/core/' + config.package.version + '/'));
gulp.src(config.releasePath + '/mibew-i18n-translation-' + config.package.version + '-*.pot')
.pipe(gulp.dest(config.uploadPath + '/i18n/_pot/' + config.package.version + '/'));
return getChildDirs(config.i18nPath + '/translations')
.then(function (dirs) {
return Promise.all(dirs.map(function (dir) {
return new Promise(function(resolve, reject) {
gulp.src(config.releasePath + '/mibew-i18n-' + dir + '-' + config.package.version + '-*.*')
.pipe(gulp.dest(config.uploadPath + '/i18n/' + dir + '/' + config.package.version + '/'))
.on('error', reject)
.on('end', resolve);
});
}));
});
});
// Perform all preparations before uploading the release of Mibew Messenger and
// its translations into the CDN
gulp.task('prepare-all', function(callback) {
runSequence('clean-all', 'prepare-release', 'prepare-i18n-release',
'prepare-for-upload', callback);
});
// Prepare release archives of the development version of Mibew Messenger
gulp.task('default', function(callback) {
runSequence(
'clean',
['js', 'chat-styles', 'page-styles', 'generate-tmp-po'],
'pack-sources',
['post-pack-cleanup', 'clean-tmp-po'],
callback
);
});
/**
* Loads and prepare js file for a client side application with the specified
* name.
*
* @param {String} name Application name
* @param {String} name Application name.
* @returns A files stream that can be piped to any gulp plugin.
*/
var getClientSideApp = function(name) {
@ -223,7 +659,85 @@ var wrapHandlebarsTemplate = function() {
+ 'Handlebars.templates["<%= relative %>"] = <%= handlebars %>;\n'
+ '})()',
context: function(context) {
return {relative: context.file.relative.replace(/\.js$/, '')};
return {relative: context.file.relative.replace(/\.js$/, '').replace(/\\/g, '/')};
}
});
}
/**
* Extracts gettext messages from handlebars templates.
*
* @returns {Function} A function that can be used in pipe() method of a file
* stream.
*/
var xgettextHandlebars = function() {
var helperRegExp = /\{{2}l10n\s*('|")(.*?[^\\])\1.*?\}{2}/g;
return through.obj(function (file, enc, callback) {
var po = new PoFile();
match = false,
contents = file.contents.toString();
while (match = helperRegExp.exec(contents)) {
// Try to find item in the .po file by its name
var item = lodash.find(po.items, function(item) {
return match[2] === item.msgid;
});
var line = contents.substr(0, match.index).split(/\r?\n|\r/g).length;
if (!item) {
// There is no such item, create new one
item = new PoFile.Item();
item.msgid = match[2].replace(/\\'/g, "'").replace(/\\"/g, '"');
po.items.push(item);
}
// Add new reference
item.references.push(file.relative + ':' + line);
}
// Update file contents
file.contents = Buffer.from(po.toString());
this.push(file);
callback();
});
}
/**
* Retrieves list of all dirs which are placed in the specified one.
*
* @param {String} srcDir A dir to search.
* @returns Promise A promise which will be resolved with list of child dirs or
* rejected with the occured error.
*/
var getChildDirs = function(srcDir) {
return (new Promise(function(resolve, reject) {
fs.readdir(srcDir, function (err, files) {
if (err) {
reject(err);
} else {
resolve(files);
}
});
})).then(function (files) {
// Replace all files that are not a directory with nulls.
return Promise.all(files.map(function (file) {
return new Promise(function (resolve, reject) {
fs.lstat(srcDir + '/' + file, function (err, stat) {
if (err) {
reject(err);
} else {
resolve(stat.isDirectory() ? file : null);
}
});
});
}));
}).then(function(dirs) {
// Remove all nulls from the array.
return dirs.filter(function (dir) {
return null !== dir;
});
});
}

1
src/i18n Submodule

@ -0,0 +1 @@
Subproject commit 55868d9973f531c3550575481bde4233cc625b91

View File

@ -1,12 +1,14 @@
# Set default handler for incoming requests
DirectoryIndex index.php
# Disable directory listing
Options -Indexes
# Follow symbolic links in the directory
Options +FollowSymLinks
<IfModule mod_negotiation.c>
# Forbid apache to guess file extensions
Options -MultiViews
</IfModule>
# Disable mod_security for Apache 1.x
<IfModule mod_security.c>
SecFilterEngine Off
@ -26,12 +28,15 @@ Options +FollowSymLinks
# Redirect requests to the front controller
<IfModule mod_rewrite.c>
# Use the front controller as a default handler
DirectoryIndex index.php
RewriteEngine On
# Use separate front controller for the system installator
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^install(|/(.*))$ install.php [QSA,L]
RewriteRule ^install(/(.*))?$ install.php [QSA,L]
# Rewrite all other requests for files and directories that do not exist to
# the main front controller
@ -40,7 +45,20 @@ Options +FollowSymLinks
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
<IfModule !mod_rewrite.c>
# There is no mod_rewrite in the system. For the root Mibew Messenger
# directory index_fallback.php should be loaded first to activate
# old-fashioned URLs. For all other directories index.php is just a
# directory index file.
DirectoryIndex index_fallback.php index.php
</IfModule>
# Deny access to internal system files
<FilesMatch "\.(yml|po|ini|handlebars|keep)$">
Deny from all
</FilesMatch>
# Deny access to CLI cron worker from the outside
<Files "cron.php">
Deny from all
</Files>

View File

@ -1,17 +1,19 @@
Mibew Messenger
Copyright 2005-2014 the original author or authors.
Copyright 2005-2023 the original author or authors.
REQUIREMENTS
* Apache web server 1.3.34 or above
* Apache web server 1.3.34 or above with the ability to use local .htaccess
files (mod_rewrite module is optional, but recommended)
* MySQL database 5.0 or above
* PHP 5.3.3 or above with MySQL support
* PHP 7.2.5 or above with PDO, pdo_mysql, cURL, mbstring and gd extensions
INSTALLATION
1. Create folder with name 'mibew' in the root of your website.
2. Upload all the files contained in this archive (retaining the directory structure) into created folder.
Be sure to chmod the mibew folder to 755.
2. Upload all the files contained in this archive (retaining the directory
structure) into created folder.
Be sure to chmod the mibew folder to 0755.
3. Add a MySQL database with the name 'mibew'
4. Copy /mibew/configs/default_config.yml to /mibew/configs/config.yml
5. Edit /mibew/configs/config.yml to the information needed to connect to the database
@ -22,10 +24,33 @@ INSTALLATION
user: admin
password: <your password>
9. Get button code and setup it on your site.
10. Change your name.
11. Wait for your visitors on 'Pending users' page.
10. Configure periodically running tasks by setting up an automated
process to visit the page http://<yourdomain>/cron?cron_key=<key>
The full URL including the secret "cron key" used to protect against
unauthorized access can be seen on the 'General' tab at the 'Settings' page.
11. Change your name.
12. Wait for your visitors on 'Pending users' page.
On unix/linux platforms change the owner of /mibew/files/avatar and
/mibew/cache folders to the user, under which the web server is running
(for instance, www). The owner should have all rights on the folders
/mibew/files/avatar and /mibew/cache
(chmod 0700 /mibew/files/avatar && chmod 0700 /mibew/cache).
UPDATE
1. Backup your actual installation (i.e. code and database).
2. Disable all plugins.
3. Delete all items in your Mibew Messenger directory on the server.
4. Unpack the archive with the official distrubition in that directory.
5. Remove install.php file.
6. Restore configuration (configs/ directory), plugins (plugins/ directory),
(maybe) custom styles (if you have any), (maybe) additional
locales (if you use any), and avatars (files/avatar/ directory) from the
backup you've made at the step 1.
7. Visit http://<yourdomain>/<path to your Mibew Messenger>/update and follow
the instructions to update the database tables (if needed).
8. Enable disabled plugins.
On unix/linux platforms change the owner of /mibew/files/avatar folder
to the user, under which the web server is running (for instance, www).
The owner should have all rights on the folder /mibew/files/avatar
(chmod 700 /mibew/files/avatar).

View File

@ -1 +1 @@
Mibew/2.0
Mibew/3.6.0

View File

@ -72,7 +72,7 @@ thread:
useragent: "varchar(255)"
# Total count of user's messages related with the thread.
messagecount: "varchar(16)"
# ID of the group at Mibew side related with the thread.
# ID of the group at Mibew Messenger side related with the thread.
groupid: "int references {opgroup}(groupid)"
# Contains "by thread" statistics
@ -104,7 +104,7 @@ requestcallback:
fields:
callbackid: "int NOT NULL auto_increment PRIMARY KEY"
token: "varchar(64) NOT NULL DEFAULT ''"
function: "varchar(64) NOT NULL"
func: "varchar(64) NOT NULL"
arguments: "varchar(1024)"
indexes:
token: [token]
@ -129,12 +129,23 @@ translation:
# Contains locales info
locale:
fields:
# Artificial primary key
# Artificial primary key.
localeid: "int NOT NULL auto_increment PRIMARY KEY"
# Locale code
code: "varchar(5) NOT NULL"
# Indicates if a locale is enabled or not.
# Human readable name of the locale.
name: "varchar(128) NOT NULL DEFAULT ''"
# Indicates if the locale is enabled or not.
enabled: "tinyint NOT NULL DEFAULT 0"
# Indicates if the locale uses RTL writing.
rtl: "tinyint NOT NULL DEFAULT 0"
# Name of the locale which is used with PHP's setlocale to format dates.
time_locale: "varchar(128) NOT NULL DEFAULT 'en_US'"
# Serialized array of various date formats.
date_format: "text"
unique_keys:
# Make sure locale code can be duplicated
code: [code]
# Contains localized mail templates
mailtemplate:
@ -190,7 +201,6 @@ operator:
istatus: "int DEFAULT 0"
idisabled: "int DEFAULT 0"
vcavatar: "varchar(255)"
vcjabbername: "varchar(255)"
# Operators privileges bitmask.
iperm: "int DEFAULT 0"
dtmrestore: "int NOT NULL DEFAULT 0"
@ -216,7 +226,7 @@ operatorstatistics:
revision:
fields:
id: "INT NOT NULL"
id: "INT NOT NULL PRIMARY KEY"
# Contains relations between operators and groups
operatortoopgroup:
@ -235,7 +245,6 @@ ban:
dtmtill: "int NOT NULL DEFAULT 0"
address: "varchar(255)"
comment: "varchar(255)"
blockedcount: "int DEFAULT 0"
# Contains dynamic configs
config:
@ -291,3 +300,37 @@ visitedpagestatistics:
acceptedinvitations: "int NOT NULL DEFAULT 0"
rejectedinvitations: "int NOT NULL DEFAULT 0"
ignoredinvitations: "int NOT NULL DEFAULT 0"
# Contains info about installed plugins
plugin:
fields:
# Artificial ID
id: "INT NOT NULL auto_increment PRIMARY KEY"
# Plugin name in "<Vendor>:<Name>" format.
name: "varchar(255) NOT NULL"
# Installed version of the plugin.
version: "varchar(255) NOT NULL"
# Indicates if the plugin is installed or not.
installed: "tinyint NOT NULL DEFAULT 0"
# Indicates if the plugin is enabled or not.
enabled: "tinyint NOT NULL DEFAULT 0"
# Indicates if the plugin is initialized or not.
initialized: "tinyint NOT NULL DEFAULT 0"
unique_keys:
name: [name]
# Contains info about all available updates
availableupdate:
fields:
# Artificial ID
id: "INT NOT NULL auto_increment PRIMARY KEY"
# Can be either "core" or fully qualified plugin's name
target: "varchar(255) NOT NULL"
# The latest available version of the plugin
version: "varchar(255) NOT NULL"
# A URL where the new version can be downloaded
url: "text"
# Description of the update
description: "text"
unique_keys:
target: [target]

View File

@ -1,5 +1,5 @@
# IMPORTANT: Before install mibew copy this file to config.yml and fill it with
# your own settings!
# IMPORTANT: Before install Mibew Messenger copy this file to config.yml and
# fill it with your own settings!
# MySQL Database parameters
@ -12,9 +12,60 @@ database:
tables_prefix: ""
use_persistent_connection: false
# Mailbox
# Mail
## This value will be used as sender address in all e-mails Mibew Messenger send.
mailbox: mibew@yourdomain.com
## Mailer parameters
mailer:
# This value determines what kind of mailer will be used. Possible values
# are "mail" and "smtp".
#
# To use standard PHP mail function just set this option to "mail". No
# additional configs are required in this case.
#
# To use SMTP-based solution set this option "smtp". This approach require
# some extra configuration to be done (see below).
transport: mail
# The lines below represents default SMTP mailer configurations. They will
# be used only if the "transport" option is set to "smtp".
host: localhost
port: 25
user: user
pass: ""
# The following option determines what kind of encryption should be used.
# false means no encyption at all. Another values once can use are "ssl" and
# "tls".
encryption: false
# Cache subsystem
cache:
# This value determines where the cached data will be stored. Possible
# values are "none", "file_system" and "memcached".
#
# If "none" is used the caching will be disabled. This option should be used
# only if none of the other options works.
#
# If "file_system" is used the cached data will be stored in files within
# the "cache/" directory. Notice, that the file system storage does not work
# on NFS systems bucause exclusive file locks are not supported where.
#
# If "memcached" is used the cached data will be stored in Memcached
# storage. Before using this kind of storage make sure PHP's memcached
# extension is installed and enabled.
storage: file_system
# The lines below represents default Memcached server configurations. They
# will be used only if the "storage" option is set to "memcached".
memcached_servers:
- host: localhost
port: 11211
# The "weight" field is optional and can be omitted and it's only positive int number.
weight: 1
# Actually, one can use any number of memcached servers he wants. Just
# add servers description like the one above.
# Locales
## Native name will be used in this locale
home_locale: en
@ -26,17 +77,22 @@ default_locale: en
# http://php.net/manual/en/timezones.php
timezone: ""
# List of proxy's IP Mibew Messenger should trust. You should set this option
# if you use Mibew Messenger with a load balancer or behind a proxy.
trusted_proxies: []
# Here is an example of what values this option can take:
# trusted_proxies:
# - 127.0.0.1
# - ::1
# - 10.0.0.0/8
# Plugins
plugins: []
## Exapmle of plugins configuration
## Example of plugins configuration
# plugins:
# -
# name: "VendorName:PluginName"
# config:
# weight: 100
# some_configurable_value: value
# -
# name: "VendorName:AnotherPluginName"
# config:
# very_important_value: "$3.50"
# "VendorName:PluginName":
# weight: 100
# some_configurable_value: value
# "VendorName:AnotherPluginName":
# very_important_value: "$3.50"

View File

@ -49,6 +49,14 @@ chat_user:
thread_id: \d{1,10}
token: \d{1,10}
chat_user_check:
path: /chat/{thread_id}/{token}/check
defaults:
_controller: Mibew\Controller\Chat\UserChatController::checkAction
requirements:
thread_id: \d{1,10}
token: \d{1,10}
chat_user_invitation:
path: /chat/invitation
defaults:
@ -72,11 +80,33 @@ chat_user_mail_send:
token: \d{1,10}
methods: [POST]
chat_user_popup_style:
path: /chat/style/popup/{style}
defaults:
_controller: Mibew\Controller\Chat\StyleController::loadPopupStyleAction
style: ""
requirements:
style: "[0-9A-Za-z_]*"
chat_user_popup_style_force_secure:
path: /chat/style/popup/{style}/force_secure
defaults:
_controller: Mibew\Controller\Chat\StyleController::loadPopupStyleAction
style: ""
force_secure: on
requirements:
style: "[0-9A-Za-z_]*"
chat_user_start:
path: /chat
defaults:
_controller: Mibew\Controller\Chat\UserChatController::startAction
chat_user_cookie_set_permission:
path: /chat/cookies-set-permission
defaults:
_controller: Mibew\Controller\Chat\UserChatController::cookieSetPermissionAction
# Pages that are available for all users
button:
path: /b
@ -90,9 +120,12 @@ cron:
path: /cron
defaults: { _controller: Mibew\Controller\CronController::runAction }
license:
path: /license
defaults: { _controller: Mibew\Controller\LicenseController::indexAction }
# A set of localization constants for the client side applications is generated
# dynamically
js_translation:
path: /locales/{locale}/translation.js
defaults:
_controller: Mibew\Controller\Localization\JsTranslationController::indexAction
widget_gateway:
path: /widget
@ -100,6 +133,13 @@ widget_gateway:
# Operators' pages
## About page
about:
path: /operator/about
defaults:
_controller: Mibew\Controller\AboutController::indexAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
## Banned visitors
ban_add:
path: /operator/ban/add
@ -160,21 +200,24 @@ canned_message_add:
path: /operator/canned-message/add
defaults:
_controller: Mibew\Controller\CannedMessageController::showEditFormAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
methods: [GET]
canned_message_add_save:
path: /operator/canned-message/add
defaults:
_controller: Mibew\Controller\CannedMessageController::submitEditFormAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
methods: [POST]
canned_message_delete:
path: /operator/canned-message/{message_id}/delete
defaults:
_controller: Mibew\Controller\CannedMessageController::deleteAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
message_id: \d{1,10}
@ -182,7 +225,8 @@ canned_message_edit:
path: /operator/canned-message/{message_id}/edit
defaults:
_controller: Mibew\Controller\CannedMessageController::showEditFormAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
message_id: \d{1,10}
methods: [GET]
@ -191,7 +235,8 @@ canned_message_edit_save:
path: /operator/canned-message/{message_id}/edit
defaults:
_controller: Mibew\Controller\CannedMessageController::submitEditFormAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
message_id: \d{1,10}
methods: [POST]
@ -200,7 +245,8 @@ canned_messages:
path: /operator/canned-message
defaults:
_controller: Mibew\Controller\CannedMessageController::indexAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
## Groups
group_add:
@ -331,7 +377,27 @@ locale_disable:
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
locale: "[a-z\-]{2,5}"
locale: "[a-z\\-]{2,5}"
locale_edit:
path: /operator/locale/{locale}/edit
defaults:
_controller: Mibew\Controller\Localization\LocaleController::showEditFormAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
locale: "[a-z\\-]{2,5}"
methods: [GET]
locale_edit_save:
path: /operator/locale/{locale}/edit
defaults:
_controller: Mibew\Controller\Localization\LocaleController::submitEditFormAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
locale: "[a-z\\-]{2,5}"
methods: [POST]
locale_enable:
path: /operator/locale/{locale}/enable
@ -340,7 +406,7 @@ locale_enable:
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
locale: "[a-z\-]{2,5}"
locale: "[a-z\\-]{2,5}"
locales:
path: /operator/locale
@ -541,6 +607,42 @@ password_recovery_reset:
defaults:
_controller: Mibew\Controller\PasswordRecoveryController::resetAction
## Plugins
plugin_enable:
path: /operator/plugin/{plugin_name}/enable
defaults:
_controller: Mibew\Controller\PluginController::enableAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
plugin_disable:
path: /operator/plugin/{plugin_name}/disable
defaults:
_controller: Mibew\Controller\PluginController::disableAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
plugin_uninstall:
path: /operator/plugin/{plugin_name}/uninstall
defaults:
_controller: Mibew\Controller\PluginController::uninstallAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
plugin_update:
path: /operator/plugin/{plugin_name}/update
defaults:
_controller: Mibew\Controller\PluginController::updateAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
plugins:
path: /operator/plugin
defaults:
_controller: Mibew\Controller\PluginController::indexAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
## Settings
settings_common:
path: /operator/settings
@ -596,7 +698,8 @@ statistics:
defaults:
type: "by-date"
_controller: Mibew\Controller\StatisticsController::indexAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_VIEWSTATISTICS]
requirements:
type: by-date|by-operator|by-page
@ -618,7 +721,7 @@ translation_edit:
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
string_id: "\d{1,10}"
string_id: "\\d{1,10}"
methods: [GET]
translation_edit_save:
@ -628,7 +731,7 @@ translation_edit_save:
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
requirements:
string_id: "\d{1,10}"
string_id: "\\d{1,10}"
methods: [POST]
translation_export:
@ -671,11 +774,26 @@ translations:
_access_permissions: [CAN_ADMINISTRATE]
## Updates
updates:
path: /operator/updates
update:
path: /update
defaults:
_controller: Mibew\Controller\UpdatesController::indexAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
_controller: Mibew\Controller\UpdateController::indexAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
update_run:
path: /update/run
defaults:
_controller: Mibew\Controller\UpdateController::runUpdateAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
update_check:
path: /update/check
defaults:
_controller: Mibew\Controller\UpdateController::checkUpdatesAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
## Users (visitors avaiting page)
users:
@ -690,7 +808,17 @@ users_update:
_controller: Mibew\Controller\UsersController::updateAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
# Remove trailing slashe. This route is the last one because previous rotes can
# System routes and includes
# The following route is a fake and is used only to load plugins routes. It can
# have any unique name.
_include_pluign_routes:
# Resource name has no meaning and can be any value.
resource: .
# The type actually indicates that plugins routes should be included.
type: plugin
# Remove trailing slashes. This route is the last one because previous rotes can
# (but definitely should not) have trailing slashes.
remove_trailing_slash:
path: /{url}

View File

@ -1,3 +1,9 @@
# The following route is a fake and is used only to load routes of the core. It
# can have any unique name.
_include_core_routes:
resource: routing.yml
type: yaml
# Override the home route to allow users use <mibew root>/install.php path to
# the installer.
home:

52
src/mibew/cron.php Normal file
View File

@ -0,0 +1,52 @@
<?php
/*
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Initialize libraries
require_once(dirname(__FILE__) . '/libs/init.php');
use Mibew\Cache\CacheFactory;
use Mibew\Maintenance\CronWorker;
use Mibew\Plugin\PluginManager;
$configs = load_system_configs();
// Prepare the cache. It is initialized in the same way as in index.php
$cache_factory = new CacheFactory($configs['cache']);
// For now directory for cache files cannot be changed via the configs file.
$cache_factory->setOption('path', MIBEW_FS_ROOT . '/cache/stash');
// Run plugins
if (get_maintenance_mode() === false) {
$plugin_manager = PluginManager::getInstance();
$plugin_manager->setCache($cache_factory->getCache());
$plugin_manager->loadPlugins($configs['plugins']);
}
// Do the job.
$worker = new CronWorker($cache_factory->getCache());
$success = $worker->run();
if ($success) {
echo("All cron jobs done\n");
} else {
echo("Cron job failed. Here are the errors:\n");
foreach ($worker->getErrors() as $error) {
echo(' ' . $error . "\n");
}
}

View File

@ -1,6 +1,8 @@
<?php
/*
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,24 +22,53 @@ require_once(dirname(__FILE__) . '/libs/init.php');
use Mibew\Application;
use Mibew\Authentication\AuthenticationManager;
use Mibew\Routing\RouteCollectionLoader;
use Mibew\Cache\CacheFactory;
use Mibew\Mail\MailerFactory;
use Mibew\Plugin\PluginManager;
use Mibew\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Mibew\Routing\Loader\CacheLoader;
use Mibew\Routing\Loader\PluginLoader;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Loader\YamlFileLoader;
$file_locator = new FileLocator(array(MIBEW_FS_ROOT));
$router = new Router(new RouteCollectionLoader($file_locator));
$router->setOption(
'route_collection',
RouteCollectionLoader::ROUTES_CORE | RouteCollectionLoader::ROUTES_PLUGINS
);
$configs = load_system_configs();
// Prepare the cache
$cache_factory = new CacheFactory($configs['cache']);
// For now directory for cache files cannot be changed via the configs file.
// TODO: Evaluate possibility of using custom cache directory.
$cache_factory->setOption('path', MIBEW_FS_ROOT . '/cache/stash');
// Run plugins
if (get_maintenance_mode() === false) {
$plugin_manager = PluginManager::getInstance();
$plugin_manager->setCache($cache_factory->getCache());
$plugin_manager->loadPlugins($configs['plugins']);
}
// The main route loader which loads nothig but works as a cache proxy for other
// loaders.
$route_loader = new CacheLoader($cache_factory->getCache());
// Real loaders are attached via the resolver.
$loader_resolver = new LoaderResolver(array(
$route_loader,
new YamlFileLoader(new FileLocator(array(MIBEW_FS_ROOT))),
new PluginLoader(),
));
$router = new Router($route_loader, 'configs/routing.yml');
$application = new Application($router, new AuthenticationManager());
$application->setCache($cache_factory->getCache());
// Use custom config-dependent mailer factory
$application->setMailerFactory(new MailerFactory($configs['mailer']));
// Process request
$request = Request::createFromGlobals();
$response = $application->handleRequest($request);
// Send response to the user
$response->prepare($request);
$response->send();

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Force the user to specify the entry point. This should be done only when
// mod_rewrite is not used by apache.
header('HTTP/1.0 301 Moved Permanently');
header('Location: index.php');

View File

@ -1,6 +1,8 @@
<?php
/*
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,24 +17,28 @@
* limitations under the License.
*/
define('INSTALLATION_IN_PROGRESS', true);
define('MAINTENANCE_MODE', 'install');
// Initialize libraries
require_once(dirname(__FILE__) . '/libs/init.php');
use Mibew\Application;
use Mibew\Authentication\DummyAuthenticationManager;
use Mibew\Routing\RouteCollectionLoader;
use Mibew\Routing\Loader\DummyPluginLoader;
use Mibew\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Loader\YamlFileLoader;
// Prepare router
$file_locator = new FileLocator(array(MIBEW_FS_ROOT));
$router = new Router(new RouteCollectionLoader($file_locator));
$router->setOption(
'route_collection',
RouteCollectionLoader::ROUTES_CORE | RouteCollectionLoader::ROUTES_INSTALLATION
);
$route_loader = new YamlFileLoader($file_locator);
$loader_resolver = new LoaderResolver(array(
$route_loader,
new DummyPluginLoader(),
));
$router = new Router($route_loader, 'configs/routing_install.yml');
$application = new Application($router, new DummyAuthenticationManager());
@ -41,5 +47,4 @@ $request = Request::createFromGlobals();
$response = $application->handleRequest($request);
// Send response to the user
$response->prepare($request);
$response->send();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,106 +0,0 @@
/*
handlebars v1.3.0
Copyright (C) 2011 by Yehuda Katz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var Handlebars=function(){var E=function(a){this.string=a};E.prototype.toString=function(){return""+this.string};var V=function(a){return U[a]||"&amp;"},q={},U={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},W=/[&<>"'`]/g,X=/[&<>"'`]/;q.extend=function(a,b){for(var c in b)Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c])};var F=Object.prototype.toString;q.toString=F;var m=function(a){return"function"===typeof a};m(/x/)&&(m=function(a){return"function"===typeof a&&"[object Function]"===
F.call(a)});q.isFunction=m;var M=Array.isArray||function(a){return a&&"object"===typeof a?"[object Array]"===F.call(a):!1};q.isArray=M;q.escapeExpression=function(a){if(a instanceof E)return a.toString();if(!a&&0!==a)return"";a=""+a;return!X.test(a)?a:a.replace(W,V)};q.isEmpty=function(a){return!a&&0!==a?!0:M(a)&&0===a.length?!0:!1};var j=function(a,b){var c;b&&b.firstLine&&(c=b.firstLine,a+=" - "+c+":"+b.firstColumn);for(var d=Error.prototype.constructor.call(this,a),f=0;f<G.length;f++)this[G[f]]=
d[G[f]];c&&(this.lineNumber=c,this.column=b.firstColumn)},G="description fileName lineNumber message name number stack".split(" ");j.prototype=Error();var m=function(a,b){this.helpers=a||{};this.partials=b||{};var c=this;c.registerHelper("helperMissing",function(a){if(2!==arguments.length)throw new N("Missing helper: '"+a+"'");});c.registerHelper("blockHelperMissing",function(a,b){var e=b.inverse||function(){},h=b.fn;B(a)&&(a=a.call(this));return!0===a?h(this):!1===a||null==a?e(this):O(a)?0<a.length?
c.helpers.each(a,b):e(this):h(a)});c.registerHelper("each",function(a,b){var c=b.fn,h=b.inverse,g=0,j="",r;B(a)&&(a=a.call(this));b.data&&(r=P(b.data));if(a&&"object"===typeof a)if(O(a))for(var k=a.length;g<k;g++)r&&(r.index=g,r.first=0===g,r.last=g===a.length-1),j+=c(a[g],{data:r});else for(k in a)a.hasOwnProperty(k)&&(r&&(r.key=k,r.index=g,r.first=0===g),j+=c(a[k],{data:r}),g++);0===g&&(j=h(this));return j});c.registerHelper("if",function(a,b){B(a)&&(a=a.call(this));return!b.hash.includeZero&&!a||
u.isEmpty(a)?b.inverse(this):b.fn(this)});c.registerHelper("unless",function(a,b){return c.helpers["if"].call(this,a,{fn:b.inverse,inverse:b.fn,hash:b.hash})});c.registerHelper("with",function(a,b){B(a)&&(a=a.call(this));if(!u.isEmpty(a))return b.fn(a)});c.registerHelper("log",function(a,b){var e=b.data&&null!=b.data.level?parseInt(b.data.level,10):1;c.log(e,a)})},n=function(a,b){y.log(a,b)},p={},u=q,N=j;p.VERSION="1.3.0";p.COMPILER_REVISION=4;p.REVISION_CHANGES={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",
3:"== 1.0.0-rc.4",4:">= 1.0.0"};var O=u.isArray,B=u.isFunction,Q=u.toString;p.HandlebarsEnvironment=m;m.prototype={constructor:m,logger:y,log:n,registerHelper:function(a,b,c){if("[object Object]"===Q.call(a)){if(c||b)throw new N("Arg not supported with multiple helpers");u.extend(this.helpers,a)}else c&&(b.not=c),this.helpers[a]=b},registerPartial:function(a,b){"[object Object]"===Q.call(a)?u.extend(this.partials,a):this.partials[a]=b}};var y={methodMap:{"0":"debug",1:"info",2:"warn",3:"error"},DEBUG:0,
INFO:1,WARN:2,ERROR:3,level:3,log:function(a,b){if(y.level<=a){var c=y.methodMap[a];"undefined"!==typeof console&&console[c]&&console[c].call(console,b)}}};p.logger=y;p.log=n;var P=function(a){var b={};u.extend(b,a);return b};p.createFrame=P;var H=function(a,b,c){var d=function(a,d){d=d||{};return b(a,d.data||c)};d.program=a;d.depth=0;return d},v={},I=p.COMPILER_REVISION,R=p.REVISION_CHANGES;v.checkRevision=function(a){var b=a&&a[0]||1;if(b!==I){if(b<I)throw new j("Template was precompiled with an older version of Handlebars than the current runtime. Please update your precompiler to a newer version ("+
R[I]+") or downgrade your runtime to an older version ("+R[b]+").");throw new j("Template was precompiled with a newer version of Handlebars than the current runtime. Please update your runtime to a newer version ("+a[1]+").");}};v.template=function(a,b){if(!b)throw new j("No environment passed to template");var c={escapeExpression:q.escapeExpression,invokePartial:function(a,c,e,h,g,n){var r=b.VM.invokePartial.apply(this,arguments);if(null!=r)return r;if(b.compile)return r={helpers:h,partials:g,data:n},
g[c]=b.compile(a,{data:void 0!==n},b),g[c](e,r);throw new j("The partial "+c+" could not be compiled when running in runtime-only mode");},programs:[],program:function(a,b,c){var h=this.programs[a];c?h=H(a,b,c):h||(h=this.programs[a]=H(a,b));return h},merge:function(a,b){var c=a||b;a&&(b&&a!==b)&&(c={},q.extend(c,b),q.extend(c,a));return c},programWithDepth:b.VM.programWithDepth,noop:b.VM.noop,compilerInfo:null};return function(d,f){f=f||{};var e=f.partial?f:b,h,g;f.partial||(h=f.helpers,g=f.partials);
e=a.call(c,e,d,h,g,f.data);f.partial||b.VM.checkRevision(c.compilerInfo);return e}};v.programWithDepth=function(a,b,c){var d=Array.prototype.slice.call(arguments,3),f=function(a,f){f=f||{};return b.apply(this,[a,f.data||c].concat(d))};f.program=a;f.depth=d.length;return f};v.program=H;v.invokePartial=function(a,b,c,d,f,e){d={partial:!0,helpers:d,partials:f,data:e};if(void 0===a)throw new j("The partial "+b+" could not be found");if(a instanceof Function)return a(c,d)};v.noop=function(){return""};
n=function(){var a=new p.HandlebarsEnvironment;q.extend(a,p);a.SafeString=E;a.Exception=j;a.Utils=q;a.VM=v;a.template=function(b){return v.template(b,a)};return a};m=n();m.create=n;var C,l=function(a){a=a||{};this.firstLine=a.first_line;this.firstColumn=a.first_column;this.lastColumn=a.last_column;this.lastLine=a.last_line},z={ProgramNode:function(a,b,c,d){var f;3===arguments.length?(d=c,c=null):2===arguments.length&&(d=b,b=null);l.call(this,d);this.type="program";this.statements=a;this.strip={};
c?((f=c[0])?(f={first_line:f.firstLine,last_line:f.lastLine,last_column:f.lastColumn,first_column:f.firstColumn},this.inverse=new z.ProgramNode(c,b,f)):this.inverse=new z.ProgramNode(c,b),this.strip.right=b.left):b&&(this.strip.left=b.right)},MustacheNode:function(a,b,c,d,f){l.call(this,f);this.type="mustache";this.strip=d;null!=c&&c.charAt?(c=c.charAt(3)||c.charAt(2),this.escaped="{"!==c&&"&"!==c):this.escaped=!!c;this.sexpr=a instanceof z.SexprNode?a:new z.SexprNode(a,b);this.sexpr.isRoot=!0;this.id=
this.sexpr.id;this.params=this.sexpr.params;this.hash=this.sexpr.hash;this.eligibleHelper=this.sexpr.eligibleHelper;this.isHelper=this.sexpr.isHelper},SexprNode:function(a,b,c){l.call(this,c);this.type="sexpr";this.hash=b;c=this.id=a[0];a=this.params=a.slice(1);this.isHelper=(this.eligibleHelper=c.isSimple)&&(a.length||b)},PartialNode:function(a,b,c,d){l.call(this,d);this.type="partial";this.partialName=a;this.context=b;this.strip=c},BlockNode:function(a,b,c,d,f){l.call(this,f);if(a.sexpr.id.original!==
d.path.original)throw new j(a.sexpr.id.original+" doesn't match "+d.path.original,this);this.type="block";this.mustache=a;this.program=b;this.inverse=c;this.strip={left:a.strip.left,right:d.strip.right};(b||c).strip.left=a.strip.right;(c||b).strip.right=d.strip.left;c&&!b&&(this.isInverse=!0)},ContentNode:function(a,b){l.call(this,b);this.type="content";this.string=a},HashNode:function(a,b){l.call(this,b);this.type="hash";this.pairs=a},IdNode:function(a,b){l.call(this,b);this.type="ID";for(var c=
"",d=[],f=0,e=0,h=a.length;e<h;e++){var g=a[e].part,c=c+((a[e].separator||"")+g);if(".."===g||"."===g||"this"===g){if(0<d.length)throw new j("Invalid path: "+c,this);".."===g?f++:this.isScoped=!0}else d.push(g)}this.original=c;this.parts=d;this.string=d.join(".");this.depth=f;this.isSimple=1===a.length&&!this.isScoped&&0===f;this.stringModeValue=this.string},PartialNameNode:function(a,b){l.call(this,b);this.type="PARTIAL_NAME";this.name=a.original},DataNode:function(a,b){l.call(this,b);this.type=
"DATA";this.id=a},StringNode:function(a,b){l.call(this,b);this.type="STRING";this.original=this.string=this.stringModeValue=a},IntegerNode:function(a,b){l.call(this,b);this.type="INTEGER";this.original=this.integer=a;this.stringModeValue=Number(a)},BooleanNode:function(a,b){l.call(this,b);this.type="BOOLEAN";this.bool=a;this.stringModeValue="true"===a},CommentNode:function(a,b){l.call(this,b);this.type="comment";this.comment=a}};C=z;var w=function(a,b){return{left:"~"===a.charAt(2),right:"~"===b.charAt(0)||
"~"===b.charAt(1)}},n=function(){this.yy={}},D={trace:function(){},yy:{},symbols_:{error:2,root:3,statements:4,EOF:5,program:6,simpleInverse:7,statement:8,openInverse:9,closeBlock:10,openBlock:11,mustache:12,partial:13,CONTENT:14,COMMENT:15,OPEN_BLOCK:16,sexpr:17,CLOSE:18,OPEN_INVERSE:19,OPEN_ENDBLOCK:20,path:21,OPEN:22,OPEN_UNESCAPED:23,CLOSE_UNESCAPED:24,OPEN_PARTIAL:25,partialName:26,partial_option0:27,sexpr_repetition0:28,sexpr_option0:29,dataName:30,param:31,STRING:32,INTEGER:33,BOOLEAN:34,OPEN_SEXPR:35,
CLOSE_SEXPR:36,hash:37,hash_repetition_plus0:38,hashSegment:39,ID:40,EQUALS:41,DATA:42,pathSegments:43,SEP:44,$accept:0,$end:1},terminals_:{2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",35:"OPEN_SEXPR",36:"CLOSE_SEXPR",40:"ID",41:"EQUALS",42:"DATA",44:"SEP"},productions_:[0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,
2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]],performAction:function(a,b,c,d,f,e){a=e.length-1;switch(f){case 1:return new d.ProgramNode(e[a-1],this._$);case 2:return new d.ProgramNode([],this._$);case 3:this.$=new d.ProgramNode([],e[a-1],e[a],this._$);break;case 4:this.$=new d.ProgramNode(e[a-
2],e[a-1],e[a],this._$);break;case 5:this.$=new d.ProgramNode(e[a-1],e[a],[],this._$);break;case 6:this.$=new d.ProgramNode(e[a],this._$);break;case 7:this.$=new d.ProgramNode([],this._$);break;case 8:this.$=new d.ProgramNode([],this._$);break;case 9:this.$=[e[a]];break;case 10:e[a-1].push(e[a]);this.$=e[a-1];break;case 11:this.$=new d.BlockNode(e[a-2],e[a-1].inverse,e[a-1],e[a],this._$);break;case 12:this.$=new d.BlockNode(e[a-2],e[a-1],e[a-1].inverse,e[a],this._$);break;case 13:this.$=e[a];break;
case 14:this.$=e[a];break;case 15:this.$=new d.ContentNode(e[a],this._$);break;case 16:this.$=new d.CommentNode(e[a],this._$);break;case 17:this.$=new d.MustacheNode(e[a-1],null,e[a-2],w(e[a-2],e[a]),this._$);break;case 18:this.$=new d.MustacheNode(e[a-1],null,e[a-2],w(e[a-2],e[a]),this._$);break;case 19:this.$={path:e[a-1],strip:w(e[a-2],e[a])};break;case 20:this.$=new d.MustacheNode(e[a-1],null,e[a-2],w(e[a-2],e[a]),this._$);break;case 21:this.$=new d.MustacheNode(e[a-1],null,e[a-2],w(e[a-2],e[a]),
this._$);break;case 22:this.$=new d.PartialNode(e[a-2],e[a-1],w(e[a-3],e[a]),this._$);break;case 23:this.$=w(e[a-1],e[a]);break;case 24:this.$=new d.SexprNode([e[a-2]].concat(e[a-1]),e[a],this._$);break;case 25:this.$=new d.SexprNode([e[a]],null,this._$);break;case 26:this.$=e[a];break;case 27:this.$=new d.StringNode(e[a],this._$);break;case 28:this.$=new d.IntegerNode(e[a],this._$);break;case 29:this.$=new d.BooleanNode(e[a],this._$);break;case 30:this.$=e[a];break;case 31:e[a-1].isHelper=!0;this.$=
e[a-1];break;case 32:this.$=new d.HashNode(e[a],this._$);break;case 33:this.$=[e[a-2],e[a]];break;case 34:this.$=new d.PartialNameNode(e[a],this._$);break;case 35:this.$=new d.PartialNameNode(new d.StringNode(e[a],this._$),this._$);break;case 36:this.$=new d.PartialNameNode(new d.IntegerNode(e[a],this._$));break;case 37:this.$=new d.DataNode(e[a],this._$);break;case 38:this.$=new d.IdNode(e[a],this._$);break;case 39:e[a-2].push({part:e[a],separator:e[a-1]});this.$=e[a-2];break;case 40:this.$=[{part:e[a]}];
break;case 43:this.$=[];break;case 44:e[a-1].push(e[a]);break;case 47:this.$=[e[a]];break;case 48:e[a-1].push(e[a])}},table:[{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,
12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,
16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:29,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:30,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:31,21:24,30:25,40:[1,28],42:[1,27],43:26},{21:33,26:32,32:[1,34],33:[1,35],40:[1,28],43:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,
8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,40:[1,28],42:[1,27],43:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,43],24:[2,43],28:43,32:[2,43],33:[2,43],34:[2,43],35:[2,43],36:[2,43],40:[2,43],42:[2,43]},{18:[2,25],24:[2,25],36:[2,25]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],35:[2,38],36:[2,38],40:[2,38],42:[2,38],44:[1,44]},{21:45,40:[1,28],43:26},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,
40],36:[2,40],40:[2,40],42:[2,40],44:[2,40]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,41],21:50,27:49,40:[1,28],43:26},{18:[2,34],40:[2,34]},{18:[2,35],40:[2,35]},{18:[2,36],40:[2,36]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,40:[1,28],43:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],
25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,45],21:56,24:[2,45],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:[1,61],36:[2,45],37:55,38:62,39:63,40:[1,64],42:[1,27],43:26},{40:[1,65]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],35:[2,37],36:[2,37],40:[2,37],42:[2,
37]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,66]},{18:[2,42]},{18:[1,67]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24],36:[2,24]},{18:[2,44],24:[2,44],32:[2,44],33:[2,44],34:[2,44],35:[2,44],
36:[2,44],40:[2,44],42:[2,44]},{18:[2,46],24:[2,46],36:[2,46]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],35:[2,26],36:[2,26],40:[2,26],42:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],35:[2,27],36:[2,27],40:[2,27],42:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],35:[2,28],36:[2,28],40:[2,28],42:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],35:[2,29],36:[2,29],40:[2,29],42:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],35:[2,30],36:[2,30],
40:[2,30],42:[2,30]},{17:68,21:24,30:25,40:[1,28],42:[1,27],43:26},{18:[2,32],24:[2,32],36:[2,32],39:69,40:[1,70]},{18:[2,47],24:[2,47],36:[2,47],40:[2,47]},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],41:[1,71],42:[2,40],44:[2,40]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],35:[2,39],36:[2,39],40:[2,39],42:[2,39],44:[2,39]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],
19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{36:[1,72]},{18:[2,48],24:[2,48],36:[2,48],40:[2,48]},{41:[1,71]},{21:56,30:60,31:73,32:[1,57],33:[1,58],34:[1,59],35:[1,61],40:[1,28],42:[1,27],43:26},{18:[2,31],24:[2,31],32:[2,31],33:[2,31],34:[2,31],35:[2,31],36:[2,31],40:[2,31],42:[2,31]},{18:[2,33],24:[2,33],36:[2,33],40:[2,33]}],defaultActions:{3:[2,2],16:[2,1],50:[2,42]},parseError:function(a){throw Error(a);},parse:function(a){var b=[0],c=[null],d=[],f=this.table,e="",h=0,g=0,j=0;this.lexer.setInput(a);
this.lexer.yy=this.yy;this.yy.lexer=this.lexer;this.yy.parser=this;"undefined"==typeof this.lexer.yylloc&&(this.lexer.yylloc={});a=this.lexer.yylloc;d.push(a);var n=this.lexer.options&&this.lexer.options.ranges;"function"===typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var k,p,l,s,m={},q,t;;){l=b[b.length-1];if(this.defaultActions[l])s=this.defaultActions[l];else{if(null===k||"undefined"==typeof k)k=void 0,k=this.lexer.lex()||1,"number"!==typeof k&&(k=this.symbols_[k]||k);s=
f[l]&&f[l][k]}if("undefined"===typeof s||!s.length||!s[0]){var u="";if(!j){t=[];for(q in f[l])this.terminals_[q]&&2<q&&t.push("'"+this.terminals_[q]+"'");u=this.lexer.showPosition?"Parse error on line "+(h+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+t.join(", ")+", got '"+(this.terminals_[k]||k)+"'":"Parse error on line "+(h+1)+": Unexpected "+(1==k?"end of input":"'"+(this.terminals_[k]||k)+"'");this.parseError(u,{text:this.lexer.match,token:this.terminals_[k]||k,line:this.lexer.yylineno,loc:a,
expected:t})}}if(s[0]instanceof Array&&1<s.length)throw Error("Parse Error: multiple actions possible at state: "+l+", token: "+k);switch(s[0]){case 1:b.push(k);c.push(this.lexer.yytext);d.push(this.lexer.yylloc);b.push(s[1]);k=null;p?(k=p,p=null):(g=this.lexer.yyleng,e=this.lexer.yytext,h=this.lexer.yylineno,a=this.lexer.yylloc,0<j&&j--);break;case 2:t=this.productions_[s[1]][1];m.$=c[c.length-t];m._$={first_line:d[d.length-(t||1)].first_line,last_line:d[d.length-1].last_line,first_column:d[d.length-
(t||1)].first_column,last_column:d[d.length-1].last_column};n&&(m._$.range=[d[d.length-(t||1)].range[0],d[d.length-1].range[1]]);l=this.performAction.call(m,e,g,h,this.yy,s[1],c,d);if("undefined"!==typeof l)return l;t&&(b=b.slice(0,-2*t),c=c.slice(0,-1*t),d=d.slice(0,-1*t));b.push(this.productions_[s[1]][0]);c.push(m.$);d.push(m._$);s=f[b[b.length-2]][b[b.length-1]];b.push(s);break;case 3:return!0}}return!0},lexer:{EOF:1,parseError:function(a,b){if(this.yy.parser)this.yy.parser.parseError(a,b);else throw Error(a);
},setInput:function(a){this._input=a;this._more=this._less=this.done=!1;this.yylineno=this.yyleng=0;this.yytext=this.matched=this.match="";this.conditionStack=["INITIAL"];this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0};this.options.ranges&&(this.yylloc.range=[0,0]);this.offset=0;return this},input:function(){var a=this._input[0];this.yytext+=a;this.yyleng++;this.offset++;this.match+=a;this.matched+=a;a.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++;
this.options.ranges&&this.yylloc.range[1]++;this._input=this._input.slice(1);return a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input;this.yytext=this.yytext.substr(0,this.yytext.length-b-1);this.offset-=b;a=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1);this.matched=this.matched.substr(0,this.matched.length-1);c.length-1&&(this.yylineno-=c.length-1);var d=this.yylloc.range;this.yylloc={first_line:this.yylloc.first_line,
last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===a.length?this.yylloc.first_column:0)+a[a.length-c.length].length-c[0].length:this.yylloc.first_column-b};this.options.ranges&&(this.yylloc.range=[d[0],d[0]+this.yyleng-b]);return this},more:function(){this._more=!0;return this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(20<a.length?"...":"")+a.substr(-20).replace(/\n/g,
"")},upcomingInput:function(){var a=this.match;20>a.length&&(a+=this._input.substr(0,20-a.length));return(a.substr(0,20)+(20<a.length?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c;this._more||(this.match=this.yytext="");for(var d=this._currentRules(),f=0;f<d.length;f++)if((b=this._input.match(this.rules[d[f]]))&&(!a||
b[0].length>a[0].length))if(a=b,c=f,!this.options.flex)break;if(a){if(b=a[0].match(/(?:\r\n?|\n).*/g))this.yylineno+=b.length;this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:b?b[b.length-1].length-b[b.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+a[0].length};this.yytext+=a[0];this.match+=a[0];this.matches=a;this.yyleng=this.yytext.length;this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]);
this._more=!1;this._input=this._input.slice(a[0].length);this.matched+=a[0];a=this.performAction.call(this,this.yy,this,d[c],this.conditionStack[this.conditionStack.length-1]);this.done&&this._input&&(this.done=!1);if(a)return a}else return""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return"undefined"!==typeof a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},
popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(a){this.begin(a)},options:{},performAction:function(a,b,c){function d(a,c){return b.yytext=b.yytext.substr(a,b.yyleng-c)}switch(c){case 0:"\\\\"===b.yytext.slice(-2)?(d(0,1),this.begin("mu")):"\\"===b.yytext.slice(-1)?(d(0,1),this.begin("emu")):
this.begin("mu");if(b.yytext)return 14;break;case 1:return 14;case 2:return this.popState(),14;case 3:return d(0,4),this.popState(),15;case 4:return 35;case 5:return 36;case 6:return 25;case 7:return 16;case 8:return 20;case 9:return 19;case 10:return 19;case 11:return 23;case 12:return 22;case 13:this.popState();this.begin("com");break;case 14:return d(3,5),this.popState(),15;case 15:return 22;case 16:return 41;case 17:return 40;case 18:return 40;case 19:return 44;case 21:return this.popState(),
24;case 22:return this.popState(),18;case 23:return b.yytext=d(1,2).replace(/\\"/g,'"'),32;case 24:return b.yytext=d(1,2).replace(/\\'/g,"'"),32;case 25:return 42;case 26:return 34;case 27:return 34;case 28:return 33;case 29:return 40;case 30:return b.yytext=d(1,2),40;case 31:return"INVALID";case 32:return 5}},rules:[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,
/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/],conditions:{mu:{rules:[4,5,6,7,8,
9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[3],inclusive:!1},INITIAL:{rules:[0,1,32],inclusive:!0}}}};n.prototype=D;D.Parser=n;var J=new n,K=function(){};K.prototype={compiler:K,disassemble:function(){for(var a=this.opcodes,b,c=[],d,f,e=0,h=a.length;e<h;e++)if(b=a[e],"DECLARE"===b.opcode)c.push("DECLARE "+b.name+"="+b.value);else{d=[];for(var g=0;g<b.args.length;g++)f=b.args[g],"string"===typeof f&&(f='"'+f.replace("\n",
"\\n")+'"'),d.push(f);c.push(b.opcode+" "+d.join(" "))}return c.join("\n")},equals:function(a){var b=this.opcodes.length;if(a.opcodes.length!==b)return!1;for(var c=0;c<b;c++){var d=this.opcodes[c],f=a.opcodes[c];if(d.opcode!==f.opcode||d.args.length!==f.args.length)return!1;for(var e=0;e<d.args.length;e++)if(d.args[e]!==f.args[e])return!1}b=this.children.length;if(a.children.length!==b)return!1;for(c=0;c<b;c++)if(!this.children[c].equals(a.children[c]))return!1;return!0},guid:0,compile:function(a,
b){this.opcodes=[];this.children=[];this.depths={list:[]};this.options=b;var c=this.options.knownHelpers;this.options.knownHelpers={helperMissing:!0,blockHelperMissing:!0,each:!0,"if":!0,unless:!0,"with":!0,log:!0};if(c)for(var d in c)this.options.knownHelpers[d]=c[d];return this.accept(a)},accept:function(a){var b=a.strip||{};b.left&&this.opcode("strip");a=this[a.type](a);b.right&&this.opcode("strip");return a},program:function(a){a=a.statements;for(var b=0,c=a.length;b<c;b++)this.accept(a[b]);this.isSimple=
1===c;this.depths.list=this.depths.list.sort(function(a,b){return a-b});return this},compileProgram:function(a){a=(new this.compiler).compile(a,this.options);var b=this.guid++,c;this.usePartial=this.usePartial||a.usePartial;this.children[b]=a;for(var d=0,f=a.depths.list.length;d<f;d++)c=a.depths.list[d],2>c||this.addDepth(c-1);return b},block:function(a){var b=a.mustache,c=a.program;a=a.inverse;c&&(c=this.compileProgram(c));a&&(a=this.compileProgram(a));var b=b.sexpr,d=this.classifySexpr(b);"helper"===
d?this.helperSexpr(b,c,a):"simple"===d?(this.simpleSexpr(b),this.opcode("pushProgram",c),this.opcode("pushProgram",a),this.opcode("emptyHash"),this.opcode("blockValue")):(this.ambiguousSexpr(b,c,a),this.opcode("pushProgram",c),this.opcode("pushProgram",a),this.opcode("emptyHash"),this.opcode("ambiguousBlockValue"));this.opcode("append")},hash:function(a){a=a.pairs;var b,c;this.opcode("pushHash");for(var d=0,f=a.length;d<f;d++)b=a[d],c=b[1],this.options.stringParams?(c.depth&&this.addDepth(c.depth),
this.opcode("getContext",c.depth||0),this.opcode("pushStringParam",c.stringModeValue,c.type),"sexpr"===c.type&&this.sexpr(c)):this.accept(c),this.opcode("assignToHash",b[0]);this.opcode("popHash")},partial:function(a){var b=a.partialName;this.usePartial=!0;a.context?this.ID(a.context):this.opcode("push","depth0");this.opcode("invokePartial",b.name);this.opcode("append")},content:function(a){this.opcode("appendContent",a.string)},mustache:function(a){this.sexpr(a.sexpr);a.escaped&&!this.options.noEscape?
this.opcode("appendEscaped"):this.opcode("append")},ambiguousSexpr:function(a,b,c){a=a.id;var d=a.parts[0],f=null!=b||null!=c;this.opcode("getContext",a.depth);this.opcode("pushProgram",b);this.opcode("pushProgram",c);this.opcode("invokeAmbiguous",d,f)},simpleSexpr:function(a){a=a.id;"DATA"===a.type?this.DATA(a):a.parts.length?this.ID(a):(this.addDepth(a.depth),this.opcode("getContext",a.depth),this.opcode("pushContext"));this.opcode("resolvePossibleLambda")},helperSexpr:function(a,b,c){b=this.setupFullMustacheParams(a,
b,c);c=a.id.parts[0];if(this.options.knownHelpers[c])this.opcode("invokeKnownHelper",b.length,c);else{if(this.options.knownHelpersOnly)throw new j("You specified knownHelpersOnly, but used the unknown helper "+c,a);this.opcode("invokeHelper",b.length,c,a.isRoot)}},sexpr:function(a){var b=this.classifySexpr(a);"simple"===b?this.simpleSexpr(a):"helper"===b?this.helperSexpr(a):this.ambiguousSexpr(a)},ID:function(a){this.addDepth(a.depth);this.opcode("getContext",a.depth);a.parts[0]?this.opcode("lookupOnContext",
a.parts[0]):this.opcode("pushContext");for(var b=1,c=a.parts.length;b<c;b++)this.opcode("lookup",a.parts[b])},DATA:function(a){this.options.data=!0;if(a.id.isScoped||a.id.depth)throw new j("Scoped data references are not supported: "+a.original,a);this.opcode("lookupData");a=a.id.parts;for(var b=0,c=a.length;b<c;b++)this.opcode("lookup",a[b])},STRING:function(a){this.opcode("pushString",a.string)},INTEGER:function(a){this.opcode("pushLiteral",a.integer)},BOOLEAN:function(a){this.opcode("pushLiteral",
a.bool)},comment:function(){},opcode:function(a){this.opcodes.push({opcode:a,args:[].slice.call(arguments,1)})},declare:function(a,b){this.opcodes.push({opcode:"DECLARE",name:a,value:b})},addDepth:function(a){0!==a&&!this.depths[a]&&(this.depths[a]=!0,this.depths.list.push(a))},classifySexpr:function(a){var b=a.isHelper,c=a.eligibleHelper,d=this.options;c&&!b&&(d.knownHelpers[a.id.parts[0]]?b=!0:d.knownHelpersOnly&&(c=!1));return b?"helper":c?"ambiguous":"simple"},pushParams:function(a){for(var b=
a.length,c;b--;)if(c=a[b],this.options.stringParams)c.depth&&this.addDepth(c.depth),this.opcode("getContext",c.depth||0),this.opcode("pushStringParam",c.stringModeValue,c.type),"sexpr"===c.type&&this.sexpr(c);else this[c.type](c)},setupFullMustacheParams:function(a,b,c){var d=a.params;this.pushParams(d);this.opcode("pushProgram",b);this.opcode("pushProgram",c);a.hash?this.hash(a.hash):this.opcode("emptyHash");return d}};var A=function(a){this.value=a},x=function(){},S=p.COMPILER_REVISION,Y=p.REVISION_CHANGES,
T=p.log;x.prototype={nameLookup:function(a,b){var c,d;0===a.indexOf("depth")&&(c=!0);d=/^[0-9]+$/.test(b)?a+"["+b+"]":x.isValidJavaScriptVariableName(b)?a+"."+b:a+"['"+b+"']";return c?"("+a+" && "+d+")":d},compilerInfo:function(){return"this.compilerInfo = ["+S+",'"+Y[S]+"'];\n"},appendToBuffer:function(a){return this.environment.isSimple?"return "+a+";":{appendToBuffer:!0,content:a,toString:function(){return"buffer += "+a+";"}}},initializeBuffer:function(){return this.quotedString("")},namespace:"Handlebars",
compile:function(a,b,c,d){this.environment=a;this.options=b||{};T("debug",this.environment.disassemble()+"\n\n");this.name=this.environment.name;this.isChild=!!c;this.context=c||{programs:[],environments:[],aliases:{}};this.preamble();this.stackSlot=0;this.stackVars=[];this.registers={list:[]};this.hashes=[];this.compileStack=[];this.inlineStack=[];this.compileChildren(a,b);a=a.opcodes;this.i=0;for(c=a.length;this.i<c;this.i++)b=a[this.i],"DECLARE"===b.opcode?this[b.name]=b.value:this[b.opcode].apply(this,
b.args),b.opcode!==this.stripNext&&(this.stripNext=!1);this.pushSource("");if(this.stackSlot||this.inlineStack.length||this.compileStack.length)throw new j("Compile completed with content left on stack");return this.createFunctionContext(d)},preamble:function(){var a=[];if(this.isChild)a.push("");else{var b=this.namespace,c="helpers = this.merge(helpers, "+b+".helpers);";this.environment.usePartial&&(c=c+" partials = this.merge(partials, "+b+".partials);");this.options.data&&(c+=" data = data || {};");
a.push(c)}this.environment.isSimple?a.push(""):a.push(", buffer = "+this.initializeBuffer());this.lastContext=0;this.source=a},createFunctionContext:function(a){var b=this.stackVars.concat(this.registers.list);0<b.length&&(this.source[1]=this.source[1]+", "+b.join(", "));if(!this.isChild)for(var c in this.context.aliases)this.context.aliases.hasOwnProperty(c)&&(this.source[1]=this.source[1]+", "+c+"="+this.context.aliases[c]);this.source[1]&&(this.source[1]="var "+this.source[1].substring(2)+";");
this.isChild||(this.source[1]+="\n"+this.context.programs.join("\n")+"\n");this.environment.isSimple||this.pushSource("return buffer;");b=this.isChild?["depth0","data"]:["Handlebars","depth0","helpers","partials","data"];c=0;for(var d=this.environment.depths.list.length;c<d;c++)b.push("depth"+this.environment.depths.list[c]);c=this.mergeSource();this.isChild||(c=this.compilerInfo()+c);if(a)return b.push(c),Function.apply(this,b);a="function "+(this.name||"")+"("+b.join(",")+") {\n "+c+"}";T("debug",
a+"\n\n");return a},mergeSource:function(){for(var a="",b,c=0,d=this.source.length;c<d;c++){var f=this.source[c];f.appendToBuffer?b=b?b+"\n + "+f.content:f.content:(b&&(a+="buffer += "+b+";\n ",b=void 0),a+=f+"\n ")}return a},blockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var a=["depth0"];this.setupParams(0,a);this.replaceStack(function(b){a.splice(1,0,b);return"blockHelperMissing.call("+a.join(", ")+")"})},ambiguousBlockValue:function(){this.context.aliases.blockHelperMissing=
"helpers.blockHelperMissing";var a=["depth0"];this.setupParams(0,a);var b=this.topStack();a.splice(1,0,b);this.pushSource("if (!"+this.lastHelper+") { "+b+" = blockHelperMissing.call("+a.join(", ")+"); }")},appendContent:function(a){this.pendingContent&&(a=this.pendingContent+a);this.stripNext&&(a=a.replace(/^\s+/,""));this.pendingContent=a},strip:function(){this.pendingContent&&(this.pendingContent=this.pendingContent.replace(/\s+$/,""));this.stripNext="strip"},append:function(){this.flushInline();
var a=this.popStack();this.pushSource("if("+a+" || "+a+" === 0) { "+this.appendToBuffer(a)+" }");this.environment.isSimple&&this.pushSource("else { "+this.appendToBuffer("''")+" }")},appendEscaped:function(){this.context.aliases.escapeExpression="this.escapeExpression";this.pushSource(this.appendToBuffer("escapeExpression("+this.popStack()+")"))},getContext:function(a){this.lastContext!==a&&(this.lastContext=a)},lookupOnContext:function(a){this.push(this.nameLookup("depth"+this.lastContext,a,"context"))},
pushContext:function(){this.pushStackLiteral("depth"+this.lastContext)},resolvePossibleLambda:function(){this.context.aliases.functionType='"function"';this.replaceStack(function(a){return"typeof "+a+" === functionType ? "+a+".apply(depth0) : "+a})},lookup:function(a){this.replaceStack(function(b){return b+" == null || "+b+" === false ? "+b+" : "+this.nameLookup(b,a,"context")})},lookupData:function(){this.pushStackLiteral("data")},pushStringParam:function(a,b){this.pushStackLiteral("depth"+this.lastContext);
this.pushString(b);"sexpr"!==b&&("string"===typeof a?this.pushString(a):this.pushStackLiteral(a))},emptyHash:function(){this.pushStackLiteral("{}");this.options.stringParams&&(this.push("{}"),this.push("{}"))},pushHash:function(){this.hash&&this.hashes.push(this.hash);this.hash={values:[],types:[],contexts:[]}},popHash:function(){var a=this.hash;this.hash=this.hashes.pop();this.options.stringParams&&(this.push("{"+a.contexts.join(",")+"}"),this.push("{"+a.types.join(",")+"}"));this.push("{\n "+
a.values.join(",\n ")+"\n }")},pushString:function(a){this.pushStackLiteral(this.quotedString(a))},push:function(a){this.inlineStack.push(a);return a},pushLiteral:function(a){this.pushStackLiteral(a)},pushProgram:function(a){null!=a?this.pushStackLiteral(this.programExpression(a)):this.pushStackLiteral(null)},invokeHelper:function(a,b,c){this.context.aliases.helperMissing="helpers.helperMissing";this.useRegister("helper");a=this.lastHelper=this.setupHelper(a,b,!0);b=this.nameLookup("depth"+this.lastContext,
b,"context");b="helper = "+a.name+" || "+b;a.paramsInit&&(b+=","+a.paramsInit);this.push("("+b+",helper ? helper.call("+a.callParams+") : helperMissing.call("+a.helperMissingParams+"))");c||this.flushInline()},invokeKnownHelper:function(a,b){var c=this.setupHelper(a,b);this.push(c.name+".call("+c.callParams+")")},invokeAmbiguous:function(a,b){this.context.aliases.functionType='"function"';this.useRegister("helper");this.emptyHash();var c=this.setupHelper(0,a,b),d=this.lastHelper=this.nameLookup("helpers",
a,"helper"),f=this.nameLookup("depth"+this.lastContext,a,"context"),e=this.nextStack();c.paramsInit&&this.pushSource(c.paramsInit);this.pushSource("if (helper = "+d+") { "+e+" = helper.call("+c.callParams+"); }");this.pushSource("else { helper = "+f+"; "+e+" = typeof helper === functionType ? helper.call("+c.callParams+") : helper; }")},invokePartial:function(a){a=[this.nameLookup("partials",a,"partial"),"'"+a+"'",this.popStack(),"helpers","partials"];this.options.data&&a.push("data");this.context.aliases.self=
"this";this.push("self.invokePartial("+a.join(", ")+")")},assignToHash:function(a){var b=this.popStack(),c,d;this.options.stringParams&&(d=this.popStack(),c=this.popStack());var f=this.hash;c&&f.contexts.push("'"+a+"': "+c);d&&f.types.push("'"+a+"': "+d);f.values.push("'"+a+"': ("+b+")")},compiler:x,compileChildren:function(a,b){for(var c=a.children,d,f,e=0,h=c.length;e<h;e++){d=c[e];f=new this.compiler;var g=this.matchExistingProgram(d);null==g?(this.context.programs.push(""),g=this.context.programs.length,
d.index=g,d.name="program"+g,this.context.programs[g]=f.compile(d,b,this.context),this.context.environments[g]=d):(d.index=g,d.name="program"+g)}},matchExistingProgram:function(a){for(var b=0,c=this.context.environments.length;b<c;b++){var d=this.context.environments[b];if(d&&d.equals(a))return b}},programExpression:function(a){this.context.aliases.self="this";if(null==a)return"self.noop";var b=this.environment.children[a];a=b.depths.list;for(var c=[b.index,b.name,"data"],d=0,f=a.length;d<f;d++)b=
a[d],1===b?c.push("depth0"):c.push("depth"+(b-1));return(0===a.length?"self.program(":"self.programWithDepth(")+c.join(", ")+")"},register:function(a,b){this.useRegister(a);this.pushSource(a+" = "+b+";")},useRegister:function(a){this.registers[a]||(this.registers[a]=!0,this.registers.list.push(a))},pushStackLiteral:function(a){return this.push(new A(a))},pushSource:function(a){this.pendingContent&&(this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent))),this.pendingContent=void 0);
a&&this.source.push(a)},pushStack:function(a){this.flushInline();var b=this.incrStack();a&&this.pushSource(b+" = "+a+";");this.compileStack.push(b);return b},replaceStack:function(a){var b="",c=this.isInline(),d,f,e;c?(d=this.popStack(!0),d instanceof A?(d=d.value,e=!0):(f=!this.stackSlot,b=!f?this.topStackName():this.incrStack(),b="("+this.push(b)+" = "+d+"),",d=this.topStack())):d=this.topStack();a=a.call(this,d);c?(e||this.popStack(),f&&this.stackSlot--,this.push("("+b+a+")")):(/^stack/.test(d)||
(d=this.nextStack()),this.pushSource(d+" = ("+b+a+");"));return d},nextStack:function(){return this.pushStack()},incrStack:function(){this.stackSlot++;this.stackSlot>this.stackVars.length&&this.stackVars.push("stack"+this.stackSlot);return this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var a=this.inlineStack;if(a.length){this.inlineStack=[];for(var b=0,c=a.length;b<c;b++){var d=a[b];d instanceof A?this.compileStack.push(d):this.pushStack(d)}}},isInline:function(){return this.inlineStack.length},
popStack:function(a){var b=this.isInline(),c=(b?this.inlineStack:this.compileStack).pop();if(!a&&c instanceof A)return c.value;if(!b){if(!this.stackSlot)throw new j("Invalid stack pop");this.stackSlot--}return c},topStack:function(a){var b=this.isInline()?this.inlineStack:this.compileStack,b=b[b.length-1];return!a&&b instanceof A?b.value:b},quotedString:function(a){return'"'+a.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,
"\\u2029")+'"'},setupHelper:function(a,b,c){var d=[];a=this.setupParams(a,d,c);var f=this.nameLookup("helpers",b,"helper");return{params:d,paramsInit:a,name:f,callParams:["depth0"].concat(d).join(", "),helperMissingParams:c&&["depth0",this.quotedString(b)].concat(d).join(", ")}},setupOptions:function(a,b){var c=[],d=[],f=[],e,h;c.push("hash:"+this.popStack());this.options.stringParams&&(c.push("hashTypes:"+this.popStack()),c.push("hashContexts:"+this.popStack()));e=this.popStack();if((h=this.popStack())||
e)h||(this.context.aliases.self="this",h="self.noop"),e||(this.context.aliases.self="this",e="self.noop"),c.push("inverse:"+e),c.push("fn:"+h);for(h=0;h<a;h++)e=this.popStack(),b.push(e),this.options.stringParams&&(f.push(this.popStack()),d.push(this.popStack()));this.options.stringParams&&(c.push("contexts:["+d.join(",")+"]"),c.push("types:["+f.join(",")+"]"));this.options.data&&c.push("data:data");return c},setupParams:function(a,b,c){a="{"+this.setupOptions(a,b).join(",")+"}";if(c)return this.useRegister("options"),
b.push("options"),"options="+a;b.push(a);return""}};for(var n="break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public let yield".split(" "),D=x.RESERVED_WORDS={},L=0,Z=n.length;L<Z;L++)D[n[L]]=
!0;x.isValidJavaScriptVariableName=function(a){return!x.RESERVED_WORDS[a]&&/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(a)?!0:!1};var $=function(a){if(a.constructor===C.ProgramNode)return a;J.yy=C;return J.parse(a)},aa=m.create,n=function(){var a=aa();a.compile=function(b,c){var d=c;if(null==b||"string"!==typeof b&&b.constructor!==a.AST.ProgramNode)throw new j("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+b);d=d||{};"data"in d||(d.data=!0);var f;return function(c,h){if(!f){var g=
a.parse(b),g=(new a.Compiler).compile(g,d),g=(new a.JavaScriptCompiler).compile(g,d,void 0,!0);f=a.template(g)}return f.call(this,c,h)}};a.precompile=function(b,c){var d=c;if(null==b||"string"!==typeof b&&b.constructor!==a.AST.ProgramNode)throw new j("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+b);d=d||{};"data"in d||(d.data=!0);var f=a.parse(b),f=(new a.Compiler).compile(f,d);return(new a.JavaScriptCompiler).compile(f,d)};a.AST=C;a.Compiler=K;a.JavaScriptCompiler=
x;a.Parser=J;a.parse=$;return a},m=n();m.create=n;return m}();

File diff suppressed because one or more lines are too long

View File

@ -1,13 +0,0 @@
/*
json2.js
2011-10-19
Public Domain.
See http://www.JSON.org/js.html
*/
var JSON;JSON||(JSON={});
(function(){function k(a){return 10>a?"0"+a:a}function o(a){p.lastIndex=0;return p.test(a)?'"'+a.replace(p,function(a){var c=r[a];return"string"===typeof c?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function m(a,j){var c,d,h,n,g=e,f,b=j[a];b&&("object"===typeof b&&"function"===typeof b.toJSON)&&(b=b.toJSON(a));"function"===typeof i&&(b=i.call(j,a,b));switch(typeof b){case "string":return o(b);case "number":return isFinite(b)?String(b):"null";case "boolean":case "null":return String(b);case "object":if(!b)return"null";
e+=l;f=[];if("[object Array]"===Object.prototype.toString.apply(b)){n=b.length;for(c=0;c<n;c+=1)f[c]=m(c,b)||"null";h=0===f.length?"[]":e?"[\n"+e+f.join(",\n"+e)+"\n"+g+"]":"["+f.join(",")+"]";e=g;return h}if(i&&"object"===typeof i){n=i.length;for(c=0;c<n;c+=1)"string"===typeof i[c]&&(d=i[c],(h=m(d,b))&&f.push(o(d)+(e?": ":":")+h))}else for(d in b)Object.prototype.hasOwnProperty.call(b,d)&&(h=m(d,b))&&f.push(o(d)+(e?": ":":")+h);h=0===f.length?"{}":e?"{\n"+e+f.join(",\n"+e)+"\n"+g+"}":"{"+f.join(",")+
"}";e=g;return h}}"function"!==typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+k(this.getUTCMonth()+1)+"-"+k(this.getUTCDate())+"T"+k(this.getUTCHours())+":"+k(this.getUTCMinutes())+":"+k(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var q=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
p=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,e,l,r={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},i;"function"!==typeof JSON.stringify&&(JSON.stringify=function(a,j,c){var d;l=e="";if(typeof c==="number")for(d=0;d<c;d=d+1)l=l+" ";else typeof c==="string"&&(l=c);if((i=j)&&typeof j!=="function"&&(typeof j!=="object"||typeof j.length!=="number"))throw Error("JSON.stringify");return m("",{"":a})});
"function"!==typeof JSON.parse&&(JSON.parse=function(a,e){function c(a,d){var g,f,b=a[d];if(b&&typeof b==="object")for(g in b)if(Object.prototype.hasOwnProperty.call(b,g)){f=c(b,g);f!==void 0?b[g]=f:delete b[g]}return e.call(a,d,b)}var d,a=String(a);q.lastIndex=0;q.test(a)&&(a=a.replace(q,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){d=eval("("+a+")");return typeof e==="function"?c({"":d},""):d}throw new SyntaxError("JSON.parse");})})();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,37 @@
/*!
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, $) {
$(document).ready(function() {
$('a.remove-link').click(function() {
var url = $(this).attr('href'),
message = Mibew.Localization.trans(
'Are you sure that you want to delete address {0} from the blocked list?',
$(this).data('ban-address')
);
Mibew.Utils.confirm(message, function(value) {
if (value) {
window.location.href = url;
}
});
return false;
});
});
})(Mibew, jQuery);

View File

@ -1,38 +0,0 @@
/*!
* Copyright 2005-2014 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
*/
var myAgent = "";
var myVer = 0;
var myRealAgent = "";
function detectAgent() {
var AGENTS = ["opera","msie","safari","firefox","netscape","mozilla"];
var agent = navigator.userAgent.toLowerCase();
for (var i = 0; i < AGENTS.length; i++) {
var agentStr = AGENTS[i];
if (agent.indexOf(agentStr) != -1) {
myAgent = agentStr;
if (!window.RegExp)
break;
var versionExpr = new RegExp(agentStr + "[ \/]?([0-9]+(\.[0-9]+)?)");
if (versionExpr.exec(agent) != null) {
myVer = parseFloat(RegExp.$1);
}
break;
}
}
myRealAgent = myAgent;
if( navigator.product == "Gecko")
myAgent = "moz";
}
detectAgent();
function getEl(name) {
return document.getElementById(name);
}

View File

@ -0,0 +1,26 @@
/*!
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, $) {
$(document).ready(function(){
$('#copy-button-code').click(function(e){
$("#button-code").select();
document.execCommand('copy');
});
});
})(Mibew, jQuery);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function (Mibew, _) {
@ -18,9 +28,6 @@
// Initialize application
app.addInitializer(function(options){
// Store plugin options
Mibew.PluginOptions = options.plugins || {};
// Initialize Server
Mibew.Objects.server = new Mibew.Server(_.extend(
{'interactionType': MibewAPIChatInteraction},
@ -44,8 +51,7 @@
app.Invitation.start(options.invitationOptions);
break;
default:
throw new Error('Dont know how to start!');
break;
throw new Error("Don't know how to start!");
}
});

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew) {
@ -14,17 +24,25 @@
Mibew.Views.MessagesCollection = Mibew.Views.CollectionBase.extend(
/** @lends Mibew.Views.MessagesCollection.prototype */
{
/**
* Default item view constructor.
* @type Function
*/
itemView: Mibew.Views.Message,
/**
* Class name for view's DOM element
* @type String
*/
className: 'messages-collection'
className: 'messages-collection',
/**
* Returns default child view constructor.
*
* The function is used instead of "childView" property to provide
* an ability to override child view constructor without this class
* overriding.
*
* @param {Backbone.Model} model The model the view created for.
* @returns {Backbone.Marionette.ItemView}
*/
getChildView: function(model) {
return Mibew.Views.Message;
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew) {
@ -14,17 +24,25 @@
Mibew.Views.StatusCollection = Mibew.Views.CollectionBase.extend(
/** @lends Mibew.Views.StatusCollection.prototype */
{
/**
* Default item view constructor.
* @type Function
*/
itemView: Mibew.Views.Status,
/**
* Class name for view's DOM element
* @type String
*/
className: 'status-collection'
className: 'status-collection',
/**
* Returns default child view constructor.
*
* The function is used instead of "childView" property to provide
* an ability to override child view constructor without this class
* overriding.
*
* @param {Backbone.Model} model The model the view created for.
* @returns {Backbone.Marionette.ItemView}
*/
getChildView: function(model) {
return Mibew.Views.Status;
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, _){
@ -109,7 +119,7 @@
eventArgs = {
'messageData': messageData,
'model': false
}
};
// Trigger event. See description of eventName and eventArgs
// above.

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){
@ -11,7 +21,7 @@
/**
* Represents chat layout
*/
Mibew.Layouts.Chat = Backbone.Marionette.Layout.extend(
Mibew.Layouts.Chat = Backbone.Marionette.LayoutView.extend(
/** @lends Mibew.Layouts.Chat.prototype */
{
/**
@ -29,7 +39,7 @@
avatarRegion: '#avatar-region',
messagesRegion: {
selector: '#messages-region',
regionType: Mibew.Regions.Messages
regionClass: Mibew.Regions.Messages
},
statusRegion: '#status-region',
messageFormRegion: '#message-form-region'
@ -49,7 +59,7 @@
return {
page: models.page.toJSON(),
user: models.user.toJSON()
}
};
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){
@ -11,7 +21,7 @@
/**
* Represents invitation layout
*/
Mibew.Layouts.Invitation = Backbone.Marionette.Layout.extend(
Mibew.Layouts.Invitation = Backbone.Marionette.LayoutView.extend(
/** @lends Mibew.Layouts.Invitation.prototype */
{
/**
@ -27,7 +37,7 @@
regions: {
messagesRegion: {
selector: '#invitation-messages-region',
regionType: Mibew.Regions.Messages
regionClass: Mibew.Regions.Messages
}
}
}

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){
@ -11,7 +21,7 @@
/**
* Represents leave message page layout
*/
Mibew.Layouts.LeaveMessage = Backbone.Marionette.Layout.extend(
Mibew.Layouts.LeaveMessage = Backbone.Marionette.LayoutView.extend(
/** @lends Mibew.Layouts.LeaveMessage.prototype */
{
/**
@ -41,7 +51,7 @@
serializeData: function() {
return {
page: Mibew.Objects.Models.page.toJSON()
}
};
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){
@ -11,7 +21,7 @@
/**
* Represents survey layout
*/
Mibew.Layouts.Survey = Backbone.Marionette.Layout.extend(
Mibew.Layouts.Survey = Backbone.Marionette.LayoutView.extend(
/** @lends Mibew.Layouts.Survey.prototype */
{
/**
@ -40,7 +50,7 @@
serializeData: function() {
return {
page: Mibew.Objects.Models.page.toJSON()
}
};
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
@ -30,6 +40,6 @@ MibewAPIChatInteraction = function() {
return [
'result'
];
}
}
};
};
MibewAPIChatInteraction.prototype = new MibewAPIInteraction();

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, Handlebars) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {
@ -39,13 +49,15 @@
*/
closeThread: function() {
// Show confirmation message if can
var confirmMessage = Mibew.Localization.get('Are you sure want to leave chat?');
var confirmMessage = Mibew.Localization.trans('Are you sure that you want to leave the chat?'),
context = this;
if (confirmMessage !== false) {
if (! confirm(confirmMessage)) {
return;
}
Mibew.Utils.confirm(confirmMessage, function(value) {
if (value) {
context.model.closeThread();
}
});
}
this.model.closeThread();
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {
@ -35,13 +45,13 @@
),
/**
* Dispalay history window
* Display history window
*/
showHistory: function() {
var user = Mibew.Objects.Models.user;
var link = this.model.get('link');
if (user.get('isAgent') && link) {
var winParams = this.model.get('windowParams');
var winParams = Mibew.Utils.buildWindowParams(this.model.get('windowParams'));
// TODO: Kill &amp; at the server side
link = link.replace('&amp;', '&', 'g');

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {
@ -38,11 +48,15 @@
* Move to secure chat
*/
secure: function() {
var link = this.model.get('link')
if (window.location.protocol == 'https:') {
return;
}
var link = this.model.get('link');
if (link) {
var style = Mibew.Objects.Models.page.get('style');
window.location.href = link.replace(/\&amp\;/g, '&')
+ (style ? ('&style=' + style) : '');
+ (style ? ((link.indexOf('?') > -1 ? '&' : '?')
+ 'style=' + style) : '');
}
}
}

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {
@ -34,6 +44,17 @@
}
),
/**
* Override Backbone.Marionette.ItemView.serializeData to pass some
* extra fields to template.
* @returns {Object} Template data
*/
serializeData: function() {
var data = this.model.toJSON();
data.user = Mibew.Objects.Models.user.toJSON();
return data;
},
/**
* Load and display send mail window
*/
@ -41,7 +62,7 @@
var link = this.model.get('link');
var page = Mibew.Objects.Models.page;
if (link) {
var winParams = this.model.get('windowParams');
var winParams = Mibew.Utils.buildWindowParams(this.model.get('windowParams'));
var style = page.get('style');
var styleArg = '';

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {

View File

@ -0,0 +1,68 @@
/*!
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {
/**
* @class Represents Tracked path control view
*/
Mibew.Views.TrackedPathControl = Mibew.Views.Control.extend(
/** @lends Mibew.Views.TrackedPathControl.prototype */
{
/**
* Template function
* @type Function
*/
template: Handlebars.templates['chat/controls/tracked_path'],
/**
* Map ui events to view methods
* The view inherits events from
* {@link Mibew.Views.Control.prototype.events}.
* @type Object
*/
events: _.extend(
{},
Mibew.Views.Control.prototype.events,
{
'click': 'showTrackedPath'
}
),
/**
* Display tracked path window
*/
showTrackedPath: function() {
var user = Mibew.Objects.Models.user;
var link = this.model.get('link');
if (user.get('isAgent') && link) {
var winParams = Mibew.Utils.buildWindowParams(this.model.get('windowParams'));
// TODO: Kill &amp; at the server side
link = link.replace('&amp;', '&', 'g');
var newWindow = window.open(link, 'UserTrackedPath', winParams);
if (newWindow !== null) {
newWindow.focus();
newWindow.opener=window;
}
}
}
}
);
})(Mibew, Handlebars, _);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, Handlebars){
@ -32,7 +42,7 @@
serializeData: function() {
return {
page: Mibew.Objects.Models.page.toJSON()
}
};
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _){
@ -71,7 +81,7 @@
// Update group id
if (this.model.get('groups')) {
values.groupId = this.ui.groupSelect.val()
values.groupId = this.ui.groupSelect.val();
}
// Update name

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, Handlebars){
@ -32,7 +42,7 @@
serializeData: function() {
return {
page: Mibew.Objects.Models.page.toJSON()
}
};
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, Handlebars) {
@ -30,9 +40,7 @@
'keydown #message-input': 'messageKeyDown',
'keyup #message-input': 'checkUserTyping',
'change #message-input': 'checkUserTyping',
'change #predefined': 'selectPredefinedAnswer',
'focus #message-input': 'setFocus',
'blur #message-input': 'dropFocus'
'change #predefined': 'selectPredefinedAnswer'
},
/**
@ -68,6 +76,7 @@
serializeData: function() {
var data = this.model.toJSON();
data.user = Mibew.Objects.Models.user.toJSON();
data.sendShortcut = this.getSendShortcut();
return data;
},
@ -75,6 +84,9 @@
* Get, check and post message
*/
postMessage: function() {
if (this.isDisabledInput()){
return;
}
var msg = this.ui.message.val();
// TODO: Think about it
// Cut multiple line breaks
@ -82,12 +94,12 @@
if (msg != '') {
this.disableInput();
this.model.postMessage(msg);
Mibew.Objects.Collections.messages.once(
'multiple:add',
this.postMessageComplete,
this
);
}
Mibew.Objects.Collections.messages.on(
'multiple:add',
this.postMessageComplete,
this
);
},
/**
@ -120,6 +132,13 @@
},
/**
* Check is disabled message input area
*/
isDisabledInput: function() {
return this.ui.message.attr('disabled') == 'disabled';
},
/**svn
* Clear message input area
*/
clearInput: function() {
@ -138,14 +157,8 @@
postMessageComplete: function() {
this.clearInput();
this.enableInput();
if (this.focused) {
this.ui.focus();
}
Mibew.Objects.Collections.messages.off(
'multiple:add',
this.postMessageComplete,
this
);
// Always set focus on message input after message sent
this.ui.message.focus();
},
/**
@ -183,17 +196,20 @@
},
/**
* Set focus indicator
* Builds a string with send shortcut.
*
* @returns {String}
*/
setFocus: function() {
this.focused = true
},
getSendShortcut: function() {
if (this.model.get('ignoreCtrl')) {
return 'Enter';
}
/**
* Unset focus indicator
*/
dropFocus: function() {
this.focused = false;
// There is no Ctrl key on mac, thus we need to use a command
// key instead.
return (navigator.userAgent.indexOf('mac') !== -1)
? '&#8984;-Enter'
: 'Ctrl-Enter';
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, Handlebars) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){
@ -29,7 +39,7 @@
*/
ui: {
groupSelect: 'select[name="group"]',
groupDescription: '#groupDescription',
groupDescription: '#group-description',
name: 'input[name="name"]',
email: 'input[name="email"]',
message: 'textarea[name="message"]',

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars, _){
@ -48,7 +58,7 @@
// Update group id
if (this.model.get('groups')) {
values.groupId = this.ui.groupSelect.val()
values.groupId = this.ui.groupSelect.val();
}
// Update name

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -44,6 +54,13 @@
_.bind(this.apiSetupAvatar, this)
)
);
// Update avatar if operator changed.
Mibew.Objects.Models.thread.on(
'change:agentId',
this.setFromThread,
this
);
},
// Model finalizer
@ -62,9 +79,37 @@
* @param args {Object} An object of passed arguments
*/
apiSetupAvatar: function(args) {
if (args.imageLink) {
this.set({imageLink: args.imageLink});
this.set({imageLink: (args.imageLink || false)});
},
/**
* Sets avatar based on data from the thread.
* @param {Object} thread An instance of Mibew.Models.Thread
*/
setFromThread: function(thread) {
if (!thread.get('agentId')) {
// There is no operator. Hide the avatar.
this.set({imageLink: false});
return;
}
// Request operator's avatar at the server side
Mibew.Objects.server.callFunctions(
[{
'function': 'getAvatar',
'arguments': {
'references': {},
'return': {
'imageLink': 'imageLink'
},
'threadId': thread.get('id'),
'token': thread.get('token')
}
}],
_.bind(this.apiSetupAvatar, this),
true
);
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _) {
@ -47,7 +57,7 @@
* Not applicable for agents.
* @type Boolean
*/
dafaultName: true
defaultName: true
}
)
}

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){
@ -49,7 +59,7 @@
}],
function(args){
if (args.closed) {
window.close();
Mibew.Utils.closeChatPopup();
} else {
// Something went wrong. Display error message
Mibew.Objects.Models.Status.message.setMessage(

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -50,7 +60,7 @@
* @returns {String} Model type
*/
getModelType: function() {
return 'SoundControl'
return 'SoundControl';
}
}
);

View File

@ -0,0 +1,63 @@
/*!
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
/**
* @class Tracked path control model
*/
Mibew.Models.TrackedPathControl = Mibew.Models.Control.extend(
/** @lends Mibew.Models.TrackedPathControl.prototype */
{
/**
* A list of default model values.
*
* The model inherits defaults from
* {@link Mibew.Models.Control.prototype.defaults}.
* @type Object
*/
defaults: _.extend(
{},
Mibew.Models.Control.prototype.defaults,
{
/**
* An URL of the tracked path page or false by default.
* @type String|Boolean
*/
link: false,
/**
* Params string for tracked path popup window
* @type String
*/
windowParams: ''
}
),
/**
* Returns model type
* @returns {String} Model type
*/
getModelType: function() {
return 'TrackedPathControl';
}
}
);
})(Mibew, _);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -53,24 +63,24 @@
// Check email
if (typeof attributes.email != 'undefined') {
if (! attributes.email) {
return l.get('leavemessage.error.email.required');
return l.trans('Please fill "{0}".', l.trans('Your email'));
}
if(! Mibew.Utils.checkEmail(attributes.email)) {
return l.get('leavemessage.error.wrong.email');
return l.trans('Please fill "{0}" correctly.', l.trans('Your email'));
}
}
// Check name
if (typeof attributes.name != 'undefined') {
if (! attributes.name) {
return l.get('leavemessage.error.name.required');
return l.trans('Please fill "{0}".', l.trans('Your name'));
}
}
// Check message
if (typeof attributes.message != 'undefined') {
if (! attributes.message) {
return l.get('leavemessage.error.message.required');
return l.trans('Please fill "{0}".', l.trans('Message'));
}
}
@ -78,7 +88,7 @@
if (this.get('showCaptcha')) {
if (typeof attributes.captcha != 'undefined') {
if (! attributes.captcha) {
return l.get('The letters you typed don\'t match the letters that were shown in the picture.');
return l.trans('The letters you typed don\'t match the letters that were shown in the picture.');
}
}
}

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone) {

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _) {
@ -60,7 +70,7 @@
playNewMessageSound: function() {
if (! this.get('skipNextMessageSound')) {
// Build sound path
var path = Mibew.Objects.Models.page.get('mibewRoot');
var path = Mibew.Objects.Models.page.get('mibewBasePath');
if (typeof path !== 'undefined') {
path += '/sounds/new_message';
// Play sound

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -43,7 +53,7 @@
* @returns {String} Model type
*/
getModelType: function() {
return 'StatusMessage'
return 'StatusMessage';
},
/**

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -45,7 +55,7 @@
* @returns {String} Model type
*/
getModelType: function() {
return 'StatusTyping'
return 'StatusTyping';
},
/**

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -51,11 +61,23 @@
* @param Object attributes Attributes hash for test
*/
validate: function(attributes) {
// Check visitor's name
if (this.get('canChangeName') && typeof attributes.name != 'undefined') {
var trimmedName = attributes.name
// Remove leading spaces from the name
.replace(/^\s+/, '')
// Remove trailing spaces from the name
.replace(/\s+$/, '');
if (trimmedName.length === 0) {
return Mibew.Localization.trans('Name is required.');
}
}
// Check email
if (this.get('showEmail')) {
if (typeof attributes.email != 'undefined') {
if(! Mibew.Utils.checkEmail(attributes.email)) {
return Mibew.Localization.get(
return Mibew.Localization.trans(
'Wrong email address.'
);
}

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){
@ -91,6 +101,15 @@
windowParams: options.windowsParams.history
});
ctrlsCollection.add(controls.history);
if (options.links.tracked) {
controls.tracked_path = new Mibew.Models.TrackedPathControl({
weight: 170,
link: options.links.tracked,
windowParams: options.windowsParams.trackedPath
});
ctrlsCollection.add(controls.tracked_path);
}
}
// Create toggle sound button
@ -148,7 +167,9 @@
// Initialize avatar only for user
if (! models.user.get('isAgent')) {
models.avatar = new Mibew.Models.Avatar();
models.avatar = new Mibew.Models.Avatar({
imageLink: (options.avatar || false)
});
layout.avatarRegion.show(new Mibew.Views.Avatar({
model: models.avatar
}));
@ -176,6 +197,15 @@
models.soundManager = new Mibew.Models.ChatSoundManager();
// If the chat is ran inside an iframe we need to tell the parent page
// that the chat is started. This is needed to reopen chat when the user
// navigates to another page.
if (!models.user.get('isAgent') && options.links.chat) {
if (window.parent && window.parent.postMessage && (window.parent !== window)) {
window.parent.postMessage('mibew-chat-started:' + window.name + ':' + options.links.chat, '*');
}
}
// TODO: May be move it somewhere else
// Periodically call update function at the server side
periodicallyCalled.push(
@ -191,6 +221,8 @@
"function": "update",
"arguments": {
"return": {
'threadState': 'threadState',
'threadAgentId': 'threadAgentId',
'typing': 'typing',
'canPost': 'canPost'
},
@ -202,7 +234,7 @@
"user": (! user.get('isAgent'))
}
}
]
];
},
function(args) {
// Check if there was an error
@ -220,6 +252,11 @@
Mibew.Objects.Models.user.set({
canPost: args.canPost || false
});
// Update thread fields
Mibew.Objects.Models.thread.set({
'agentId': args.threadAgentId,
'state': args.threadState
});
}
)
);
@ -230,12 +267,12 @@
// Restart server updater because module just started and there are no
// reasons to wait refresh time to get results of previous request
Mibew.Objects.server.restartUpdater();
})
});
// Add module finalizer
chat.addFinalizer(function() {
// Close layout
Mibew.Objects.chatLayout.close();
Mibew.Objects.chatLayout.destroy();
// Stop call functions periodically

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){
@ -68,7 +78,7 @@
"user": true
}
}
]
];
},
function() {}
)
@ -80,12 +90,12 @@
// Restart server updater because module just started and there are no
// reasons to wait refresh time to get results of previous request
Mibew.Objects.server.restartUpdater();
})
});
// Add module finalizer
invitation.addFinalizer(function() {
// Close layout
Mibew.Objects.invitationLayout.close();
Mibew.Objects.invitationLayout.destroy();
// Stop call functions periodically

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){
@ -48,8 +58,8 @@
// When message sent form should be hide and description should be
// changed
models.leaveMessageForm.on('submit:complete', function() {
objs.leaveMessageLayout.leaveMessageFormRegion.close();
objs.leaveMessageLayout.descriptionRegion.close();
objs.leaveMessageLayout.leaveMessageFormRegion.empty();
objs.leaveMessageLayout.descriptionRegion.empty();
objs.leaveMessageLayout.descriptionRegion.show(
new Mibew.Views.LeaveMessageSentDescription()
@ -61,7 +71,7 @@
// Add module finalizer
leaveMessage.addFinalizer(function() {
// Close layout
Mibew.Objects.leaveMessageLayout.close();
Mibew.Objects.leaveMessageLayout.destroy();
// Remove instance of leaveMessage form model
delete Mibew.Objects.Models.leaveMessageForm;

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){
@ -40,7 +50,7 @@
// Add module finalizer
survey.addFinalizer(function() {
// Close layout
Mibew.Objects.surveyLayout.close();
Mibew.Objects.surveyLayout.destroy();
// Remove instance of survey form model
delete Mibew.Objects.Models.surveyForm;

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){
@ -16,11 +26,11 @@
{
/**
* Show view event handler. Register handler to view's
* 'after:item:added' event.
* 'add:child' event.
* @param {Backbone.Marionette.ItemView} view View to show in region
*/
onShow: function(view) {
view.on('after:item:added', this.scrollToBottom, this);
view.on('add:child', this.scrollToBottom, this);
},
/**

View File

@ -0,0 +1,43 @@
/*!
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew){
/**
* @namespace Holds utility functions
*/
Mibew.Utils = Mibew.Utils || {};
/**
* Closes chat window.
*
* The method helps to close chat popup no mater how it's implemented
* (iframe or window).
*/
Mibew.Utils.closeChatPopup = function() {
if (window.parent && (window.parent !== window) && window.parent.postMessage) {
// It seems that the chat is working in an iframe. Tell the parent
// window that the chat is stoped so it could close the iframe.
window.parent.postMessage('mibew-chat-closed:' + window.name, '*');
} else {
// Just close the window.
window.close();
}
};
})(Mibew);

View File

@ -0,0 +1,629 @@
/*!
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @namespace Holds all Mibew Messenger functionality
*/
var Mibew = Mibew || {};
(function(Mibew) {
if (Mibew.ChatPopup) {
// It seems that this file was already loaded. We do not need to do the
// job twice.
return;
}
/**
* @namespace Holds all functionality related with chat popups
*/
Mibew.ChatPopup = {};
/**
* @namespace Holds objects instances
*/
Mibew.Objects = Mibew.Objects || {};
/**
* @namespace Holds all popups instances.
*/
Mibew.Objects.ChatPopups = {};
/**
* @namespace Holds utility functions
*/
Mibew.Utils = {};
/**
* Create a cookie for the second level domain with path equals to '/'.
*
* @param {String} name Cookie name
* @param {String} value Cookie value
* @param {Date} expires Indicates when the cookie expires. If the value is
* omitted a session cookie will be created.
*/
Mibew.Utils.createCookie = function(name, value, expires) {
if (navigator.cookieEnabled) {
var domain_parts = document.location.hostname.split('.').reverse();
var domain = domain_parts[0];
var position = 0;
do {
document.cookie = "" + name + "=" + value + "; "
+ "path=/; "
+ (document.location.protocol == 'https:' ? "SameSite=None; secure; " : '')
+ "domain=" + (Mibew.Utils.cookiesDomain || domain) + "; "
+ (expires ? ('expires=' + expires.toUTCString() + '; ') : '');
if (Mibew.Utils.readCookie(name) == value) {
if (!Mibew.Utils.cookiesDomain) {
Mibew.Utils.cookiesDomain = domain;
}
}
else {
position++;
domain = domain_parts[position] + '.' + domain;
}
} while((position < domain_parts.length) && !Mibew.Utils.cookiesDomain);
}
};
/**
* Try to read cookie.
*
* @param {String} name Cookie name
* @returns {String|Boolean} Cookie value or boolean false if cookie with
* specified name does not exist
*/
Mibew.Utils.readCookie = function(name) {
var cookies = document.cookie.split('; ');
var nameForSearch = name + '=';
var value = false;
for (var i = 0; i < cookies.length; i++) {
if (cookies[i].indexOf(nameForSearch) != -1) {
value = cookies[i].substr(nameForSearch.length);
break;
}
}
return value;
};
/**
* Deletes cookie.
*
* @param {String} name Name of the cookie that should be deleted.
*/
Mibew.Utils.deleteCookie = function(name) {
Mibew.Utils.createCookie(name, '', (new Date(0)));
};
/**
* Sets correct prototypes chain.
*
* This function is based on the logic used in Object.create method.
* Unfortunately not all target browsers support this function thus it
* should be implemented here.
*
* Warning: this methods completely rewrites prototype of "ctor" argument.
*
* @type {Function}
* @param {Function} ctor An object constructor which prototype should be
* updated.
* @param {Function} superCtor An object constructor which prototype should
* be used.
*/
Mibew.Utils.inherits = (function() {
// Tmp function is defined in closure because in such case only one
// temporary function will be kept in memory regardless of inherits
// function calls number.
var Tmp = function() {};
return function(ctor, superCtor) {
Tmp.prototype = superCtor.prototype;
ctor.prototype = new Tmp();
Tmp.prototype = null;
ctor.prototype.constructor = ctor;
};
})();
/**
* Attaches an event listener to the target object's event.
*
* This method uses native "addEventListener" in modern browsers and a
* workaround for IE < 9.
*
* @param {Object} target The object which fires the event.
* @param {String} eventName Name of the event.
* @param {Function} listener The function that should be triggered.
*/
Mibew.Utils.addEventListener = function(target, eventName, listener) {
if (target.addEventListener) {
// A regular browser is used
target.addEventListener(eventName, listener, false);
} else {
if (target.attachEvent) {
// This is needed for IE < 9
target.attachEvent(
'on' + eventName,
// The closure is used to use valid this reference in the
// listener.
function (event) {
listener.call(target, event);
});
}
}
};
/**
* Loads CSS file and attach it to DOM.
*
* @param {String} url URL of the CSS that should be loaded.
* @param {String} [id] ID of the DOM element that will be created. Can be
* omitted.
* @returns {Element} Appended DOM item.
*/
Mibew.Utils.loadStyleSheet = function(url, id) {
var styleSheet = document.createElement('link');
styleSheet.setAttribute('rel', 'stylesheet');
styleSheet.setAttribute('type', 'text/css');
styleSheet.setAttribute('href', url);
if (id) {
styleSheet.setAttribute('id', id);
}
document.getElementsByTagName('head')[0].appendChild(styleSheet);
return styleSheet;
};
/**
* Loads JavaScript file and attach it to DOM.
*
* @param {String} url URL of the JavaScript file that should be loaded.
* @param {String} [id] ID of the DOM element that will be created. Can be
* omitted.
* @returns {Element} Appended DOM item.
*/
Mibew.Utils.loadScript = function(url, id) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', url);
if (id) {
script.setAttribute('id', id);
}
document.getElementsByTagName('head')[0].appendChild(script);
return script;
};
/**
* Initialize a proper chat popup.
*
* This is a helper function which choose which popup (iframe or window)
* should be created, create it and store into Mibew.Objects.ChatPopups
* hash.
*
* @param {Object} options List of popup options.
*/
Mibew.ChatPopup.init = function(options) {
var canUseIFrame = (window.postMessage && options.preferIFrame),
Popup = canUseIFrame ? Mibew.ChatPopup.IFrame : Mibew.ChatPopup.Window;
Mibew.Objects.ChatPopups[options.id] = new Popup(options);
};
/**
* A constructor for base (abstract) popup object.
*
* @constructor
* @param {Object} options A list of popup options.
*/
var BasePopup = function(options) {
/**
* Unique ID of the popup.
* @type {String}
*/
this.id = options.id;
/**
* Chat initialization URL.
* @type {String}
*/
this.url = options.url;
/**
* Width of the popup in pixels.
* @type {Number}
*/
this.width = options.width;
/**
* Height of the popup in pixels.
* @type {Number}
*/
this.height = options.height;
/**
* Indicats if the popup should be resizable.
*
* It can be appliedonly for window popup.
*
* @type {Boolean}
*/
this.resizable = options.resizable || false;
/**
* Contains URL of JavaScript file that loads css file for IFrame popup.
*
* @type {String}
*/
this.styleLoader = options.styleLoader;
/**
* Indicates if special actions should be done to fix problems with
* mod_security.
* @type {Boolean}
*/
this.modSecurity = options.modSecurity || false;
/**
* Chat style
* @type {String}
*/
this.styleName = options.style;
};
/**
* Builds an URL that initializes a chat.
*
* @returns {String} Chat URL.
*/
BasePopup.prototype.buildChatUrl = function() {
var href = document.location.href,
referrer = document.referrer;
if (this.modSecurity) {
href = href.replace('http://','').replace('https://','');
referrer = referrer.replace('http://','').replace('https://','');
}
return this.url
+ ((this.url.indexOf('?') === -1) ? '?' : '&') + 'url=' + encodeURIComponent(href)
+ '&referrer=' + encodeURIComponent(referrer);
};
/**
* Constructs IFrame popup.
*
* @constructor
* @extends BasePopup
* @param {Object} options List of popup options.
*/
Mibew.ChatPopup.IFrame = function(options) {
// Call parent constructor.
BasePopup.call(this, options);
/**
* Store options in case we need some of them later.
* @type {Object}
*/
this.options = options;
/**
* Wrapper for popup iframe DOM Element.
* @type {Node}
*/
this.wrapperDiv = null;
/**
* Popup iframe DOM Element.
* @type {Node}
*/
this.iframe = null;
/**
* Toggle iframe DOM Element.
* @type {Node}
*/
this.toggleDiv = null;
/**
* Indicates if the popup is opened.
* @type {Boolean}
*/
this.isOpened = false;
/**
* Indicates if the popup is minified.
* @type {Boolean}
*/
this.isMinified = false;
/**
* Indicates if cookies are blocked.
* @type {Boolean}
*/
this.cookiesBlocked = false;
// Load default styles. These styles hide the popup while real styles
// are loading.
this.attachDefaultStyles();
// Load extra style sheets.
Mibew.Utils.loadScript(this.styleLoader);
// Check if the popup should be reopened.
var openedChatUrl = Mibew.Utils.readCookie('mibew-chat-frame-' + this.id);
if (openedChatUrl) {
// The chat was not closed so the popup should be reopened when a
// new page is visited.
this.safeOpen(openedChatUrl);
}
// Check if it's possible to set cookies at all
var rnd = Math.random();
Mibew.Utils.createCookie('mibewCheckToken', rnd);
var checkCookiesBlock = Mibew.Utils.loadScript(options.url.split('?')[0] + '/cookies-set-permission' + '?rnd=' + rnd);
checkCookiesBlock.popup = this;
checkCookiesBlock.onload = function() {
this.popup.cookiesBlocked = false;
};
checkCookiesBlock.onerror = function() {
this.popup.cookiesBlocked = true;
};
};
// Set correct prototype chain for IFrame popup.
Mibew.Utils.inherits(Mibew.ChatPopup.IFrame, BasePopup);
/**
* Attaches default styles to the DOM.
*
* This function do its job only once no matter how many times it is called.
*
* @type {Function}
*/
Mibew.ChatPopup.IFrame.prototype.attachDefaultStyles = (function() {
var executed = false;
return function() {
if (executed) {
// The function was already called. Just do nothing.
return;
}
executed = true;
var style = document.createElement('style'),
// These rules hides the popup while real styles are loading.
css = '.mibew-chat-frame {height: 0px; width: 0px;}';
style.setAttribute('type', 'text/css');
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.getElementsByTagName('head')[0].appendChild(style);
};
})();
/**
* Opens the popup.
*
* @param {String} [url] The URL that should be opened in the popup. If the
* value is omitted, the chat initialization URL will be loaded.
*/
Mibew.ChatPopup.IFrame.prototype.open = function(url) {
if (this.isOpened) {
// Do not open the popup twice.
return;
}
if (this.cookiesBlocked) {
// Last resort. Replace this iframe-based popup with window-based popup
// and try to open a chat in a separate window.
Mibew.Objects.ChatPopups[this.id] = new Mibew.ChatPopup.Window(this.options);
Mibew.Objects.ChatPopups[this.id].open(url);
return;
}
if (!this.wrapperDiv) {
// Create new iframe and its wrapper.
// There is a bug in IE <= 7 that make "name" attribute unchangeble
// for elements that already exist. Thus a temporary div is used
// here as a workaround.
this.wrapperDiv = document.createElement('div');
this.wrapperDiv.className = 'mibew-chat-wrapper';
this.wrapperDiv.setAttribute('id', 'mibew-chat-wrapper-' + this.id);
this.wrapperDiv.style.display = 'none';
this.wrapperDiv.innerHTML = '<iframe name="mibewChat' + this.id + '"></iframe>';
this.iframe = this.wrapperDiv.getElementsByTagName('iframe')[0];
this.iframe.setAttribute('id', 'mibew-chat-frame-' + this.id);
this.iframe.className = 'mibew-chat-frame';
this.iframe.setAttribute('frameBorder', 0);
document.getElementsByTagName('body')[0].appendChild(this.wrapperDiv);
// Setup toggle element. As it's not a part of the iframe, it should be
// treated separately.
this.toggleDiv = document.createElement('div');
this.toggleDiv.setAttribute('id', 'mibew-chat-frame-toggle-' + this.id);
this.toggleDiv.className = 'mibew-chat-frame-toggle mibew-chat-frame-toggle-on';
Mibew.Utils.addEventListener(this.toggleDiv, 'click', function(event) {
var popups = Mibew.Objects.ChatPopups,
matches = /^mibew-chat-frame-toggle-([0-9A-Za-z]+)$/.exec(this.id);
if (matches && popups[matches[1]]) {
popups[matches[1]].toggle();
}
});
document.getElementsByTagName('body')[0].appendChild(this.toggleDiv);
}
this.wrapperDiv.style.display = 'block';
this.toggleDiv.style.display = 'block';
this.iframe.src = url || this.buildChatUrl();
this.isOpened = true;
// Store style name in case we need it during iframe reopening
Mibew.Utils.createCookie('mibew-chat-frame-style-' + this.id, this.styleName);
// Check minification status of the popup and toggle it if needed.
var minifiedPopup = Mibew.Utils.readCookie('mibew-chat-frame-minified-' + this.id);
if (minifiedPopup === 'true') {
this.toggle();
}
};
/**
* Check chat URL via special request, open the chat if check passes,
* close the popup if the check fails.
*
* @param {String} [url] The URL to open in the popup
*/
Mibew.ChatPopup.IFrame.prototype.safeOpen = function(url) {
var check = Mibew.Utils.loadScript(url + '/check', 'mibew-check-iframe-' + this.id);
check.popup = this;
check.url = url;
var style = Mibew.Utils.readCookie('mibew-chat-frame-style-' + this.id);
check.onload = function() {
this.popup.open(this.url + (style ? '?style=' + style : ''));
};
check.onerror = function() {
this.popup.close();
};
};
/**
* Closes the popup.
*/
Mibew.ChatPopup.IFrame.prototype.close = function() {
if (!this.isOpened) {
// A popup that was not opened thus it cannot be closed.
return;
}
this.wrapperDiv.style.display = 'none';
this.iframe.src = '';
this.isOpened = false;
this.toggleDiv.style.display = 'none';
Mibew.Utils.deleteCookie('mibew-chat-frame-' + this.id);
Mibew.Utils.deleteCookie('mibew-chat-frame-minified-' + this.id);
};
/**
* Toggles the popup.
*/
Mibew.ChatPopup.IFrame.prototype.toggle = function() {
this.wrapperDiv.style.display = this.isMinified ? "block" : "none";
this.isMinified = !this.isMinified;
this.toggleDiv.className = 'mibew-chat-frame-toggle mibew-chat-frame-toggle-'
+ (this.isMinified ? 'off' : 'on');
Mibew.Utils.createCookie('mibew-chat-frame-minified-' + this.id, this.isMinified);
};
/**
* Constructs Window popup.
*
* @constructor
* @extends BasePopup
* @param {Object} options List of popup options.
*/
Mibew.ChatPopup.Window = function(options) {
BasePopup.call(this, options);
this.window = null;
};
// Set correct prototype chain for Window popup.
Mibew.Utils.inherits(Mibew.ChatPopup.Window, BasePopup);
/**
* Opens the popup.
*
* @param {String} [url] The URL that should be opened in the popup. If the
* value is omitted, the chat initialization URL will be loaded.
*/
Mibew.ChatPopup.Window.prototype.open = function(url) {
// Windows is already opened, nothing to do.
if (this.window != null && !this.window.closed) {
return;
}
this.window = window.open(
url || this.buildChatUrl(),
'mibewChat' + this.id,
this.getWindowParams()
);
this.window.focus();
this.window.opener = window;
};
/**
* Closes the popup.
*/
Mibew.ChatPopup.Window.prototype.close = function() {
if (!this.window) {
// There is nothing to close.
return;
}
this.window.close();
this.window = null;
};
/**
* Builds window params string.
*
* Generated params string can be used in window.open method as the third
* argument.
*
* @protected
* @returns {String}
*/
Mibew.ChatPopup.Window.prototype.getWindowParams = function() {
return [
'toolbar=0',
'scrollbars=0',
'location=0',
'status=1',
'menubar=0',
'width=' + this.width.toString(),
'height=' + this.height.toString(),
'resizable=' + (this.resizable ? '1' : '0')
].join(',');
};
// Attach a listener to window's "message" event to get the url of the chat
// which is opened in iframe popup.
Mibew.Utils.addEventListener(window, 'message', function(event) {
var matches = /^mibew-chat-started\:mibewChat([0-9A-Za-z]+)\:(.*)$/.exec(event.data);
if (matches) {
Mibew.Utils.createCookie('mibew-chat-frame-' + matches[1], matches[2]);
}
});
// Attach a listener to window's "message" event to close the iframe when
// the chat is closed.
Mibew.Utils.addEventListener(window, 'message', function(event) {
var popups = Mibew.Objects.ChatPopups,
matches = /^mibew-chat-closed\:mibewChat([0-9A-Za-z]+)$/.exec(event.data);
if (matches && popups[matches[1]]) {
popups[matches[1]].close();
}
});
})(Mibew);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone, _){
@ -14,24 +24,24 @@
* Mibew.Views.CompositeBase
* @private
* @param {Backbone.Model} item Collection item
* @param {Function} ItemViewType Default item view constructor
* @param {Object} itemViewOptions Additional item view options
* @param {Function} ChildViewType Default item view constructor
* @param {Object} childViewOptions Additional item view options
* @returns Item view instance
*/
var buildItemView = function(item, ItemViewType, itemViewOptions) {
var buildChildView = function(item, ChildViewType, childViewOptions) {
// Build options object
var options = _.extend({model: item}, itemViewOptions);
var options = _.extend({model: item}, childViewOptions);
// Try to find special view for this model
if (typeof item.getModelType != 'function') {
return new ItemViewType(options);
return new ChildViewType(options);
}
var modelType = item.getModelType();
if (modelType && Mibew.Views[modelType]) {
return new Mibew.Views[modelType](options);
} else {
return new ItemViewType(options);
return new ChildViewType(options);
}
}
};
/**
* @class Represents base collection view
@ -43,13 +53,13 @@
* Default item view constructor.
* @type Function
*/
itemView: Backbone.Marionette.ItemView,
childView: Backbone.Marionette.ItemView,
/**
* Return special contructor for an item view if it exists or the
* default constructor otherwise.
*/
buildItemView: buildItemView
buildChildView: buildChildView
}
);
@ -60,7 +70,7 @@
* Return special contructor for an item view if it exists or the
* default constructor otherwise.
*/
buildItemView: buildItemView
buildChildView: buildChildView
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew) {
@ -14,17 +24,25 @@
Mibew.Views.ControlsCollection = Mibew.Views.CollectionBase.extend(
/** @lends Mibew.Views.ControlsCollection.prototype */
{
/**
* Default item view constructor.
* @type Function
*/
itemView: Mibew.Views.Control,
/**
* Class name for view's DOM element
* @type String
*/
className: 'controls-collection'
className: 'controls-collection',
/**
* Returns default child view constructor.
*
* The function is used instead of "childView" property to provide
* an ability to override child view constructor without this class
* overriding.
*
* @param {Backbone.Model} model The model the view created for.
* @returns {Backbone.Marionette.ItemView}
*/
getChildView: function(model) {
return Mibew.Views.Control;
}
}
);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Backbone){

View File

@ -1,63 +1,22 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, Handlebars){
/**
* Register 'apply' Handlebars helper.
*
* This helper provide an ability to apply several helpers to single
* Handlebars expression
*
* Example of helper usage:
* <code>
* {{apply text "emHelper, strongHelper"}}
* </code>
* In the example above helpers will apply to text one after another: first
* 'emHelper' and second 'strongHelper'.
*/
Handlebars.registerHelper('apply', function(text, helpers) {
var result = text;
var validHelperName = /^[0-9A-z_]+$/;
helpers = helpers.split(/\s*,\s*/);
// Apply helpers one after another
for (var prop in helpers) {
if (! helpers.hasOwnProperty(prop) ||
! validHelperName.test(helpers[prop])) {
continue;
}
if (typeof Handlebars.helpers[helpers[prop]] != 'function') {
throw new Error(
"Unregistered helper '" + helpers[prop] + "'!"
);
}
result = Handlebars.helpers[helpers[prop]](result).toString();
}
return new Handlebars.SafeString(result);
});
/**
* Register 'allowTags' Handlebars helper.
*
* This helper unescape HTML entities for allowed (span and strong) tags.
*/
Handlebars.registerHelper('allowTags', function(text) {
var result = text;
result = result.replace(
/&lt;(span|strong)&gt;(.*?)&lt;\/\1&gt;/g,
'<$1>$2</$1>'
);
result = result.replace(
/&lt;span class=&quot;(.*?)&quot;&gt;(.*?)&lt;\/span&gt;/g,
'<span class="$1">$2</span>'
);
return new Handlebars.SafeString(result);
});
/**
* Register 'formatTime' Handlebars helper.
*
@ -82,33 +41,33 @@
/**
* Register 'urlReplace' Handlebars helper.
*
* This helper serch URLs and replace them by 'a' tag
* This helper seeks URLs and replaces them by 'a' tag
*/
Handlebars.registerHelper('urlReplace', function(text) {
return new Handlebars.SafeString(
text.replace(
text.toString().replace(
/((?:https?|ftp):\/\/\S*)/g,
'<a href="$1" target="_blank">$1</a>'
)
);
});
/**
* Register 'nl2br' Handlebars helper.
*
* This helper replace all new line characters (\n) by 'br' tags
*/
Handlebars.registerHelper('nl2br', function(text) {
return new Handlebars.SafeString(text.replace(/\n/g, "<br/>"));
});
/**
* Register 'l10n' Handlebars helper
*
* This helper returns translated string with specified key
* This helper returns translated string with specified key. Example of usage:
* <code>
* {{l10n "localization.string" arg1 arg2 arg3}}
* </code>
* where:
* - "localization.string" is localization constant.
* - arg* are arguments that will replace the placeholders.
*/
Handlebars.registerHelper('l10n', function(key) {
return (Mibew.Localization.get(key) || '');
Handlebars.registerHelper('l10n', function() {
var l = Mibew.Localization,
slice = Array.prototype.slice;
return l.trans.apply(l, slice.call(arguments));
});
/**
@ -150,4 +109,236 @@
return options.inverse(this);
}
});
/**
* Registers "ifAny" helper.
*
* This helper checks if at least one argumet can be treated as
* "true" value. Example of usage:
* <code>
* {{#ifAny first second third}}
* At least one of argument can be threated as "true".
* {{else}}
* All values are "falsy"
* {{/ifAny}}
* </code>
*/
Handlebars.registerHelper('ifAny', function() {
var argsCount = arguments.length,
// The last helper's argument is the options hash. We need it to
// render the template.
options = arguments[argsCount - 1],
// All other helper's arguments are values that are used to evalute
// condition. Exctract that values from arguments pseudo array.
values = [].slice.call(arguments, 0, argsCount - 1);
for (var i = 0, l = values.length; i < l; i++) {
if (values[i]) {
// A true value is found. Render the positive block.
return options.fn(this);
}
}
// All values are "falsy". Render the negative block.
return options.inverse(this);
});
/**
* Registers "ifEqual" helper.
*
* This helper checks if two values are equal or not. Example of usage:
* <code>
* {{#ifEqual first second}}
* The first argument is equal to the second one.
* {{else}}
* The arguments are not equal.
* {{/ifEqual}}
* </code>
*/
Handlebars.registerHelper('ifEqual', function(left, right, options) {
// Not strict equality is used intentionally here.
if (left == right) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
/**
* Registers "repeat" helper.
*
* This helper repeats a string specified number of times. Example of usage:
* <code>
* {{#repeat times}}content to repeat{{/repeat}}
* </code>
*/
Handlebars.registerHelper('repeat', function(count, options) {
var result = '',
content = options.fn(this);
for (var i = 0; i < count; i++) {
result += content;
}
return result;
});
/**
* Registers "replace" helper.
*
* This helper replaces all found substrings with the specifed replacement.
* Example of usage:
* <code>
* {{#replace search replacement}}target content{{/replace}}
* </code>
*/
Handlebars.registerHelper('replace', function(search, replacement, options) {
var unescapedSearch = search
// Allow using new line character
.replace(/\\n/g, '\n')
// Allow using tab character
.replace(/\\t/g, '\t')
// Allow using all UTF characters in \uXXX format.
.replace(/\\u([A-Za-z0-9])/g, function(match, code) {
return String.fromCharCode(parseInt(code, 16));
});
return options.fn(this).split(unescapedSearch).join(replacement);
});
/**
* Registers "cutString" helper.
*
* This helper cuts a string if it exceeds specified length. Example of
* usage:
* <code>
* {{cutString string length}}
* </code>
*/
Handlebars.registerHelper('cutString', function(length, options) {
return options.fn(this).substr(0, length);
});
/**
* Registers "block" helper.
*
* This helper defines default content of a block. Example of usage:
* <code>
* {{#block "blockName"}}
* Default content for the block
* {{/block}}
* </code>
*/
Handlebars.registerHelper('block', function(name, options) {
if (this._blocksStorage && this._blocksStorage.hasOwnProperty(name)) {
return this._blocksStorage[name];
}
return options.fn(this);
});
/**
* Registers "extends" helper.
*
* This is used for templates inheritance. Example of usage:
* <code>
* {{#extends "parentTemplateName"}}
* {{#override "blockName"}}
* Overridden first block
* {{/override}}
*
* {{#override "anotherBlockName"}}
* Overridden second block
* {{/override}}
* {{/extends}}
* </code>
*/
Handlebars.registerHelper('extends', function(parentTemplate, options) {
// Create a blocks storage. If the current inheritance level is not the
// deepest one, a storage already exists. In this case we do not need
// to override it.
this._blocksStorage = this._blocksStorage || {};
// Render content inside "extends" helper to override blocks
options.fn(this);
// Check if the parent template exists
if (!Handlebars.templates.hasOwnProperty(parentTemplate)) {
throw Error('Parent template "' + parentTemplate + '" is not defined');
}
// Render the parent template. We assume that templates are stored in
// Handlebars.templates property. It is the most common case and take
// place when templates were compiled with node.js Handlebars CLI tool.
return Handlebars.templates[parentTemplate](this);
});
/**
* Registers "override" helper.
*
* This helper overrides content of a block. Example of usage:
* <code>
* {{#extends "parentTemplateName"}}
* {{#override "blockName"}}
* Overridden first block
* {{/override}}
*
* {{#override "anotherBlockName"}}
* Overridden second block
* {{/override}}
* {{/extends}}
* </code>
*/
Handlebars.registerHelper('override', function(name, options) {
// We need to provide unlimited inheritance 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 (!this._blocksStorage.hasOwnProperty(name)) {
this._blocksStorage[name] = options.fn(this);
}
// An empty string is returned for consistency.
return '';
});
/**
* Registers "ifOverridden" helper.
*
* This helper checks if a block is overridden or not. Example of usage:
* <code>
* {{#ifOverridden "blockName"}}
* The block was overridden
* {{else}}
* The block was not overridden
* {{/ifOverridden}}
* </code>
*/
Handlebars.registerHelper('ifOverridden', function(name, options) {
if (this._blocksStorage && this._blocksStorage.hasOwnProperty(name)) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
/**
* Registers "unlessOverridden" helper.
*
* This helper checks if a block is overridden or not. Example of usage:
* <code>
* {{#unlessOverridden "blockName"}}
* The block was not overridden
* {{else}}
* The block was overridden
* {{/unlessOverridden}}
* </code>
*/
Handlebars.registerHelper('unlessOverridden', function(name, options) {
if (this._blocksStorage && this._blocksStorage.hasOwnProperty(name)) {
return options.inverse(this);
} else {
return options.fn(this);
}
});
})(Mibew, Handlebars);

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
@ -16,7 +26,7 @@ var Mibew = {};
// Use Backbone.Marionette with handlebars.js
Backbone.Marionette.TemplateCache.prototype.compileTemplate = function(rawTemplate) {
return Handlebars.compile(rawTemplate);
}
};
// Use all handlebars template as partials too
// We does not use Handlebars.partials property because of it can be changed

View File

@ -1,9 +1,19 @@
/*!
* Copyright 2005-2014 the original author or authors.
* This file is a part of Mibew Messenger.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* Copyright 2005-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(Mibew, _){
@ -20,16 +30,24 @@
var localStrings = {};
/**
* Localize string
* @param {String} str String for localization
* @returns {String} Localized string
* Localize string.
*
* @param {String} str String for localization.
* @param {...String} placeholder A value that will replace a placeholder.
* @returns {String} Localized string.
*/
Mibew.Localization.get = function(str) {
if (! localStrings.hasOwnProperty(str)) {
return false;
}
return localStrings[str];
}
Mibew.Localization.trans = function(str) {
// Replace "{n}" style placeholders with specified arguments. The first
// argument is skipped because it is the localized string.
var placeholders = Array.prototype.slice.call(arguments, 1);
// If there is no localized string use passed in one.
var localized = localStrings.hasOwnProperty(str) ? localStrings[str] : str;
return localized.replace(/\{([0-9]+)\}/g, function(match, index) {
return placeholders[parseInt(index)] || '';
});
};
/**
* Store localization object. Can be call multiple times, localization
@ -38,6 +56,6 @@
*/
Mibew.Localization.set = function(strs) {
_.extend(localStrings, strs);
}
};
})(Mibew, _);

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