From e083418678e27346ba8d49839bfe4c13f1f7749f Mon Sep 17 00:00:00 2001 From: Anmol Date: Tue, 8 Dec 2015 18:16:49 +0530 Subject: [PATCH 1/2] change in nginx.conf and added addons in folders --- conf/nginx.conf | 2 +- sources/addon/adultphotoflag | 1 - sources/addon/bbmath | 1 - sources/addon/bookmarker | 1 - sources/addon/buglink | 1 - sources/addon/calc | 1 - sources/addon/chords | 1 - sources/addon/custom_home | 1 - sources/addon/diaspora | 1 - sources/addon/diaspost | 1 - sources/addon/dirstats | 1 - sources/addon/donate | 1 - sources/addon/dwpost | 1 - sources/addon/embedly | 1 - sources/addon/extcron | 1 - sources/addon/flattrwidget | 1 - sources/addon/fortunate | 1 - sources/addon/frphotos | 1 - sources/addon/hexit | 1 - sources/addon/ijpost | 1 - sources/addon/irc | 1 - sources/addon/jappixmini | 1 - sources/addon/js_upload | 1 - sources/addon/ldapauth | 1 - sources/addon/libertree | 1 - sources/addon/likebanner | 1 - sources/addon/ljpost | 1 - sources/addon/mahjongg | 1 - sources/addon/mailhost | 1 - sources/addon/morechoice | 1 - sources/addon/moremoods | 1 - sources/addon/nofed | 1 - sources/addon/nsabait | 1 - sources/addon/nsfw | 1 - sources/addon/openclipatar | 1 - sources/addon/openstreetmap | 1 - sources/addon/piwik | 1 - sources/addon/planets | 1 - sources/addon/pumpio | 1 - sources/addon/qrator | 1 - sources/addon/rainbowtag | 1 - sources/addon/randpost | 1 - sources/addon/redphotos | 1 - sources/addon/redred | 1 - sources/addon/rtof | 1 - sources/addon/sendzid | 1 - sources/addon/smiley_pack | 1 - sources/addon/smileybutton | 1 - sources/addon/startpage | 1 - sources/addon/statistics_json | 1 - sources/addon/statusnet | 1 - sources/addon/superblock | 1 - sources/addon/tictac | 1 - sources/addon/torch | 1 - sources/addon/tour | 1 - sources/addon/twitter | 1 - sources/addon/upload_limits | 1 - sources/addon/visage | 1 - sources/addon/wppost | 1 - 59 files changed, 1 insertion(+), 59 deletions(-) delete mode 120000 sources/addon/adultphotoflag delete mode 120000 sources/addon/bbmath delete mode 120000 sources/addon/bookmarker delete mode 120000 sources/addon/buglink delete mode 120000 sources/addon/calc delete mode 120000 sources/addon/chords delete mode 120000 sources/addon/custom_home delete mode 120000 sources/addon/diaspora delete mode 120000 sources/addon/diaspost delete mode 120000 sources/addon/dirstats delete mode 120000 sources/addon/donate delete mode 120000 sources/addon/dwpost delete mode 120000 sources/addon/embedly delete mode 120000 sources/addon/extcron delete mode 120000 sources/addon/flattrwidget delete mode 120000 sources/addon/fortunate delete mode 120000 sources/addon/frphotos delete mode 120000 sources/addon/hexit delete mode 120000 sources/addon/ijpost delete mode 120000 sources/addon/irc delete mode 120000 sources/addon/jappixmini delete mode 120000 sources/addon/js_upload delete mode 120000 sources/addon/ldapauth delete mode 120000 sources/addon/libertree delete mode 120000 sources/addon/likebanner delete mode 120000 sources/addon/ljpost delete mode 120000 sources/addon/mahjongg delete mode 120000 sources/addon/mailhost delete mode 120000 sources/addon/morechoice delete mode 120000 sources/addon/moremoods delete mode 120000 sources/addon/nofed delete mode 120000 sources/addon/nsabait delete mode 120000 sources/addon/nsfw delete mode 120000 sources/addon/openclipatar delete mode 120000 sources/addon/openstreetmap delete mode 120000 sources/addon/piwik delete mode 120000 sources/addon/planets delete mode 120000 sources/addon/pumpio delete mode 120000 sources/addon/qrator delete mode 120000 sources/addon/rainbowtag delete mode 120000 sources/addon/randpost delete mode 120000 sources/addon/redphotos delete mode 120000 sources/addon/redred delete mode 120000 sources/addon/rtof delete mode 120000 sources/addon/sendzid delete mode 120000 sources/addon/smiley_pack delete mode 120000 sources/addon/smileybutton delete mode 120000 sources/addon/startpage delete mode 120000 sources/addon/statistics_json delete mode 120000 sources/addon/statusnet delete mode 120000 sources/addon/superblock delete mode 120000 sources/addon/tictac delete mode 120000 sources/addon/torch delete mode 120000 sources/addon/tour delete mode 120000 sources/addon/twitter delete mode 120000 sources/addon/upload_limits delete mode 120000 sources/addon/visage delete mode 120000 sources/addon/wppost diff --git a/conf/nginx.conf b/conf/nginx.conf index cc966b89..abdbbefe 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,4 +1,4 @@ -location YNH_WWW_PATH / { +location YNH_WWW_PATH { # Path to source alias YNH_WWW_ALIAS/ ; diff --git a/sources/addon/adultphotoflag b/sources/addon/adultphotoflag deleted file mode 120000 index 024e70fd..00000000 --- a/sources/addon/adultphotoflag +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/adultphotoflag \ No newline at end of file diff --git a/sources/addon/bbmath b/sources/addon/bbmath deleted file mode 120000 index 8e149947..00000000 --- a/sources/addon/bbmath +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/bbmath \ No newline at end of file diff --git a/sources/addon/bookmarker b/sources/addon/bookmarker deleted file mode 120000 index 5ded7cf2..00000000 --- a/sources/addon/bookmarker +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/bookmarker \ No newline at end of file diff --git a/sources/addon/buglink b/sources/addon/buglink deleted file mode 120000 index 2d77f27a..00000000 --- a/sources/addon/buglink +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/buglink \ No newline at end of file diff --git a/sources/addon/calc b/sources/addon/calc deleted file mode 120000 index 44461b0f..00000000 --- a/sources/addon/calc +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/calc \ No newline at end of file diff --git a/sources/addon/chords b/sources/addon/chords deleted file mode 120000 index 9b5afa56..00000000 --- a/sources/addon/chords +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/chords \ No newline at end of file diff --git a/sources/addon/custom_home b/sources/addon/custom_home deleted file mode 120000 index bcf608f3..00000000 --- a/sources/addon/custom_home +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/custom_home \ No newline at end of file diff --git a/sources/addon/diaspora b/sources/addon/diaspora deleted file mode 120000 index 18fe8f4e..00000000 --- a/sources/addon/diaspora +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/diaspora \ No newline at end of file diff --git a/sources/addon/diaspost b/sources/addon/diaspost deleted file mode 120000 index c9ae3e9e..00000000 --- a/sources/addon/diaspost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/diaspost \ No newline at end of file diff --git a/sources/addon/dirstats b/sources/addon/dirstats deleted file mode 120000 index 2b3a3bd5..00000000 --- a/sources/addon/dirstats +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/dirstats \ No newline at end of file diff --git a/sources/addon/donate b/sources/addon/donate deleted file mode 120000 index 2c392ad6..00000000 --- a/sources/addon/donate +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/donate \ No newline at end of file diff --git a/sources/addon/dwpost b/sources/addon/dwpost deleted file mode 120000 index 435ef3a1..00000000 --- a/sources/addon/dwpost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/dwpost \ No newline at end of file diff --git a/sources/addon/embedly b/sources/addon/embedly deleted file mode 120000 index 2bf8e1e6..00000000 --- a/sources/addon/embedly +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/embedly \ No newline at end of file diff --git a/sources/addon/extcron b/sources/addon/extcron deleted file mode 120000 index 0e8d5b10..00000000 --- a/sources/addon/extcron +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/extcron \ No newline at end of file diff --git a/sources/addon/flattrwidget b/sources/addon/flattrwidget deleted file mode 120000 index fc9233d8..00000000 --- a/sources/addon/flattrwidget +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/flattrwidget \ No newline at end of file diff --git a/sources/addon/fortunate b/sources/addon/fortunate deleted file mode 120000 index 9b6e449b..00000000 --- a/sources/addon/fortunate +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/fortunate \ No newline at end of file diff --git a/sources/addon/frphotos b/sources/addon/frphotos deleted file mode 120000 index a48db497..00000000 --- a/sources/addon/frphotos +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/frphotos \ No newline at end of file diff --git a/sources/addon/hexit b/sources/addon/hexit deleted file mode 120000 index 003aeca3..00000000 --- a/sources/addon/hexit +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/hexit \ No newline at end of file diff --git a/sources/addon/ijpost b/sources/addon/ijpost deleted file mode 120000 index a2c28c85..00000000 --- a/sources/addon/ijpost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/ijpost \ No newline at end of file diff --git a/sources/addon/irc b/sources/addon/irc deleted file mode 120000 index 96bb702f..00000000 --- a/sources/addon/irc +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/irc \ No newline at end of file diff --git a/sources/addon/jappixmini b/sources/addon/jappixmini deleted file mode 120000 index 57a425f2..00000000 --- a/sources/addon/jappixmini +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/jappixmini \ No newline at end of file diff --git a/sources/addon/js_upload b/sources/addon/js_upload deleted file mode 120000 index 954a68cb..00000000 --- a/sources/addon/js_upload +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/js_upload \ No newline at end of file diff --git a/sources/addon/ldapauth b/sources/addon/ldapauth deleted file mode 120000 index 9110cc08..00000000 --- a/sources/addon/ldapauth +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/ldapauth \ No newline at end of file diff --git a/sources/addon/libertree b/sources/addon/libertree deleted file mode 120000 index ad355bb4..00000000 --- a/sources/addon/libertree +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/libertree \ No newline at end of file diff --git a/sources/addon/likebanner b/sources/addon/likebanner deleted file mode 120000 index bcaf7710..00000000 --- a/sources/addon/likebanner +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/likebanner \ No newline at end of file diff --git a/sources/addon/ljpost b/sources/addon/ljpost deleted file mode 120000 index 2912d56a..00000000 --- a/sources/addon/ljpost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/ljpost \ No newline at end of file diff --git a/sources/addon/mahjongg b/sources/addon/mahjongg deleted file mode 120000 index aed1a8be..00000000 --- a/sources/addon/mahjongg +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/mahjongg \ No newline at end of file diff --git a/sources/addon/mailhost b/sources/addon/mailhost deleted file mode 120000 index 926de865..00000000 --- a/sources/addon/mailhost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/mailhost \ No newline at end of file diff --git a/sources/addon/morechoice b/sources/addon/morechoice deleted file mode 120000 index eede88f3..00000000 --- a/sources/addon/morechoice +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/morechoice \ No newline at end of file diff --git a/sources/addon/moremoods b/sources/addon/moremoods deleted file mode 120000 index 26462449..00000000 --- a/sources/addon/moremoods +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/moremoods \ No newline at end of file diff --git a/sources/addon/nofed b/sources/addon/nofed deleted file mode 120000 index e47fa5f9..00000000 --- a/sources/addon/nofed +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/nofed \ No newline at end of file diff --git a/sources/addon/nsabait b/sources/addon/nsabait deleted file mode 120000 index dbc91b1f..00000000 --- a/sources/addon/nsabait +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/nsabait \ No newline at end of file diff --git a/sources/addon/nsfw b/sources/addon/nsfw deleted file mode 120000 index 45f9d6e5..00000000 --- a/sources/addon/nsfw +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/nsfw \ No newline at end of file diff --git a/sources/addon/openclipatar b/sources/addon/openclipatar deleted file mode 120000 index 1aca7361..00000000 --- a/sources/addon/openclipatar +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/openclipatar \ No newline at end of file diff --git a/sources/addon/openstreetmap b/sources/addon/openstreetmap deleted file mode 120000 index 502e623f..00000000 --- a/sources/addon/openstreetmap +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/openstreetmap \ No newline at end of file diff --git a/sources/addon/piwik b/sources/addon/piwik deleted file mode 120000 index 1c02b005..00000000 --- a/sources/addon/piwik +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/piwik \ No newline at end of file diff --git a/sources/addon/planets b/sources/addon/planets deleted file mode 120000 index 623f5cf0..00000000 --- a/sources/addon/planets +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/planets \ No newline at end of file diff --git a/sources/addon/pumpio b/sources/addon/pumpio deleted file mode 120000 index 8d2db101..00000000 --- a/sources/addon/pumpio +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/pumpio \ No newline at end of file diff --git a/sources/addon/qrator b/sources/addon/qrator deleted file mode 120000 index dfc52e0a..00000000 --- a/sources/addon/qrator +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/qrator \ No newline at end of file diff --git a/sources/addon/rainbowtag b/sources/addon/rainbowtag deleted file mode 120000 index 382135e6..00000000 --- a/sources/addon/rainbowtag +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/rainbowtag \ No newline at end of file diff --git a/sources/addon/randpost b/sources/addon/randpost deleted file mode 120000 index 7d19da3e..00000000 --- a/sources/addon/randpost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/randpost \ No newline at end of file diff --git a/sources/addon/redphotos b/sources/addon/redphotos deleted file mode 120000 index 5f4aade9..00000000 --- a/sources/addon/redphotos +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/redphotos \ No newline at end of file diff --git a/sources/addon/redred b/sources/addon/redred deleted file mode 120000 index 3970fca4..00000000 --- a/sources/addon/redred +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/redred \ No newline at end of file diff --git a/sources/addon/rtof b/sources/addon/rtof deleted file mode 120000 index 1571f258..00000000 --- a/sources/addon/rtof +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/rtof \ No newline at end of file diff --git a/sources/addon/sendzid b/sources/addon/sendzid deleted file mode 120000 index e1b1d238..00000000 --- a/sources/addon/sendzid +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/sendzid \ No newline at end of file diff --git a/sources/addon/smiley_pack b/sources/addon/smiley_pack deleted file mode 120000 index 971efecf..00000000 --- a/sources/addon/smiley_pack +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/smiley_pack \ No newline at end of file diff --git a/sources/addon/smileybutton b/sources/addon/smileybutton deleted file mode 120000 index 51d06824..00000000 --- a/sources/addon/smileybutton +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/smileybutton \ No newline at end of file diff --git a/sources/addon/startpage b/sources/addon/startpage deleted file mode 120000 index be49638d..00000000 --- a/sources/addon/startpage +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/startpage \ No newline at end of file diff --git a/sources/addon/statistics_json b/sources/addon/statistics_json deleted file mode 120000 index cdd6ca3e..00000000 --- a/sources/addon/statistics_json +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/statistics_json \ No newline at end of file diff --git a/sources/addon/statusnet b/sources/addon/statusnet deleted file mode 120000 index 3297a173..00000000 --- a/sources/addon/statusnet +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/statusnet \ No newline at end of file diff --git a/sources/addon/superblock b/sources/addon/superblock deleted file mode 120000 index f2b1ef07..00000000 --- a/sources/addon/superblock +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/superblock \ No newline at end of file diff --git a/sources/addon/tictac b/sources/addon/tictac deleted file mode 120000 index a65e7d37..00000000 --- a/sources/addon/tictac +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/tictac \ No newline at end of file diff --git a/sources/addon/torch b/sources/addon/torch deleted file mode 120000 index 10bbde90..00000000 --- a/sources/addon/torch +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/torch \ No newline at end of file diff --git a/sources/addon/tour b/sources/addon/tour deleted file mode 120000 index 2e83e52d..00000000 --- a/sources/addon/tour +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/tour \ No newline at end of file diff --git a/sources/addon/twitter b/sources/addon/twitter deleted file mode 120000 index 6286a41c..00000000 --- a/sources/addon/twitter +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/twitter \ No newline at end of file diff --git a/sources/addon/upload_limits b/sources/addon/upload_limits deleted file mode 120000 index ad196540..00000000 --- a/sources/addon/upload_limits +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/upload_limits \ No newline at end of file diff --git a/sources/addon/visage b/sources/addon/visage deleted file mode 120000 index 9ba0502a..00000000 --- a/sources/addon/visage +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/visage \ No newline at end of file diff --git a/sources/addon/wppost b/sources/addon/wppost deleted file mode 120000 index 2f23099f..00000000 --- a/sources/addon/wppost +++ /dev/null @@ -1 +0,0 @@ -../extend/addon/official/wppost \ No newline at end of file From 9c7a6ebdbe751e16366682c2cd2c66e21c78496b Mon Sep 17 00:00:00 2001 From: Anmol Date: Tue, 8 Dec 2015 18:27:50 +0530 Subject: [PATCH 2/2] Added addons with subfolder. earlier:addons/addon-name.php, now:addon/subfolder/addon-name.php --- sources/addons/.gitignore | 24 + sources/addons/README.md | 6 + .../addons/adultphotoflag/adultphotoflag.php | 28 + sources/addons/bbmath/README | 3 + sources/addons/bbmath/bbmath.php | 22 + sources/addons/bbmath/gpl.txt | 339 + sources/addons/bbmath/phplatex.php | 139 + sources/addons/bookmarker/bookmarker.php | 41 + sources/addons/buglink/bug-x.gif | Bin 0 -> 134 bytes sources/addons/buglink/buglink.php | 15 + sources/addons/buglink/lang/C/messages.po | 22 + sources/addons/buglink/lang/ca/strings.php | 3 + sources/addons/buglink/lang/cs/strings.php | 3 + sources/addons/buglink/lang/de/strings.php | 3 + sources/addons/buglink/lang/eo/strings.php | 3 + sources/addons/buglink/lang/es/strings.php | 3 + sources/addons/buglink/lang/fr/strings.php | 3 + sources/addons/buglink/lang/is/strings.php | 3 + sources/addons/buglink/lang/it/strings.php | 3 + sources/addons/buglink/lang/nb-no/strings.php | 3 + sources/addons/buglink/lang/pl/strings.php | 3 + sources/addons/buglink/lang/pt-br/strings.php | 3 + sources/addons/buglink/lang/ru/strings.php | 3 + sources/addons/buglink/lang/sv/strings.php | 2 + sources/addons/buglink/lang/zh-cn/strings.php | 3 + sources/addons/calc/calc.apd | 3 + sources/addons/calc/calc.php | 368 + sources/addons/calc/calc.png | Bin 0 -> 7286 bytes sources/addons/chords/README.md | 9 + sources/addons/chords/chord | Bin 0 -> 21909 bytes sources/addons/chords/chord-generator.cpp | 1133 +++ sources/addons/chords/chords.apd | 3 + sources/addons/chords/chords.php | 129 + sources/addons/chords/chords.png | Bin 0 -> 11413 bytes sources/addons/custom_home/README.md | 12 + sources/addons/custom_home/custom_home.php | 40 + sources/addons/dfedfix/dfedfix.php | 30 + sources/addons/diaspora/diaspora.php | 3397 ++++++++ sources/addons/diaspora/p.php | 52 + sources/addons/diaspora/receive.php | 75 + sources/addons/diaspost/diasphp.php | 107 + sources/addons/diaspost/diaspora.png | Bin 0 -> 952 bytes sources/addons/diaspost/diaspost.css | 0 sources/addons/diaspost/diaspost.php | 337 + sources/addons/dirstats/dirstats.php | 204 + sources/addons/dirstats/view/tpl/dirstats.tpl | 20 + sources/addons/donate/donate.apd | 3 + sources/addons/donate/donate.php | 75 + sources/addons/donate/donate.png | Bin 0 -> 7097 bytes sources/addons/donate/tipping.jpg | Bin 0 -> 109373 bytes sources/addons/donate/view/tpl/donate.tpl | 64 + sources/addons/dwpost/dwpost.css | 0 sources/addons/dwpost/dwpost.php | 229 + sources/addons/dwpost/lang/C/messages.po | 46 + sources/addons/dwpost/lang/ca/strings.php | 9 + sources/addons/dwpost/lang/cs/strings.php | 9 + sources/addons/dwpost/lang/de/strings.php | 9 + sources/addons/dwpost/lang/eo/strings.php | 9 + sources/addons/dwpost/lang/es/strings.php | 9 + sources/addons/dwpost/lang/fr/strings.php | 9 + sources/addons/dwpost/lang/is/strings.php | 9 + sources/addons/dwpost/lang/it/strings.php | 9 + sources/addons/dwpost/lang/nb-no/strings.php | 9 + sources/addons/dwpost/lang/pl/strings.php | 9 + sources/addons/dwpost/lang/pt-br/strings.php | 9 + sources/addons/dwpost/lang/ru/strings.php | 9 + sources/addons/dwpost/lang/sv/strings.php | 3 + sources/addons/dwpost/lang/zh-cn/strings.php | 9 + sources/addons/embedly/embedly.php | 25 + sources/addons/extcron/extcron.php | 22 + sources/addons/extcron/lang/C/messages.po | 0 sources/addons/flattrwidget/CHANGELOG | 3 + sources/addons/flattrwidget/README.md | 76 + sources/addons/flattrwidget/flattrwidget.php | 129 + .../flattrwidget/img/flattr-badge-large.png | Bin 0 -> 1639 bytes .../flattrwidget/img/red-flattr-widget.png | Bin 0 -> 50194 bytes .../flattrwidget/img/red-flattr-widget2.png | Bin 0 -> 36619 bytes sources/addons/flattrwidget/style.css | 0 sources/addons/fortunate/README | 7 + sources/addons/fortunate/cookie.php | 351 + sources/addons/fortunate/fortunate.apd | 3 + sources/addons/fortunate/fortunate.css | 7 + sources/addons/fortunate/fortunate.php | 43 + sources/addons/fortunate/fortunate.png | Bin 0 -> 7010 bytes sources/addons/frphotos/frphotohelper.php | 75 + sources/addons/frphotos/frphotos.php | 98 + sources/addons/frphotos/view/tpl/frphotos.tpl | 13 + sources/addons/hexit/hexit.apd | 3 + sources/addons/hexit/hexit.php | 185 + sources/addons/hexit/hexit.png | Bin 0 -> 6362 bytes sources/addons/ijpost/ijpost.css | 0 sources/addons/ijpost/ijpost.php | 229 + sources/addons/ijpost/lang/C/messages.po | 46 + sources/addons/ijpost/lang/ca/strings.php | 9 + sources/addons/ijpost/lang/cs/strings.php | 9 + sources/addons/ijpost/lang/de/strings.php | 9 + sources/addons/ijpost/lang/eo/strings.php | 9 + sources/addons/ijpost/lang/es/strings.php | 9 + sources/addons/ijpost/lang/fr/strings.php | 9 + sources/addons/ijpost/lang/is/strings.php | 9 + sources/addons/ijpost/lang/it/strings.php | 9 + sources/addons/ijpost/lang/nb-no/strings.php | 9 + sources/addons/ijpost/lang/pl/strings.php | 9 + sources/addons/ijpost/lang/pt-br/strings.php | 9 + sources/addons/ijpost/lang/ru/strings.php | 9 + sources/addons/ijpost/lang/sv/strings.php | 3 + sources/addons/ijpost/lang/zh-cn/strings.php | 9 + sources/addons/irc/irc.apd | 3 + sources/addons/irc/irc.css | 0 sources/addons/irc/irc.php | 119 + sources/addons/irc/irc.png | Bin 0 -> 4334 bytes sources/addons/jappixmini/MIT.txt | 7 + sources/addons/jappixmini/README | 27 + sources/addons/jappixmini/jappix/AUTHORS | 54 + sources/addons/jappixmini/jappix/COPYING | 662 ++ sources/addons/jappixmini/jappix/INSTALL | 23 + sources/addons/jappixmini/jappix/README | 20 + sources/addons/jappixmini/jappix/THANKS | 27 + sources/addons/jappixmini/jappix/VERSION | 1 + .../addons/jappixmini/jappix/css/adhoc.css | 26 + .../jappixmini/jappix/css/anonymous.css | 29 + .../addons/jappixmini/jappix/css/archives.css | 93 + .../addons/jappixmini/jappix/css/board.css | 47 + .../jappixmini/jappix/css/buddylist.css | 530 ++ .../addons/jappixmini/jappix/css/channel.css | 545 ++ .../jappixmini/jappix/css/directory.css | 16 + .../jappixmini/jappix/css/discovery.css | 61 + .../jappixmini/jappix/css/favorites.css | 179 + sources/addons/jappixmini/jappix/css/home.css | 579 ++ sources/addons/jappixmini/jappix/css/ie.css | 146 + .../addons/jappixmini/jappix/css/images.css | 89 + .../addons/jappixmini/jappix/css/inbox.css | 202 + .../addons/jappixmini/jappix/css/install.css | 285 + .../jappixmini/jappix/css/integratebox.css | 34 + .../jappix/css/jquery.datepicker.css | 148 + sources/addons/jappixmini/jappix/css/main.css | 131 + .../addons/jappixmini/jappix/css/manager.css | 543 ++ sources/addons/jappixmini/jappix/css/me.css | 49 + .../addons/jappixmini/jappix/css/mini-ie.css | 73 + sources/addons/jappixmini/jappix/css/mini.css | 540 ++ .../addons/jappixmini/jappix/css/mobile.css | 288 + .../addons/jappixmini/jappix/css/mucadmin.css | 91 + .../addons/jappixmini/jappix/css/myinfos.css | 330 + .../addons/jappixmini/jappix/css/options.css | 97 + .../addons/jappixmini/jappix/css/others.css | 118 + .../jappixmini/jappix/css/pageengine.css | 601 ++ .../jappixmini/jappix/css/pageswitch.css | 209 + .../addons/jappixmini/jappix/css/popup.css | 612 ++ .../addons/jappixmini/jappix/css/privacy.css | 197 + .../addons/jappixmini/jappix/css/rosterx.css | 53 + .../addons/jappixmini/jappix/css/search.css | 60 + .../addons/jappixmini/jappix/css/smileys.css | 196 + .../jappixmini/jappix/css/stats-svg.css | 71 + .../addons/jappixmini/jappix/css/tools.css | 346 + .../jappixmini/jappix/css/userinfos.css | 100 + .../addons/jappixmini/jappix/css/vcard.css | 106 + .../addons/jappixmini/jappix/css/welcome.css | 170 + .../jappixmini/jappix/img/others/blank.gif | Bin 0 -> 43 bytes .../jappix/img/others/default-avatar.png | Bin 0 -> 1436 bytes .../jappixmini/jappix/img/others/lock.png | Bin 0 -> 140 bytes .../jappixmini/jappix/img/sprites/animate.gif | Bin 0 -> 1898 bytes .../jappixmini/jappix/img/sprites/animate.png | Bin 0 -> 7746 bytes .../jappix/img/sprites/background.png | Bin 0 -> 8782 bytes .../jappix/img/sprites/browsers.png | Bin 0 -> 10955 bytes .../jappixmini/jappix/img/sprites/buttons.png | Bin 0 -> 379 bytes .../jappixmini/jappix/img/sprites/home.png | Bin 0 -> 28465 bytes .../jappixmini/jappix/img/sprites/install.png | Bin 0 -> 9980 bytes .../jappixmini/jappix/img/sprites/logs.png | Bin 0 -> 1947 bytes .../jappixmini/jappix/img/sprites/manager.png | Bin 0 -> 21102 bytes .../jappixmini/jappix/img/sprites/me.png | Bin 0 -> 5100 bytes .../jappixmini/jappix/img/sprites/mini.gif | Bin 0 -> 3430 bytes .../jappixmini/jappix/img/sprites/mini.png | Bin 0 -> 5540 bytes .../jappixmini/jappix/img/sprites/mobile.png | Bin 0 -> 2874 bytes .../jappixmini/jappix/img/sprites/smileys.png | Bin 0 -> 19253 bytes .../jappixmini/jappix/img/sprites/talk.png | Bin 0 -> 43207 bytes .../jappixmini/jappix/img/sprites/welcome.png | Bin 0 -> 4356 bytes .../jappixmini/jappix/img/wait/wait-big.gif | Bin 0 -> 3496 bytes .../jappix/img/wait/wait-medium.png | Bin 0 -> 4129 bytes .../jappixmini/jappix/img/wait/wait-small.gif | Bin 0 -> 847 bytes sources/addons/jappixmini/jappix/js/adhoc.js | 85 + .../addons/jappixmini/jappix/js/anonymous.js | 131 + .../addons/jappixmini/jappix/js/archives.js | 418 + sources/addons/jappixmini/jappix/js/audio.js | 46 + .../jappixmini/jappix/js/autocompletion.js | 99 + sources/addons/jappixmini/jappix/js/avatar.js | 205 + sources/addons/jappixmini/jappix/js/base64.js | 80 + sources/addons/jappixmini/jappix/js/board.js | 141 + .../jappixmini/jappix/js/browser-detect.js | 124 + sources/addons/jappixmini/jappix/js/bubble.js | 59 + sources/addons/jappixmini/jappix/js/caps.js | 349 + sources/addons/jappixmini/jappix/js/chat.js | 297 + .../addons/jappixmini/jappix/js/chatstate.js | 174 + sources/addons/jappixmini/jappix/js/common.js | 311 + .../addons/jappixmini/jappix/js/connection.js | 526 ++ .../addons/jappixmini/jappix/js/constants.js | 211 + .../addons/jappixmini/jappix/js/dataform.js | 921 +++ .../addons/jappixmini/jappix/js/datastore.js | 209 + sources/addons/jappixmini/jappix/js/date.js | 214 + .../addons/jappixmini/jappix/js/directory.js | 87 + .../addons/jappixmini/jappix/js/discovery.js | 169 + sources/addons/jappixmini/jappix/js/error.js | 139 + .../addons/jappixmini/jappix/js/favorites.js | 537 ++ .../addons/jappixmini/jappix/js/features.js | 213 + sources/addons/jappixmini/jappix/js/filter.js | 189 + .../addons/jappixmini/jappix/js/groupchat.js | 283 + sources/addons/jappixmini/jappix/js/home.js | 371 + .../addons/jappixmini/jappix/js/httpauth.js | 41 + sources/addons/jappixmini/jappix/js/inbox.js | 694 ++ .../jappixmini/jappix/js/integratebox.js | 340 + .../addons/jappixmini/jappix/js/interface.js | 386 + sources/addons/jappixmini/jappix/js/iq.js | 193 + .../jappixmini/jappix/js/jquery.datepicker.js | 896 ++ .../jappixmini/jappix/js/jquery.form.js | 785 ++ sources/addons/jappixmini/jappix/js/jquery.js | 7179 +++++++++++++++++ .../jappix/js/jquery.placeholder.js | 116 + .../jappixmini/jappix/js/jquery.textrange.js | 14 + .../jappixmini/jappix/js/jquery.timers.js | 138 + sources/addons/jappixmini/jappix/js/jsjac.js | 4288 ++++++++++ sources/addons/jappixmini/jappix/js/jxhr.js | 116 + sources/addons/jappixmini/jappix/js/links.js | 38 + sources/addons/jappixmini/jappix/js/me.js | 62 + .../addons/jappixmini/jappix/js/message.js | 900 +++ .../addons/jappixmini/jappix/js/microblog.js | 1447 ++++ sources/addons/jappixmini/jappix/js/mini.js | 1623 ++++ sources/addons/jappixmini/jappix/js/mobile.js | 592 ++ .../addons/jappixmini/jappix/js/mucadmin.js | 373 + sources/addons/jappixmini/jappix/js/music.js | 259 + sources/addons/jappixmini/jappix/js/name.js | 131 + .../jappixmini/jappix/js/notification.js | 422 + sources/addons/jappixmini/jappix/js/oob.js | 184 + .../addons/jappixmini/jappix/js/options.js | 643 ++ sources/addons/jappixmini/jappix/js/pep.js | 827 ++ sources/addons/jappixmini/jappix/js/popup.js | 42 + .../addons/jappixmini/jappix/js/presence.js | 1075 +++ .../addons/jappixmini/jappix/js/privacy.js | 963 +++ .../addons/jappixmini/jappix/js/receipts.js | 94 + sources/addons/jappixmini/jappix/js/roster.js | 1122 +++ .../addons/jappixmini/jappix/js/rosterx.js | 187 + sources/addons/jappixmini/jappix/js/search.js | 288 + .../addons/jappixmini/jappix/js/smileys.js | 113 + .../addons/jappixmini/jappix/js/storage.js | 134 + sources/addons/jappixmini/jappix/js/talk.js | 263 + .../addons/jappixmini/jappix/js/tooltip.js | 268 + .../addons/jappixmini/jappix/js/userinfos.js | 426 + .../addons/jappixmini/jappix/js/utilities.js | 437 + sources/addons/jappixmini/jappix/js/vcard.js | 630 ++ .../addons/jappixmini/jappix/js/welcome.js | 299 + .../addons/jappixmini/jappix/js/xmpplinks.js | 78 + .../jappix/lang/ar/LC_MESSAGES/main.mo | Bin 0 -> 13245 bytes .../jappix/lang/ar/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/bg/LC_MESSAGES/main.mo | Bin 0 -> 64778 bytes .../jappix/lang/bg/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/cs/LC_MESSAGES/main.mo | Bin 0 -> 49063 bytes .../jappix/lang/cs/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/de/LC_MESSAGES/main.mo | Bin 0 -> 49073 bytes .../jappix/lang/de/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/en/LC_MESSAGES/main.pot | 1856 +++++ .../jappix/lang/eo/LC_MESSAGES/main.mo | Bin 0 -> 48077 bytes .../jappix/lang/eo/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/es/LC_MESSAGES/main.mo | Bin 0 -> 43885 bytes .../jappix/lang/es/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/et/LC_MESSAGES/main.mo | Bin 0 -> 47624 bytes .../jappix/lang/et/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/fa/LC_MESSAGES/main.mo | Bin 0 -> 26308 bytes .../jappix/lang/fa/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/fr/LC_MESSAGES/main.mo | Bin 0 -> 52792 bytes .../jappix/lang/fr/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/hu/LC_MESSAGES/main.mo | Bin 0 -> 50183 bytes .../jappix/lang/hu/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/id/LC_MESSAGES/main.mo | Bin 0 -> 48941 bytes .../jappix/lang/id/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/it/LC_MESSAGES/main.mo | Bin 0 -> 44893 bytes .../jappix/lang/it/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/ja/LC_MESSAGES/main.mo | Bin 0 -> 52928 bytes .../jappix/lang/ja/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/nl/LC_MESSAGES/main.mo | Bin 0 -> 9342 bytes .../jappix/lang/nl/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/oc/LC_MESSAGES/main.mo | Bin 0 -> 13730 bytes .../jappix/lang/oc/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/pl/LC_MESSAGES/main.mo | Bin 0 -> 41024 bytes .../jappix/lang/pl/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/pt-BR/LC_MESSAGES/main.mo | Bin 0 -> 48169 bytes .../jappix/lang/pt-BR/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/ru/LC_MESSAGES/main.mo | Bin 0 -> 60469 bytes .../jappix/lang/ru/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/sk/LC_MESSAGES/main.mo | Bin 0 -> 43057 bytes .../jappix/lang/sk/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/sv/LC_MESSAGES/main.mo | Bin 0 -> 29178 bytes .../jappix/lang/sv/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/uk/LC_MESSAGES/main.mo | Bin 0 -> 19238 bytes .../jappix/lang/uk/LC_MESSAGES/main.po | 1870 +++++ .../jappix/lang/zh/LC_MESSAGES/main.mo | Bin 0 -> 35976 bytes .../jappix/lang/zh/LC_MESSAGES/main.po | 1870 +++++ .../jappixmini/jappix/php/avatar-upload.php | 118 + sources/addons/jappixmini/jappix/php/bosh.php | 167 + .../addons/jappixmini/jappix/php/desktop.php | 181 + .../jappixmini/jappix/php/download-chat.php | 53 + .../jappixmini/jappix/php/drawsvgchart.php | 495 ++ .../jappixmini/jappix/php/file-share.php | 122 + .../jappixmini/jappix/php/form-hosts.php | 49 + .../jappixmini/jappix/php/form-main.php | 125 + .../jappixmini/jappix/php/form-users.php | 30 + .../jappixmini/jappix/php/functions-get.php | 280 + .../jappix/php/functions-manager.php | 769 ++ .../jappixmini/jappix/php/functions.php | 1427 ++++ .../jappixmini/jappix/php/generate-chat.php | 235 + .../jappixmini/jappix/php/geolocation.php | 43 + .../jappixmini/jappix/php/get-store.php | 37 + sources/addons/jappixmini/jappix/php/get.php | 338 + .../addons/jappixmini/jappix/php/gettext.php | 949 +++ .../addons/jappixmini/jappix/php/install.php | 289 + .../addons/jappixmini/jappix/php/jsmin.php | 375 + .../addons/jappixmini/jappix/php/manager.php | 839 ++ .../jappixmini/jappix/php/mobile-detect.php | 100 + .../addons/jappixmini/jappix/php/mobile.php | 73 + .../jappixmini/jappix/php/music-search.php | 103 + .../jappixmini/jappix/php/post-design.php | 215 + .../jappixmini/jappix/php/post-hosts.php | 95 + .../jappixmini/jappix/php/post-main.php | 130 + .../jappixmini/jappix/php/post-store.php | 100 + .../jappixmini/jappix/php/post-users.php | 48 + .../jappixmini/jappix/php/read-design.php | 125 + .../jappixmini/jappix/php/read-hosts.php | 84 + .../jappixmini/jappix/php/read-main.php | 77 + sources/addons/jappixmini/jappix/php/send.php | 130 + .../addons/jappixmini/jappix/php/static.php | 40 + .../jappixmini/jappix/php/stats-svg.php | 106 + .../jappixmini/jappix/php/store-tree.php | 51 + .../addons/jappixmini/jappix/php/upload.php | 40 + .../jappixmini/jappix/php/vars-design.php | 49 + .../jappixmini/jappix/php/vars-hosts.php | 32 + .../jappixmini/jappix/php/vars-main.php | 37 + .../jappixmini/jappix/php/vars-store.php | 29 + .../addons/jappixmini/jappix/snd/new-chat.oga | Bin 0 -> 6472 bytes .../jappixmini/jappix/snd/notification.oga | Bin 0 -> 3710 bytes .../jappixmini/jappix/snd/receive-message.oga | Bin 0 -> 5271 bytes .../jappixmini/jappix/xml/anonymous.xml | 5 + .../addons/jappixmini/jappix/xml/desktop.xml | 5 + .../addons/jappixmini/jappix/xml/install.xml | 5 + .../addons/jappixmini/jappix/xml/manager.xml | 5 + sources/addons/jappixmini/jappix/xml/mini.xml | 5 + .../addons/jappixmini/jappix/xml/mobile.xml | 5 + sources/addons/jappixmini/jappixmini.css | 0 sources/addons/jappixmini/jappixmini.php | 704 ++ sources/addons/jappixmini/lang/C/messages.po | 74 + sources/addons/jappixmini/lang/ca/strings.php | 16 + sources/addons/jappixmini/lang/cs/strings.php | 16 + sources/addons/jappixmini/lang/de/strings.php | 16 + sources/addons/jappixmini/lang/eo/strings.php | 16 + sources/addons/jappixmini/lang/es/strings.php | 16 + sources/addons/jappixmini/lang/fr/strings.php | 16 + sources/addons/jappixmini/lang/is/strings.php | 16 + sources/addons/jappixmini/lang/it/strings.php | 16 + .../addons/jappixmini/lang/nb-no/strings.php | 16 + sources/addons/jappixmini/lang/pl/strings.php | 16 + .../addons/jappixmini/lang/pt-br/strings.php | 16 + sources/addons/jappixmini/lang/ru/strings.php | 16 + sources/addons/jappixmini/lang/sv/strings.php | 3 + .../addons/jappixmini/lang/zh-cn/strings.php | 16 + sources/addons/jappixmini/lib.js | 281 + sources/addons/jappixmini/proxy.php | 178 + .../js_upload/file-uploader/client/demo.htm | 38 + .../file-uploader/client/do-nothing.htm | 1 + .../file-uploader/client/fileuploader.css | 31 + .../file-uploader/client/fileuploader.js | 1247 +++ .../file-uploader/client/loading.gif | Bin 0 -> 1688 bytes .../js_upload/file-uploader/gpl-2.0.txt | 339 + .../js_upload/file-uploader/license.txt | 24 + .../addons/js_upload/file-uploader/readme.md | 152 + .../server/OctetStreamReader.java | 125 + .../server/coldfusion/coldfusion.cfc | 1 + .../file-uploader/server/coldfusion/demo.cfm | 1 + .../server/coldfusion/readme.txt | 9 + .../js_upload/file-uploader/server/perl.cgi | 62 + .../js_upload/file-uploader/server/php.php | 162 + .../js_upload/file-uploader/server/readme.txt | 18 + .../file-uploader/server/uploads/.gitignore | 2 + .../file-uploader/tests/action-acceptance.php | 46 + .../tests/action-handler-queue-test.php | 31 + .../tests/action-handler-test.php | 31 + .../tests/action-slow-response.php | 2 + .../tests/browser-bugs/safari-bug1.htm | 9 + .../tests/browser-bugs/safari-bug2.htm | 19 + .../application-javascript.php | 1 + .../iframe-content-tests/application-json.php | 1 + .../tests/iframe-content-tests/header-404.php | 2 + .../tests/iframe-content-tests/somepage.php | 1 + .../iframe-content-tests/text-html-large.php | 6 + .../tests/iframe-content-tests/text-html.php | 7 + .../iframe-content-tests/text-javascript.php | 1 + .../tests/iframe-content-tests/text-plain.php | 2 + .../file-uploader/tests/jquery-1.4.2.min.js | 154 + .../jquery-ui/jquery-ui-1.8.4.custom.min.js | 200 + .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 260 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 251 bytes .../images/ui-bg_flat_10_000000_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 0 -> 104 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 0 -> 125 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 0 -> 4427 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 0 -> 90 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 0 -> 129 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_228ef1_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ef8c08_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes .../ui-lightness/jquery-ui-1.8.4.custom.css | 334 + .../file-uploader/tests/qunit/package.json | 21 + .../file-uploader/tests/qunit/qunit/qunit.css | 119 + .../file-uploader/tests/qunit/qunit/qunit.js | 1069 +++ .../file-uploader/tests/qunit/test/index.html | 17 + .../file-uploader/tests/qunit/test/same.js | 1423 ++++ .../file-uploader/tests/qunit/test/test.js | 171 + .../1imagelonglonglonglonglonglongname.gif | Bin 0 -> 1688 bytes .../tests/sample-files/2larger.txt | 1 + .../tests/sample-files/3empty.txt | 0 .../tests/sample-files/4text.txt | 1 + .../tests/sample-files/5text.txt | 1 + .../tests/sample-files/6text.txt | 1 + .../tests/sample-files/7small.txt | 1 + .../tests/sample-files/8text.txt | 1 + .../tests/separate-file-list.htm | 24 + .../file-uploader/tests/test-acceptance.htm | 106 + .../file-uploader/tests/test-drop-zone.htm | 48 + .../tests/test-handler-queue.htm | 81 + .../tests/test-upload-handlers.htm | 382 + sources/addons/js_upload/js_upload.php | 365 + sources/addons/js_upload/lang/C/messages.po | 54 + sources/addons/js_upload/lang/ca/strings.php | 11 + sources/addons/js_upload/lang/cs/strings.php | 11 + sources/addons/js_upload/lang/de/strings.php | 11 + sources/addons/js_upload/lang/eo/strings.php | 11 + sources/addons/js_upload/lang/es/strings.php | 11 + sources/addons/js_upload/lang/fr/strings.php | 11 + sources/addons/js_upload/lang/is/strings.php | 11 + sources/addons/js_upload/lang/it/strings.php | 11 + .../addons/js_upload/lang/nb-no/strings.php | 11 + sources/addons/js_upload/lang/pl/strings.php | 11 + .../addons/js_upload/lang/pt-br/strings.php | 11 + sources/addons/js_upload/lang/ru/strings.php | 11 + sources/addons/js_upload/lang/sv/strings.php | 11 + .../addons/js_upload/lang/zh-cn/strings.php | 11 + sources/addons/ldapauth/README | 43 + sources/addons/ldapauth/ldapauth.php | 181 + sources/addons/libertree/lang/C/messages.po | 46 + sources/addons/libertree/lang/ca/strings.php | 9 + sources/addons/libertree/lang/cs/strings.php | 9 + sources/addons/libertree/lang/de/strings.php | 9 + sources/addons/libertree/lang/eo/strings.php | 9 + sources/addons/libertree/lang/es/strings.php | 9 + sources/addons/libertree/lang/fr/strings.php | 9 + sources/addons/libertree/lang/is/strings.php | 9 + sources/addons/libertree/lang/it/strings.php | 9 + .../addons/libertree/lang/nb-no/strings.php | 9 + sources/addons/libertree/lang/pl/strings.php | 9 + .../addons/libertree/lang/pt-br/strings.php | 9 + sources/addons/libertree/lang/ru/strings.php | 9 + sources/addons/libertree/lang/sv/strings.php | 3 + .../addons/libertree/lang/zh-cn/strings.php | 9 + sources/addons/libertree/libertree.css | 0 sources/addons/libertree/libertree.php | 210 + sources/addons/libertree/libertree.png | Bin 0 -> 5011 bytes sources/addons/likebanner/FreeSansBold.ttf | Bin 0 -> 359272 bytes sources/addons/likebanner/like_banner.png | Bin 0 -> 7491 bytes sources/addons/likebanner/likebanner.apd | 4 + sources/addons/likebanner/likebanner.php | 70 + sources/addons/likebanner/likebanner.png | Bin 0 -> 3567 bytes sources/addons/ljpost/lang/C/messages.po | 46 + sources/addons/ljpost/lang/ca/strings.php | 9 + sources/addons/ljpost/lang/cs/strings.php | 9 + sources/addons/ljpost/lang/de/strings.php | 9 + sources/addons/ljpost/lang/eo/strings.php | 9 + sources/addons/ljpost/lang/es/strings.php | 9 + sources/addons/ljpost/lang/fr/strings.php | 9 + sources/addons/ljpost/lang/is/strings.php | 9 + sources/addons/ljpost/lang/it/strings.php | 9 + sources/addons/ljpost/lang/nb-no/strings.php | 9 + sources/addons/ljpost/lang/pl/strings.php | 9 + sources/addons/ljpost/lang/pt-br/strings.php | 9 + sources/addons/ljpost/lang/ru/strings.php | 9 + sources/addons/ljpost/lang/sv/strings.php | 3 + sources/addons/ljpost/lang/zh-cn/strings.php | 9 + sources/addons/ljpost/ljpost.css | 0 sources/addons/ljpost/ljpost.php | 243 + sources/addons/logrot/logrot.php | 80 + sources/addons/logrot/view/tpl/admin.tpl | 4 + sources/addons/mahjongg/mahjongg.apd | 3 + sources/addons/mahjongg/mahjongg.php | 42 + sources/addons/mahjongg/mahjongg.png | Bin 0 -> 5951 bytes sources/addons/mahjongg/mahjongg.swf | Bin 0 -> 72018 bytes sources/addons/mailhost/mailhost.css | 0 sources/addons/mailhost/mailhost.php | 57 + sources/addons/morechoice/morechoice.php | 123 + sources/addons/moremoods/moremoods.php | 42 + sources/addons/morepokes/lang/C/messages.po | 164 + sources/addons/morepokes/lang/ca/strings.php | 38 + sources/addons/morepokes/lang/cs/messages.po | 167 + sources/addons/morepokes/lang/cs/strings.php | 43 + sources/addons/morepokes/lang/de/messages.po | 167 + sources/addons/morepokes/lang/de/strings.php | 43 + sources/addons/morepokes/lang/eo/strings.php | 38 + sources/addons/morepokes/lang/es/strings.php | 38 + sources/addons/morepokes/lang/fr/strings.php | 38 + sources/addons/morepokes/lang/is/strings.php | 38 + sources/addons/morepokes/lang/it/messages.po | 167 + sources/addons/morepokes/lang/it/strings.php | 43 + .../addons/morepokes/lang/nb-no/strings.php | 38 + sources/addons/morepokes/lang/pl/strings.php | 38 + .../addons/morepokes/lang/pt-br/strings.php | 38 + sources/addons/morepokes/lang/ro/messages.po | 167 + sources/addons/morepokes/lang/ro/strings.php | 43 + sources/addons/morepokes/lang/ru/strings.php | 38 + sources/addons/morepokes/lang/sv/strings.php | 2 + .../addons/morepokes/lang/zh-cn/strings.php | 38 + sources/addons/morepokes/morepokes.php | 38 + sources/addons/nofed/nofed.css | 0 sources/addons/nofed/nofed.php | 115 + sources/addons/nofed/rhash-32.png | Bin 0 -> 1322 bytes sources/addons/nsabait/nsabait.css | 0 sources/addons/nsabait/nsabait.php | 164 + sources/addons/nsabait/wordlist.txt | 2 + sources/addons/nsabait/words.txt | 372 + sources/addons/nsfw/README | 8 + sources/addons/nsfw/lang/C/messages.po | 57 + sources/addons/nsfw/lang/ca/strings.php | 10 + sources/addons/nsfw/lang/cs/strings.php | 10 + sources/addons/nsfw/lang/de/strings.php | 10 + sources/addons/nsfw/lang/eo/strings.php | 10 + sources/addons/nsfw/lang/es/strings.php | 10 + sources/addons/nsfw/lang/fr/strings.php | 10 + sources/addons/nsfw/lang/is/strings.php | 10 + sources/addons/nsfw/lang/it/strings.php | 10 + sources/addons/nsfw/lang/nb-no/strings.php | 10 + sources/addons/nsfw/lang/pl/strings.php | 10 + sources/addons/nsfw/lang/pt-br/strings.php | 10 + sources/addons/nsfw/lang/ru/strings.php | 10 + sources/addons/nsfw/lang/sv/strings.php | 3 + sources/addons/nsfw/lang/zh-cn/strings.php | 10 + sources/addons/nsfw/nsfw.css | 0 sources/addons/nsfw/nsfw.php | 214 + .../openclipatar/openclipart-banner.png | Bin 0 -> 8337 bytes sources/addons/openclipatar/openclipatar.css | 24 + sources/addons/openclipatar/openclipatar.php | 309 + .../addons/openclipatar/view/tpl/admin.tpl | 7 + .../openclipatar/view/tpl/avatar-ajax.tpl | 3 + .../openclipatar/view/tpl/avatar-entry.tpl | 11 + .../addons/openclipatar/view/tpl/avatars.tpl | 18 + sources/addons/openstreetmap/README.md | 75 + .../addons/openstreetmap/lang/C/messages.po | 44 + .../addons/openstreetmap/lang/ca/strings.php | 8 + .../addons/openstreetmap/lang/cs/strings.php | 8 + .../addons/openstreetmap/lang/de/strings.php | 8 + .../addons/openstreetmap/lang/eo/strings.php | 8 + .../addons/openstreetmap/lang/es/strings.php | 8 + .../addons/openstreetmap/lang/fr/strings.php | 8 + .../addons/openstreetmap/lang/is/strings.php | 8 + .../addons/openstreetmap/lang/it/strings.php | 8 + .../openstreetmap/lang/nb-no/strings.php | 8 + .../addons/openstreetmap/lang/pl/strings.php | 8 + .../openstreetmap/lang/pt-br/strings.php | 8 + .../addons/openstreetmap/lang/ru/strings.php | 8 + .../addons/openstreetmap/lang/sv/strings.php | 4 + .../openstreetmap/lang/zh-cn/strings.php | 8 + sources/addons/openstreetmap/openstreetmap.js | 39 + .../addons/openstreetmap/openstreetmap.php | 185 + .../addons/openstreetmap/view/tpl/admin.tpl | 5 + sources/addons/piwik/LICENSE | 24 + sources/addons/piwik/README.md | 64 + sources/addons/piwik/lang/C/messages.po | 62 + sources/addons/piwik/lang/ca/strings.php | 11 + sources/addons/piwik/lang/cs/strings.php | 11 + sources/addons/piwik/lang/de/strings.php | 11 + sources/addons/piwik/lang/eo/strings.php | 11 + sources/addons/piwik/lang/es/strings.php | 11 + sources/addons/piwik/lang/fr/strings.php | 11 + sources/addons/piwik/lang/is/strings.php | 11 + sources/addons/piwik/lang/it/strings.php | 11 + sources/addons/piwik/lang/nb-no/strings.php | 11 + sources/addons/piwik/lang/pl/strings.php | 11 + sources/addons/piwik/lang/pt-br/strings.php | 11 + sources/addons/piwik/lang/ru/strings.php | 11 + sources/addons/piwik/lang/sv/strings.php | 4 + sources/addons/piwik/lang/zh-cn/strings.php | 11 + sources/addons/piwik/piwik.css | 10 + sources/addons/piwik/piwik.php | 116 + sources/addons/piwik/view/tpl/admin.tpl | 6 + sources/addons/planets/planets.css | 0 sources/addons/planets/planets.php | 159 + sources/addons/pumpio/pumpio.css | 0 sources/addons/pumpio/pumpio.php | 506 ++ sources/addons/pumpio/pumpio.png | Bin 0 -> 1216 bytes sources/addons/qrator/phpqrcode/CHANGELOG | 38 + sources/addons/qrator/phpqrcode/INSTALL | 67 + sources/addons/qrator/phpqrcode/LICENSE | 165 + sources/addons/qrator/phpqrcode/README | 45 + sources/addons/qrator/phpqrcode/VERSION | 2 + .../phpqrcode/bindings/tcpdf/qrcode.php | 2875 +++++++ .../addons/qrator/phpqrcode/cache/frame_1.dat | 2 + .../addons/qrator/phpqrcode/cache/frame_1.png | Bin 0 -> 126 bytes .../qrator/phpqrcode/cache/frame_10.dat | Bin 0 -> 204 bytes .../qrator/phpqrcode/cache/frame_10.png | Bin 0 -> 202 bytes .../qrator/phpqrcode/cache/frame_11.dat | Bin 0 -> 210 bytes .../qrator/phpqrcode/cache/frame_11.png | Bin 0 -> 205 bytes .../qrator/phpqrcode/cache/frame_12.dat | Bin 0 -> 222 bytes .../qrator/phpqrcode/cache/frame_12.png | Bin 0 -> 216 bytes .../qrator/phpqrcode/cache/frame_13.dat | Bin 0 -> 223 bytes .../qrator/phpqrcode/cache/frame_13.png | Bin 0 -> 210 bytes .../qrator/phpqrcode/cache/frame_14.dat | Bin 0 -> 227 bytes .../qrator/phpqrcode/cache/frame_14.png | Bin 0 -> 213 bytes .../qrator/phpqrcode/cache/frame_15.dat | Bin 0 -> 242 bytes .../qrator/phpqrcode/cache/frame_15.png | Bin 0 -> 219 bytes .../qrator/phpqrcode/cache/frame_16.dat | 1 + .../qrator/phpqrcode/cache/frame_16.png | Bin 0 -> 211 bytes .../qrator/phpqrcode/cache/frame_17.dat | Bin 0 -> 237 bytes .../qrator/phpqrcode/cache/frame_17.png | Bin 0 -> 211 bytes .../qrator/phpqrcode/cache/frame_18.dat | 2 + .../qrator/phpqrcode/cache/frame_18.png | Bin 0 -> 228 bytes .../qrator/phpqrcode/cache/frame_19.dat | 3 + .../qrator/phpqrcode/cache/frame_19.png | Bin 0 -> 225 bytes .../addons/qrator/phpqrcode/cache/frame_2.dat | 1 + .../addons/qrator/phpqrcode/cache/frame_2.png | Bin 0 -> 144 bytes .../qrator/phpqrcode/cache/frame_20.dat | Bin 0 -> 250 bytes .../qrator/phpqrcode/cache/frame_20.png | Bin 0 -> 225 bytes .../qrator/phpqrcode/cache/frame_21.dat | 1 + .../qrator/phpqrcode/cache/frame_21.png | Bin 0 -> 235 bytes .../qrator/phpqrcode/cache/frame_22.dat | 3 + .../qrator/phpqrcode/cache/frame_22.png | Bin 0 -> 226 bytes .../qrator/phpqrcode/cache/frame_23.dat | 3 + .../qrator/phpqrcode/cache/frame_23.png | Bin 0 -> 220 bytes .../qrator/phpqrcode/cache/frame_24.dat | 1 + .../qrator/phpqrcode/cache/frame_24.png | Bin 0 -> 242 bytes .../qrator/phpqrcode/cache/frame_25.dat | 3 + .../qrator/phpqrcode/cache/frame_25.png | Bin 0 -> 242 bytes .../qrator/phpqrcode/cache/frame_26.dat | 2 + .../qrator/phpqrcode/cache/frame_26.png | Bin 0 -> 244 bytes .../qrator/phpqrcode/cache/frame_27.dat | Bin 0 -> 284 bytes .../qrator/phpqrcode/cache/frame_27.png | Bin 0 -> 237 bytes .../qrator/phpqrcode/cache/frame_28.dat | Bin 0 -> 318 bytes .../qrator/phpqrcode/cache/frame_28.png | Bin 0 -> 234 bytes .../qrator/phpqrcode/cache/frame_29.dat | 2 + .../qrator/phpqrcode/cache/frame_29.png | Bin 0 -> 232 bytes .../addons/qrator/phpqrcode/cache/frame_3.dat | 1 + .../addons/qrator/phpqrcode/cache/frame_3.png | Bin 0 -> 147 bytes .../qrator/phpqrcode/cache/frame_30.dat | Bin 0 -> 324 bytes .../qrator/phpqrcode/cache/frame_30.png | Bin 0 -> 255 bytes .../qrator/phpqrcode/cache/frame_31.dat | 1 + .../qrator/phpqrcode/cache/frame_31.png | Bin 0 -> 260 bytes .../qrator/phpqrcode/cache/frame_32.dat | 2 + .../qrator/phpqrcode/cache/frame_32.png | Bin 0 -> 262 bytes .../qrator/phpqrcode/cache/frame_33.dat | 14 + .../qrator/phpqrcode/cache/frame_33.png | Bin 0 -> 253 bytes .../qrator/phpqrcode/cache/frame_34.dat | Bin 0 -> 331 bytes .../qrator/phpqrcode/cache/frame_34.png | Bin 0 -> 256 bytes .../qrator/phpqrcode/cache/frame_35.dat | Bin 0 -> 342 bytes .../qrator/phpqrcode/cache/frame_35.png | Bin 0 -> 243 bytes .../qrator/phpqrcode/cache/frame_36.dat | Bin 0 -> 370 bytes .../qrator/phpqrcode/cache/frame_36.png | Bin 0 -> 272 bytes .../qrator/phpqrcode/cache/frame_37.dat | Bin 0 -> 376 bytes .../qrator/phpqrcode/cache/frame_37.png | Bin 0 -> 279 bytes .../qrator/phpqrcode/cache/frame_38.dat | 1 + .../qrator/phpqrcode/cache/frame_38.png | Bin 0 -> 279 bytes .../qrator/phpqrcode/cache/frame_39.dat | Bin 0 -> 404 bytes .../qrator/phpqrcode/cache/frame_39.png | Bin 0 -> 264 bytes .../addons/qrator/phpqrcode/cache/frame_4.dat | 1 + .../addons/qrator/phpqrcode/cache/frame_4.png | Bin 0 -> 149 bytes .../qrator/phpqrcode/cache/frame_40.dat | 2 + .../qrator/phpqrcode/cache/frame_40.png | Bin 0 -> 267 bytes .../addons/qrator/phpqrcode/cache/frame_5.dat | 1 + .../addons/qrator/phpqrcode/cache/frame_5.png | Bin 0 -> 150 bytes .../addons/qrator/phpqrcode/cache/frame_6.dat | Bin 0 -> 132 bytes .../addons/qrator/phpqrcode/cache/frame_6.png | Bin 0 -> 151 bytes .../addons/qrator/phpqrcode/cache/frame_7.dat | Bin 0 -> 196 bytes .../addons/qrator/phpqrcode/cache/frame_7.png | Bin 0 -> 189 bytes .../addons/qrator/phpqrcode/cache/frame_8.dat | Bin 0 -> 201 bytes .../addons/qrator/phpqrcode/cache/frame_8.png | Bin 0 -> 204 bytes .../addons/qrator/phpqrcode/cache/frame_9.dat | Bin 0 -> 206 bytes .../addons/qrator/phpqrcode/cache/frame_9.png | Bin 0 -> 199 bytes .../phpqrcode/cache/mask_0/mask_101_0.dat | Bin 0 -> 157 bytes .../phpqrcode/cache/mask_0/mask_105_0.dat | Bin 0 -> 162 bytes .../phpqrcode/cache/mask_0/mask_109_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_113_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_117_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_121_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_125_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_129_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_133_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_137_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_141_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_145_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_149_0.dat | 3 + .../phpqrcode/cache/mask_0/mask_153_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_157_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_161_0.dat | Bin 0 -> 241 bytes .../phpqrcode/cache/mask_0/mask_165_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_169_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_173_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_177_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_21_0.dat | Bin 0 -> 48 bytes .../phpqrcode/cache/mask_0/mask_25_0.dat | Bin 0 -> 57 bytes .../phpqrcode/cache/mask_0/mask_29_0.dat | Bin 0 -> 59 bytes .../phpqrcode/cache/mask_0/mask_33_0.dat | Bin 0 -> 62 bytes .../phpqrcode/cache/mask_0/mask_37_0.dat | Bin 0 -> 65 bytes .../phpqrcode/cache/mask_0/mask_41_0.dat | Bin 0 -> 68 bytes .../phpqrcode/cache/mask_0/mask_45_0.dat | Bin 0 -> 106 bytes .../phpqrcode/cache/mask_0/mask_49_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_53_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_57_0.dat | 4 + .../phpqrcode/cache/mask_0/mask_61_0.dat | Bin 0 -> 119 bytes .../phpqrcode/cache/mask_0/mask_65_0.dat | Bin 0 -> 123 bytes .../phpqrcode/cache/mask_0/mask_69_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_73_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_77_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_81_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_85_0.dat | 2 + .../phpqrcode/cache/mask_0/mask_89_0.dat | 1 + .../phpqrcode/cache/mask_0/mask_93_0.dat | 3 + .../phpqrcode/cache/mask_0/mask_97_0.dat | Bin 0 -> 150 bytes .../phpqrcode/cache/mask_1/mask_101_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_105_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_109_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_113_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_117_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_121_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_125_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_129_1.dat | Bin 0 -> 164 bytes .../phpqrcode/cache/mask_1/mask_133_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_137_1.dat | 3 + .../phpqrcode/cache/mask_1/mask_141_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_145_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_149_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_153_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_157_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_161_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_165_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_169_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_173_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_177_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_21_1.dat | Bin 0 -> 42 bytes .../phpqrcode/cache/mask_1/mask_25_1.dat | Bin 0 -> 48 bytes .../phpqrcode/cache/mask_1/mask_29_1.dat | Bin 0 -> 50 bytes .../phpqrcode/cache/mask_1/mask_33_1.dat | Bin 0 -> 53 bytes .../phpqrcode/cache/mask_1/mask_37_1.dat | Bin 0 -> 56 bytes .../phpqrcode/cache/mask_1/mask_41_1.dat | Bin 0 -> 58 bytes .../phpqrcode/cache/mask_1/mask_45_1.dat | Bin 0 -> 82 bytes .../phpqrcode/cache/mask_1/mask_49_1.dat | Bin 0 -> 84 bytes .../phpqrcode/cache/mask_1/mask_53_1.dat | Bin 0 -> 87 bytes .../phpqrcode/cache/mask_1/mask_57_1.dat | Bin 0 -> 92 bytes .../phpqrcode/cache/mask_1/mask_61_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_65_1.dat | Bin 0 -> 99 bytes .../phpqrcode/cache/mask_1/mask_69_1.dat | Bin 0 -> 102 bytes .../phpqrcode/cache/mask_1/mask_73_1.dat | Bin 0 -> 104 bytes .../phpqrcode/cache/mask_1/mask_77_1.dat | Bin 0 -> 110 bytes .../phpqrcode/cache/mask_1/mask_81_1.dat | Bin 0 -> 114 bytes .../phpqrcode/cache/mask_1/mask_85_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_89_1.dat | 1 + .../phpqrcode/cache/mask_1/mask_93_1.dat | 2 + .../phpqrcode/cache/mask_1/mask_97_1.dat | 2 + .../phpqrcode/cache/mask_2/mask_101_2.dat | 3 + .../phpqrcode/cache/mask_2/mask_105_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_109_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_113_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_117_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_121_2.dat | Bin 0 -> 127 bytes .../phpqrcode/cache/mask_2/mask_125_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_129_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_133_2.dat | 10 + .../phpqrcode/cache/mask_2/mask_137_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_141_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_145_2.dat | 4 + .../phpqrcode/cache/mask_2/mask_149_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_153_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_157_2.dat | 3 + .../phpqrcode/cache/mask_2/mask_161_2.dat | Bin 0 -> 190 bytes .../phpqrcode/cache/mask_2/mask_165_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_169_2.dat | Bin 0 -> 196 bytes .../phpqrcode/cache/mask_2/mask_173_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_177_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_21_2.dat | Bin 0 -> 35 bytes .../phpqrcode/cache/mask_2/mask_25_2.dat | Bin 0 -> 41 bytes .../phpqrcode/cache/mask_2/mask_29_2.dat | Bin 0 -> 45 bytes .../phpqrcode/cache/mask_2/mask_33_2.dat | Bin 0 -> 47 bytes .../phpqrcode/cache/mask_2/mask_37_2.dat | Bin 0 -> 47 bytes .../phpqrcode/cache/mask_2/mask_41_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_45_2.dat | Bin 0 -> 68 bytes .../phpqrcode/cache/mask_2/mask_49_2.dat | Bin 0 -> 70 bytes .../phpqrcode/cache/mask_2/mask_53_2.dat | Bin 0 -> 73 bytes .../phpqrcode/cache/mask_2/mask_57_2.dat | Bin 0 -> 76 bytes .../phpqrcode/cache/mask_2/mask_61_2.dat | Bin 0 -> 78 bytes .../phpqrcode/cache/mask_2/mask_65_2.dat | Bin 0 -> 89 bytes .../phpqrcode/cache/mask_2/mask_69_2.dat | Bin 0 -> 88 bytes .../phpqrcode/cache/mask_2/mask_73_2.dat | Bin 0 -> 94 bytes .../phpqrcode/cache/mask_2/mask_77_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_81_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_85_2.dat | 2 + .../phpqrcode/cache/mask_2/mask_89_2.dat | 1 + .../phpqrcode/cache/mask_2/mask_93_2.dat | Bin 0 -> 103 bytes .../phpqrcode/cache/mask_2/mask_97_2.dat | 2 + .../phpqrcode/cache/mask_3/mask_101_3.dat | 1 + .../phpqrcode/cache/mask_3/mask_105_3.dat | 1 + .../phpqrcode/cache/mask_3/mask_109_3.dat | 1 + .../phpqrcode/cache/mask_3/mask_113_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_117_3.dat | 4 + .../phpqrcode/cache/mask_3/mask_121_3.dat | Bin 0 -> 212 bytes .../phpqrcode/cache/mask_3/mask_125_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_129_3.dat | 8 + .../phpqrcode/cache/mask_3/mask_133_3.dat | Bin 0 -> 216 bytes .../phpqrcode/cache/mask_3/mask_137_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_141_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_145_3.dat | 3 + .../phpqrcode/cache/mask_3/mask_149_3.dat | 1 + .../phpqrcode/cache/mask_3/mask_153_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_157_3.dat | Bin 0 -> 248 bytes .../phpqrcode/cache/mask_3/mask_161_3.dat | 3 + .../phpqrcode/cache/mask_3/mask_165_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_169_3.dat | 1 + .../phpqrcode/cache/mask_3/mask_173_3.dat | 1 + .../phpqrcode/cache/mask_3/mask_177_3.dat | Bin 0 -> 312 bytes .../phpqrcode/cache/mask_3/mask_21_3.dat | Bin 0 -> 60 bytes .../phpqrcode/cache/mask_3/mask_25_3.dat | Bin 0 -> 75 bytes .../phpqrcode/cache/mask_3/mask_29_3.dat | Bin 0 -> 75 bytes .../phpqrcode/cache/mask_3/mask_33_3.dat | Bin 0 -> 79 bytes .../phpqrcode/cache/mask_3/mask_37_3.dat | Bin 0 -> 83 bytes .../phpqrcode/cache/mask_3/mask_41_3.dat | Bin 0 -> 85 bytes .../phpqrcode/cache/mask_3/mask_45_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_49_3.dat | Bin 0 -> 127 bytes .../phpqrcode/cache/mask_3/mask_53_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_57_3.dat | Bin 0 -> 126 bytes .../phpqrcode/cache/mask_3/mask_61_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_65_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_69_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_73_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_77_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_81_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_85_3.dat | Bin 0 -> 160 bytes .../phpqrcode/cache/mask_3/mask_89_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_93_3.dat | 2 + .../phpqrcode/cache/mask_3/mask_97_3.dat | Bin 0 -> 175 bytes .../phpqrcode/cache/mask_4/mask_101_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_105_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_109_4.dat | Bin 0 -> 182 bytes .../phpqrcode/cache/mask_4/mask_113_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_117_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_121_4.dat | Bin 0 -> 208 bytes .../phpqrcode/cache/mask_4/mask_125_4.dat | Bin 0 -> 213 bytes .../phpqrcode/cache/mask_4/mask_129_4.dat | Bin 0 -> 220 bytes .../phpqrcode/cache/mask_4/mask_133_4.dat | 3 + .../phpqrcode/cache/mask_4/mask_137_4.dat | Bin 0 -> 248 bytes .../phpqrcode/cache/mask_4/mask_141_4.dat | Bin 0 -> 254 bytes .../phpqrcode/cache/mask_4/mask_145_4.dat | Bin 0 -> 255 bytes .../phpqrcode/cache/mask_4/mask_149_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_153_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_157_4.dat | 1 + .../phpqrcode/cache/mask_4/mask_161_4.dat | 1 + .../phpqrcode/cache/mask_4/mask_165_4.dat | 3 + .../phpqrcode/cache/mask_4/mask_169_4.dat | Bin 0 -> 297 bytes .../phpqrcode/cache/mask_4/mask_173_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_177_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_21_4.dat | Bin 0 -> 57 bytes .../phpqrcode/cache/mask_4/mask_25_4.dat | Bin 0 -> 76 bytes .../phpqrcode/cache/mask_4/mask_29_4.dat | Bin 0 -> 78 bytes .../phpqrcode/cache/mask_4/mask_33_4.dat | Bin 0 -> 89 bytes .../phpqrcode/cache/mask_4/mask_37_4.dat | Bin 0 -> 86 bytes .../phpqrcode/cache/mask_4/mask_41_4.dat | Bin 0 -> 89 bytes .../phpqrcode/cache/mask_4/mask_45_4.dat | Bin 0 -> 120 bytes .../phpqrcode/cache/mask_4/mask_49_4.dat | Bin 0 -> 124 bytes .../phpqrcode/cache/mask_4/mask_53_4.dat | Bin 0 -> 128 bytes .../phpqrcode/cache/mask_4/mask_57_4.dat | Bin 0 -> 130 bytes .../phpqrcode/cache/mask_4/mask_61_4.dat | Bin 0 -> 132 bytes .../phpqrcode/cache/mask_4/mask_65_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_69_4.dat | 1 + .../phpqrcode/cache/mask_4/mask_73_4.dat | 3 + .../phpqrcode/cache/mask_4/mask_77_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_81_4.dat | 3 + .../phpqrcode/cache/mask_4/mask_85_4.dat | Bin 0 -> 154 bytes .../phpqrcode/cache/mask_4/mask_89_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_93_4.dat | 2 + .../phpqrcode/cache/mask_4/mask_97_4.dat | Bin 0 -> 176 bytes .../phpqrcode/cache/mask_5/mask_101_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_105_5.dat | Bin 0 -> 224 bytes .../phpqrcode/cache/mask_5/mask_109_5.dat | Bin 0 -> 211 bytes .../phpqrcode/cache/mask_5/mask_113_5.dat | 9 + .../phpqrcode/cache/mask_5/mask_117_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_121_5.dat | Bin 0 -> 256 bytes .../phpqrcode/cache/mask_5/mask_125_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_129_5.dat | Bin 0 -> 259 bytes .../phpqrcode/cache/mask_5/mask_133_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_137_5.dat | 3 + .../phpqrcode/cache/mask_5/mask_141_5.dat | Bin 0 -> 297 bytes .../phpqrcode/cache/mask_5/mask_145_5.dat | Bin 0 -> 300 bytes .../phpqrcode/cache/mask_5/mask_149_5.dat | 3 + .../phpqrcode/cache/mask_5/mask_153_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_157_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_161_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_165_5.dat | Bin 0 -> 332 bytes .../phpqrcode/cache/mask_5/mask_169_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_173_5.dat | 4 + .../phpqrcode/cache/mask_5/mask_177_5.dat | 11 + .../phpqrcode/cache/mask_5/mask_21_5.dat | Bin 0 -> 74 bytes .../phpqrcode/cache/mask_5/mask_25_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_29_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_33_5.dat | Bin 0 -> 106 bytes .../phpqrcode/cache/mask_5/mask_37_5.dat | Bin 0 -> 103 bytes .../phpqrcode/cache/mask_5/mask_41_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_45_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_49_5.dat | Bin 0 -> 146 bytes .../phpqrcode/cache/mask_5/mask_53_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_57_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_61_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_65_5.dat | Bin 0 -> 163 bytes .../phpqrcode/cache/mask_5/mask_69_5.dat | Bin 0 -> 167 bytes .../phpqrcode/cache/mask_5/mask_73_5.dat | Bin 0 -> 184 bytes .../phpqrcode/cache/mask_5/mask_77_5.dat | 1 + .../phpqrcode/cache/mask_5/mask_81_5.dat | 3 + .../phpqrcode/cache/mask_5/mask_85_5.dat | Bin 0 -> 186 bytes .../phpqrcode/cache/mask_5/mask_89_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_93_5.dat | 2 + .../phpqrcode/cache/mask_5/mask_97_5.dat | 1 + .../phpqrcode/cache/mask_6/mask_101_6.dat | 2 + .../phpqrcode/cache/mask_6/mask_105_6.dat | 3 + .../phpqrcode/cache/mask_6/mask_109_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_113_6.dat | 3 + .../phpqrcode/cache/mask_6/mask_117_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_121_6.dat | Bin 0 -> 309 bytes .../phpqrcode/cache/mask_6/mask_125_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_129_6.dat | Bin 0 -> 310 bytes .../phpqrcode/cache/mask_6/mask_133_6.dat | Bin 0 -> 296 bytes .../phpqrcode/cache/mask_6/mask_137_6.dat | 2 + .../phpqrcode/cache/mask_6/mask_141_6.dat | 10 + .../phpqrcode/cache/mask_6/mask_145_6.dat | Bin 0 -> 357 bytes .../phpqrcode/cache/mask_6/mask_149_6.dat | 2 + .../phpqrcode/cache/mask_6/mask_153_6.dat | Bin 0 -> 367 bytes .../phpqrcode/cache/mask_6/mask_157_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_161_6.dat | Bin 0 -> 399 bytes .../phpqrcode/cache/mask_6/mask_165_6.dat | Bin 0 -> 400 bytes .../phpqrcode/cache/mask_6/mask_169_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_173_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_177_6.dat | 14 + .../phpqrcode/cache/mask_6/mask_21_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_25_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_29_6.dat | 3 + .../phpqrcode/cache/mask_6/mask_33_6.dat | Bin 0 -> 124 bytes .../phpqrcode/cache/mask_6/mask_37_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_41_6.dat | Bin 0 -> 132 bytes .../phpqrcode/cache/mask_6/mask_45_6.dat | Bin 0 -> 189 bytes .../phpqrcode/cache/mask_6/mask_49_6.dat | 2 + .../phpqrcode/cache/mask_6/mask_53_6.dat | Bin 0 -> 195 bytes .../phpqrcode/cache/mask_6/mask_57_6.dat | 2 + .../phpqrcode/cache/mask_6/mask_61_6.dat | 2 + .../phpqrcode/cache/mask_6/mask_65_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_69_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_73_6.dat | Bin 0 -> 230 bytes .../phpqrcode/cache/mask_6/mask_77_6.dat | 1 + .../phpqrcode/cache/mask_6/mask_81_6.dat | 3 + .../phpqrcode/cache/mask_6/mask_85_6.dat | Bin 0 -> 229 bytes .../phpqrcode/cache/mask_6/mask_89_6.dat | Bin 0 -> 263 bytes .../phpqrcode/cache/mask_6/mask_93_6.dat | Bin 0 -> 276 bytes .../phpqrcode/cache/mask_6/mask_97_6.dat | 2 + .../phpqrcode/cache/mask_7/mask_101_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_105_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_109_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_113_7.dat | 11 + .../phpqrcode/cache/mask_7/mask_117_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_121_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_125_7.dat | Bin 0 -> 288 bytes .../phpqrcode/cache/mask_7/mask_129_7.dat | Bin 0 -> 282 bytes .../phpqrcode/cache/mask_7/mask_133_7.dat | Bin 0 -> 281 bytes .../phpqrcode/cache/mask_7/mask_137_7.dat | 5 + .../phpqrcode/cache/mask_7/mask_141_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_145_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_149_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_153_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_157_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_161_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_165_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_169_7.dat | Bin 0 -> 383 bytes .../phpqrcode/cache/mask_7/mask_173_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_177_7.dat | Bin 0 -> 407 bytes .../phpqrcode/cache/mask_7/mask_21_7.dat | 4 + .../phpqrcode/cache/mask_7/mask_25_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_29_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_33_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_37_7.dat | Bin 0 -> 122 bytes .../phpqrcode/cache/mask_7/mask_41_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_45_7.dat | Bin 0 -> 173 bytes .../phpqrcode/cache/mask_7/mask_49_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_53_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_57_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_61_7.dat | 2 + .../phpqrcode/cache/mask_7/mask_65_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_69_7.dat | Bin 0 -> 202 bytes .../phpqrcode/cache/mask_7/mask_73_7.dat | Bin 0 -> 221 bytes .../phpqrcode/cache/mask_7/mask_77_7.dat | Bin 0 -> 226 bytes .../phpqrcode/cache/mask_7/mask_81_7.dat | 1 + .../phpqrcode/cache/mask_7/mask_85_7.dat | Bin 0 -> 213 bytes .../phpqrcode/cache/mask_7/mask_89_7.dat | Bin 0 -> 244 bytes .../phpqrcode/cache/mask_7/mask_93_7.dat | Bin 0 -> 248 bytes .../phpqrcode/cache/mask_7/mask_97_7.dat | 2 + sources/addons/qrator/phpqrcode/index.php | 94 + sources/addons/qrator/phpqrcode/phpqrcode.php | 3312 ++++++++ .../addons/qrator/phpqrcode/qrbitstream.php | 180 + sources/addons/qrator/phpqrcode/qrconfig.php | 17 + sources/addons/qrator/phpqrcode/qrconst.php | 54 + sources/addons/qrator/phpqrcode/qrencode.php | 502 ++ sources/addons/qrator/phpqrcode/qrimage.php | 95 + sources/addons/qrator/phpqrcode/qrinput.php | 729 ++ sources/addons/qrator/phpqrcode/qrlib.php | 43 + sources/addons/qrator/phpqrcode/qrmask.php | 328 + sources/addons/qrator/phpqrcode/qrrscode.php | 210 + sources/addons/qrator/phpqrcode/qrspec.php | 592 ++ sources/addons/qrator/phpqrcode/qrsplit.php | 311 + sources/addons/qrator/phpqrcode/qrtools.php | 172 + .../addons/qrator/phpqrcode/tools/merge.bat | 2 + .../addons/qrator/phpqrcode/tools/merge.php | 70 + .../addons/qrator/phpqrcode/tools/merge.sh | 2 + .../qrator/phpqrcode/tools/merged_config.php | 17 + .../qrator/phpqrcode/tools/merged_header.php | 36 + sources/addons/qrator/qrator.apd | 3 + sources/addons/qrator/qrator.php | 86 + sources/addons/qrator/qrator.png | Bin 0 -> 294 bytes sources/addons/rainbowtag/rainbowtag.css | 0 sources/addons/rainbowtag/rainbowtag.php | 102 + sources/addons/randpost/randpost.php | 286 + sources/addons/redfiles/redfilehelper.php | 94 + sources/addons/redfiles/redfiles.php | 126 + sources/addons/redfiles/view/tpl/redfiles.tpl | 13 + sources/addons/redphotos/redphotohelper.php | 104 + sources/addons/redphotos/redphotos.php | 126 + .../addons/redphotos/view/tpl/redphotos.tpl | 14 + sources/addons/redred/redred.css | 0 sources/addons/redred/redred.php | 199 + sources/addons/redred/rhash-32.png | Bin 0 -> 1322 bytes sources/addons/rtof/friendica.png | Bin 0 -> 1593 bytes sources/addons/rtof/rtof.css | 0 sources/addons/rtof/rtof.php | 177 + sources/addons/sendzid/sendzid.php | 29 + sources/addons/skeleton/README.md | 8 + sources/addons/skeleton/skeleton.php | 71 + .../addons/smiley_pack/icons/animals/bee.gif | Bin 0 -> 4506 bytes .../smiley_pack/icons/animals/bigspider.gif | Bin 0 -> 25976 bytes .../smiley_pack/icons/animals/bunny.gif | Bin 0 -> 1482 bytes .../icons/animals/bunnyflowers.gif | Bin 0 -> 6640 bytes .../addons/smiley_pack/icons/animals/cat.gif | Bin 0 -> 864 bytes .../smiley_pack/icons/animals/chick.gif | Bin 0 -> 3667 bytes .../addons/smiley_pack/icons/animals/cow.gif | Bin 0 -> 780 bytes .../addons/smiley_pack/icons/animals/crab.gif | Bin 0 -> 2718 bytes .../addons/smiley_pack/icons/animals/dog.gif | Bin 0 -> 5371 bytes .../smiley_pack/icons/animals/dolphin.gif | Bin 0 -> 1581 bytes .../smiley_pack/icons/animals/dragonfly.gif | Bin 0 -> 2545 bytes .../smiley_pack/icons/animals/elephant.gif | Bin 0 -> 951 bytes .../addons/smiley_pack/icons/animals/fish.gif | Bin 0 -> 4499 bytes .../addons/smiley_pack/icons/animals/frog.gif | Bin 0 -> 1580 bytes .../smiley_pack/icons/animals/giraffe.gif | Bin 0 -> 4896 bytes .../smiley_pack/icons/animals/hamster.gif | Bin 0 -> 1246 bytes .../smiley_pack/icons/animals/horse.gif | Bin 0 -> 2464 bytes .../smiley_pack/icons/animals/ladybird.gif | Bin 0 -> 990 bytes .../smiley_pack/icons/animals/monkey.gif | Bin 0 -> 4901 bytes .../smiley_pack/icons/animals/parrot.gif | Bin 0 -> 1770 bytes .../addons/smiley_pack/icons/animals/pig.gif | Bin 0 -> 925 bytes .../smiley_pack/icons/animals/sheep.gif | Bin 0 -> 7631 bytes .../smiley_pack/icons/animals/snail.gif | Bin 0 -> 645 bytes .../addons/smiley_pack/icons/animals/tux.gif | Bin 0 -> 1573 bytes .../addons/smiley_pack/icons/babies/baby.gif | Bin 0 -> 334 bytes .../smiley_pack/icons/babies/babycot.gif | Bin 0 -> 3453 bytes .../smiley_pack/icons/babies/pregnant.gif | Bin 0 -> 1507 bytes .../addons/smiley_pack/icons/babies/stork.gif | Bin 0 -> 18984 bytes .../smiley_pack/icons/confused/confused.gif | Bin 0 -> 594 bytes .../smiley_pack/icons/confused/dazed.gif | Bin 0 -> 1614 bytes .../smiley_pack/icons/confused/shrug.gif | Bin 0 -> 184 bytes .../smiley_pack/icons/confused/stupid.gif | Bin 0 -> 10700 bytes .../addons/smiley_pack/icons/cool/affro.gif | Bin 0 -> 158 bytes .../addons/smiley_pack/icons/cool/cool.gif | Bin 0 -> 5140 bytes .../smiley_pack/icons/devilangel/angel.gif | Bin 0 -> 312 bytes .../icons/devilangel/blondedevil.gif | Bin 0 -> 2957 bytes .../smiley_pack/icons/devilangel/catdevil.gif | Bin 0 -> 1965 bytes .../smiley_pack/icons/devilangel/cherub.gif | Bin 0 -> 1614 bytes .../smiley_pack/icons/devilangel/daseesaw.gif | Bin 0 -> 6780 bytes .../smiley_pack/icons/devilangel/devil.gif | Bin 0 -> 1996 bytes .../icons/devilangel/graveside.gif | Bin 0 -> 8226 bytes .../smiley_pack/icons/devilangel/saint.gif | Bin 0 -> 1197 bytes .../smiley_pack/icons/devilangel/turnevil.gif | Bin 0 -> 636 bytes .../smiley_pack/icons/disgust/fartblush.gif | Bin 0 -> 29855 bytes .../smiley_pack/icons/disgust/fartinbed.gif | Bin 0 -> 23289 bytes .../smiley_pack/icons/disgust/toilet.gif | Bin 0 -> 8936 bytes .../smiley_pack/icons/disgust/vomit.gif | Bin 0 -> 2727 bytes .../addons/smiley_pack/icons/drink/tea.gif | Bin 0 -> 9915 bytes .../addons/smiley_pack/icons/drool/drool.gif | Bin 0 -> 1379 bytes .../icons/fantasy/alienmonster.gif | Bin 0 -> 7636 bytes .../smiley_pack/icons/fantasy/barbarian.gif | Bin 0 -> 454 bytes .../smiley_pack/icons/fantasy/dinosaur.gif | Bin 0 -> 2837 bytes .../smiley_pack/icons/fantasy/doctor.gif | Bin 0 -> 703 bytes .../smiley_pack/icons/fantasy/dragon.gif | Bin 0 -> 3431 bytes .../smiley_pack/icons/fantasy/dragonwhelp.gif | Bin 0 -> 2338 bytes .../smiley_pack/icons/fantasy/ghost.gif | Bin 0 -> 1050 bytes .../smiley_pack/icons/fantasy/mummy.gif | Bin 0 -> 6552 bytes .../addons/smiley_pack/icons/fight/2guns.gif | Bin 0 -> 810 bytes .../addons/smiley_pack/icons/fight/acid.gif | Bin 0 -> 70861 bytes .../smiley_pack/icons/fight/alienfight.gif | Bin 0 -> 26128 bytes .../addons/smiley_pack/icons/fight/alpha.png | Bin 0 -> 664 bytes .../addons/smiley_pack/icons/fight/army.gif | Bin 0 -> 3024 bytes .../smiley_pack/icons/fight/arrowhead.gif | Bin 0 -> 174 bytes .../addons/smiley_pack/icons/fight/bfg.gif | Bin 0 -> 2267 bytes .../addons/smiley_pack/icons/fight/bowman.gif | Bin 0 -> 1337 bytes .../smiley_pack/icons/fight/chainsaw.gif | Bin 0 -> 20364 bytes .../smiley_pack/icons/fight/crossbow.gif | Bin 0 -> 891 bytes .../smiley_pack/icons/fight/crusader.gif | Bin 0 -> 403 bytes .../addons/smiley_pack/icons/fight/dead.gif | Bin 0 -> 167 bytes .../addons/smiley_pack/icons/fight/gangs.gif | Bin 0 -> 1746 bytes .../smiley_pack/icons/fight/hammersplat.gif | Bin 0 -> 16839 bytes .../smiley_pack/icons/fight/lasergun.gif | Bin 0 -> 2070 bytes .../smiley_pack/icons/fight/machinegun.gif | Bin 0 -> 1708 bytes .../addons/smiley_pack/icons/fight/marine.gif | Bin 0 -> 5829 bytes .../addons/smiley_pack/icons/fight/sabre.gif | Bin 0 -> 664 bytes .../smiley_pack/icons/fight/samurai.gif | Bin 0 -> 3286 bytes .../addons/smiley_pack/icons/fight/tank.gif | Bin 0 -> 11457 bytes .../smiley_pack/icons/fight/throw-rocks.gif | Bin 0 -> 2101 bytes .../addons/smiley_pack/icons/fight/viking.gif | Bin 0 -> 9650 bytes .../addons/smiley_pack/icons/food/apple.gif | Bin 0 -> 1689 bytes .../addons/smiley_pack/icons/food/banana.gif | Bin 0 -> 1545 bytes .../smiley_pack/icons/food/birthdaycake.gif | Bin 0 -> 6453 bytes .../smiley_pack/icons/food/broccoli.gif | Bin 0 -> 4025 bytes .../addons/smiley_pack/icons/food/cake.gif | Bin 0 -> 668 bytes .../addons/smiley_pack/icons/food/carrot.gif | Bin 0 -> 583 bytes .../addons/smiley_pack/icons/food/cooking.gif | Bin 0 -> 3125 bytes .../addons/smiley_pack/icons/food/fryegg.gif | Bin 0 -> 6492 bytes .../addons/smiley_pack/icons/food/popcorn.gif | Bin 0 -> 1155 bytes .../addons/smiley_pack/icons/food/tomato.gif | Bin 0 -> 2632 bytes .../addons/smiley_pack/icons/happy/cloud9.gif | Bin 0 -> 265 bytes .../smiley_pack/icons/happy/tearsofjoy.gif | Bin 0 -> 1297 bytes .../addons/smiley_pack/icons/laugh/hahaha.gif | Bin 0 -> 8268 bytes .../addons/smiley_pack/icons/laugh/loltv.gif | Bin 0 -> 2335 bytes .../addons/smiley_pack/icons/laugh/rofl.gif | Bin 0 -> 1010 bytes .../smiley_pack/icons/laugh/snicker.jpeg | Bin 0 -> 1465 bytes .../smiley_pack/icons/love/iloveyou.gif | Bin 0 -> 15681 bytes .../addons/smiley_pack/icons/love/inlove.gif | Bin 0 -> 1005 bytes .../addons/smiley_pack/icons/love/love.gif | Bin 0 -> 3451 bytes .../smiley_pack/icons/love/lovebear.gif | Bin 0 -> 4491 bytes .../addons/smiley_pack/icons/love/lovebed.gif | Bin 0 -> 10249 bytes .../smiley_pack/icons/love/loveheart.gif | Bin 0 -> 652 bytes sources/addons/smiley_pack/icons/music/dj.gif | Bin 0 -> 4446 bytes .../addons/smiley_pack/icons/music/drums.gif | Bin 0 -> 7596 bytes .../addons/smiley_pack/icons/music/elvis.gif | Bin 0 -> 1789 bytes .../addons/smiley_pack/icons/music/guitar.gif | Bin 0 -> 2070 bytes .../smiley_pack/icons/music/trumpet.gif | Bin 0 -> 461 bytes .../addons/smiley_pack/icons/music/violin.gif | Bin 0 -> 1798 bytes .../smiley_pack/icons/oldcore/beard.png | Bin 0 -> 1094 bytes .../smiley_pack/icons/oldcore/headbang.gif | Bin 0 -> 885 bytes .../smiley_pack/icons/oldcore/laughing.gif | Bin 0 -> 306 bytes .../smiley_pack/icons/oldcore/shaka.gif | Bin 0 -> 2238 bytes .../smiley_pack/icons/oldcore/surprised.gif | Bin 0 -> 303 bytes .../smiley_pack/icons/oldcore/whitebeard.png | Bin 0 -> 1060 bytes .../addons/smiley_pack/icons/respect/bow.gif | Bin 0 -> 1778 bytes .../smiley_pack/icons/respect/bravo.gif | Bin 0 -> 761 bytes .../smiley_pack/icons/respect/hailking.gif | Bin 0 -> 23733 bytes .../smiley_pack/icons/respect/number1.gif | Bin 0 -> 365 bytes .../smiley_pack/icons/respect/towel.gif | Bin 0 -> 1522 bytes .../addons/smiley_pack/icons/sad/crying.png | Bin 0 -> 1259 bytes .../addons/smiley_pack/icons/sad/prisoner.gif | Bin 0 -> 1961 bytes sources/addons/smiley_pack/icons/sad/sigh.gif | Bin 0 -> 748 bytes .../smiley_pack/icons/smoking/smoking.gif | Bin 0 -> 2288 bytes .../smiley_pack/icons/sport/archery.gif | Bin 0 -> 2793 bytes .../smiley_pack/icons/sport/basketball.gif | Bin 0 -> 8378 bytes .../smiley_pack/icons/sport/bowling.gif | Bin 0 -> 3562 bytes .../smiley_pack/icons/sport/cycling.gif | Bin 0 -> 1883 bytes .../addons/smiley_pack/icons/sport/darts.gif | Bin 0 -> 7103 bytes .../smiley_pack/icons/sport/fencing.gif | Bin 0 -> 11247 bytes .../smiley_pack/icons/sport/football.gif | Bin 0 -> 1937 bytes .../addons/smiley_pack/icons/sport/golf.gif | Bin 0 -> 2399 bytes .../smiley_pack/icons/sport/horseriding.gif | Bin 0 -> 10489 bytes .../smiley_pack/icons/sport/juggling.gif | Bin 0 -> 4292 bytes .../smiley_pack/icons/sport/skipping.gif | Bin 0 -> 859 bytes .../smiley_pack/icons/sport/snooker.gif | Bin 0 -> 11255 bytes .../smiley_pack/icons/sport/surfing.gif | Bin 0 -> 1639 bytes .../addons/smiley_pack/icons/sport/tennis.gif | Bin 0 -> 1061 bytes .../smiley_pack/icons/things/cloud9.gif | Bin 0 -> 1488 bytes .../smiley_pack/icons/tired/countsheep.gif | Bin 0 -> 1520 bytes .../smiley_pack/icons/tired/hammock.gif | Bin 0 -> 8317 bytes .../addons/smiley_pack/icons/tired/pillow.gif | Bin 0 -> 467 bytes .../addons/smiley_pack/icons/tired/yawn.gif | Bin 0 -> 1745 bytes sources/addons/smiley_pack/smiley_pack.php | 504 ++ sources/addons/smileybutton/icon.gif | Bin 0 -> 293 bytes sources/addons/smileybutton/smileybutton.css | 0 sources/addons/smileybutton/smileybutton.php | 286 + sources/addons/startpage/lang/C/messages.po | 34 + sources/addons/startpage/lang/ca/strings.php | 6 + sources/addons/startpage/lang/cs/strings.php | 6 + sources/addons/startpage/lang/de/strings.php | 6 + sources/addons/startpage/lang/eo/strings.php | 6 + sources/addons/startpage/lang/es/strings.php | 6 + sources/addons/startpage/lang/fr/strings.php | 6 + sources/addons/startpage/lang/is/strings.php | 6 + sources/addons/startpage/lang/it/strings.php | 6 + .../addons/startpage/lang/nb-no/strings.php | 6 + sources/addons/startpage/lang/pl/strings.php | 6 + .../addons/startpage/lang/pt-br/strings.php | 6 + sources/addons/startpage/lang/ru/strings.php | 6 + sources/addons/startpage/lang/sv/strings.php | 3 + .../addons/startpage/lang/zh-cn/strings.php | 6 + sources/addons/startpage/startpage.css | 0 sources/addons/startpage/startpage.php | 119 + .../statistics_json/statistics_json.php | 129 + sources/addons/statusnet/README | 105 + sources/addons/statusnet/gnusocial.png | Bin 0 -> 4442 bytes sources/addons/statusnet/lang/C/messages.po | 177 + sources/addons/statusnet/lang/ca/strings.php | 34 + sources/addons/statusnet/lang/cs/strings.php | 33 + sources/addons/statusnet/lang/de/strings.php | 34 + sources/addons/statusnet/lang/eo/strings.php | 32 + sources/addons/statusnet/lang/es/strings.php | 32 + sources/addons/statusnet/lang/fr/strings.php | 32 + sources/addons/statusnet/lang/is/strings.php | 32 + sources/addons/statusnet/lang/it/strings.php | 34 + .../addons/statusnet/lang/nb-no/strings.php | 32 + sources/addons/statusnet/lang/pl/strings.php | 34 + .../addons/statusnet/lang/pt-br/strings.php | 32 + sources/addons/statusnet/lang/ru/strings.php | 32 + sources/addons/statusnet/lang/sv/strings.php | 14 + .../addons/statusnet/lang/zh-cn/strings.php | 34 + .../addons/statusnet/signinwithgnusocial.png | Bin 0 -> 9622 bytes sources/addons/statusnet/statusnet.css | 7 + sources/addons/statusnet/statusnet.php | 940 +++ sources/addons/statusnet/view/tpl/admin.tpl | 17 + sources/addons/superblock/lang/ca/strings.php | 13 + sources/addons/superblock/lang/de/strings.php | 13 + sources/addons/superblock/lang/es/strings.php | 13 + sources/addons/superblock/lang/fr/strings.php | 14 + sources/addons/superblock/lang/it/strings.php | 14 + sources/addons/superblock/lang/nl/strings.php | 14 + .../addons/superblock/lang/pt-br/strings.php | 14 + sources/addons/superblock/lang/ru/strings.php | 14 + sources/addons/superblock/superblock.css | 0 sources/addons/superblock/superblock.php | 222 + sources/addons/testdrive/README.md | 23 + sources/addons/testdrive/lang/C/messages.po | 44 + sources/addons/testdrive/lang/ca/strings.php | 5 + sources/addons/testdrive/lang/cs/messages.po | 41 + sources/addons/testdrive/lang/cs/strings.php | 11 + sources/addons/testdrive/lang/de/messages.po | 41 + sources/addons/testdrive/lang/de/strings.php | 11 + sources/addons/testdrive/lang/eo/strings.php | 5 + sources/addons/testdrive/lang/es/strings.php | 5 + sources/addons/testdrive/lang/fr/strings.php | 5 + sources/addons/testdrive/lang/is/strings.php | 5 + sources/addons/testdrive/lang/it/messages.po | 41 + sources/addons/testdrive/lang/it/strings.php | 11 + .../addons/testdrive/lang/nb-no/strings.php | 5 + sources/addons/testdrive/lang/pl/messages.po | 41 + sources/addons/testdrive/lang/pl/strings.php | 11 + .../addons/testdrive/lang/pt-br/strings.php | 5 + sources/addons/testdrive/lang/ro/messages.po | 40 + sources/addons/testdrive/lang/ro/strings.php | 11 + sources/addons/testdrive/lang/ru/strings.php | 5 + sources/addons/testdrive/lang/sv/strings.php | 3 + .../addons/testdrive/lang/zh-cn/strings.php | 5 + sources/addons/testdrive/testdrive.php | 109 + sources/addons/tictac/lang/C/messages.po | 72 + sources/addons/tictac/lang/ca/strings.php | 14 + sources/addons/tictac/lang/cs/strings.php | 14 + sources/addons/tictac/lang/de/strings.php | 14 + sources/addons/tictac/lang/eo/strings.php | 14 + sources/addons/tictac/lang/es/strings.php | 14 + sources/addons/tictac/lang/fr/strings.php | 14 + sources/addons/tictac/lang/is/strings.php | 14 + sources/addons/tictac/lang/it/strings.php | 14 + sources/addons/tictac/lang/nb-no/strings.php | 14 + sources/addons/tictac/lang/pl/strings.php | 14 + sources/addons/tictac/lang/pt-br/strings.php | 14 + sources/addons/tictac/lang/ru/strings.php | 14 + sources/addons/tictac/lang/sv/strings.php | 14 + sources/addons/tictac/lang/zh-cn/strings.php | 14 + sources/addons/tictac/tictac.apd | 3 + sources/addons/tictac/tictac.php | 665 ++ sources/addons/tictac/tictac.png | Bin 0 -> 8237 bytes sources/addons/torch/torch.apd | 3 + sources/addons/torch/torch.php | 9 + sources/addons/torch/torch.png | Bin 0 -> 5237 bytes sources/addons/tour/LICENSE | 69 + sources/addons/tour/README | 4 + sources/addons/tour/jquery-tourbus.min.css | 1 + sources/addons/tour/jquery-tourbus.min.js | 1 + sources/addons/tour/jquery.scrollTo.min.js | 7 + sources/addons/tour/tour.php | 179 + sources/addons/twitter/LICENSE | 24 + sources/addons/twitter/README.md | 116 + sources/addons/twitter/cacert.pem | 3895 +++++++++ sources/addons/twitter/codebird.php | 1026 +++ sources/addons/twitter/lang/C/messages.po | 120 + sources/addons/twitter/lang/ca/strings.php | 24 + sources/addons/twitter/lang/cs/strings.php | 21 + sources/addons/twitter/lang/de/strings.php | 24 + sources/addons/twitter/lang/eo/strings.php | 20 + sources/addons/twitter/lang/es/strings.php | 20 + sources/addons/twitter/lang/fr/strings.php | 20 + sources/addons/twitter/lang/is/strings.php | 20 + sources/addons/twitter/lang/it/strings.php | 24 + sources/addons/twitter/lang/nb-no/strings.php | 20 + sources/addons/twitter/lang/pl/strings.php | 24 + sources/addons/twitter/lang/pt-br/strings.php | 20 + sources/addons/twitter/lang/ru/strings.php | 20 + sources/addons/twitter/lang/sv/strings.php | 11 + sources/addons/twitter/lang/zh-cn/strings.php | 24 + sources/addons/twitter/lighter.png | Bin 0 -> 2490 bytes sources/addons/twitter/twitter.css | 7 + sources/addons/twitter/twitter.php | 915 +++ sources/addons/twitter/twitter.png | Bin 0 -> 5245 bytes sources/addons/twitter/view/tpl/admin.tpl | 3 + .../addons/upload_limits/upload_limits.php | 31 + sources/addons/visage/visage.apd | 5 + sources/addons/visage/visage.css | 0 sources/addons/visage/visage.php | 182 + sources/addons/visage/visage.png | Bin 0 -> 3175 bytes sources/addons/wholikesme/wholikesme.php | 37 + sources/addons/wppost/lang/C/messages.po | 62 + sources/addons/wppost/lang/ca/strings.php | 13 + sources/addons/wppost/lang/cs/strings.php | 13 + sources/addons/wppost/lang/de/strings.php | 13 + sources/addons/wppost/lang/eo/strings.php | 13 + sources/addons/wppost/lang/es/strings.php | 13 + sources/addons/wppost/lang/fr/strings.php | 13 + sources/addons/wppost/lang/is/strings.php | 13 + sources/addons/wppost/lang/it/strings.php | 13 + sources/addons/wppost/lang/nb-no/strings.php | 13 + sources/addons/wppost/lang/pl/strings.php | 13 + sources/addons/wppost/lang/pt-br/strings.php | 13 + sources/addons/wppost/lang/ru/strings.php | 13 + sources/addons/wppost/lang/sv/strings.php | 3 + sources/addons/wppost/lang/zh-cn/strings.php | 13 + sources/addons/wppost/wordpress-logo.png | Bin 0 -> 1304 bytes sources/addons/wppost/wppost.css | 19 + sources/addons/wppost/wppost.php | 432 + 1330 files changed, 143256 insertions(+) create mode 100644 sources/addons/.gitignore create mode 100644 sources/addons/README.md create mode 100755 sources/addons/adultphotoflag/adultphotoflag.php create mode 100644 sources/addons/bbmath/README create mode 100644 sources/addons/bbmath/bbmath.php create mode 100644 sources/addons/bbmath/gpl.txt create mode 100644 sources/addons/bbmath/phplatex.php create mode 100755 sources/addons/bookmarker/bookmarker.php create mode 100755 sources/addons/buglink/bug-x.gif create mode 100755 sources/addons/buglink/buglink.php create mode 100644 sources/addons/buglink/lang/C/messages.po create mode 100644 sources/addons/buglink/lang/ca/strings.php create mode 100644 sources/addons/buglink/lang/cs/strings.php create mode 100644 sources/addons/buglink/lang/de/strings.php create mode 100644 sources/addons/buglink/lang/eo/strings.php create mode 100644 sources/addons/buglink/lang/es/strings.php create mode 100644 sources/addons/buglink/lang/fr/strings.php create mode 100644 sources/addons/buglink/lang/is/strings.php create mode 100644 sources/addons/buglink/lang/it/strings.php create mode 100644 sources/addons/buglink/lang/nb-no/strings.php create mode 100644 sources/addons/buglink/lang/pl/strings.php create mode 100644 sources/addons/buglink/lang/pt-br/strings.php create mode 100644 sources/addons/buglink/lang/ru/strings.php create mode 100644 sources/addons/buglink/lang/sv/strings.php create mode 100644 sources/addons/buglink/lang/zh-cn/strings.php create mode 100644 sources/addons/calc/calc.apd create mode 100755 sources/addons/calc/calc.php create mode 100644 sources/addons/calc/calc.png create mode 100644 sources/addons/chords/README.md create mode 100755 sources/addons/chords/chord create mode 100755 sources/addons/chords/chord-generator.cpp create mode 100644 sources/addons/chords/chords.apd create mode 100755 sources/addons/chords/chords.php create mode 100644 sources/addons/chords/chords.png create mode 100644 sources/addons/custom_home/README.md create mode 100644 sources/addons/custom_home/custom_home.php create mode 100644 sources/addons/dfedfix/dfedfix.php create mode 100755 sources/addons/diaspora/diaspora.php create mode 100644 sources/addons/diaspora/p.php create mode 100644 sources/addons/diaspora/receive.php create mode 100644 sources/addons/diaspost/diasphp.php create mode 100644 sources/addons/diaspost/diaspora.png create mode 100755 sources/addons/diaspost/diaspost.css create mode 100755 sources/addons/diaspost/diaspost.php create mode 100644 sources/addons/dirstats/dirstats.php create mode 100644 sources/addons/dirstats/view/tpl/dirstats.tpl create mode 100644 sources/addons/donate/donate.apd create mode 100644 sources/addons/donate/donate.php create mode 100644 sources/addons/donate/donate.png create mode 100644 sources/addons/donate/tipping.jpg create mode 100644 sources/addons/donate/view/tpl/donate.tpl create mode 100644 sources/addons/dwpost/dwpost.css create mode 100644 sources/addons/dwpost/dwpost.php create mode 100644 sources/addons/dwpost/lang/C/messages.po create mode 100644 sources/addons/dwpost/lang/ca/strings.php create mode 100644 sources/addons/dwpost/lang/cs/strings.php create mode 100644 sources/addons/dwpost/lang/de/strings.php create mode 100644 sources/addons/dwpost/lang/eo/strings.php create mode 100644 sources/addons/dwpost/lang/es/strings.php create mode 100644 sources/addons/dwpost/lang/fr/strings.php create mode 100644 sources/addons/dwpost/lang/is/strings.php create mode 100644 sources/addons/dwpost/lang/it/strings.php create mode 100644 sources/addons/dwpost/lang/nb-no/strings.php create mode 100644 sources/addons/dwpost/lang/pl/strings.php create mode 100644 sources/addons/dwpost/lang/pt-br/strings.php create mode 100644 sources/addons/dwpost/lang/ru/strings.php create mode 100644 sources/addons/dwpost/lang/sv/strings.php create mode 100644 sources/addons/dwpost/lang/zh-cn/strings.php create mode 100644 sources/addons/embedly/embedly.php create mode 100755 sources/addons/extcron/extcron.php create mode 100644 sources/addons/extcron/lang/C/messages.po create mode 100644 sources/addons/flattrwidget/CHANGELOG create mode 100644 sources/addons/flattrwidget/README.md create mode 100644 sources/addons/flattrwidget/flattrwidget.php create mode 100644 sources/addons/flattrwidget/img/flattr-badge-large.png create mode 100644 sources/addons/flattrwidget/img/red-flattr-widget.png create mode 100644 sources/addons/flattrwidget/img/red-flattr-widget2.png create mode 100644 sources/addons/flattrwidget/style.css create mode 100644 sources/addons/fortunate/README create mode 100644 sources/addons/fortunate/cookie.php create mode 100644 sources/addons/fortunate/fortunate.apd create mode 100644 sources/addons/fortunate/fortunate.css create mode 100644 sources/addons/fortunate/fortunate.php create mode 100644 sources/addons/fortunate/fortunate.png create mode 100644 sources/addons/frphotos/frphotohelper.php create mode 100644 sources/addons/frphotos/frphotos.php create mode 100644 sources/addons/frphotos/view/tpl/frphotos.tpl create mode 100644 sources/addons/hexit/hexit.apd create mode 100644 sources/addons/hexit/hexit.php create mode 100644 sources/addons/hexit/hexit.png create mode 100644 sources/addons/ijpost/ijpost.css create mode 100644 sources/addons/ijpost/ijpost.php create mode 100644 sources/addons/ijpost/lang/C/messages.po create mode 100644 sources/addons/ijpost/lang/ca/strings.php create mode 100644 sources/addons/ijpost/lang/cs/strings.php create mode 100644 sources/addons/ijpost/lang/de/strings.php create mode 100644 sources/addons/ijpost/lang/eo/strings.php create mode 100644 sources/addons/ijpost/lang/es/strings.php create mode 100644 sources/addons/ijpost/lang/fr/strings.php create mode 100644 sources/addons/ijpost/lang/is/strings.php create mode 100644 sources/addons/ijpost/lang/it/strings.php create mode 100644 sources/addons/ijpost/lang/nb-no/strings.php create mode 100644 sources/addons/ijpost/lang/pl/strings.php create mode 100644 sources/addons/ijpost/lang/pt-br/strings.php create mode 100644 sources/addons/ijpost/lang/ru/strings.php create mode 100644 sources/addons/ijpost/lang/sv/strings.php create mode 100644 sources/addons/ijpost/lang/zh-cn/strings.php create mode 100644 sources/addons/irc/irc.apd create mode 100644 sources/addons/irc/irc.css create mode 100644 sources/addons/irc/irc.php create mode 100644 sources/addons/irc/irc.png create mode 100644 sources/addons/jappixmini/MIT.txt create mode 100644 sources/addons/jappixmini/README create mode 100644 sources/addons/jappixmini/jappix/AUTHORS create mode 100644 sources/addons/jappixmini/jappix/COPYING create mode 100644 sources/addons/jappixmini/jappix/INSTALL create mode 100644 sources/addons/jappixmini/jappix/README create mode 100644 sources/addons/jappixmini/jappix/THANKS create mode 100644 sources/addons/jappixmini/jappix/VERSION create mode 100644 sources/addons/jappixmini/jappix/css/adhoc.css create mode 100644 sources/addons/jappixmini/jappix/css/anonymous.css create mode 100644 sources/addons/jappixmini/jappix/css/archives.css create mode 100644 sources/addons/jappixmini/jappix/css/board.css create mode 100644 sources/addons/jappixmini/jappix/css/buddylist.css create mode 100644 sources/addons/jappixmini/jappix/css/channel.css create mode 100644 sources/addons/jappixmini/jappix/css/directory.css create mode 100644 sources/addons/jappixmini/jappix/css/discovery.css create mode 100644 sources/addons/jappixmini/jappix/css/favorites.css create mode 100644 sources/addons/jappixmini/jappix/css/home.css create mode 100644 sources/addons/jappixmini/jappix/css/ie.css create mode 100644 sources/addons/jappixmini/jappix/css/images.css create mode 100644 sources/addons/jappixmini/jappix/css/inbox.css create mode 100644 sources/addons/jappixmini/jappix/css/install.css create mode 100644 sources/addons/jappixmini/jappix/css/integratebox.css create mode 100644 sources/addons/jappixmini/jappix/css/jquery.datepicker.css create mode 100644 sources/addons/jappixmini/jappix/css/main.css create mode 100644 sources/addons/jappixmini/jappix/css/manager.css create mode 100644 sources/addons/jappixmini/jappix/css/me.css create mode 100644 sources/addons/jappixmini/jappix/css/mini-ie.css create mode 100644 sources/addons/jappixmini/jappix/css/mini.css create mode 100644 sources/addons/jappixmini/jappix/css/mobile.css create mode 100644 sources/addons/jappixmini/jappix/css/mucadmin.css create mode 100644 sources/addons/jappixmini/jappix/css/myinfos.css create mode 100644 sources/addons/jappixmini/jappix/css/options.css create mode 100644 sources/addons/jappixmini/jappix/css/others.css create mode 100644 sources/addons/jappixmini/jappix/css/pageengine.css create mode 100644 sources/addons/jappixmini/jappix/css/pageswitch.css create mode 100644 sources/addons/jappixmini/jappix/css/popup.css create mode 100644 sources/addons/jappixmini/jappix/css/privacy.css create mode 100644 sources/addons/jappixmini/jappix/css/rosterx.css create mode 100644 sources/addons/jappixmini/jappix/css/search.css create mode 100644 sources/addons/jappixmini/jappix/css/smileys.css create mode 100644 sources/addons/jappixmini/jappix/css/stats-svg.css create mode 100644 sources/addons/jappixmini/jappix/css/tools.css create mode 100644 sources/addons/jappixmini/jappix/css/userinfos.css create mode 100644 sources/addons/jappixmini/jappix/css/vcard.css create mode 100644 sources/addons/jappixmini/jappix/css/welcome.css create mode 100644 sources/addons/jappixmini/jappix/img/others/blank.gif create mode 100644 sources/addons/jappixmini/jappix/img/others/default-avatar.png create mode 100644 sources/addons/jappixmini/jappix/img/others/lock.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/animate.gif create mode 100644 sources/addons/jappixmini/jappix/img/sprites/animate.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/background.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/browsers.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/buttons.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/home.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/install.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/logs.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/manager.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/me.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/mini.gif create mode 100644 sources/addons/jappixmini/jappix/img/sprites/mini.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/mobile.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/smileys.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/talk.png create mode 100644 sources/addons/jappixmini/jappix/img/sprites/welcome.png create mode 100644 sources/addons/jappixmini/jappix/img/wait/wait-big.gif create mode 100644 sources/addons/jappixmini/jappix/img/wait/wait-medium.png create mode 100644 sources/addons/jappixmini/jappix/img/wait/wait-small.gif create mode 100644 sources/addons/jappixmini/jappix/js/adhoc.js create mode 100644 sources/addons/jappixmini/jappix/js/anonymous.js create mode 100644 sources/addons/jappixmini/jappix/js/archives.js create mode 100644 sources/addons/jappixmini/jappix/js/audio.js create mode 100644 sources/addons/jappixmini/jappix/js/autocompletion.js create mode 100644 sources/addons/jappixmini/jappix/js/avatar.js create mode 100644 sources/addons/jappixmini/jappix/js/base64.js create mode 100644 sources/addons/jappixmini/jappix/js/board.js create mode 100644 sources/addons/jappixmini/jappix/js/browser-detect.js create mode 100644 sources/addons/jappixmini/jappix/js/bubble.js create mode 100644 sources/addons/jappixmini/jappix/js/caps.js create mode 100644 sources/addons/jappixmini/jappix/js/chat.js create mode 100644 sources/addons/jappixmini/jappix/js/chatstate.js create mode 100644 sources/addons/jappixmini/jappix/js/common.js create mode 100644 sources/addons/jappixmini/jappix/js/connection.js create mode 100644 sources/addons/jappixmini/jappix/js/constants.js create mode 100644 sources/addons/jappixmini/jappix/js/dataform.js create mode 100644 sources/addons/jappixmini/jappix/js/datastore.js create mode 100644 sources/addons/jappixmini/jappix/js/date.js create mode 100644 sources/addons/jappixmini/jappix/js/directory.js create mode 100644 sources/addons/jappixmini/jappix/js/discovery.js create mode 100644 sources/addons/jappixmini/jappix/js/error.js create mode 100644 sources/addons/jappixmini/jappix/js/favorites.js create mode 100644 sources/addons/jappixmini/jappix/js/features.js create mode 100644 sources/addons/jappixmini/jappix/js/filter.js create mode 100644 sources/addons/jappixmini/jappix/js/groupchat.js create mode 100644 sources/addons/jappixmini/jappix/js/home.js create mode 100644 sources/addons/jappixmini/jappix/js/httpauth.js create mode 100644 sources/addons/jappixmini/jappix/js/inbox.js create mode 100644 sources/addons/jappixmini/jappix/js/integratebox.js create mode 100644 sources/addons/jappixmini/jappix/js/interface.js create mode 100644 sources/addons/jappixmini/jappix/js/iq.js create mode 100644 sources/addons/jappixmini/jappix/js/jquery.datepicker.js create mode 100644 sources/addons/jappixmini/jappix/js/jquery.form.js create mode 100644 sources/addons/jappixmini/jappix/js/jquery.js create mode 100644 sources/addons/jappixmini/jappix/js/jquery.placeholder.js create mode 100644 sources/addons/jappixmini/jappix/js/jquery.textrange.js create mode 100644 sources/addons/jappixmini/jappix/js/jquery.timers.js create mode 100644 sources/addons/jappixmini/jappix/js/jsjac.js create mode 100644 sources/addons/jappixmini/jappix/js/jxhr.js create mode 100644 sources/addons/jappixmini/jappix/js/links.js create mode 100644 sources/addons/jappixmini/jappix/js/me.js create mode 100644 sources/addons/jappixmini/jappix/js/message.js create mode 100644 sources/addons/jappixmini/jappix/js/microblog.js create mode 100644 sources/addons/jappixmini/jappix/js/mini.js create mode 100644 sources/addons/jappixmini/jappix/js/mobile.js create mode 100644 sources/addons/jappixmini/jappix/js/mucadmin.js create mode 100644 sources/addons/jappixmini/jappix/js/music.js create mode 100644 sources/addons/jappixmini/jappix/js/name.js create mode 100644 sources/addons/jappixmini/jappix/js/notification.js create mode 100644 sources/addons/jappixmini/jappix/js/oob.js create mode 100644 sources/addons/jappixmini/jappix/js/options.js create mode 100644 sources/addons/jappixmini/jappix/js/pep.js create mode 100644 sources/addons/jappixmini/jappix/js/popup.js create mode 100644 sources/addons/jappixmini/jappix/js/presence.js create mode 100644 sources/addons/jappixmini/jappix/js/privacy.js create mode 100644 sources/addons/jappixmini/jappix/js/receipts.js create mode 100644 sources/addons/jappixmini/jappix/js/roster.js create mode 100644 sources/addons/jappixmini/jappix/js/rosterx.js create mode 100644 sources/addons/jappixmini/jappix/js/search.js create mode 100644 sources/addons/jappixmini/jappix/js/smileys.js create mode 100644 sources/addons/jappixmini/jappix/js/storage.js create mode 100644 sources/addons/jappixmini/jappix/js/talk.js create mode 100644 sources/addons/jappixmini/jappix/js/tooltip.js create mode 100644 sources/addons/jappixmini/jappix/js/userinfos.js create mode 100644 sources/addons/jappixmini/jappix/js/utilities.js create mode 100644 sources/addons/jappixmini/jappix/js/vcard.js create mode 100644 sources/addons/jappixmini/jappix/js/welcome.js create mode 100644 sources/addons/jappixmini/jappix/js/xmpplinks.js create mode 100644 sources/addons/jappixmini/jappix/lang/ar/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/ar/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/bg/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/bg/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/cs/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/cs/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/de/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/de/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/en/LC_MESSAGES/main.pot create mode 100644 sources/addons/jappixmini/jappix/lang/eo/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/eo/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/es/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/es/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/et/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/et/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/fa/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/fa/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/fr/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/fr/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/hu/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/hu/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/id/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/id/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/it/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/it/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/ja/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/ja/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/nl/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/nl/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/oc/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/oc/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/pl/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/pl/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/ru/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/ru/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/sk/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/sk/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/sv/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/sv/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/uk/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/uk/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/lang/zh/LC_MESSAGES/main.mo create mode 100644 sources/addons/jappixmini/jappix/lang/zh/LC_MESSAGES/main.po create mode 100644 sources/addons/jappixmini/jappix/php/avatar-upload.php create mode 100644 sources/addons/jappixmini/jappix/php/bosh.php create mode 100644 sources/addons/jappixmini/jappix/php/desktop.php create mode 100644 sources/addons/jappixmini/jappix/php/download-chat.php create mode 100644 sources/addons/jappixmini/jappix/php/drawsvgchart.php create mode 100644 sources/addons/jappixmini/jappix/php/file-share.php create mode 100644 sources/addons/jappixmini/jappix/php/form-hosts.php create mode 100644 sources/addons/jappixmini/jappix/php/form-main.php create mode 100644 sources/addons/jappixmini/jappix/php/form-users.php create mode 100644 sources/addons/jappixmini/jappix/php/functions-get.php create mode 100644 sources/addons/jappixmini/jappix/php/functions-manager.php create mode 100644 sources/addons/jappixmini/jappix/php/functions.php create mode 100644 sources/addons/jappixmini/jappix/php/generate-chat.php create mode 100644 sources/addons/jappixmini/jappix/php/geolocation.php create mode 100644 sources/addons/jappixmini/jappix/php/get-store.php create mode 100644 sources/addons/jappixmini/jappix/php/get.php create mode 100644 sources/addons/jappixmini/jappix/php/gettext.php create mode 100644 sources/addons/jappixmini/jappix/php/install.php create mode 100644 sources/addons/jappixmini/jappix/php/jsmin.php create mode 100644 sources/addons/jappixmini/jappix/php/manager.php create mode 100644 sources/addons/jappixmini/jappix/php/mobile-detect.php create mode 100644 sources/addons/jappixmini/jappix/php/mobile.php create mode 100644 sources/addons/jappixmini/jappix/php/music-search.php create mode 100644 sources/addons/jappixmini/jappix/php/post-design.php create mode 100644 sources/addons/jappixmini/jappix/php/post-hosts.php create mode 100644 sources/addons/jappixmini/jappix/php/post-main.php create mode 100644 sources/addons/jappixmini/jappix/php/post-store.php create mode 100644 sources/addons/jappixmini/jappix/php/post-users.php create mode 100644 sources/addons/jappixmini/jappix/php/read-design.php create mode 100644 sources/addons/jappixmini/jappix/php/read-hosts.php create mode 100644 sources/addons/jappixmini/jappix/php/read-main.php create mode 100644 sources/addons/jappixmini/jappix/php/send.php create mode 100644 sources/addons/jappixmini/jappix/php/static.php create mode 100644 sources/addons/jappixmini/jappix/php/stats-svg.php create mode 100644 sources/addons/jappixmini/jappix/php/store-tree.php create mode 100644 sources/addons/jappixmini/jappix/php/upload.php create mode 100644 sources/addons/jappixmini/jappix/php/vars-design.php create mode 100644 sources/addons/jappixmini/jappix/php/vars-hosts.php create mode 100644 sources/addons/jappixmini/jappix/php/vars-main.php create mode 100644 sources/addons/jappixmini/jappix/php/vars-store.php create mode 100644 sources/addons/jappixmini/jappix/snd/new-chat.oga create mode 100644 sources/addons/jappixmini/jappix/snd/notification.oga create mode 100644 sources/addons/jappixmini/jappix/snd/receive-message.oga create mode 100644 sources/addons/jappixmini/jappix/xml/anonymous.xml create mode 100644 sources/addons/jappixmini/jappix/xml/desktop.xml create mode 100644 sources/addons/jappixmini/jappix/xml/install.xml create mode 100644 sources/addons/jappixmini/jappix/xml/manager.xml create mode 100644 sources/addons/jappixmini/jappix/xml/mini.xml create mode 100644 sources/addons/jappixmini/jappix/xml/mobile.xml create mode 100644 sources/addons/jappixmini/jappixmini.css create mode 100644 sources/addons/jappixmini/jappixmini.php create mode 100644 sources/addons/jappixmini/lang/C/messages.po create mode 100644 sources/addons/jappixmini/lang/ca/strings.php create mode 100644 sources/addons/jappixmini/lang/cs/strings.php create mode 100644 sources/addons/jappixmini/lang/de/strings.php create mode 100644 sources/addons/jappixmini/lang/eo/strings.php create mode 100644 sources/addons/jappixmini/lang/es/strings.php create mode 100644 sources/addons/jappixmini/lang/fr/strings.php create mode 100644 sources/addons/jappixmini/lang/is/strings.php create mode 100644 sources/addons/jappixmini/lang/it/strings.php create mode 100644 sources/addons/jappixmini/lang/nb-no/strings.php create mode 100644 sources/addons/jappixmini/lang/pl/strings.php create mode 100644 sources/addons/jappixmini/lang/pt-br/strings.php create mode 100644 sources/addons/jappixmini/lang/ru/strings.php create mode 100644 sources/addons/jappixmini/lang/sv/strings.php create mode 100644 sources/addons/jappixmini/lang/zh-cn/strings.php create mode 100644 sources/addons/jappixmini/lib.js create mode 100644 sources/addons/jappixmini/proxy.php create mode 100755 sources/addons/js_upload/file-uploader/client/demo.htm create mode 100755 sources/addons/js_upload/file-uploader/client/do-nothing.htm create mode 100755 sources/addons/js_upload/file-uploader/client/fileuploader.css create mode 100755 sources/addons/js_upload/file-uploader/client/fileuploader.js create mode 100755 sources/addons/js_upload/file-uploader/client/loading.gif create mode 100755 sources/addons/js_upload/file-uploader/gpl-2.0.txt create mode 100755 sources/addons/js_upload/file-uploader/license.txt create mode 100755 sources/addons/js_upload/file-uploader/readme.md create mode 100755 sources/addons/js_upload/file-uploader/server/OctetStreamReader.java create mode 100755 sources/addons/js_upload/file-uploader/server/coldfusion/coldfusion.cfc create mode 100755 sources/addons/js_upload/file-uploader/server/coldfusion/demo.cfm create mode 100755 sources/addons/js_upload/file-uploader/server/coldfusion/readme.txt create mode 100755 sources/addons/js_upload/file-uploader/server/perl.cgi create mode 100755 sources/addons/js_upload/file-uploader/server/php.php create mode 100755 sources/addons/js_upload/file-uploader/server/readme.txt create mode 100755 sources/addons/js_upload/file-uploader/server/uploads/.gitignore create mode 100755 sources/addons/js_upload/file-uploader/tests/action-acceptance.php create mode 100755 sources/addons/js_upload/file-uploader/tests/action-handler-queue-test.php create mode 100755 sources/addons/js_upload/file-uploader/tests/action-handler-test.php create mode 100755 sources/addons/js_upload/file-uploader/tests/action-slow-response.php create mode 100755 sources/addons/js_upload/file-uploader/tests/browser-bugs/safari-bug1.htm create mode 100755 sources/addons/js_upload/file-uploader/tests/browser-bugs/safari-bug2.htm create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/application-javascript.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/application-json.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/header-404.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/somepage.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/text-html-large.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/text-html.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/text-javascript.php create mode 100755 sources/addons/js_upload/file-uploader/tests/iframe-content-tests/text-plain.php create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-1.4.2.min.js create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/jquery-ui-1.8.4.custom.min.js create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_flat_10_000000_40x100.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-icons_222222_256x240.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-icons_228ef1_256x240.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-icons_ef8c08_256x240.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-icons_ffd27a_256x240.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/images/ui-icons_ffffff_256x240.png create mode 100755 sources/addons/js_upload/file-uploader/tests/jquery-ui/ui-lightness/jquery-ui-1.8.4.custom.css create mode 100755 sources/addons/js_upload/file-uploader/tests/qunit/package.json create mode 100755 sources/addons/js_upload/file-uploader/tests/qunit/qunit/qunit.css create mode 100755 sources/addons/js_upload/file-uploader/tests/qunit/qunit/qunit.js create mode 100755 sources/addons/js_upload/file-uploader/tests/qunit/test/index.html create mode 100755 sources/addons/js_upload/file-uploader/tests/qunit/test/same.js create mode 100755 sources/addons/js_upload/file-uploader/tests/qunit/test/test.js create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/1imagelonglonglonglonglonglongname.gif create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/2larger.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/3empty.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/4text.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/5text.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/6text.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/7small.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/sample-files/8text.txt create mode 100755 sources/addons/js_upload/file-uploader/tests/separate-file-list.htm create mode 100755 sources/addons/js_upload/file-uploader/tests/test-acceptance.htm create mode 100755 sources/addons/js_upload/file-uploader/tests/test-drop-zone.htm create mode 100755 sources/addons/js_upload/file-uploader/tests/test-handler-queue.htm create mode 100755 sources/addons/js_upload/file-uploader/tests/test-upload-handlers.htm create mode 100755 sources/addons/js_upload/js_upload.php create mode 100644 sources/addons/js_upload/lang/C/messages.po create mode 100644 sources/addons/js_upload/lang/ca/strings.php create mode 100644 sources/addons/js_upload/lang/cs/strings.php create mode 100644 sources/addons/js_upload/lang/de/strings.php create mode 100644 sources/addons/js_upload/lang/eo/strings.php create mode 100644 sources/addons/js_upload/lang/es/strings.php create mode 100644 sources/addons/js_upload/lang/fr/strings.php create mode 100644 sources/addons/js_upload/lang/is/strings.php create mode 100644 sources/addons/js_upload/lang/it/strings.php create mode 100644 sources/addons/js_upload/lang/nb-no/strings.php create mode 100644 sources/addons/js_upload/lang/pl/strings.php create mode 100644 sources/addons/js_upload/lang/pt-br/strings.php create mode 100644 sources/addons/js_upload/lang/ru/strings.php create mode 100644 sources/addons/js_upload/lang/sv/strings.php create mode 100644 sources/addons/js_upload/lang/zh-cn/strings.php create mode 100755 sources/addons/ldapauth/README create mode 100755 sources/addons/ldapauth/ldapauth.php create mode 100644 sources/addons/libertree/lang/C/messages.po create mode 100644 sources/addons/libertree/lang/ca/strings.php create mode 100644 sources/addons/libertree/lang/cs/strings.php create mode 100644 sources/addons/libertree/lang/de/strings.php create mode 100644 sources/addons/libertree/lang/eo/strings.php create mode 100644 sources/addons/libertree/lang/es/strings.php create mode 100644 sources/addons/libertree/lang/fr/strings.php create mode 100644 sources/addons/libertree/lang/is/strings.php create mode 100644 sources/addons/libertree/lang/it/strings.php create mode 100644 sources/addons/libertree/lang/nb-no/strings.php create mode 100644 sources/addons/libertree/lang/pl/strings.php create mode 100644 sources/addons/libertree/lang/pt-br/strings.php create mode 100644 sources/addons/libertree/lang/ru/strings.php create mode 100644 sources/addons/libertree/lang/sv/strings.php create mode 100644 sources/addons/libertree/lang/zh-cn/strings.php create mode 100755 sources/addons/libertree/libertree.css create mode 100755 sources/addons/libertree/libertree.php create mode 100644 sources/addons/libertree/libertree.png create mode 100644 sources/addons/likebanner/FreeSansBold.ttf create mode 100644 sources/addons/likebanner/like_banner.png create mode 100644 sources/addons/likebanner/likebanner.apd create mode 100644 sources/addons/likebanner/likebanner.php create mode 100644 sources/addons/likebanner/likebanner.png create mode 100644 sources/addons/ljpost/lang/C/messages.po create mode 100644 sources/addons/ljpost/lang/ca/strings.php create mode 100644 sources/addons/ljpost/lang/cs/strings.php create mode 100644 sources/addons/ljpost/lang/de/strings.php create mode 100644 sources/addons/ljpost/lang/eo/strings.php create mode 100644 sources/addons/ljpost/lang/es/strings.php create mode 100644 sources/addons/ljpost/lang/fr/strings.php create mode 100644 sources/addons/ljpost/lang/is/strings.php create mode 100644 sources/addons/ljpost/lang/it/strings.php create mode 100644 sources/addons/ljpost/lang/nb-no/strings.php create mode 100644 sources/addons/ljpost/lang/pl/strings.php create mode 100644 sources/addons/ljpost/lang/pt-br/strings.php create mode 100644 sources/addons/ljpost/lang/ru/strings.php create mode 100644 sources/addons/ljpost/lang/sv/strings.php create mode 100644 sources/addons/ljpost/lang/zh-cn/strings.php create mode 100755 sources/addons/ljpost/ljpost.css create mode 100755 sources/addons/ljpost/ljpost.php create mode 100644 sources/addons/logrot/logrot.php create mode 100644 sources/addons/logrot/view/tpl/admin.tpl create mode 100644 sources/addons/mahjongg/mahjongg.apd create mode 100755 sources/addons/mahjongg/mahjongg.php create mode 100644 sources/addons/mahjongg/mahjongg.png create mode 100755 sources/addons/mahjongg/mahjongg.swf create mode 100644 sources/addons/mailhost/mailhost.css create mode 100644 sources/addons/mailhost/mailhost.php create mode 100644 sources/addons/morechoice/morechoice.php create mode 100644 sources/addons/moremoods/moremoods.php create mode 100644 sources/addons/morepokes/lang/C/messages.po create mode 100644 sources/addons/morepokes/lang/ca/strings.php create mode 100644 sources/addons/morepokes/lang/cs/messages.po create mode 100644 sources/addons/morepokes/lang/cs/strings.php create mode 100644 sources/addons/morepokes/lang/de/messages.po create mode 100644 sources/addons/morepokes/lang/de/strings.php create mode 100644 sources/addons/morepokes/lang/eo/strings.php create mode 100644 sources/addons/morepokes/lang/es/strings.php create mode 100644 sources/addons/morepokes/lang/fr/strings.php create mode 100644 sources/addons/morepokes/lang/is/strings.php create mode 100755 sources/addons/morepokes/lang/it/messages.po create mode 100644 sources/addons/morepokes/lang/it/strings.php create mode 100644 sources/addons/morepokes/lang/nb-no/strings.php create mode 100644 sources/addons/morepokes/lang/pl/strings.php create mode 100644 sources/addons/morepokes/lang/pt-br/strings.php create mode 100644 sources/addons/morepokes/lang/ro/messages.po create mode 100644 sources/addons/morepokes/lang/ro/strings.php create mode 100644 sources/addons/morepokes/lang/ru/strings.php create mode 100644 sources/addons/morepokes/lang/sv/strings.php create mode 100644 sources/addons/morepokes/lang/zh-cn/strings.php create mode 100644 sources/addons/morepokes/morepokes.php create mode 100755 sources/addons/nofed/nofed.css create mode 100755 sources/addons/nofed/nofed.php create mode 100644 sources/addons/nofed/rhash-32.png create mode 100755 sources/addons/nsabait/nsabait.css create mode 100755 sources/addons/nsabait/nsabait.php create mode 100644 sources/addons/nsabait/wordlist.txt create mode 100644 sources/addons/nsabait/words.txt create mode 100755 sources/addons/nsfw/README create mode 100644 sources/addons/nsfw/lang/C/messages.po create mode 100644 sources/addons/nsfw/lang/ca/strings.php create mode 100644 sources/addons/nsfw/lang/cs/strings.php create mode 100644 sources/addons/nsfw/lang/de/strings.php create mode 100644 sources/addons/nsfw/lang/eo/strings.php create mode 100644 sources/addons/nsfw/lang/es/strings.php create mode 100644 sources/addons/nsfw/lang/fr/strings.php create mode 100644 sources/addons/nsfw/lang/is/strings.php create mode 100644 sources/addons/nsfw/lang/it/strings.php create mode 100644 sources/addons/nsfw/lang/nb-no/strings.php create mode 100644 sources/addons/nsfw/lang/pl/strings.php create mode 100644 sources/addons/nsfw/lang/pt-br/strings.php create mode 100644 sources/addons/nsfw/lang/ru/strings.php create mode 100644 sources/addons/nsfw/lang/sv/strings.php create mode 100644 sources/addons/nsfw/lang/zh-cn/strings.php create mode 100755 sources/addons/nsfw/nsfw.css create mode 100755 sources/addons/nsfw/nsfw.php create mode 100644 sources/addons/openclipatar/openclipart-banner.png create mode 100644 sources/addons/openclipatar/openclipatar.css create mode 100644 sources/addons/openclipatar/openclipatar.php create mode 100644 sources/addons/openclipatar/view/tpl/admin.tpl create mode 100644 sources/addons/openclipatar/view/tpl/avatar-ajax.tpl create mode 100644 sources/addons/openclipatar/view/tpl/avatar-entry.tpl create mode 100644 sources/addons/openclipatar/view/tpl/avatars.tpl create mode 100644 sources/addons/openstreetmap/README.md create mode 100644 sources/addons/openstreetmap/lang/C/messages.po create mode 100644 sources/addons/openstreetmap/lang/ca/strings.php create mode 100644 sources/addons/openstreetmap/lang/cs/strings.php create mode 100644 sources/addons/openstreetmap/lang/de/strings.php create mode 100644 sources/addons/openstreetmap/lang/eo/strings.php create mode 100644 sources/addons/openstreetmap/lang/es/strings.php create mode 100644 sources/addons/openstreetmap/lang/fr/strings.php create mode 100644 sources/addons/openstreetmap/lang/is/strings.php create mode 100644 sources/addons/openstreetmap/lang/it/strings.php create mode 100644 sources/addons/openstreetmap/lang/nb-no/strings.php create mode 100644 sources/addons/openstreetmap/lang/pl/strings.php create mode 100644 sources/addons/openstreetmap/lang/pt-br/strings.php create mode 100644 sources/addons/openstreetmap/lang/ru/strings.php create mode 100644 sources/addons/openstreetmap/lang/sv/strings.php create mode 100644 sources/addons/openstreetmap/lang/zh-cn/strings.php create mode 100644 sources/addons/openstreetmap/openstreetmap.js create mode 100755 sources/addons/openstreetmap/openstreetmap.php create mode 100644 sources/addons/openstreetmap/view/tpl/admin.tpl create mode 100644 sources/addons/piwik/LICENSE create mode 100755 sources/addons/piwik/README.md create mode 100644 sources/addons/piwik/lang/C/messages.po create mode 100644 sources/addons/piwik/lang/ca/strings.php create mode 100644 sources/addons/piwik/lang/cs/strings.php create mode 100644 sources/addons/piwik/lang/de/strings.php create mode 100644 sources/addons/piwik/lang/eo/strings.php create mode 100644 sources/addons/piwik/lang/es/strings.php create mode 100644 sources/addons/piwik/lang/fr/strings.php create mode 100644 sources/addons/piwik/lang/is/strings.php create mode 100644 sources/addons/piwik/lang/it/strings.php create mode 100644 sources/addons/piwik/lang/nb-no/strings.php create mode 100644 sources/addons/piwik/lang/pl/strings.php create mode 100644 sources/addons/piwik/lang/pt-br/strings.php create mode 100644 sources/addons/piwik/lang/ru/strings.php create mode 100644 sources/addons/piwik/lang/sv/strings.php create mode 100644 sources/addons/piwik/lang/zh-cn/strings.php create mode 100755 sources/addons/piwik/piwik.css create mode 100644 sources/addons/piwik/piwik.php create mode 100644 sources/addons/piwik/view/tpl/admin.tpl create mode 100755 sources/addons/planets/planets.css create mode 100755 sources/addons/planets/planets.php create mode 100755 sources/addons/pumpio/pumpio.css create mode 100755 sources/addons/pumpio/pumpio.php create mode 100644 sources/addons/pumpio/pumpio.png create mode 100644 sources/addons/qrator/phpqrcode/CHANGELOG create mode 100644 sources/addons/qrator/phpqrcode/INSTALL create mode 100644 sources/addons/qrator/phpqrcode/LICENSE create mode 100644 sources/addons/qrator/phpqrcode/README create mode 100644 sources/addons/qrator/phpqrcode/VERSION create mode 100644 sources/addons/qrator/phpqrcode/bindings/tcpdf/qrcode.php create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_1.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_10.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_10.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_11.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_11.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_12.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_12.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_13.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_13.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_14.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_14.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_15.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_15.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_16.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_16.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_17.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_17.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_18.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_18.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_19.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_19.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_2.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_20.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_20.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_21.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_21.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_22.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_22.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_23.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_23.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_24.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_24.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_25.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_25.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_26.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_26.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_27.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_27.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_28.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_28.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_29.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_29.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_3.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_30.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_30.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_31.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_31.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_32.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_32.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_33.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_33.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_34.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_34.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_35.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_35.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_36.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_36.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_37.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_37.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_38.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_38.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_39.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_39.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_4.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_40.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_40.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_5.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_6.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_7.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_8.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_8.png create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_9.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/frame_9.png create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_101_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_105_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_109_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_113_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_117_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_121_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_125_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_129_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_133_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_137_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_141_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_145_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_149_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_153_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_157_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_161_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_165_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_169_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_173_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_177_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_21_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_25_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_29_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_33_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_37_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_41_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_45_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_49_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_53_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_57_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_61_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_65_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_69_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_73_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_77_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_81_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_85_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_89_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_93_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_0/mask_97_0.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_101_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_105_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_109_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_113_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_117_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_121_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_125_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_129_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_133_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_137_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_141_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_145_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_149_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_153_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_157_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_161_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_165_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_169_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_173_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_177_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_21_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_25_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_29_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_33_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_37_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_41_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_45_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_49_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_53_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_57_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_61_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_65_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_69_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_73_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_77_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_81_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_85_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_89_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_93_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_1/mask_97_1.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_101_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_105_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_109_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_113_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_117_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_121_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_125_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_129_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_133_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_137_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_141_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_145_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_149_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_153_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_157_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_161_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_165_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_169_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_173_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_177_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_21_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_25_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_29_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_33_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_37_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_41_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_45_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_49_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_53_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_57_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_61_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_65_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_69_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_73_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_77_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_81_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_85_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_89_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_93_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_2/mask_97_2.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_101_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_105_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_109_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_113_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_117_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_121_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_125_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_129_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_133_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_137_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_141_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_145_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_149_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_153_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_157_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_161_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_165_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_169_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_173_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_177_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_21_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_25_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_29_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_33_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_37_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_41_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_45_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_49_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_53_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_57_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_61_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_65_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_69_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_73_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_77_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_81_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_85_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_89_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_93_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_3/mask_97_3.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_101_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_105_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_109_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_113_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_117_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_121_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_125_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_129_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_133_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_137_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_141_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_145_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_149_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_153_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_157_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_161_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_165_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_169_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_173_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_177_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_21_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_25_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_29_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_33_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_37_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_41_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_45_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_49_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_53_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_57_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_61_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_65_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_69_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_73_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_77_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_81_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_85_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_89_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_93_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_4/mask_97_4.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_101_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_105_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_109_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_113_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_117_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_121_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_125_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_129_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_133_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_137_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_141_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_145_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_149_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_153_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_157_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_161_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_165_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_169_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_173_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_177_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_21_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_25_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_29_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_33_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_37_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_41_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_45_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_49_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_53_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_57_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_61_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_65_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_69_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_73_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_77_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_81_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_85_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_89_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_93_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_5/mask_97_5.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_101_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_105_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_109_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_113_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_117_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_121_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_125_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_129_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_133_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_137_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_141_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_145_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_149_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_153_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_157_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_161_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_165_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_169_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_173_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_177_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_21_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_25_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_29_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_33_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_37_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_41_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_45_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_49_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_53_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_57_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_61_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_65_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_69_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_73_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_77_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_81_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_85_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_89_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_93_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_6/mask_97_6.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_101_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_105_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_109_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_113_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_117_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_121_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_125_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_129_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_133_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_137_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_141_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_145_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_149_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_153_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_157_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_161_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_165_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_169_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_173_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_177_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_21_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_25_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_29_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_33_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_37_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_41_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_45_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_49_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_53_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_57_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_61_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_65_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_69_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_73_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_77_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_81_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_85_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_89_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_93_7.dat create mode 100644 sources/addons/qrator/phpqrcode/cache/mask_7/mask_97_7.dat create mode 100644 sources/addons/qrator/phpqrcode/index.php create mode 100644 sources/addons/qrator/phpqrcode/phpqrcode.php create mode 100644 sources/addons/qrator/phpqrcode/qrbitstream.php create mode 100644 sources/addons/qrator/phpqrcode/qrconfig.php create mode 100644 sources/addons/qrator/phpqrcode/qrconst.php create mode 100644 sources/addons/qrator/phpqrcode/qrencode.php create mode 100644 sources/addons/qrator/phpqrcode/qrimage.php create mode 100644 sources/addons/qrator/phpqrcode/qrinput.php create mode 100644 sources/addons/qrator/phpqrcode/qrlib.php create mode 100644 sources/addons/qrator/phpqrcode/qrmask.php create mode 100644 sources/addons/qrator/phpqrcode/qrrscode.php create mode 100644 sources/addons/qrator/phpqrcode/qrspec.php create mode 100644 sources/addons/qrator/phpqrcode/qrsplit.php create mode 100644 sources/addons/qrator/phpqrcode/qrtools.php create mode 100644 sources/addons/qrator/phpqrcode/tools/merge.bat create mode 100644 sources/addons/qrator/phpqrcode/tools/merge.php create mode 100644 sources/addons/qrator/phpqrcode/tools/merge.sh create mode 100644 sources/addons/qrator/phpqrcode/tools/merged_config.php create mode 100644 sources/addons/qrator/phpqrcode/tools/merged_header.php create mode 100644 sources/addons/qrator/qrator.apd create mode 100644 sources/addons/qrator/qrator.php create mode 100644 sources/addons/qrator/qrator.png create mode 100755 sources/addons/rainbowtag/rainbowtag.css create mode 100644 sources/addons/rainbowtag/rainbowtag.php create mode 100644 sources/addons/randpost/randpost.php create mode 100644 sources/addons/redfiles/redfilehelper.php create mode 100644 sources/addons/redfiles/redfiles.php create mode 100644 sources/addons/redfiles/view/tpl/redfiles.tpl create mode 100644 sources/addons/redphotos/redphotohelper.php create mode 100644 sources/addons/redphotos/redphotos.php create mode 100644 sources/addons/redphotos/view/tpl/redphotos.tpl create mode 100755 sources/addons/redred/redred.css create mode 100755 sources/addons/redred/redred.php create mode 100644 sources/addons/redred/rhash-32.png create mode 100644 sources/addons/rtof/friendica.png create mode 100755 sources/addons/rtof/rtof.css create mode 100755 sources/addons/rtof/rtof.php create mode 100755 sources/addons/sendzid/sendzid.php create mode 100644 sources/addons/skeleton/README.md create mode 100644 sources/addons/skeleton/skeleton.php create mode 100644 sources/addons/smiley_pack/icons/animals/bee.gif create mode 100644 sources/addons/smiley_pack/icons/animals/bigspider.gif create mode 100644 sources/addons/smiley_pack/icons/animals/bunny.gif create mode 100644 sources/addons/smiley_pack/icons/animals/bunnyflowers.gif create mode 100644 sources/addons/smiley_pack/icons/animals/cat.gif create mode 100644 sources/addons/smiley_pack/icons/animals/chick.gif create mode 100644 sources/addons/smiley_pack/icons/animals/cow.gif create mode 100644 sources/addons/smiley_pack/icons/animals/crab.gif create mode 100644 sources/addons/smiley_pack/icons/animals/dog.gif create mode 100644 sources/addons/smiley_pack/icons/animals/dolphin.gif create mode 100644 sources/addons/smiley_pack/icons/animals/dragonfly.gif create mode 100644 sources/addons/smiley_pack/icons/animals/elephant.gif create mode 100644 sources/addons/smiley_pack/icons/animals/fish.gif create mode 100644 sources/addons/smiley_pack/icons/animals/frog.gif create mode 100644 sources/addons/smiley_pack/icons/animals/giraffe.gif create mode 100644 sources/addons/smiley_pack/icons/animals/hamster.gif create mode 100644 sources/addons/smiley_pack/icons/animals/horse.gif create mode 100644 sources/addons/smiley_pack/icons/animals/ladybird.gif create mode 100644 sources/addons/smiley_pack/icons/animals/monkey.gif create mode 100644 sources/addons/smiley_pack/icons/animals/parrot.gif create mode 100644 sources/addons/smiley_pack/icons/animals/pig.gif create mode 100644 sources/addons/smiley_pack/icons/animals/sheep.gif create mode 100644 sources/addons/smiley_pack/icons/animals/snail.gif create mode 100644 sources/addons/smiley_pack/icons/animals/tux.gif create mode 100644 sources/addons/smiley_pack/icons/babies/baby.gif create mode 100644 sources/addons/smiley_pack/icons/babies/babycot.gif create mode 100644 sources/addons/smiley_pack/icons/babies/pregnant.gif create mode 100644 sources/addons/smiley_pack/icons/babies/stork.gif create mode 100644 sources/addons/smiley_pack/icons/confused/confused.gif create mode 100644 sources/addons/smiley_pack/icons/confused/dazed.gif create mode 100644 sources/addons/smiley_pack/icons/confused/shrug.gif create mode 100644 sources/addons/smiley_pack/icons/confused/stupid.gif create mode 100644 sources/addons/smiley_pack/icons/cool/affro.gif create mode 100644 sources/addons/smiley_pack/icons/cool/cool.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/angel.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/blondedevil.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/catdevil.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/cherub.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/daseesaw.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/devil.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/graveside.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/saint.gif create mode 100644 sources/addons/smiley_pack/icons/devilangel/turnevil.gif create mode 100644 sources/addons/smiley_pack/icons/disgust/fartblush.gif create mode 100644 sources/addons/smiley_pack/icons/disgust/fartinbed.gif create mode 100644 sources/addons/smiley_pack/icons/disgust/toilet.gif create mode 100644 sources/addons/smiley_pack/icons/disgust/vomit.gif create mode 100644 sources/addons/smiley_pack/icons/drink/tea.gif create mode 100644 sources/addons/smiley_pack/icons/drool/drool.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/alienmonster.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/barbarian.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/dinosaur.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/doctor.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/dragon.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/dragonwhelp.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/ghost.gif create mode 100644 sources/addons/smiley_pack/icons/fantasy/mummy.gif create mode 100644 sources/addons/smiley_pack/icons/fight/2guns.gif create mode 100644 sources/addons/smiley_pack/icons/fight/acid.gif create mode 100644 sources/addons/smiley_pack/icons/fight/alienfight.gif create mode 100644 sources/addons/smiley_pack/icons/fight/alpha.png create mode 100644 sources/addons/smiley_pack/icons/fight/army.gif create mode 100644 sources/addons/smiley_pack/icons/fight/arrowhead.gif create mode 100644 sources/addons/smiley_pack/icons/fight/bfg.gif create mode 100644 sources/addons/smiley_pack/icons/fight/bowman.gif create mode 100644 sources/addons/smiley_pack/icons/fight/chainsaw.gif create mode 100644 sources/addons/smiley_pack/icons/fight/crossbow.gif create mode 100644 sources/addons/smiley_pack/icons/fight/crusader.gif create mode 100644 sources/addons/smiley_pack/icons/fight/dead.gif create mode 100644 sources/addons/smiley_pack/icons/fight/gangs.gif create mode 100644 sources/addons/smiley_pack/icons/fight/hammersplat.gif create mode 100644 sources/addons/smiley_pack/icons/fight/lasergun.gif create mode 100644 sources/addons/smiley_pack/icons/fight/machinegun.gif create mode 100644 sources/addons/smiley_pack/icons/fight/marine.gif create mode 100644 sources/addons/smiley_pack/icons/fight/sabre.gif create mode 100644 sources/addons/smiley_pack/icons/fight/samurai.gif create mode 100644 sources/addons/smiley_pack/icons/fight/tank.gif create mode 100644 sources/addons/smiley_pack/icons/fight/throw-rocks.gif create mode 100644 sources/addons/smiley_pack/icons/fight/viking.gif create mode 100644 sources/addons/smiley_pack/icons/food/apple.gif create mode 100644 sources/addons/smiley_pack/icons/food/banana.gif create mode 100644 sources/addons/smiley_pack/icons/food/birthdaycake.gif create mode 100644 sources/addons/smiley_pack/icons/food/broccoli.gif create mode 100644 sources/addons/smiley_pack/icons/food/cake.gif create mode 100644 sources/addons/smiley_pack/icons/food/carrot.gif create mode 100644 sources/addons/smiley_pack/icons/food/cooking.gif create mode 100644 sources/addons/smiley_pack/icons/food/fryegg.gif create mode 100644 sources/addons/smiley_pack/icons/food/popcorn.gif create mode 100644 sources/addons/smiley_pack/icons/food/tomato.gif create mode 100644 sources/addons/smiley_pack/icons/happy/cloud9.gif create mode 100644 sources/addons/smiley_pack/icons/happy/tearsofjoy.gif create mode 100644 sources/addons/smiley_pack/icons/laugh/hahaha.gif create mode 100644 sources/addons/smiley_pack/icons/laugh/loltv.gif create mode 100644 sources/addons/smiley_pack/icons/laugh/rofl.gif create mode 100644 sources/addons/smiley_pack/icons/laugh/snicker.jpeg create mode 100644 sources/addons/smiley_pack/icons/love/iloveyou.gif create mode 100644 sources/addons/smiley_pack/icons/love/inlove.gif create mode 100644 sources/addons/smiley_pack/icons/love/love.gif create mode 100644 sources/addons/smiley_pack/icons/love/lovebear.gif create mode 100644 sources/addons/smiley_pack/icons/love/lovebed.gif create mode 100644 sources/addons/smiley_pack/icons/love/loveheart.gif create mode 100644 sources/addons/smiley_pack/icons/music/dj.gif create mode 100644 sources/addons/smiley_pack/icons/music/drums.gif create mode 100644 sources/addons/smiley_pack/icons/music/elvis.gif create mode 100644 sources/addons/smiley_pack/icons/music/guitar.gif create mode 100644 sources/addons/smiley_pack/icons/music/trumpet.gif create mode 100644 sources/addons/smiley_pack/icons/music/violin.gif create mode 100644 sources/addons/smiley_pack/icons/oldcore/beard.png create mode 100644 sources/addons/smiley_pack/icons/oldcore/headbang.gif create mode 100755 sources/addons/smiley_pack/icons/oldcore/laughing.gif create mode 100644 sources/addons/smiley_pack/icons/oldcore/shaka.gif create mode 100755 sources/addons/smiley_pack/icons/oldcore/surprised.gif create mode 100644 sources/addons/smiley_pack/icons/oldcore/whitebeard.png create mode 100644 sources/addons/smiley_pack/icons/respect/bow.gif create mode 100644 sources/addons/smiley_pack/icons/respect/bravo.gif create mode 100644 sources/addons/smiley_pack/icons/respect/hailking.gif create mode 100644 sources/addons/smiley_pack/icons/respect/number1.gif create mode 100644 sources/addons/smiley_pack/icons/respect/towel.gif create mode 100644 sources/addons/smiley_pack/icons/sad/crying.png create mode 100644 sources/addons/smiley_pack/icons/sad/prisoner.gif create mode 100644 sources/addons/smiley_pack/icons/sad/sigh.gif create mode 100644 sources/addons/smiley_pack/icons/smoking/smoking.gif create mode 100644 sources/addons/smiley_pack/icons/sport/archery.gif create mode 100644 sources/addons/smiley_pack/icons/sport/basketball.gif create mode 100644 sources/addons/smiley_pack/icons/sport/bowling.gif create mode 100644 sources/addons/smiley_pack/icons/sport/cycling.gif create mode 100644 sources/addons/smiley_pack/icons/sport/darts.gif create mode 100644 sources/addons/smiley_pack/icons/sport/fencing.gif create mode 100644 sources/addons/smiley_pack/icons/sport/football.gif create mode 100644 sources/addons/smiley_pack/icons/sport/golf.gif create mode 100644 sources/addons/smiley_pack/icons/sport/horseriding.gif create mode 100644 sources/addons/smiley_pack/icons/sport/juggling.gif create mode 100644 sources/addons/smiley_pack/icons/sport/skipping.gif create mode 100644 sources/addons/smiley_pack/icons/sport/snooker.gif create mode 100644 sources/addons/smiley_pack/icons/sport/surfing.gif create mode 100644 sources/addons/smiley_pack/icons/sport/tennis.gif create mode 100644 sources/addons/smiley_pack/icons/things/cloud9.gif create mode 100644 sources/addons/smiley_pack/icons/tired/countsheep.gif create mode 100644 sources/addons/smiley_pack/icons/tired/hammock.gif create mode 100644 sources/addons/smiley_pack/icons/tired/pillow.gif create mode 100644 sources/addons/smiley_pack/icons/tired/yawn.gif create mode 100644 sources/addons/smiley_pack/smiley_pack.php create mode 100644 sources/addons/smileybutton/icon.gif create mode 100755 sources/addons/smileybutton/smileybutton.css create mode 100755 sources/addons/smileybutton/smileybutton.php create mode 100644 sources/addons/startpage/lang/C/messages.po create mode 100644 sources/addons/startpage/lang/ca/strings.php create mode 100644 sources/addons/startpage/lang/cs/strings.php create mode 100644 sources/addons/startpage/lang/de/strings.php create mode 100644 sources/addons/startpage/lang/eo/strings.php create mode 100644 sources/addons/startpage/lang/es/strings.php create mode 100644 sources/addons/startpage/lang/fr/strings.php create mode 100644 sources/addons/startpage/lang/is/strings.php create mode 100644 sources/addons/startpage/lang/it/strings.php create mode 100644 sources/addons/startpage/lang/nb-no/strings.php create mode 100644 sources/addons/startpage/lang/pl/strings.php create mode 100644 sources/addons/startpage/lang/pt-br/strings.php create mode 100644 sources/addons/startpage/lang/ru/strings.php create mode 100644 sources/addons/startpage/lang/sv/strings.php create mode 100644 sources/addons/startpage/lang/zh-cn/strings.php create mode 100644 sources/addons/startpage/startpage.css create mode 100644 sources/addons/startpage/startpage.php create mode 100644 sources/addons/statistics_json/statistics_json.php create mode 100755 sources/addons/statusnet/README create mode 100644 sources/addons/statusnet/gnusocial.png create mode 100644 sources/addons/statusnet/lang/C/messages.po create mode 100644 sources/addons/statusnet/lang/ca/strings.php create mode 100644 sources/addons/statusnet/lang/cs/strings.php create mode 100644 sources/addons/statusnet/lang/de/strings.php create mode 100644 sources/addons/statusnet/lang/eo/strings.php create mode 100644 sources/addons/statusnet/lang/es/strings.php create mode 100644 sources/addons/statusnet/lang/fr/strings.php create mode 100644 sources/addons/statusnet/lang/is/strings.php create mode 100644 sources/addons/statusnet/lang/it/strings.php create mode 100644 sources/addons/statusnet/lang/nb-no/strings.php create mode 100644 sources/addons/statusnet/lang/pl/strings.php create mode 100644 sources/addons/statusnet/lang/pt-br/strings.php create mode 100644 sources/addons/statusnet/lang/ru/strings.php create mode 100644 sources/addons/statusnet/lang/sv/strings.php create mode 100644 sources/addons/statusnet/lang/zh-cn/strings.php create mode 100644 sources/addons/statusnet/signinwithgnusocial.png create mode 100755 sources/addons/statusnet/statusnet.css create mode 100755 sources/addons/statusnet/statusnet.php create mode 100644 sources/addons/statusnet/view/tpl/admin.tpl create mode 100644 sources/addons/superblock/lang/ca/strings.php create mode 100644 sources/addons/superblock/lang/de/strings.php create mode 100644 sources/addons/superblock/lang/es/strings.php create mode 100644 sources/addons/superblock/lang/fr/strings.php create mode 100644 sources/addons/superblock/lang/it/strings.php create mode 100644 sources/addons/superblock/lang/nl/strings.php create mode 100644 sources/addons/superblock/lang/pt-br/strings.php create mode 100644 sources/addons/superblock/lang/ru/strings.php create mode 100644 sources/addons/superblock/superblock.css create mode 100644 sources/addons/superblock/superblock.php create mode 100644 sources/addons/testdrive/README.md create mode 100644 sources/addons/testdrive/lang/C/messages.po create mode 100644 sources/addons/testdrive/lang/ca/strings.php create mode 100644 sources/addons/testdrive/lang/cs/messages.po create mode 100644 sources/addons/testdrive/lang/cs/strings.php create mode 100644 sources/addons/testdrive/lang/de/messages.po create mode 100644 sources/addons/testdrive/lang/de/strings.php create mode 100644 sources/addons/testdrive/lang/eo/strings.php create mode 100644 sources/addons/testdrive/lang/es/strings.php create mode 100644 sources/addons/testdrive/lang/fr/strings.php create mode 100644 sources/addons/testdrive/lang/is/strings.php create mode 100644 sources/addons/testdrive/lang/it/messages.po create mode 100644 sources/addons/testdrive/lang/it/strings.php create mode 100644 sources/addons/testdrive/lang/nb-no/strings.php create mode 100644 sources/addons/testdrive/lang/pl/messages.po create mode 100644 sources/addons/testdrive/lang/pl/strings.php create mode 100644 sources/addons/testdrive/lang/pt-br/strings.php create mode 100644 sources/addons/testdrive/lang/ro/messages.po create mode 100644 sources/addons/testdrive/lang/ro/strings.php create mode 100644 sources/addons/testdrive/lang/ru/strings.php create mode 100644 sources/addons/testdrive/lang/sv/strings.php create mode 100644 sources/addons/testdrive/lang/zh-cn/strings.php create mode 100644 sources/addons/testdrive/testdrive.php create mode 100644 sources/addons/tictac/lang/C/messages.po create mode 100644 sources/addons/tictac/lang/ca/strings.php create mode 100644 sources/addons/tictac/lang/cs/strings.php create mode 100644 sources/addons/tictac/lang/de/strings.php create mode 100644 sources/addons/tictac/lang/eo/strings.php create mode 100644 sources/addons/tictac/lang/es/strings.php create mode 100644 sources/addons/tictac/lang/fr/strings.php create mode 100644 sources/addons/tictac/lang/is/strings.php create mode 100644 sources/addons/tictac/lang/it/strings.php create mode 100644 sources/addons/tictac/lang/nb-no/strings.php create mode 100644 sources/addons/tictac/lang/pl/strings.php create mode 100644 sources/addons/tictac/lang/pt-br/strings.php create mode 100644 sources/addons/tictac/lang/ru/strings.php create mode 100644 sources/addons/tictac/lang/sv/strings.php create mode 100644 sources/addons/tictac/lang/zh-cn/strings.php create mode 100644 sources/addons/tictac/tictac.apd create mode 100755 sources/addons/tictac/tictac.php create mode 100644 sources/addons/tictac/tictac.png create mode 100644 sources/addons/torch/torch.apd create mode 100644 sources/addons/torch/torch.php create mode 100644 sources/addons/torch/torch.png create mode 100644 sources/addons/tour/LICENSE create mode 100644 sources/addons/tour/README create mode 100644 sources/addons/tour/jquery-tourbus.min.css create mode 100644 sources/addons/tour/jquery-tourbus.min.js create mode 100644 sources/addons/tour/jquery.scrollTo.min.js create mode 100644 sources/addons/tour/tour.php create mode 100644 sources/addons/twitter/LICENSE create mode 100644 sources/addons/twitter/README.md create mode 100644 sources/addons/twitter/cacert.pem create mode 100644 sources/addons/twitter/codebird.php create mode 100644 sources/addons/twitter/lang/C/messages.po create mode 100644 sources/addons/twitter/lang/ca/strings.php create mode 100644 sources/addons/twitter/lang/cs/strings.php create mode 100644 sources/addons/twitter/lang/de/strings.php create mode 100644 sources/addons/twitter/lang/eo/strings.php create mode 100644 sources/addons/twitter/lang/es/strings.php create mode 100644 sources/addons/twitter/lang/fr/strings.php create mode 100644 sources/addons/twitter/lang/is/strings.php create mode 100644 sources/addons/twitter/lang/it/strings.php create mode 100644 sources/addons/twitter/lang/nb-no/strings.php create mode 100644 sources/addons/twitter/lang/pl/strings.php create mode 100644 sources/addons/twitter/lang/pt-br/strings.php create mode 100644 sources/addons/twitter/lang/ru/strings.php create mode 100644 sources/addons/twitter/lang/sv/strings.php create mode 100644 sources/addons/twitter/lang/zh-cn/strings.php create mode 100755 sources/addons/twitter/lighter.png create mode 100755 sources/addons/twitter/twitter.css create mode 100755 sources/addons/twitter/twitter.php create mode 100644 sources/addons/twitter/twitter.png create mode 100644 sources/addons/twitter/view/tpl/admin.tpl create mode 100644 sources/addons/upload_limits/upload_limits.php create mode 100644 sources/addons/visage/visage.apd create mode 100644 sources/addons/visage/visage.css create mode 100755 sources/addons/visage/visage.php create mode 100644 sources/addons/visage/visage.png create mode 100644 sources/addons/wholikesme/wholikesme.php create mode 100644 sources/addons/wppost/lang/C/messages.po create mode 100644 sources/addons/wppost/lang/ca/strings.php create mode 100644 sources/addons/wppost/lang/cs/strings.php create mode 100644 sources/addons/wppost/lang/de/strings.php create mode 100644 sources/addons/wppost/lang/eo/strings.php create mode 100644 sources/addons/wppost/lang/es/strings.php create mode 100644 sources/addons/wppost/lang/fr/strings.php create mode 100644 sources/addons/wppost/lang/is/strings.php create mode 100644 sources/addons/wppost/lang/it/strings.php create mode 100644 sources/addons/wppost/lang/nb-no/strings.php create mode 100644 sources/addons/wppost/lang/pl/strings.php create mode 100644 sources/addons/wppost/lang/pt-br/strings.php create mode 100644 sources/addons/wppost/lang/ru/strings.php create mode 100644 sources/addons/wppost/lang/sv/strings.php create mode 100644 sources/addons/wppost/lang/zh-cn/strings.php create mode 100644 sources/addons/wppost/wordpress-logo.png create mode 100755 sources/addons/wppost/wppost.css create mode 100755 sources/addons/wppost/wppost.php diff --git a/sources/addons/.gitignore b/sources/addons/.gitignore new file mode 100644 index 00000000..5dade782 --- /dev/null +++ b/sources/addons/.gitignore @@ -0,0 +1,24 @@ +favicon.* +.htconfig.php +\#* +*.log +*.out +*.version* +favicon.* +*~ + +#ignore reports, should be generted with every build +report/ + +#ignore config files from eclipse, we don't want IDE files in our repository +.project +.buildpath +.externalToolBuilders +.settings +#ignore OSX .DS_Store files +.DS_Store + +/nbproject/private/ + +#Kdevelop project files +*.kdev4 diff --git a/sources/addons/README.md b/sources/addons/README.md new file mode 100644 index 00000000..ffb55595 --- /dev/null +++ b/sources/addons/README.md @@ -0,0 +1,6 @@ +hubzilla-addons +================ + +These are addons for hubzilla sites (see https://github.com/redmatrix/hubzilla ) + + diff --git a/sources/addons/adultphotoflag/adultphotoflag.php b/sources/addons/adultphotoflag/adultphotoflag.php new file mode 100755 index 00000000..a8b1371a --- /dev/null +++ b/sources/addons/adultphotoflag/adultphotoflag.php @@ -0,0 +1,28 @@ + + + */ + +function adultphotoflag_load() { + register_hook('get_features','addon/adultphotoflag/adultphotoflag.php','adultphotoflag_get_features'); +} + +function adultphotoflag_unload() { + unregister_hook('get_features','addon/adultphotoflag/adultphotoflag.php','adultphotoflag_get_features'); +} + +function adultphotoflag_get_features(&$a,&$b) { + + $b['tools'][] = array( + 'adult_photo_flagging', + t('Flag Adult Photos'), + t('Provide photo edit option to hide inappropriate photos from default album view'),false); + +} + diff --git a/sources/addons/bbmath/README b/sources/addons/bbmath/README new file mode 100644 index 00000000..e2e9f62c --- /dev/null +++ b/sources/addons/bbmath/README @@ -0,0 +1,3 @@ +Adds a new tag, [tex] that can be used in bbcode. Note that you still also have to use $...$ to get equations correct, i.e. [tex] doesn't eneter math-mode by default. + +Requires images and tmp directory in your Red root directory (e.g. /var/www/red). Must be writable by server (e.g chown -R www-data tmp images). Also requires latex and imagemagick to be installed. diff --git a/sources/addons/bbmath/bbmath.php b/sources/addons/bbmath/bbmath.php new file mode 100644 index 00000000..118772dd --- /dev/null +++ b/sources/addons/bbmath/bbmath.php @@ -0,0 +1,22 @@ + + * + */ + +require_once('phplatex.php'); +function bbmath_load() { + register_hook('bbcode','addon/bbmath/bbmath.php','bbmath_bbcode'); + +} +function bbmath_unload() { + unregister_hook('bbcode','addon/bbmath/bbmath.php','bbmath_bbcode'); +} + +function bbmath_bbcode($a,&$text) { + $text = preg_replace_callback('|\[tex\](.*?)\[/tex\]|',function($m) { return texify($m[1]); },$text); +} diff --git a/sources/addons/bbmath/gpl.txt b/sources/addons/bbmath/gpl.txt new file mode 100644 index 00000000..d511905c --- /dev/null +++ b/sources/addons/bbmath/gpl.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sources/addons/bbmath/phplatex.php b/sources/addons/bbmath/phplatex.php new file mode 100644 index 00000000..cf10cd94 --- /dev/null +++ b/sources/addons/bbmath/phplatex.php @@ -0,0 +1,139 @@ +300) $dpi=300; + + $back=phplatex_colorhex($br,$bg,$bb); + $fore=phplatex_colorhex($r,$g,$b); + + # Figure out TeX, either to get the right cache entry or to, you know, compile + # Semi-common (ams) symbol packages are included. + $totex = "\\documentclass[14pt,landscape]{extarticle}\n". + "\\usepackage{color}\n". + "\\usepackage{amsmath}\n\\usepackage{amsfonts}\n\\usepackage{amssymb}\n". + $extraprelude."\n". + "\\pagestyle{empty}\n". #removes header/footer; necessary for trim + "\\begin{document}\n". + "\\color[rgb]{".$r.",".$g.",".$b."}\n". + "\\pagecolor[rgb]{".$br.",".$bg.",".$bb."}\n". + $string."\n". + "\\end{document}\n"; + + $strhash = sha1($totex).'.'.$dpi; #file cache entry string: 40-char hash string plus size + $stralt = str_replace("&","&", preg_replace("/[\"\n]/","",$string)); #stuck in the alt and title attributes + #May need some extra safety. + $heredir=getcwd(); + + #Experiment: Tries to adjust vertical positioning, so that rendered TeX text looks natural enough inline with HTML text + #Only descenders are really a problem since HTML's leeway is upwards. + #TODO: This can always use more work. + # Avoid using characters that are part of TeX commands. + # Some things vary per font, e.g. the slash. In the default CM it is a descender, in Times and others it isn't. + $ascenders ="/(b|d|f|h|i|j|k|l|t|A|B|C|D|E|F|G|H|I|J|L|K|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|\[|\]|\\{|\\}|\(|\)|\/|0|1|2|3|4|5|6|7|8|9|\\#|\*|\?|'|\\\\'|\\\\`|\\\\v)/"; + $monoliners="/(a|c|e|m|n|o|r|s|u|v|w|x|z|-|=|\+|:|.)/"; + $descenders="/(g|j|p|\/|q|y|Q|,|;|\[|\]|\\{|\\}|\(|\)|\#|\\\\LaTeX|\\\\TeX|\\\\c\{)/"; + $deepdescenders="/(\[|\]|\\{|\\}|\(|\)|\\int)/"; + + $ba = preg_match_all($ascenders, $string,$m); + $bm = preg_match_all($monoliners, $string,$m); + $bd = preg_match_all($descenders, $string,$m); + $dd = preg_match_all($deepdescenders, $string,$m); + if ($dd>0) $verticalalign="vertical-align: -25%"; # deep descenders: move down + else if ($bd>0 && $ba==0) $verticalalign="vertical-align: -15%"; # descenders: move down + else if ($bd==0 && $ba>0) $verticalalign="vertical-align: 0%"; # ascenders only: move up/do nothing? + else if ($bd==0 && $ba==0) $verticalalign="vertical-align: 0%"; # neither vertical-align: 0% + else $verticalalign="vertical-align: -15%"; # both ascender and regular descender + + #check image cache, return link if exists + #the vertical-align is to fix text baseline/descender(/tail) details in and on-average sort of way + if (file_exists($heredir.'/images/'.$strhash.'.'.$imgfmt)) + return ''.$stralt.''; + + + #chdir to have superfluous files be created in tmp. (you stiill have to empty this yourself) + error_reporting(0); # not checking existence myself, that would be double. + if (chdir("tmp")===FALSE) { return '[directory access error, fix permissions]'; } #I should chech whether file creation is allowed to give a nice error for that problem case + error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE); # TODO: set old value + + $tfn = tempnam(getcwd(), 'PTX'); #file in tmp dir + + #write temporary .tex file + if ( ($tex = fopen($tfn.'.tex', "w"))==FALSE) { return '[file access error] '.phplatex_cleantmp($tfn,$heredir); } + fwrite($tex, $totex); + fclose($tex); + + + #Run latex to create a .dvi. Have it try to fix minor errors instead of breaking/pausing on them. + exec($path_to_latex.' --interaction=nonstopmode '.$tfn.'.tex'); + if (!file_exists($tfn.".dvi")) { + $log = file_get_contents($tfn.'.log'); #The log always exists, but now it's actually interesting since it'll contain an error + return '[latex error, code follows]
'.$totex.'

Log file:

'.$log.'

'.phplatex_cleantmp($tfn,$heredir); + } + + + #DVI -> PostScript. Since dvips uses lpr, which may be configured to actually print by default, force writing to a file with -o + exec($path_to_dvips.' '.$tfn.'.dvi -o '.$tfn.'.ps'); + if ( !file_exists($tfn.'.ps')) { + return '[dvi2ps error] '.phplatex_cleantmp($tfn,$heredir); + } + + + #PostScript -> image. Trim based on corner pixel, and set transparent color. + exec($path_to_convert.' -transparent-color "#'.$back.'" -colorspace RGB -density '.$dpi.' -trim +page '.$tfn.'.ps -transparent "#'.$back.'" '.$tfn.'.'.$imgfmt); + #Note: +page OR -page +0+0 OR +repage moves the image to the cropped area (kills offset) + #Older code tried: exec('/usr/bin/mogrify -density 90 -trim +page -format $imgfmt '.$tfn.'.ps'); + # It seems some versions of convert may not have -trim. Old versions? + + if (!file_exists($tfn.'.'.$imgfmt)) { + return '[image convert error] '.phplatex_cleantmp($tfn,$heredir); + } + + #Copy result image to chache. + copy($tfn.'.'.$imgfmt, $heredir.'/images/'.$strhash.'.'.$imgfmt); + + #Clean up temporary files, and return link to just-created image + return phplatex_cleantmp($tfn,$heredir).'LaTeX formula: '.$stralt.''; +} +?> diff --git a/sources/addons/bookmarker/bookmarker.php b/sources/addons/bookmarker/bookmarker.php new file mode 100755 index 00000000..41a86350 --- /dev/null +++ b/sources/addons/bookmarker/bookmarker.php @@ -0,0 +1,41 @@ + + * + */ + +function bookmarker_install() { + register_hook('prepare_body', 'addon/bookmarker/bookmarker.php', 'bookmarker_prepare_body', 10); +} + + +function bookmarker_uninstall() { + unregister_hook('prepare_body', 'addon/bookmarker/bookmarker.php', 'bookmarker_prepare_body'); +} + +function bookmarker_prepare_body(&$a,&$b) { + + + if(get_pconfig(local_channel(),'bookmarker','disable')) + return; + + if(! strpos($b['html'],'bookmark-identifier')) + return; + + if(! function_exists('redbasic_init')) + return; + + $id = $b['item']['id']; + if(local_channel()) + $link = ' '; + else + $link = ' '; + + $b['html'] = str_replace('#^',$link,$b['html']); + +} diff --git a/sources/addons/buglink/bug-x.gif b/sources/addons/buglink/bug-x.gif new file mode 100755 index 0000000000000000000000000000000000000000..10936caa77447918523dac210ec106b3f9e48cca GIT binary patch literal 134 zcmZ?wbhEHb6krfwXkq{XMMcE|ZSCg_4F7>BD(e4#AkCoolZ6o^sRJTFYMGe5Ids%TpZV|Fm*ZV=u*7+-1gPSCWLw)Xj)pv*tCG{F-zu2 dPrj|vyW$S0D+X{pDRI1Kl4=;J{ep$T8USlOEiV87 literal 0 HcmV?d00001 diff --git a/sources/addons/buglink/buglink.php b/sources/addons/buglink/buglink.php new file mode 100755 index 00000000..a237601b --- /dev/null +++ b/sources/addons/buglink/buglink.php @@ -0,0 +1,15 @@ + + */ + + +function buglink_load() { register_hook('page_end', 'addon/buglink/buglink.php', 'buglink_active'); } + + +function buglink_unload() { unregister_hook('page_end', 'addon/buglink/buglink.php', 'buglink_active'); } + +function buglink_active(&$a,&$b) { $b .= ''; } diff --git a/sources/addons/buglink/lang/C/messages.po b/sources/addons/buglink/lang/C/messages.po new file mode 100644 index 00000000..260c583a --- /dev/null +++ b/sources/addons/buglink/lang/C/messages.po @@ -0,0 +1,22 @@ +# ADDON buglink +# Copyright (C) +# This file is distributed under the same license as the Friendica buglink addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: buglink.php:15 +msgid "Report Bug" +msgstr "" diff --git a/sources/addons/buglink/lang/ca/strings.php b/sources/addons/buglink/lang/ca/strings.php new file mode 100644 index 00000000..01fc9adb --- /dev/null +++ b/sources/addons/buglink/lang/ca/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Informar de problema"; diff --git a/sources/addons/buglink/lang/cs/strings.php b/sources/addons/buglink/lang/cs/strings.php new file mode 100644 index 00000000..a1cd51f4 --- /dev/null +++ b/sources/addons/buglink/lang/cs/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Nahlásit chybu"; diff --git a/sources/addons/buglink/lang/de/strings.php b/sources/addons/buglink/lang/de/strings.php new file mode 100644 index 00000000..cf96a178 --- /dev/null +++ b/sources/addons/buglink/lang/de/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Fehlerreport erstellen"; diff --git a/sources/addons/buglink/lang/eo/strings.php b/sources/addons/buglink/lang/eo/strings.php new file mode 100644 index 00000000..00d95a40 --- /dev/null +++ b/sources/addons/buglink/lang/eo/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Skribi cimraporton"; diff --git a/sources/addons/buglink/lang/es/strings.php b/sources/addons/buglink/lang/es/strings.php new file mode 100644 index 00000000..fe632488 --- /dev/null +++ b/sources/addons/buglink/lang/es/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Informe de errores"; diff --git a/sources/addons/buglink/lang/fr/strings.php b/sources/addons/buglink/lang/fr/strings.php new file mode 100644 index 00000000..0075fb0d --- /dev/null +++ b/sources/addons/buglink/lang/fr/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Signaler un bug"; diff --git a/sources/addons/buglink/lang/is/strings.php b/sources/addons/buglink/lang/is/strings.php new file mode 100644 index 00000000..7b3823a6 --- /dev/null +++ b/sources/addons/buglink/lang/is/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Tilkynna bilun"; diff --git a/sources/addons/buglink/lang/it/strings.php b/sources/addons/buglink/lang/it/strings.php new file mode 100644 index 00000000..90df28fe --- /dev/null +++ b/sources/addons/buglink/lang/it/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Segnala un Bug"; diff --git a/sources/addons/buglink/lang/nb-no/strings.php b/sources/addons/buglink/lang/nb-no/strings.php new file mode 100644 index 00000000..ec212e9a --- /dev/null +++ b/sources/addons/buglink/lang/nb-no/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = ""; diff --git a/sources/addons/buglink/lang/pl/strings.php b/sources/addons/buglink/lang/pl/strings.php new file mode 100644 index 00000000..8229e7a6 --- /dev/null +++ b/sources/addons/buglink/lang/pl/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Zgłoś problem"; diff --git a/sources/addons/buglink/lang/pt-br/strings.php b/sources/addons/buglink/lang/pt-br/strings.php new file mode 100644 index 00000000..6283d77e --- /dev/null +++ b/sources/addons/buglink/lang/pt-br/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Relate um Bug"; diff --git a/sources/addons/buglink/lang/ru/strings.php b/sources/addons/buglink/lang/ru/strings.php new file mode 100644 index 00000000..c4223648 --- /dev/null +++ b/sources/addons/buglink/lang/ru/strings.php @@ -0,0 +1,3 @@ +strings["Report Bug"] = "Сообщить об ошибке"; diff --git a/sources/addons/buglink/lang/sv/strings.php b/sources/addons/buglink/lang/sv/strings.php new file mode 100644 index 00000000..ab4fa67a --- /dev/null +++ b/sources/addons/buglink/lang/sv/strings.php @@ -0,0 +1,2 @@ +strings["Report Bug"] = "报案程序错误"; diff --git a/sources/addons/calc/calc.apd b/sources/addons/calc/calc.apd new file mode 100644 index 00000000..8171ce06 --- /dev/null +++ b/sources/addons/calc/calc.apd @@ -0,0 +1,3 @@ +url: $baseurl/calc +name: Calculator +photo: $baseurl/addon/calc/calc.png diff --git a/sources/addons/calc/calc.php b/sources/addons/calc/calc.php new file mode 100755 index 00000000..2935b4a2 --- /dev/null +++ b/sources/addons/calc/calc.php @@ -0,0 +1,368 @@ + + */ + + +function calc_load() { + register_hook('app_menu', 'addon/calc/calc.php', 'calc_app_menu'); +} + +function calc_unload() { + unregister_hook('app_menu', 'addon/calc/calc.php', 'calc_app_menu'); + +} + +function calc_app_menu($a,&$b) { + $b['app_menu'][] = ''; +} + + +function calc_module() {} + + + + +function calc_init($a) { + +$x = <<< EOT + + + +EOT; +$a->page['htmlhead'] .= $x; +} + +function calc_content($app) { + +$o = ''; + +$o .= <<< EOT + + +

Calculator

+

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ +EOT; +return $o; + +} diff --git a/sources/addons/calc/calc.png b/sources/addons/calc/calc.png new file mode 100644 index 0000000000000000000000000000000000000000..e7d15c8c0a09fd74dba9b2777b54c07ed00fbf14 GIT binary patch literal 7286 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 Uby&k8rg;<77zbm=7PBM%8_nVyKL7v# literal 0 HcmV?d00001 diff --git a/sources/addons/chords/chord-generator.cpp b/sources/addons/chords/chord-generator.cpp new file mode 100755 index 00000000..6a7f2c09 --- /dev/null +++ b/sources/addons/chords/chord-generator.cpp @@ -0,0 +1,1133 @@ +// +// I have been messing around with this program now for a couple weeks +// and thought it might be useful to someone. Given a chord by name, +// it generates all possible ways to play that chord on a guitar and +// scores them based on things like finger span, root as bass note, +// number of open strings, etc (see below). Then it prints the top +// 50 it found (or more, you can set it). The program is pretty +// configurable if you can stand to read the stuff at the top where +// all the #define's are. Currently it prints out the score, and the +// pieces that made up the score...you may want to get rid of the +// extra info, but I found it interesting. +// +// It generates some wild chords and some interesting versions that +// I have NEVER seen before. Probably a great program to find inversions +// and stuff (especially if you lower the score given for having a root +// note 1st). The program could easily be modified to do Drop D tuning +// or any other alternate tuning, and I think it could do other instruments +// without much change, but I have not tried. +// +// I have been having fun playing with this, if you make a changes or +// fixes I would appreciate a copy. Other than that, this is public +// domain, have a party. Oh yeah, the code is C++... +// +// Thanks, +// Rick Eesley +// re@warren.mentorg.com +// +// +// +// Chords can be built like: | = seperate fields, [ ... ] = range of values +// <> = nothing +// +// [<--optional--->] +// [<--repeating-->] +// [A...G] | <> | <> | <> | # | +// | # | min | maj | | +// | b | m | add | | +// | | sus2 | aug | | +// | | sus4 | dim | | +// | | dim | + | | +// | | aug | - | | +// | | | # | +// | | | b | +// | | | / | +// +// Legal chord names: A A7 Amaj7 Amaj9 Ammaj7 Aadd4 Asus2Add4 E7b13b11 ... +// Does not do: C/G which is a c chord with a g root, just find a c +// chord and pick out a g root you like for those... +// Does not do: E5 (that's not a chord, just 2 notes) +// +// + + +#undef DEBUG +int lefty = 0; + +////////////////////////////////////////////////////////////////////// +// Scoring a chord is influenced by these multipliers, change them around +// to your own preferences +////////////////////////////////////////////////////////////////////// + +// +// Score for where this lands on the fretboard (Lower is better) +// score += (15 - AverageFret) * POSITION_SCORE; +#define POSITION_SCORE 20 + +// Score for minimal span (ie: chord covering from fret 2 to fret 4 has +// a span of 2. Open strings do NOT count in span, this is a measure +// of whether a chord is playable +// The maximum span allowed is set by the #define MAXSPAN +// score += (MAXSPAN - span) * SPAN_SCORE; +#define SPAN_SCORE 12 + +// This score is for total Span (ie: includes open strings, which span +// does not. +// score += (15 - tspan) * TSPAN_SCORE; +#define TSPAN_SCORE 3 + +// This score is for number of open strings (I like them). +// score += numberOfOpens * OPENS_SCORE +#define OPENS_SCORE 10 + +// This score multiplier is the score to add if the most bass string +// is the root note +// score += ROOT_SCORE +#define ROOT_SCORE 50 + +// This score multipier is used to penalize for adjacent notes +// score += ADJ_SCORE * (5-adjNotes) +// THe five is the max number of adjacent strings possible (duh...) +#define ADJ_SCORE 9 + +// This is the maximum finger reach, if this is bumped up to five or +// more you get a zillion more fingers (mainly 'cause 5 takes you to +// the notes on the next string...so leave it probably +#define MAXSPAN 4 + +// This is number of top scores to keep, something < 20 leaves out +// too much, 100 is a lot to look at...but I am going with it... +#define CHORDSTACK 250 + +// +// These are different types of scores, NUMSCORETYPES MUST be set to the +// number of these types, so if any are added change it TOO! +// Add any new scores onto the end, the total MUST be the 0th element +// +#define NUMSCORETYPES 7 + +#define SCORE_TOTAL 0 +#define SCORE_SPAN 1 +#define SCORE_TOTALSPAN 2 +#define SCORE_OPENSTRINGS 3 +#define SCORE_FIRSTROOT 4 +#define SCORE_LOWONNECK 5 +#define SCORE_ADJNOTES 6 + +// Just in case someone wants to port this to banjo or mandolin or something +#define NUM_STRINGS 6 + + +#include +#include +#include +#include + +/* A A# B C C# D D# E F F# G G# */ +/* A Bb B C Db D Eb E F Gb G Ab */ +/* 0 1 2 3 4 5 6 7 8 9 10 11 */ + +/* STRINGS ARE: E=0, A=1, D=2, G=3, B=4, E=5 IN ORDER */ + +// This can be reset for alternate tunings, this is EADGBE tuning +// here: + + int openStrings[NUM_STRINGS] = { 7, 0, 5, 10, 2, 7 }; + +static char *strNotes[] = { "A ", "A#", "B ", "C ", "C#", "D ", + "D#", "E ", "F ", "F#", "G ", "G#" }; + +// +// This class contains a decode chord, and can take a string and turn +// it into a chord. A chord is a triad or greater here. The code is +// decoded from a string into notes in the c array (notes: are A=0, A#=1, +// and so on. The longest chord you can possibly have is 12 notes which +// would be every note in an octave, since chords are typical 3 to 5 +// notes, remaining notes in the c[] array are set to -1 +// +class Chord +{ + public: + // String set to last error + char errorStr[64]; + + // Notes that are in the chord -1 should be ignored + int notes[12]; + + // NOtes that are optional have a 1, otherwise a zero + int optional[12]; + + // ------------------ MEMBER FUNCTIONS ---------------------------- + + // Clears last chord + void clear(); + + // Decodes input string into notes[] array, return error string + int findChord(char *s); + + // Print last error message from chord parse + void printError(); + + // Prints out notes[] array to screen + void print(char *chordName); + + // Is the note note in the chord + int inChord(int note); + + // Is this chord covered by the array of notes (ie: Does the + // array contain all the notes of the chord + int covered(int *noteArray); + + // Return the root note of the chord + int getRoot() { return notes[0]; } + + // Given a chord string, return the note that starts it (and recognize + // sharps and flats (b and #) + int get_base(char *s); + + // Get a note offset from another... + int note_offset(int base, int offset) { + if((! base) && (offset == (-1))) + return(11); + return ((base + offset) % 12); + } +} ; + +// +// This class holds a fingering for a chord, as well as a score for that +// fingering. This class also keeps the CHORDSTACK (ie: 100) best version +// of that chord to print out in sorted order (best score 1st). +// +class Fretboard +{ + public: + + // Score of current chord, held in an array so we can track the + // components of the score (see the SCORE_ defines in the begining + // of this file + int score[NUMSCORETYPES]; + + // Fretboard of the current chord, fretboard[0] is the low (bass) E + // string. A fretboard value of 0 is an open string, -1 is an + // X'ed out string (not strung) + int fretboard[NUM_STRINGS]; + + // Notes of the current fretboard fingering for a chord + int notes[NUM_STRINGS]; + + // The best fret layouts so far based on score + int bestFrets[CHORDSTACK][NUM_STRINGS]; + + // The best fret layout note sets so far based on score + int bestNotes[CHORDSTACK][NUM_STRINGS]; + + // The best scores + int bestScores[CHORDSTACK][NUMSCORETYPES]; + + // Keep track of stack sDepth to speed it up! + int sDepth; + + // ------------------ MEMBER FUNCTIONS ---------------------------- + + // Construct one + Fretboard(); + + // Given a chord (and the current fretboard state) score this doggie + // and leave the score value in score + void getScore(Chord &chord); + + // Print the current Fretboard state (not the stack) + void print(); + + // Print the fretboard stack + void printStack(); + + // Iterate over different fretboard variations for a chord + void iterate(Chord &chord); + + // Take the current fretboard state and put it into the stack + void addToBest(); + + // Get the span of the current chord, excluding open string + int getSpan(); + + // Get the span of the current chord, INCLUDING open string + int getTotalSpan(); +}; + +// +// Before building a chord, clear the notes and optional arrays +// +void +Chord::clear() +{ + for (int i = 0; i < 12; i++) + { + notes[i] = -1; + optional[i] = 0; + } +} + +// +// Print out the last error string +// +void +Chord::printError() +{ + printf("Error: %s\n", errorStr); +} + +// +// I dunno, our C++ compiler at work did not have strupr, so heres mine +// +void +myStrupr(char *s) +{ + while (*s) + { + if (islower(*s)) + *s = toupper(*s); + s++; + } +} + +// +// Decodes input string into notes[] array, return error string +// always: 0 = root, 1 = 3rd, 2 = 5th +// Also sets the optional array in parallel with the notes[] +// +int +Chord::findChord(char *s) +{ + clear(); + + // up case the string + myStrupr(s); + + // DECODE ROOT NOTE : A - G + notes[0] = get_base(s); + s++; + + // CHECK FOR SHARP OR FLAT ROOT NOTE + if (*s == '#') s++; + if (*s == 'B') s++; + + // MODIFY THE ROOT BY M, MIN, SUS2, SUS4, or diminished + if (!strncmp(s, "MIN", 3 )) + { + notes[1] = note_offset(notes[0], 3); + s += 3; + optional[2] = 1; + } + else if (!strncmp(s, "MAJ", 3)) + { + // Do nothing, but stops program from seeing the + // first m in maj as a minor (see next line)...so give a normal 3rd + notes[1] = note_offset(notes[0], 4); + optional[2] = 1; + } + else if (!strncmp(s, "M", 1)) + { + notes[1] = note_offset(notes[0], 3); + s += 1; + optional[2] = 1; + } + else if (!strncmp(s, "SUS", 1)) + { + s += 3; // go past sus + if (*s == '2') + notes[1] = note_offset(notes[0], 2); + else if (*s == '4') + notes[1] = note_offset(notes[0], 5); + else + { + strcpy(errorStr, "sus must be followed by 2 or 4"); + return 1; + } + s++; // Go past 2 or 4 + optional[2] = 1; + } + else if ((!strncmp(s, "DIM", 3 )) && (!isdigit(s[3]))) + { + // If it is diminished, just return (no other stuff allowed)/ + notes[1] = note_offset(notes[0], 3); + notes[2] = note_offset(notes[0], 6); + notes[3] = note_offset(notes[0], 9); + return 0; + } + else if ((!strncmp(s, "AUG", 3 )) && (!isdigit(s[3]))) + { + // If it is diminished, just return (no other stuff allowed)/ + notes[1] = note_offset(notes[0], 4); + notes[2] = note_offset(notes[0], 8); + return 0; + } + else + { + notes[1] = note_offset(notes[0], 4); + // optional[1] = 1; + // optional[2] = 1; + } + + notes[2] = note_offset(notes[0], 7); + + + // At this point, the 1,3,5 triad or variant is built, now add onto + // it until the string end is reached... + // Next note to add is index = 3... + int index = 3; + enum homeboy { NORMAL, MAJ, ADD, AUG, DIM } mtype ; + char lbuf[10]; + + while (*s) + { + // FIrst, check the mtype of modifier, ie: Aug, Maj, etc... + mtype = NORMAL; + if (!strncmp(s, "MAJ", 3)) + { + mtype = MAJ; + s += 3; + } + else if (!strncmp(s, "ADD", 3)) + { + mtype = ADD; + s += 3; + } + else if (!strncmp(s, "AUG", 3)) + { + mtype = AUG ; + s += 3; + } + else if (!strncmp(s, "DIM", 3)) + { + mtype = DIM; + s += 3; + } + else if ( *s == '+' ) + { + mtype = AUG; + s += 1; + } + else if ( *s == '-' ) + { + mtype = DIM; + s += 1; + } + else if ( *s == '#' ) + { + mtype = AUG; + s += 1; + } + else if ( *s == 'B' ) + { + mtype = DIM; + s += 1; + } + else if ( *s == '/' ) + { + mtype = ADD; + s += 1; + } + // Now find the number... + if (isdigit(*s)) + { + lbuf[0] = *s++; + lbuf[1] = '\0'; + } + else + { + sprintf(errorStr, "Expecting number, got %s", s); + return 1; + } + // 2nd digit? + if (isdigit(*s)) + { + lbuf[1] = *s++; + lbuf[2] = '\0'; + } + + int number = atoi(lbuf); + + switch (number) + { + case 7 : + notes[index] = note_offset(notes[0], 10); + break; + case 9 : + notes[index] = note_offset(notes[0], 2); + + // put the 7th in 2nd so it can be maj'ed if need be... + if ((mtype == NORMAL) || (mtype == MAJ)) + { + index++; + notes[index] = note_offset(notes[0], 10); + optional[index] = 1; // 7th is optional, unless it is maj! + } + + break; + case 11 : + notes[index] = note_offset(notes[0], 5); + + // put the 7th in 2nd so it can be maj'ed if need be... + if ((mtype == NORMAL) || (mtype == MAJ)) + { + index++; + notes[index] = note_offset(notes[0], 10); + optional[index] = 1; // 7th is optional, unless it is maj! + } + + break; + case 13 : + notes[index] = note_offset(notes[0], 9); + index++; + notes[index] = note_offset(notes[0], 5); + optional[index] = 1; // 7th is optional, unless it is maj! + index++; + notes[index] = note_offset(notes[0], 2); + optional[index] = 1; // 7th is optional, unless it is maj! + + // put the 7th in 2nd so it can be maj'ed if need be... + if ((mtype == NORMAL) || (mtype == MAJ)) + { + index++; + notes[index] = note_offset(notes[0], 10); + optional[index] = 1; // 7th is optional, unless it is maj! + } + + break; + case 2: + notes[index] = note_offset(notes[0], 2); + break; + case 4: + notes[index] = note_offset(notes[0], 5); + break; + case 6: + notes[index] = note_offset(notes[0], 9); + break; + case 5: + notes[index] = note_offset(notes[0], 7); + break; + default: + sprintf(errorStr, "Cannot do number: %d\n", number); + return 1; + } + + switch (mtype) + { + case DIM: + notes[index] = note_offset(notes[index], -1); + break; + case MAJ: + // It is a major, so not optional + optional[index] = 0; + case AUG : + notes[index] = note_offset(notes[index], 1); + break; + case NORMAL: + case ADD: + break; + default: + break; + } + + index++; + } + return 0; +} + +// +// Print out chord by name +// +void +Chord::print(char *cname) +{ + printf("Notes for chord '%s': ", cname); + for (int i = 0; i < 12; i++) + { + if (notes[i] != -1) + printf("%s ", strNotes[notes[i]]); + } + printf("\n\n"); +} + +// +// Are all the notes in this chord covered by the notes in the +// noteArray, it is not necessary to cover the notes in the optional +// array of the chord +// +int +Chord::covered(int *noteArray) +{ + // noteArray is an array of notes this chord has, it is NUM_STRINGS notes + // long (like a guitar fretboard dude...unused notes may be set + // to -1 (which wont compare since -1 is tossed... + + for (int i = 0; i < 12; i++) + { + if (notes[i] != -1) + { + int gotIt = 0; + for (int j = 0; j < NUM_STRINGS; j++) + { + if (noteArray[j] == notes[i]) + { + gotIt = 1; + break; + } + } + // If it was not found, and it is NOT optional, then it is + // not covered + if ((gotIt == 0) && (optional[i] == 0)) + return 0; + } + } + return 1; +} + + +// +// Is the given note in the chord +// +int +Chord::inChord(int note) +{ + for (int i = 0; i < 12; i++) + { + // Check if we are off the end of the notes set + if (notes[i] == -1) + return 0; + // Check if the note was found + if (note == notes[i]) + return 1; + } + // Did not find out, return 0 + return 0; +} + +// +// Given a chord string, pick off the root (either C or C# or Cb)...and +// return that integer value (A = 0) +// +int +Chord::get_base(char *s) +{ + + static int halfsteps[] = { 0, 2, 3, 5, 7, 8, 10 }; + + if ((*s < 'A') || (*s > 'G')) + return 0; + + if (s[1] == '#') + return ( note_offset(halfsteps[s[0] - 'A'], 1)); + else if (s[1] == 'B') + return ( note_offset(halfsteps[s[0] - 'A'], -1)); + else + return ( halfsteps[s[0] - 'A']); +} + + +// +// Print out the current fretboard +// +void +Fretboard::print() +{ + printf("SCORE: %3d ", score[SCORE_TOTAL]); + printf( + " SPN: %2d TSPN: %2d OS: %2d ROOT: %2d LOW %2d ADJ %2d", + score[SCORE_SPAN], score[SCORE_TOTALSPAN], score[SCORE_OPENSTRINGS], + score[SCORE_FIRSTROOT], score[SCORE_LOWONNECK], + score[SCORE_ADJNOTES]); + + printf(" FB: "); + for (int i = 0; i < NUM_STRINGS; i++) + { + if (fretboard[i] != -1) + printf(" %2d", fretboard[i]); + else + printf(" X"); + } + + printf(" NT: "); + for (int i = 0; i < NUM_STRINGS; i++) + if (notes[i] != -1) + printf(" %s", strNotes[notes[i]]); + else + printf(" X "); + printf("\n"); +} + +// +// Construct a fretboard -- reset to the openStrings, clear the stack +// and reset all the bestScores to -1 +// +Fretboard::Fretboard() +{ + sDepth = 0; + score[0] = 0; + for (int i = 0; i < NUM_STRINGS; i++) + { + notes[i] = openStrings[i]; + fretboard[i] = 0; + } + for (int i = 0; i < CHORDSTACK; i++) + { + bestScores[i][0] = -1; + } +} + +// +// Get the span of this chord, don't count open strings +// +int +Fretboard::getSpan() +{ + int min = 100, max = 0; + for (int i = 0; i < NUM_STRINGS; i++) + { + // Dont count X strings or open strings + if (fretboard[i] <= 0) + continue; + if (fretboard[i] > max) max = fretboard[i]; + if (fretboard[i] < min) min = fretboard[i]; + } + if (min == 100) + // All open strings, took awhile to catch this bug + return 0; + else + return (max - min); +} + +// +// Get the span of this chord, DO count open strings +// +int +Fretboard::getTotalSpan() +{ + int min = 100, max = 0; + for (int i = 0; i < NUM_STRINGS; i++) + { + // Dont count X strings + if (fretboard[i] < 0) + continue; + if (fretboard[i] > max) max = fretboard[i]; + if (fretboard[i] < min) min = fretboard[i]; + } + if (min == -1) + min = 0; + return (max - min); +} + +// +// Add this chord to the best (if there is room in the stack) +// +void +Fretboard::addToBest() +{ + // CHORDSTACK is the sDepth of keepers... +#ifdef DEBUG + printf("ATB: "); + this->print(); +#endif + + int i; + + // NOTE: at the start, bestScores is full of -1's, so any reall + // real score will be better (worst score is 0) + for (i = 0; i < sDepth; i++) + { + if (score[0] > bestScores[i][0]) + break; + } + + // If score was not better than any in the stack just return + if (i >= CHORDSTACK) + return ; + // MOve down old guys to make room for the new guy + for (int j = CHORDSTACK - 1; j >= i; j--) + { + for (int q = 0; q < NUM_STRINGS; q++) + { + bestFrets[j][q] = bestFrets[j - 1][q]; + bestNotes[j][q] = bestNotes[j - 1][q]; + } + for (int q = 0; q < NUMSCORETYPES; q++) + bestScores[j][q] = bestScores[j - 1][q]; + } + + for (int q = 0; q < NUM_STRINGS; q++) + { + bestFrets[i][q] = fretboard[q]; + bestNotes[i][q] = notes[q]; + } + for (int q = 0; q < NUMSCORETYPES; q++) + bestScores[i][q] = score[q]; + + sDepth++; + if (sDepth > CHORDSTACK) + sDepth--; +} + +// +// Print out the stack to the screen +// +void +Fretboard::printStack() +{ + static char *strNotes[] = { "A ", "A#", "B ", "C ", "C#", "D ", + "D#", "E ", "F ", "F#", "G ", "G#" }; + + + for (int f = 0; f < sDepth; f++) + { + printf("\n\n "); + + if(lefty) { + for (int i = NUM_STRINGS - 1; i >= 0; i--) + if (bestNotes[f][i] != -1) + printf(" %s", strNotes[bestNotes[f][i]]); + else + printf(" X "); + } + else { + for (int i = 0; i < NUM_STRINGS; i++) + if (bestNotes[f][i] != -1) + printf(" %s", strNotes[bestNotes[f][i]]); + else + printf(" X "); + } + printf("\n"); + if(lefty) { + for (int i = NUM_STRINGS - 1; i >= 0; i--) + if (bestFrets[f][i] != -1) + printf(" %2d", bestFrets[f][i]); + else + printf(" X"); + + } + else { + for (int i = 0; i < NUM_STRINGS; i++) + + if (bestFrets[f][i] != -1) + printf(" %2d", bestFrets[f][i]); + else + printf(" X"); + } + + printf("\n\n"); + + + int highest = 0; + + for(int i = 0; i < NUM_STRINGS; i++) + if(bestFrets[f][i] > highest) + highest = bestFrets[f][i]; + + printf("\n"); + + for(int i = 0; i <= (highest + 1); i ++) { + if(lefty) { + for (int x = NUM_STRINGS-1; x >= 0; x--) { + if(i == 0) { + if(bestFrets[f][x] == -1) + printf(" X"); + else + if(bestFrets[f][x] == 0) + printf(" 0"); + else + printf(" "); + } + else { + if(bestFrets[f][x] == i) + printf(" *"); + else + printf(" |"); + } + } + } + else { + + for (int x = 0; x < NUM_STRINGS; x++) { + if(i == 0) { + if(bestFrets[f][x] == -1) + printf(" X"); + else + if(bestFrets[f][x] == 0) + printf(" 0"); + else + printf(" "); + } + else { + if(bestFrets[f][x] == i) + printf(" *"); + else + printf(" |"); + } + } + } + printf("\n ---------------- %2d\n",i); + + + + + } + } +} + + +// +// Get the score for this chord +// +void +Fretboard::getScore(Chord &chord) +{ + + // First, points for small span (excluding opens) + score[SCORE_SPAN] = (MAXSPAN - getSpan()) * SPAN_SCORE; + + // Then, points for small total span + score[SCORE_TOTALSPAN] = (15 - getTotalSpan()) * 3; + + score[SCORE_OPENSTRINGS] = 0; + // Points for open strings + for (int i = 0; i < NUM_STRINGS; i++) + { + if (fretboard[i] == 0) + { + score[SCORE_OPENSTRINGS] += OPENS_SCORE; + } + } + + // Points for first string being the root ... + score[SCORE_FIRSTROOT] = 0; + int i; + for (i = 0; (fretboard[i] == -1) && (i < NUM_STRINGS) ; i++) + ; + if (notes[i] == chord.getRoot()) + { + score[SCORE_FIRSTROOT] = ROOT_SCORE; + } + + // Points for being low on the neck... + int sum = 0, cnt = 0; + for (i = 0; i < NUM_STRINGS; i++) + { + // Don't count X strings or open strings + if (fretboard[i] > 0) + { + sum += fretboard[i]; + cnt++; + } + } + if (cnt) + score[SCORE_LOWONNECK] = (int)(15 - ((double) sum / (double) cnt)) + * POSITION_SCORE; + else + score[SCORE_LOWONNECK] = 15 * POSITION_SCORE; + + + int adjNotes = 0; + for (i = 0; i < 5; i++) + { + if ((notes[i] != -1) && (notes[i] == notes[i + 1])) + adjNotes++; + } + score[SCORE_ADJNOTES] = (ADJ_SCORE * (5 - adjNotes)); + + // FInally, total up the score + score[SCORE_TOTAL] = 0; + for (i = 1; i < NUMSCORETYPES; i++) + score[SCORE_TOTAL] += score[i]; +} + + +// +// Iterate over all fretboard config's for this chord, call addToBest +// with any good ones (ie: < span, etc etc...) +// +void +Fretboard::iterate(Chord &chord) +{ + int string = 0; + + // Start notes setup, increment up the neck for each string until + // you find a note that is in this chord (may be an open note) + for (int i = 0; i < NUM_STRINGS; i++) + { + while (! chord.inChord(notes[i])) + { + fretboard[i]++; + notes[i] = ( notes[i] + 1 ) % 12; + } + } + + // Back up the first note one...so the loop will work + fretboard[0] = -1; + + // While we are still on the fretboard! + while (string < NUM_STRINGS) + { + + // increment the current string + fretboard[string]++; + if (fretboard[string] == 0) + notes[string] = openStrings[string]; + else + notes[string] = ( notes[string] + 1 ) % 12; + + while (! chord.inChord(notes[string])) + { + fretboard[string]++; + notes[string] = ( notes[string] + 1 ) % 12; + } + + if (fretboard[string] > 15) + { + + // Before turning over the 3rd string from the bass, try + // to make a chord with the bass string, and 2nd from + // bass string X'ed out...(ie: set to -1) + if (string == 0) + { + + notes[0] = fretboard[0] = -1; + int span = getSpan(); + if ((span < MAXSPAN) && chord.covered(notes)) + { + getScore(chord); + addToBest(); + } + } + + if (string == 1) + { + int store = notes[0]; + int fstore = fretboard[0]; + notes[1] = fretboard[1] = -1; + notes[0] = fretboard[0] = -1; + int span = getSpan(); + if ((span < MAXSPAN) && chord.covered(notes)) + { + getScore(chord); + addToBest(); + } + // Restore the notes you X'ed out + notes[0] = store; + fretboard[0] = fstore; + } + + fretboard[string] = 0; + notes[string] = openStrings[string]; + while (! chord.inChord(notes[string])) + { + fretboard[string]++; + notes[string] = chord.note_offset(notes[string], 1); + } + string++; + continue; + } + +#ifdef DEBUG + printf("TRY: "); this->print(); +#endif + + string = 0; + int span = getSpan(); + if (span >= MAXSPAN) + { +#ifdef DEBUG + printf("Rejected for span\n"); +#endif + continue; + } + if (!chord.covered(notes)) + { +#ifdef DEBUG + printf("Rejected for coverage\n"); +#endif + continue; + } + + getScore(chord); + + addToBest(); + } +} + +// +// uh, main +// +int main(int argc, char **argv) +{ + char buf[256], buf2[256]; + + if(argc > 1) + { + strcpy(buf, argv[1]); + if(argc > 3) { + if(! strcmp(argv[3],"lefty")) { + lefty = 1; + + } + + + } + + if(argc > 2) { + if(! strcmp(argv[2],"dadgad")) { + openStrings[0] = 5; + openStrings[1] = 0; + openStrings[2] = 5; + openStrings[3] = 10; + openStrings[4] = 0; + openStrings[5] = 5; + } + if(! strcmp(argv[2],"openg")) { + openStrings[0] = 5; + openStrings[1] = 10; + openStrings[2] = 5; + openStrings[3] = 10; + openStrings[4] = 2; + openStrings[5] = 5; + + } + if(! strcmp(argv[2],"opene")) { + openStrings[0] = 7; + openStrings[1] = 2; + openStrings[2] = 7; + openStrings[3] = 11; + openStrings[4] = 2; + openStrings[5] = 7; + + } + if(! strcmp(argv[2],"lefty")) { + lefty = 1; + + } + } + + + // Allocate it for DOS/WINDOWS, to avoid stack overflow (weak) + Fretboard *fb = new Fretboard; ; + Chord chord; + + + // findChord upppercases the input string, so save a copy + strcpy(buf2, buf); + + if (chord.findChord(buf)) + { + chord.printError(); + + } + else { + chord.print(buf2); + fb->iterate(chord); + + fb->printStack(); + } + delete fb; + } + return 0; +} + diff --git a/sources/addons/chords/chords.apd b/sources/addons/chords/chords.apd new file mode 100644 index 00000000..2ab5b99d --- /dev/null +++ b/sources/addons/chords/chords.apd @@ -0,0 +1,3 @@ +url: $baseurl/chords +name: Guitar Chords +photo: $baseurl/addon/chords/chords.png diff --git a/sources/addons/chords/chords.php b/sources/addons/chords/chords.php new file mode 100755 index 00000000..93bdbd94 --- /dev/null +++ b/sources/addons/chords/chords.php @@ -0,0 +1,129 @@ + + */ + + +function chords_load() { + register_hook('app_menu', 'addon/chords/chords.php', 'chords_app_menu'); +} + +function chords_unload() { + unregister_hook('app_menu', 'addon/chords/chords.php', 'chords_app_menu'); + +} + +function chords_app_menu($a,&$b) { + $b['app_menu'][] = ''; +} + + +function chords_module() {} + + +function chords_content($a) { + + +$o .= '

Guitar Chords

'; +$o .= 'The complete online guitar chord dictionary
'; +$args = ''; +$l = ''; + +if($_SERVER['REQUEST_METHOD'] == 'POST') { + if(isset($_POST['chord']) && strlen($_POST['chord'])) + $args .= escapeshellarg(ucfirst(trim($_POST['chord']))); + if((strlen($args)) && (isset($_POST['tuning'])) && (strlen($_POST['tuning']))) + $args .= ' '.escapeshellarg($_POST['tuning']); + if((strlen($args)) && (isset($_POST['lefty']))) + $args .= ' lefty'; +} + +if((! strlen($args)) && (! stristr(basename($_SERVER['QUERY_STRING']),'chords')) && strlen(basename($_SERVER['QUERY_STRING']))) + $args = escapeshellarg(ucfirst(basename($_SERVER['QUERY_STRING']))); + +$tunings = array("","openg", "opene", "dadgad"); +$tnames = array("Em11 [Standard] (EADGBE)", + "G/D [Drop D] (DGDGBD)","Open E (EBEG#BE)","Dsus4 (DADGAD)"); +$t = ((isset($_POST['tuning'])) ? $_POST['tuning'] : ''); +if(isset($_POST['lefty']) && $_POST['lefty'] == '1') + $l = 'checked="checked"'; + + $ch = ((isset($_POST['chord'])) ? $_POST['chord'] : ''); +$o .= <<< EOT + +
+Chord name: (ex: Em7) +  Tuning: +Left-Handed: +
+ +
+

+EOT; + +if(strlen($args)) { + $o .= '
';
+  $o .= shell_exec("addon/chords/chord ".$args);
+  $o .=  '
'; +} +else { + +$o .= <<< EOT + +

+This is a fairly comprehensive and complete guitar chord dictionary which will list most of the available ways to play a certain chord, starting from the base of the fingerboard up to a few frets beyond the twelfth fret (beyond which everything repeats). A couple of non-standard tunings are provided for the benefit of slide players, etc. +

+

+Chord names start with a root note (A-G) and may include sharps (#) and flats (b). This software will parse most of the standard naming conventions such as maj, min, dim, sus(2 or 4), aug, with optional repeating elements. +

+

+Valid examples include A, A7, Am7, Amaj7, Amaj9, Ammaj7, Aadd4, Asus2Add4, E7b13b11 ... +

+Quick Reference:
+ +EOT; + +$keys = array('A','Bb','B', 'C','Db','D','Eb','E','F','Gb','G','Ab'); +$o .= ''; +$o .= ""; +foreach($keys as $k) + $o .= ""; +$o .= ""; +foreach($keys as $k) + $o .= ""; +$o .= ""; +foreach($keys as $k) + $o .= ""; +$o .= ""; +$o .= "
$k
{$k}m
{$k}7
"; + +} + +return $o; + +} + + + + + + + + + + diff --git a/sources/addons/chords/chords.png b/sources/addons/chords/chords.png new file mode 100644 index 0000000000000000000000000000000000000000..9427943fc0980ea32facb4454e9d73af31cc5dd0 GIT binary patch literal 11413 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 + */ + + +function custom_home_load() { + register_hook('home_mod_content', 'addon/custom_home/custom_home.php', 'custom_home_home'); + logger("loaded custom_home"); +} + +function custom_home_unload() { + unregister_hook('home_mod_content', 'addon/custom_home/custom_home.php', 'custom_home_home'); + unregister_hook('home_content', 'addon/custom_home/custom_home.php', 'custom_home_home'); + logger("removed custom_home"); +} + +function custom_home_home(&$a, &$o){ + + $x = get_config('system','custom_home'); + if($x) { + if ($x == "random") { + $rand = db_getfunc('rand'); + $r = q("select channel_address from channel where channel_r_stream = 1 and channel_address != 'sys' order by $rand limit 1"); + $x = z_root() . '/channel/' . $r[0]['channel_address']; + } + else { + $x = z_root() . '/' . $x; + } + + goaway(zid($x)); + } + +//If nothing is set + return $o; +} + diff --git a/sources/addons/dfedfix/dfedfix.php b/sources/addons/dfedfix/dfedfix.php new file mode 100644 index 00000000..af7b3837 --- /dev/null +++ b/sources/addons/dfedfix/dfedfix.php @@ -0,0 +1,30 @@ +',' +' . z_root() . '/channel/' . $b['user']['channel_address'] . '',$x); + $x = str_replace('.AQAB" />','.AQAB "/> +',$x); + $b['xml'] = $x; + +} + \ No newline at end of file diff --git a/sources/addons/diaspora/diaspora.php b/sources/addons/diaspora/diaspora.php new file mode 100755 index 00000000..b2e21013 --- /dev/null +++ b/sources/addons/diaspora/diaspora.php @@ -0,0 +1,3397 @@ +',''), + array('',''), + $msg['message']); + + + $parsed_xml = parse_xml_string($msg['message'],false); + + $xmlbase = $parsed_xml->post; + +// logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DATA); + + + if($xmlbase->request) { + $ret = diaspora_request($importer,$xmlbase->request); + } + elseif($xmlbase->status_message) { + $ret = diaspora_post($importer,$xmlbase->status_message,$msg); + } + elseif($xmlbase->profile) { + $ret = diaspora_profile($importer,$xmlbase->profile,$msg); + } + elseif($xmlbase->comment) { + $ret = diaspora_comment($importer,$xmlbase->comment,$msg); + } + elseif($xmlbase->like) { + $ret = diaspora_like($importer,$xmlbase->like,$msg); + } + elseif($xmlbase->asphoto) { + $ret = diaspora_asphoto($importer,$xmlbase->asphoto,$msg); + } + elseif($xmlbase->reshare) { + $ret = diaspora_reshare($importer,$xmlbase->reshare,$msg); + } + elseif($xmlbase->retraction) { + $ret = diaspora_retraction($importer,$xmlbase->retraction,$msg); + } + elseif($xmlbase->signed_retraction) { + $ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg); + } + elseif($xmlbase->relayable_retraction) { + $ret = diaspora_signed_retraction($importer,$xmlbase->relayable_retraction,$msg); + } + elseif($xmlbase->photo) { + $ret = diaspora_photo($importer,$xmlbase->photo,$msg); + } + elseif($xmlbase->conversation) { + $ret = diaspora_conversation($importer,$xmlbase->conversation,$msg); + } + elseif($xmlbase->message) { + $ret = diaspora_message($importer,$xmlbase->message,$msg); + } + else { + logger('diaspora_dispatch: unknown message type: ' . print_r($xmlbase,true)); + } + return $ret; +} + + +function diaspora_is_blacklisted($s) { + + if(! check_siteallowed($s)) { + logger('blacklisted site: ' . $s); + return true; + } + + return false; +} + +function diaspora_process_outbound(&$a, &$arr) { + +/* + + We are passed the following array from the notifier, providing everything we need to make delivery decisions. + + $arr = array( + 'channel' => $channel, + 'env_recips' => $env_recips, + 'recipients' => $recipients, + 'item' => $item, + 'target_item' => $target_item, + 'hub' => $hub, + 'top_level_post' => $top_level_post, + 'private' => $private, + 'followup' => $followup, + 'relay_to_owner' => $relay_to_owner, + 'uplink' => $uplink, + 'cmd' => $cmd, + 'expire' => $expire, + 'mail' => $mail, + 'location' => $location, + 'fsuggest' => $fsuggest, + 'normal_mode' => $normal_mode, + 'packet_type' => $packet_type, + 'walltowall' => $walltowall, + 'queued' => pass these queued items (outq_hash) back to notifier.php for delivery + ); +*/ + + + // allow this to be set per message + + if(strpos($arr['target_item']['postopts'],'nodspr') !== false) + return; + + $allowed = get_pconfig($arr['channel']['channel_id'],'system','diaspora_allowed'); + + if(! intval($allowed)) { + logger('mod-diaspora: disallowed for channel ' . $arr['channel']['channel_name']); + return; + } + + + if($arr['location']) + return; + + + $target_item = $arr['target_item']; + + if($target_item && array_key_exists('item_obscured',$target_item) && intval($target_item['item_obscured'])) { + $key = get_config('system','prvkey'); + if($target_item['title']) + $target_item['title'] = crypto_unencapsulate(json_decode($target_item['title'],true),$key); + if($target_item['body']) + $target_item['body'] = crypto_unencapsulate(json_decode($target_item['body'],true),$key); + } + + + + if($arr['env_recips']) { + $hashes = array(); + + // re-explode the recipients, but only for this hub/pod + + foreach($arr['env_recips'] as $recip) + $hashes[] = "'" . $recip['hash'] . "'"; + + $r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_url = '%s' + and xchan_hash in (" . implode(',', $hashes) . ") and xchan_network in ('diaspora', 'friendica-over-diaspora') ", + dbesc($arr['hub']['hubloc_url']) + ); + + if(! $r) { + logger('diaspora_process_outbound: no recipients'); + return; + } + + foreach($r as $contact) { + + if($arr['mail']) { + $qi = diaspora_send_mail($arr['item'],$arr['channel'],$contact); + if($qi) + $arr['queued'][] = $qi; + continue; + } + + if(! $arr['normal_mode']) + continue; + + // special handling for followup to public post + // all other public posts processed as public batches further below + + if((! $arr['private']) && ($arr['followup'])) { + $qi = diaspora_send_followup($target_item,$arr['channel'],$contact, true); + if($qi) + $arr['queued'][] = $qi; + continue; + } + + if(! $contact['xchan_pubkey']) + continue; + + if(intval($target_item['item_deleted']) + && (($target_item['mid'] === $target_item['parent_mid']) || $arr['followup'])) { + // send both top-level retractions and relayable retractions for owner to relay + $qi = diaspora_send_retraction($target_item,$arr['channel'],$contact); + if($qi) + $arr['queued'][] = $qi; + continue; + } + elseif($arr['followup']) { + // send comments and likes to owner to relay + $qi = diaspora_send_followup($target_item,$arr['channel'],$contact); + if($qi) + $arr['queued'][] = $qi; + continue; + } + + elseif($target_item['mid'] !== $target_item['parent_mid']) { + // we are the relay - send comments, likes and relayable_retractions + // (of comments and likes) to our conversants + $qi = diaspora_send_relay($target_item,$arr['channel'],$contact); + if($qi) + $arr['queued'][] = $qi; + continue; + } + elseif($arr['top_level_post']) { + $qi = diaspora_send_status($target_item,$arr['channel'],$contact); + if($qi) + $arr['queued'][] = $qi; + continue; + } + } + } + else { + // public message + + $contact = $arr['hub']; + + if(intval($target_item['item_deleted']) + && ($target_item['mid'] === $target_item['parent_mid'])) { + // top-level retraction + logger('delivery: diaspora retract: ' . $loc); + $qi = diaspora_send_retraction($target_item,$arr['channel'],$contact,true); + if($qi) + $arr['queued'][] = $qi; + return; + } + elseif($target_item['mid'] !== $target_item['parent_mid']) { + // we are the relay - send comments, likes and relayable_retractions to our conversants + logger('delivery: diaspora relay: ' . $loc); + $qi = diaspora_send_relay($target_item,$arr['channel'],$contact,true); + if($qi) + $arr['queued'][] = $qi; + return; + } + elseif($arr['top_level_post']) { + logger('delivery: diaspora status: ' . $loc); + $qi = diaspora_send_status($target_item,$arr['channel'],$contact,true); + if($qi) + $arr['queued'][] = $qi; + return; + } + + } + + +} + + +function diaspora_handle_from_contact($contact_hash) { + + logger("diaspora_handle_from_contact: contact id is " . $contact_hash, LOGGER_DEBUG); + + $r = q("SELECT xchan_addr from xchan where xchan_hash = '%s' limit 1", + dbesc($contact_hash) + ); + if($r) { + return $r[0]['xchan_addr']; + } + return false; +} + +function diaspora_get_contact_by_handle($uid,$handle) { + + if(diaspora_is_blacklisted($handle)) + return false; + require_once('include/identity.php'); + + $sys = get_sys_channel(); + if(($sys) && ($sys['channel_id'] == $uid)) { + $r = q("SELECT * FROM xchan where xchan_addr = '%s' limit 1", + dbesc($handle) + ); + } + else { + $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where xchan_addr = '%s' and abook_channel = %d limit 1", + dbesc($handle), + intval($uid) + ); + } + + return (($r) ? $r[0] : false); +} + +function find_diaspora_person_by_handle($handle) { + + $person = false; + $refresh = false; + + if(diaspora_is_blacklisted($handle)) + return false; + + $r = q("select * from xchan where xchan_addr = '%s' limit 1", + dbesc($handle) + ); + if($r) { + $person = $r[0]; + logger('find_diaspora_person_by handle: in cache ' . print_r($r,true), LOGGER_DATA); + if($person['xchan_name_date'] < datetime_convert('UTC','UTC', 'now - 1 month')) { + logger('Updating Diaspora cached record for ' . $handle); + $refresh = true; + } + } + + if((! $person) || ($refresh)) { + + // try webfinger. Make sure to distinguish between diaspora, + // hubzilla w/diaspora protocol and friendica w/diaspora protocol. + + $result = discover_by_webbie($handle); + if($result) { + $r = q("select * from xchan where xchan_addr = '%s' limit 1", + dbesc(str_replace('acct:','',$handle)) + ); + if($r) { + $person = $r[0]; + logger('find_diaspora_person_by handle: discovered ' . print_r($r,true), LOGGER_DATA); + } + } + } + + return $person; +} + + +function get_diaspora_key($handle) { + logger('Fetching diaspora key for: ' . $handle, LOGGER_DEBUG); + $r = find_diaspora_person_by_handle($handle); + return(($r) ? $r['xchan_pubkey'] : ''); +} + + +function diaspora_pubmsg_build($msg,$channel,$contact,$prvkey,$pubkey) { + + $a = get_app(); + + logger('diaspora_pubmsg_build: ' . $msg, LOGGER_DATA); + + $handle = $channel['channel_address'] . '@' . get_app()->get_hostname(); + + + $b64url_data = base64url_encode($msg,false); + + $data = str_replace(array("\n","\r"," ","\t"),array('','','',''),$b64url_data); + + $type = 'application/xml'; + $encoding = 'base64url'; + $alg = 'RSA-SHA256'; + + $signable_data = $data . '.' . base64url_encode($type,false) . '.' + . base64url_encode($encoding,false) . '.' . base64url_encode($alg,false) ; + + $signature = rsa_sign($signable_data,$prvkey); + $sig = base64url_encode($signature,false); + +$magic_env = <<< EOT + + +
+ $handle +
+ + base64url + RSA-SHA256 + $data + $sig + +
+EOT; + + logger('diaspora_pubmsg_build: magic_env: ' . $magic_env, LOGGER_DATA); + return $magic_env; + +} + + + + +function diaspora_msg_build($msg,$channel,$contact,$prvkey,$pubkey,$public = false) { + $a = get_app(); + + if($public) + return diaspora_pubmsg_build($msg,$channel,$contact,$prvkey,$pubkey); + + logger('diaspora_msg_build: ' . $msg, LOGGER_DATA); + + // without a public key nothing will work + + if(! $pubkey) { + logger('diaspora_msg_build: pubkey missing: contact id: ' . $contact['abook_id']); + return ''; + } + + $inner_aes_key = random_string(32); + $b_inner_aes_key = base64_encode($inner_aes_key); + $inner_iv = random_string(16); + $b_inner_iv = base64_encode($inner_iv); + + $outer_aes_key = random_string(32); + $b_outer_aes_key = base64_encode($outer_aes_key); + $outer_iv = random_string(16); + $b_outer_iv = base64_encode($outer_iv); + + $handle = $channel['channel_address'] . '@' . get_app()->get_hostname(); + + $padded_data = pkcs5_pad($msg,16); + $inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv); + + $b64_data = base64_encode($inner_encrypted); + + + $b64url_data = base64url_encode($b64_data,false); + $data = str_replace(array("\n","\r"," ","\t"),array('','','',''),$b64url_data); + + $type = 'application/xml'; + $encoding = 'base64url'; + $alg = 'RSA-SHA256'; + + $signable_data = $data . '.' . base64url_encode($type,false) . '.' + . base64url_encode($encoding,false) . '.' . base64url_encode($alg,false) ; + + logger('diaspora_msg_build: signable_data: ' . $signable_data, LOGGER_DATA); + + $signature = rsa_sign($signable_data,$prvkey); + $sig = base64url_encode($signature,false); + +$decrypted_header = <<< EOT + + $b_inner_iv + $b_inner_aes_key + $handle + +EOT; + + $decrypted_header = pkcs5_pad($decrypted_header,16); + + $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv); + + $outer_json = json_encode(array('iv' => $b_outer_iv,'key' => $b_outer_aes_key)); + + $encrypted_outer_key_bundle = ''; + openssl_public_encrypt($outer_json,$encrypted_outer_key_bundle,$pubkey); + + $b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle); + + logger('outer_bundle: ' . $b64_encrypted_outer_key_bundle . ' key: ' . $pubkey, LOGGER_DATA); + + $encrypted_header_json_object = json_encode(array('aes_key' => base64_encode($encrypted_outer_key_bundle), + 'ciphertext' => base64_encode($ciphertext))); + $cipher_json = base64_encode($encrypted_header_json_object); + + $encrypted_header = '' . $cipher_json . ''; + +$magic_env = <<< EOT + + + $encrypted_header + + base64url + RSA-SHA256 + $data + $sig + + +EOT; + + logger('diaspora_msg_build: magic_env: ' . $magic_env, LOGGER_DATA); + return $magic_env; + +} + +/** + * + * diaspora_decode($importer,$xml) + * array $importer -> from user table + * string $xml -> urldecoded Diaspora salmon + * + * Returns array + * 'message' -> decoded Diaspora XML message + * 'author' -> author diaspora handle + * 'key' -> author public key (converted to pkcs#8) + * + * Author and key are used elsewhere to save a lookup for verifying replies and likes + */ + + +function diaspora_decode($importer,$xml) { + + $public = false; + $basedom = parse_xml_string($xml); + + $children = $basedom->children('https://joindiaspora.com/protocol'); + + if($children->header) { + $public = true; + $author_link = str_replace('acct:','',$children->header->author_id); + } + else { + + $encrypted_header = json_decode(base64_decode($children->encrypted_header)); + + $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key); + $ciphertext = base64_decode($encrypted_header->ciphertext); + + $outer_key_bundle = ''; + openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['channel_prvkey']); + + $j_outer_key_bundle = json_decode($outer_key_bundle); + + $outer_iv = base64_decode($j_outer_key_bundle->iv); + $outer_key = base64_decode($j_outer_key_bundle->key); + + $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv); + + + $decrypted = pkcs5_unpad($decrypted); + + /** + * $decrypted now contains something like + * + * + * 8e+G2+ET8l5BPuW0sVTnQw== + * UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU= + +***** OBSOLETE + + * + * Ryan Hughes + * acct:galaxor@diaspora.pirateship.org + * + +***** CURRENT + + * galaxor@diaspora.priateship.org + +***** END DIFFS + + * + */ + + logger('decrypted: ' . $decrypted, LOGGER_DATA); + $idom = parse_xml_string($decrypted,false); + + $inner_iv = base64_decode($idom->iv); + $inner_aes_key = base64_decode($idom->aes_key); + + $author_link = str_replace('acct:','',$idom->author_id); + + } + + $dom = $basedom->children(NAMESPACE_SALMON_ME); + + // figure out where in the DOM tree our data is hiding + + if($dom->provenance->data) + $base = $dom->provenance; + elseif($dom->env->data) + $base = $dom->env; + elseif($dom->data) + $base = $dom; + + if(! $base) { + logger('mod-diaspora: unable to locate salmon data in xml '); + http_status_exit(400); + } + + + // Stash the signature away for now. We have to find their key or it won't be good for anything. + $signature = base64url_decode($base->sig); + + // unpack the data + + // strip whitespace so our data element will return to one big base64 blob + $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data); + + + // stash away some other stuff for later + + $type = $base->data[0]->attributes()->type[0]; + $keyhash = $base->sig[0]->attributes()->keyhash[0]; + $encoding = $base->encoding; + $alg = $base->alg; + + $signed_data = $data . '.' . base64url_encode($type,false) . '.' . base64url_encode($encoding,false) . '.' . base64url_encode($alg,false); + + + // decode the data + $data = base64url_decode($data); + + + if($public) { + $inner_decrypted = $data; + } + else { + + // Decode the encrypted blob + + $inner_encrypted = base64_decode($data); + $inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv); + $inner_decrypted = pkcs5_unpad($inner_decrypted); + } + + if(! $author_link) { + logger('mod-diaspora: Could not retrieve author URI.'); + http_status_exit(400); + } + + // Once we have the author URI, go to the web and try to find their public key + // (first this will look it up locally if it is in the fcontact cache) + // This will also convert diaspora public key from pkcs#1 to pkcs#8 + + logger('mod-diaspora: Fetching key for ' . $author_link ); + $key = get_diaspora_key($author_link); + + if(! $key) { + logger('mod-diaspora: Could not retrieve author key.'); + http_status_exit(400); + } + + $verify = rsa_verify($signed_data,$signature,$key); + + if(! $verify) { + logger('mod-diaspora: Message did not verify. Discarding.'); + http_status_exit(400); + } + + logger('mod-diaspora: Message verified.'); + + return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key); + +} + + +/* sender is now sharing with recipient */ + +function diaspora_request($importer,$xml) { + + $a = get_app(); + + $sender_handle = unxmlify($xml->sender_handle); + $recipient_handle = unxmlify($xml->recipient_handle); + + if(! $sender_handle || ! $recipient_handle) + return; + + + // Do we already have an abook record? + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$sender_handle); + + if($contact && $contact['abook_id']) { + + // perhaps we were already sharing with this person. Now they're sharing with us. + // That makes us friends. Maybe. + + // Please note some of these permissions such as PERMS_R_PAGES are impossible for Disapora. + // They cannot authenticate to our system. + + $newperms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK|PERMS_W_STREAM|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT|PERMS_R_STORAGE|PERMS_R_PAGES; + + $r = q("update abook set abook_their_perms = %d where abook_id = %d and abook_channel = %d", + intval($newperms), + intval($contact['abook_id']), + intval($importer['channel_id']) + ); + + return; + } + + $ret = find_diaspora_person_by_handle($sender_handle); + + if((! $ret) || (! strstr($ret['xchan_network'],'diaspora'))) { + logger('diaspora_request: Cannot resolve diaspora handle ' . $sender_handle . ' for ' . $recipient_handle); + return; + } + + +//FIXME +/* + if(feature_enabled($channel['channel_id'],'premium_channel')) { + $myaddr = $importer['channel_address'] . '@' . get_app()->get_hostname(); + $cnv = random_string(); + $mid = random_string(); + + $msg = t('You have started sharing with a $Projectname premium channel.'); + $msg .= t('$Projectname premium channels are not available for sharing with Diaspora members. This sharing request has been blocked.') . "\r"; + + $msg .= t('Please do not reply to this message, as this channel is not sharing with you and any reply will not be seen by the recipient.') . "\r"; + + $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); + $signed_text = $mid . ';' . $cnv . ';' . $msg . ';' + . $created . ';' . $myaddr . ';' . $cnv; + + $sig = base64_encode(rsa_sign($signed_text,$importer['channel_prvkey'],'sha256')); + + $conv = array( + 'guid' => xmlify($cnv), + 'subject' => xmlify(t('Sharing request failed.')), + 'created_at' => xmlify($created), + 'diaspora_handle' => xmlify($myaddr), + 'participant_handles' => xmlify($myaddr . ';' . $sender_handle) + ); + + $msg = array( + 'guid' => xmlify($mid), + 'parent_guid' => xmlify($cnv), + 'parent_author_signature' => xmlify($sig), + 'author_signature' => xmlify($sig), + 'text' => xmlify($msg), + 'created_at' => xmlify($created), + 'diaspora_handle' => xmlify($myaddr), + 'conversation_guid' => xmlify($cnv) + ); + + $conv['messages'] = array($msg); + $tpl = get_markup_template('diaspora_conversation.tpl'); + $xmsg = replace_macros($tpl, array('$conv' => $conv)); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg,$importer,$ret,$importer['channel_prvkey'],$ret['xchan_pubkey'],false))); + + $qi = diaspora_queue($importer,$ret,$slap,false); + return $qi; + } + +*/ +// End FIXME + + + $role = get_pconfig($channel['channel_id'],'system','permissions_role'); + if($role) { + $x = get_role_perms($role); + if($x['perms_auto']) + $default_perms = $x['perms_accept']; + } + if(! $default_perms) + $default_perms = intval(get_pconfig($importer['channel_id'],'system','autoperms')); + + $their_perms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK|PERMS_W_STREAM|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT|PERMS_R_STORAGE|PERMS_R_PAGES; + + + $closeness = get_pconfig($importer['channel_id'],'system','new_abook_closeness'); + if($closeness === false) + $closeness = 80; + + + $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_my_perms, abook_their_perms, abook_closeness, abook_created, abook_updated, abook_connected, abook_dob, abook_pending) values ( %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', %d )", + intval($importer['channel_account_id']), + intval($importer['channel_id']), + dbesc($ret['xchan_hash']), + intval($default_perms), + intval($their_perms), + intval($closeness), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(NULL_DATE), + intval(($default_perms) ? 0 : 1) + ); + + + if($r) { + logger("New Diaspora introduction received for {$importer['channel_name']}"); + + $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash left join hubloc on hubloc_hash = xchan_hash where abook_channel = %d and abook_xchan = '%s' order by abook_created desc limit 1", + intval($importer['channel_id']), + dbesc($ret['xchan_hash']) + ); + if($new_connection) { + require_once('include/enotify.php'); + notification(array( + 'type' => NOTIFY_INTRO, + 'from_xchan' => $ret['xchan_hash'], + 'to_xchan' => $importer['channel_hash'], + 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'], + )); + + + if($default_perms) { + // Send back a sharing notification to them + $x = diaspora_share($importer,$new_connection[0]); + if($x) + proc_run('php','include/deliver.php',$x); + + } + + $clone = array(); + foreach($new_connection[0] as $k => $v) { + if(strpos($k,'abook_') === 0) { + $clone[$k] = $v; + } + } + unset($clone['abook_id']); + unset($clone['abook_account']); + unset($clone['abook_channel']); + + build_sync_packet($importer['channel_id'], array('abook' => array($clone))); + + } + } + + // find the abook record we just created + + $contact_record = diaspora_get_contact_by_handle($importer['channel_id'],$sender_handle); + + if(! $contact_record) { + logger('diaspora_request: unable to locate newly created contact record.'); + return; + } + + /** If there is a default group for this channel, add this member to it */ + + if($importer['channel_default_group']) { + require_once('include/group.php'); + $g = group_rec_byhash($importer['channel_id'],$importer['channel_default_group']); + if($g) + group_add_member($importer['channel_id'],'',$contact_record['xchan_hash'],$g['id']); + } + + return; +} + + + +function diaspora_post($importer,$xml,$msg) { + + $a = get_app(); + $guid = notags(unxmlify($xml->guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $app = notags(xmlify($xml->provider_display_name)); + + + if($diaspora_handle != $msg['author']) { + logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); + return 202; + } + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$diaspora_handle); + if(! $contact) + return; + + + + if(! $app) { + if(strstr($contact['xchan_network'],'friendica')) + $app = 'Friendica'; + else + $app = 'Diaspora'; + } + + + $search_guid = ((strlen($guid) == 64) ? $guid . '%' : $guid); + + $r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($search_guid) + ); + + if($r) { + // check dates if post editing is implemented + logger('diaspora_post: message exists: ' . $guid); + return; + } + + $created = unxmlify($xml->created_at); + $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); + + $body = diaspora2bb($xml->raw_message); + + if($xml->photo) { + $body = '[img]' . $xml->photo->remote_photo_path . $xml->photo->remote_photo_name . '[/img]' . "\n\n" . $body; + $body = scale_external_images($body); + } + + $maxlen = get_max_import_size(); + + if($maxlen && mb_strlen($body) > $maxlen) { + $body = mb_substr($body,0,$maxlen,'UTF-8'); + logger('message length exceeds max_import_size: truncated'); + } + +//WTF? FIXME + // Add OEmbed and other information to the body +// $body = add_page_info_to_body($body, false, true); + + $datarray = array(); + + + // Look for tags and linkify them + $results = linkify_tags(get_app(), $body, $importer['channel_id'], true); + + $datarray['term'] = array(); + + if($results) { + foreach($results as $result) { + $success = $result['success']; + if($success['replaced']) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => $success['termtype'], + 'otype' => TERM_OBJ_POST, + 'term' => $success['term'], + 'url' => $success['url'] + ); + } + } + } + + $cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $mtch[2], + 'url' => $mtch[1] + ); + } + } + + $cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + // don't include plustags in the term + $term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]); + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $term, + 'url' => $mtch[1] + ); + } + } + + + + + $plink = service_plink($contact,$guid); + + $datarray['aid'] = $importer['channel_account_id']; + $datarray['uid'] = $importer['channel_id']; + + $datarray['verb'] = ACTIVITY_POST; + $datarray['mid'] = $datarray['parent_mid'] = $guid; + + $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created); + $datarray['item_private'] = $private; + + $datarray['plink'] = $plink; + + $datarray['author_xchan'] = $contact['xchan_hash']; + $datarray['owner_xchan'] = $contact['xchan_hash']; + + $datarray['body'] = $body; + + $datarray['app'] = $app; + + $datarray['item_unseen'] = 1; + $datarray['item_thread_top'] = 1; + + $tgroup = tgroup_check($importer['channel_id'],$datarray); + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $tgroup)) { + logger('diaspora_post: Ignoring this author.'); + return 202; + } + + if($importer['system']) { + $datarray['comment_policy'] = 'network: diaspora'; + } + + if(! post_is_importable($datarray,$contact)) { + logger('diaspora_post: filtering this author.'); + return 202; + } + + $result = item_store($datarray); + return; + +} + + +function get_diaspora_reshare_xml($url,$recurse = 0) { + + $x = z_fetch_url($url); + if(! $x['success']) + $x = z_fetch_url(str_replace('https://','http://',$url)); + if(! $x['success']) { + logger('get_diaspora_reshare_xml: unable to fetch source url ' . $url); + return; + } + logger('get_diaspora_reshare_xml: source: ' . $x['body'], LOGGER_DEBUG); + + $source_xml = parse_xml_string($x['body'],false); + + if(! $source_xml) { + logger('get_diaspora_reshare_xml: unparseable result from ' . $url); + return ''; + } + + if($source_xml->post->status_message) { + return $source_xml; + } + + // see if it's a reshare of a reshare + + if($source_xml->post->reshare) + $xml = $source_xml->post->reshare; + else + return false; + + if($xml->root_diaspora_id && $xml->root_guid && $recurse < 15) { + $orig_author = notags(unxmlify($xml->root_diaspora_id)); + $orig_guid = notags(unxmlify($xml->root_guid)); + $source_url = 'https://' . substr($orig_author,strpos($orig_author,'@')+1) . '/p/' . $orig_guid . '.xml'; + $y = get_diaspora_reshare_xml($source_url,$recurse+1); + if($y) + return $y; + } + return false; +} + + + +function diaspora_reshare($importer,$xml,$msg) { + + logger('diaspora_reshare: init: ' . print_r($xml,true), LOGGER_DATA); + + $a = get_app(); + $guid = notags(unxmlify($xml->guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + + + if($diaspora_handle != $msg['author']) { + logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); + return 202; + } + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$diaspora_handle); + if(! $contact) + return; + + $search_guid = ((strlen($guid) == 64) ? $guid . '%' : $guid); + $r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($search_guid) + ); + if($r) { + logger('diaspora_reshare: message exists: ' . $guid); + return; + } + + $orig_author = notags(unxmlify($xml->root_diaspora_id)); + $orig_guid = notags(unxmlify($xml->root_guid)); + + $source_url = 'https://' . substr($orig_author,strpos($orig_author,'@')+1) . '/p/' . $orig_guid . '.xml'; + $orig_url = 'https://'.substr($orig_author,strpos($orig_author,'@')+1).'/posts/'.$orig_guid; + + $source_xml = get_diaspora_reshare_xml($source_url); + + if($source_xml->post->status_message) { + $body = diaspora2bb($source_xml->post->status_message->raw_message); + + $orig_author = notags(unxmlify($source_xml->post->status_message->diaspora_handle)); + $orig_guid = notags(unxmlify($source_xml->post->status_message->guid)); + + + // Checking for embedded pictures + if($source_xml->post->status_message->photo->remote_photo_path && + $source_xml->post->status_message->photo->remote_photo_name) { + + $remote_photo_path = notags(unxmlify($source_xml->post->status_message->photo->remote_photo_path)); + $remote_photo_name = notags(unxmlify($source_xml->post->status_message->photo->remote_photo_name)); + + $body = '[img]'.$remote_photo_path.$remote_photo_name.'[/img]'."\n".$body; + + logger('diaspora_reshare: embedded picture link found: '.$body, LOGGER_DEBUG); + } + + $body = scale_external_images($body); + + // Add OEmbed and other information to the body +// $body = add_page_info_to_body($body, false, true); + } + else { + // Maybe it is a reshare of a photo that will be delivered at a later time (testing) + logger('diaspora_reshare: no reshare content found: ' . print_r($source_xml,true)); + $body = ""; + //return; + } + + $maxlen = get_max_import_size(); + + if($maxlen && mb_strlen($body) > $maxlen) { + $body = mb_substr($body,0,$maxlen,'UTF-8'); + logger('message length exceeds max_import_size: truncated'); + } + + $person = find_diaspora_person_by_handle($orig_author); + + if($person) { + $orig_author_name = $person['xchan_name']; + $orig_author_link = $person['xchan_url']; + $orig_author_photo = $person['xchan_photo_m']; + } + + + $created = unxmlify($xml->created_at); + $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); + + $datarray = array(); + + // Look for tags and linkify them + $results = linkify_tags(get_app(), $body, $importer['channel_id'], true); + + $datarray['term'] = array(); + + if($results) { + foreach($results as $result) { + $success = $result['success']; + if($success['replaced']) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => $success['termtype'], + 'otype' => TERM_OBJ_POST, + 'term' => $success['term'], + 'url' => $success['url'] + ); + } + } + } + + $cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $mtch[2], + 'url' => $mtch[1] + ); + } + } + + $cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + // don't include plustags in the term + $term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]); + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $term, + 'url' => $mtch[1] + ); + } + } + + + + + + $newbody = "[share author='" . urlencode($orig_author_name) + . "' profile='" . $orig_author_link + . "' avatar='" . $orig_author_photo + . "' link='" . $orig_url + . "' posted='" . datetime_convert('UTC','UTC',unxmlify($source_xml->post->status_message->created_at)) + . "' message_id='" . unxmlify($source_xml->post->status_message->guid) + . "']" . $body . "[/share]"; + + + $plink = service_plink($contact,$guid); + $datarray['aid'] = $importer['channel_account_id']; + $datarray['uid'] = $importer['channel_id']; + $datarray['mid'] = $datarray['parent_mid'] = $guid; + $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created); + $datarray['item_private'] = $private; + $datarray['plink'] = $plink; + $datarray['owner_xchan'] = $contact['xchan_hash']; + $datarray['author_xchan'] = $contact['xchan_hash']; + + $datarray['body'] = $newbody; + $datarray['app'] = 'Diaspora'; + + + $tgroup = tgroup_check($importer['channel_id'],$datarray); + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $tgroup)) { + logger('diaspora_reshare: Ignoring this author.'); + return 202; + } + + if(! post_is_importable($datarray,$contact)) { + logger('diaspora_reshare: filtering this author.'); + return 202; + } + + $result = item_store($datarray); + + return; + +} + + +function diaspora_asphoto($importer,$xml,$msg) { + logger('diaspora_asphoto called'); + + $a = get_app(); + $guid = notags(unxmlify($xml->guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + + if($diaspora_handle != $msg['author']) { + logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); + return 202; + } + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$diaspora_handle); + if(! $contact) + return; + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream'))) { + logger('diaspora_asphoto: Ignoring this author.'); + return 202; + } + + $message_id = $diaspora_handle . ':' . $guid; + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($message_id), + dbesc($guid) + ); + if(count($r)) { + logger('diaspora_asphoto: message exists: ' . $guid); + return; + } + + // allocate a guid on our system - we aren't fixing any collisions. + // we're ignoring them + + $g = q("select * from guid where guid = '%s' limit 1", + dbesc($guid) + ); + if(! count($g)) { + q("insert into guid ( guid ) values ( '%s' )", + dbesc($guid) + ); + } + + $created = unxmlify($xml->created_at); + $private = ((unxmlify($xml->public) == 'false') ? 1 : 0); + + if(strlen($xml->objectId) && ($xml->objectId != 0) && ($xml->image_url)) { + $body = '[url=' . notags(unxmlify($xml->image_url)) . '][img]' . notags(unxmlify($xml->objectId)) . '[/img][/url]' . "\n"; + $body = scale_external_images($body,false); + } + elseif($xml->image_url) { + $body = '[img]' . notags(unxmlify($xml->image_url)) . '[/img]' . "\n"; + $body = scale_external_images($body); + } + else { + logger('diaspora_asphoto: no photo url found.'); + return; + } + + $plink = service_plink($contact,$guid); + + $datarray = array(); + + $datarray['uid'] = $importer['channel_id']; + $datarray['contact-id'] = $contact['id']; + $datarray['wall'] = 0; + $datarray['network'] = NETWORK_DIASPORA; + $datarray['guid'] = $guid; + $datarray['uri'] = $datarray['parent-uri'] = $message_id; + $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created); + $datarray['private'] = $private; + $datarray['parent'] = 0; + $datarray['plink'] = $plink; + $datarray['owner-name'] = $contact['name']; + $datarray['owner-link'] = $contact['url']; + //$datarray['owner-avatar'] = $contact['thumb']; + $datarray['owner-avatar'] = ((x($contact,'thumb')) ? $contact['thumb'] : $contact['photo']); + $datarray['author-name'] = $contact['name']; + $datarray['author-link'] = $contact['url']; + $datarray['author-avatar'] = $contact['thumb']; + $datarray['body'] = $body; + + $datarray['app'] = 'Diaspora/Cubbi.es'; + + $message_id = item_store($datarray); + + //if($message_id) { + // q("update item set plink = '%s' where id = %d", + // dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id), + // intval($message_id) + // ); + //} + + return; + +} + + + + + + +function diaspora_comment($importer,$xml,$msg) { + + $a = get_app(); + $guid = notags(unxmlify($xml->guid)); + $parent_guid = notags(unxmlify($xml->parent_guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $target_type = notags(unxmlify($xml->target_type)); + $text = unxmlify($xml->text); + $author_signature = notags(unxmlify($xml->author_signature)); + + $parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : ''); + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$msg['author']); + if(! $contact) { + logger('diaspora_comment: cannot find contact: ' . $msg['author']); + return; + } + + + + $pubcomment = get_pconfig($importer['channel_id'],'system','diaspora_public_comments'); + + // by default comments on public posts are allowed from anybody on Diaspora. That is their policy. + // Once this setting is set to something we'll track your preference and it will over-ride the default. + + if($pubcomment === false) + $pubcomment = 1; + + // Friendica is currently truncating guids at 64 chars + $search_guid = $parent_guid; + if(strlen($parent_guid) == 64) + $search_guid = $parent_guid . '%'; + + $r = q("SELECT * FROM item WHERE uid = %d AND mid LIKE '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($search_guid) + ); + if(! $r) { + logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid); + return; + } + + $parent_item = $r[0]; + + if(intval($parent_item['item_private'])) + $pubcomment = 0; + + $search_guid = $guid; + if(strlen($guid) == 64) + $search_guid = $guid . '%'; + + + $r = q("SELECT * FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($search_guid) + ); + if($r) { + logger('diaspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid); + return; + } + + + + /* How Diaspora performs comment signature checking: + + - If an item has been sent by the comment author to the top-level post owner to relay on + to the rest of the contacts on the top-level post, the top-level post owner should check + the author_signature, then create a parent_author_signature before relaying the comment on + - If an item has been relayed on by the top-level post owner, the contacts who receive it + check only the parent_author_signature. Basically, they trust that the top-level post + owner has already verified the authenticity of anything he/she sends out + - In either case, the signature that get checked is the signature created by the person + who sent the psuedo-salmon + */ + + $signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $diaspora_handle; + $key = $msg['key']; + + if($parent_author_signature) { + // If a parent_author_signature exists, then we've received the comment + // relayed from the top-level post owner. There's no need to check the + // author_signature if the parent_author_signature is valid + + $parent_author_signature = base64_decode($parent_author_signature); + + if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) { + logger('diaspora_comment: top-level owner verification failed.'); + return; + } + } + else { + // If there's no parent_author_signature, then we've received the comment + // from the comment creator. In that case, the person is commenting on + // our post, so he/she must be a contact of ours and his/her public key + // should be in $msg['key'] + + if($importer['system']) { + // don't relay to the sys channel + logger('diaspora_comment: relay to sys channel blocked.'); + return; + } + + $author_signature = base64_decode($author_signature); + + if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) { + logger('diaspora_comment: comment author verification failed.'); + return; + } + } + + // Phew! Everything checks out. Now create an item. + + // Find the original comment author information. + // We need this to make sure we display the comment author + // information (name and avatar) correctly. + + if(strcasecmp($diaspora_handle,$msg['author']) == 0) + $person = $contact; + else { + $person = find_diaspora_person_by_handle($diaspora_handle); + + if(! is_array($person)) { + logger('diaspora_comment: unable to find author details'); + return; + } + } + + + $body = diaspora2bb($text); + + + $maxlen = get_max_import_size(); + + if($maxlen && mb_strlen($body) > $maxlen) { + $body = mb_substr($body,0,$maxlen,'UTF-8'); + logger('message length exceeds max_import_size: truncated'); + } + + + $datarray = array(); + + // Look for tags and linkify them + $results = linkify_tags(get_app(), $body, $importer['channel_id'], true); + + $datarray['term'] = array(); + + if($results) { + foreach($results as $result) { + $success = $result['success']; + if($success['replaced']) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => $success['termtype'], + 'otype' => TERM_OBJ_POST, + 'term' => $success['term'], + 'url' => $success['url'] + ); + } + } + } + + $cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $mtch[2], + 'url' => $mtch[1] + ); + } + } + + $cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + // don't include plustags in the term + $term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]); + $datarray['term'][] = array( + 'uid' => $importer['channel_id'], + 'type' => TERM_MENTION, + 'otype' => TERM_OBJ_POST, + 'term' => $term, + 'url' => $mtch[1] + ); + } + } + + $datarray['aid'] = $importer['channel_account_id']; + $datarray['uid'] = $importer['channel_id']; + $datarray['verb'] = ACTIVITY_POST; + $datarray['mid'] = $guid; + $datarray['parent_mid'] = $parent_item['mid']; + + // set the route to that of the parent so downstream hubs won't reject it. + $datarray['route'] = $parent_item['route']; + + // No timestamps for comments? OK, we'll the use current time. + $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert(); + $datarray['item_private'] = $parent_item['item_private']; + + $datarray['owner_xchan'] = $parent_item['owner_xchan']; + $datarray['author_xchan'] = $person['xchan_hash']; + + $datarray['body'] = $body; + + if(strstr($person['xchan_network'],'friendica')) + $app = 'Friendica'; + else + $app = 'Diaspora'; + + $datarray['app'] = $app; + + if(! $parent_author_signature) { + $key = get_config('system','pubkey'); + $x = array('signer' => $diaspora_handle, 'body' => $text, + 'signed_text' => $signed_data, 'signature' => base64_encode($author_signature)); + $datarray['diaspora_meta'] = json_encode($x); + } + + + + // So basically if something arrives at the sys channel it's by definition public and we allow it. + // If $pubcomment and the parent was public, we allow it. + // In all other cases, honour the permissions for this Diaspora connection + + $tgroup = tgroup_check($importer['channel_id'],$datarray); + + if((! $importer['system']) && (! $pubcomment) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments')) && (! $tgroup)) { + logger('diaspora_comment: Ignoring this author.'); + return 202; + } + + + + + $result = item_store($datarray); + + if($result && $result['success']) + $message_id = $result['item_id']; + + if(intval($parent_item['item_origin']) && (! $parent_author_signature)) { + // if the message isn't already being relayed, notify others + // the existence of parent_author_signature means the parent_author or owner + // is already relaying. + + proc_run('php','include/notifier.php','comment-import',$message_id); + } + + if($result['item_id']) { + $r = q("select * from item where id = %d limit 1", + intval($result['item_id']) + ); + if($r) + send_status_notifications($result['item_id'],$r[0]); + } + + return; +} + + + + +function diaspora_conversation($importer,$xml,$msg) { + + $a = get_app(); + + $guid = notags(unxmlify($xml->guid)); + $subject = notags(unxmlify($xml->subject)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $participant_handles = notags(unxmlify($xml->participant_handles)); + $created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at))); + + $parent_uri = $diaspora_handle . ':' . $guid; + + $messages = $xml->message; + + if(! count($messages)) { + logger('diaspora_conversation: empty conversation'); + return; + } + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$msg['author']); + if(! $contact) { + logger('diaspora_conversation: cannot find contact: ' . $msg['author']); + return; + } + + + if(! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_mail')) { + logger('diaspora_conversation: Ignoring this author.'); + return 202; + } + + $conversation = null; + + $c = q("select * from conv where uid = %d and guid = '%s' limit 1", + intval($importer['channel_id']), + dbesc($guid) + ); + if(count($c)) + $conversation = $c[0]; + else { + if($subject) + $nsubject = str_rot47(base64url_encode($subject)); + + $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ", + intval($importer['channel_id']), + dbesc($guid), + dbesc($diaspora_handle), + dbesc(datetime_convert('UTC','UTC',$created_at)), + dbesc(datetime_convert()), + dbesc($nsubject), + dbesc($participant_handles) + ); + if($r) + $c = q("select * from conv where uid = %d and guid = '%s' limit 1", + intval($importer['channel_id']), + dbesc($guid) + ); + if(count($c)) + $conversation = $c[0]; + } + if(! $conversation) { + logger('diaspora_conversation: unable to create conversation.'); + return; + } + + $conversation['subject'] = base64url_decode(str_rot47($conversation['subject'])); + + foreach($messages as $mesg) { + + $reply = 0; + + $msg_guid = notags(unxmlify($mesg->guid)); + $msg_parent_guid = notags(unxmlify($mesg->parent_guid)); + $msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature)); + $msg_author_signature = notags(unxmlify($mesg->author_signature)); + $msg_text = unxmlify($mesg->text); + $msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($mesg->created_at))); + $msg_diaspora_handle = notags(unxmlify($mesg->diaspora_handle)); + $msg_conversation_guid = notags(unxmlify($mesg->conversation_guid)); + if($msg_conversation_guid != $guid) { + logger('diaspora_conversation: message conversation guid does not belong to the current conversation. ' . $xml); + continue; + } + + $body = diaspora2bb($msg_text); + + + $maxlen = get_max_import_size(); + + if($maxlen && mb_strlen($body) > $maxlen) { + $body = mb_substr($body,0,$maxlen,'UTF-8'); + logger('message length exceeds max_import_size: truncated'); + } + + + $author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid; + + $author_signature = base64_decode($msg_author_signature); + + if(strcasecmp($msg_diaspora_handle,$msg['author']) == 0) { + $person = $contact; + $key = $msg['key']; + } + else { + $person = find_diaspora_person_by_handle($msg_diaspora_handle); + + if(is_array($person) && x($person,'xchan_pubkey')) + $key = $person['xchan_pubkey']; + else { + logger('diaspora_conversation: unable to find author details'); + continue; + } + } + + if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) { + logger('diaspora_conversation: verification failed.'); + continue; + } + + if($msg_parent_author_signature) { + $owner_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid; + + $parent_author_signature = base64_decode($msg_parent_author_signature); + + $key = $msg['key']; + + if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) { + logger('diaspora_conversation: owner verification failed.'); + continue; + } + } + + $r = q("select id from mail where mid = '%s' limit 1", + dbesc($message_id) + ); + if(count($r)) { + logger('diaspora_conversation: duplicate message already delivered.', LOGGER_DEBUG); + continue; + } + + if($subject) + $subject = str_rot47(base64url_encode($subject)); + if($body) + $body = str_rot47(base64url_encode($body)); + + q("insert into mail ( `channel_id`, `convid`, `conv_guid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_obscured`,`mid`,`parent_mid`,`created`) values ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s')", + intval($importer['channel_id']), + intval($conversation['id']), + intval($conversation['guid']), + dbesc($person['xchan_hash']), + dbesc($importer['channel_hash']), + dbesc($subject), + dbesc($body), + intval(1), + dbesc($msg_guid), + dbesc($parent_uri), + dbesc($msg_created_at) + ); + + q("update conv set updated = '%s' where id = %d", + dbesc(datetime_convert()), + intval($conversation['id']) + ); + + require_once('include/enotify.php'); +/****** +//FIXME + + notification(array( + 'type' => NOTIFY_MAIL, + 'notify_flags' => $importer['notify-flags'], + 'language' => $importer['language'], + 'to_name' => $importer['username'], + 'to_email' => $importer['email'], + 'uid' =>$importer['importer_uid'], + 'item' => array('subject' => $subject, 'body' => $body), + 'source_name' => $person['name'], + 'source_link' => $person['url'], + 'source_photo' => $person['thumb'], + 'verb' => ACTIVITY_POST, + 'otype' => 'mail' + )); +*******/ + + } + + return; +} + +function diaspora_message($importer,$xml,$msg) { + + $a = get_app(); + + $msg_guid = notags(unxmlify($xml->guid)); + $msg_parent_guid = notags(unxmlify($xml->parent_guid)); + $msg_parent_author_signature = notags(unxmlify($xml->parent_author_signature)); + $msg_author_signature = notags(unxmlify($xml->author_signature)); + $msg_text = unxmlify($xml->text); + $msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at))); + $msg_diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $msg_conversation_guid = notags(unxmlify($xml->conversation_guid)); + + $parent_uri = $msg_parent_guid; + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$msg_diaspora_handle); + if(! $contact) { + logger('diaspora_message: cannot find contact: ' . $msg_diaspora_handle); + return; + } + + if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) { + logger('diaspora_message: Ignoring this author.'); + return 202; + } + + $conversation = null; + + $c = q("select * from conv where uid = %d and guid = '%s' limit 1", + intval($importer['channel_id']), + dbesc($msg_conversation_guid) + ); + if($c) + $conversation = $c[0]; + else { + logger('diaspora_message: conversation not available.'); + return; + } + + $reply = 0; + + $subject = $conversation['subject']; + $body = diaspora2bb($msg_text); + + + $maxlen = get_max_import_size(); + + if($maxlen && mb_strlen($body) > $maxlen) { + $body = mb_substr($body,0,$maxlen,'UTF-8'); + logger('message length exceeds max_import_size: truncated'); + } + + + + $message_id = $msg_diaspora_handle . ':' . $msg_guid; + + $author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($xml->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid; + + + $author_signature = base64_decode($msg_author_signature); + + $person = find_diaspora_person_by_handle($msg_diaspora_handle); + if(is_array($person) && x($person,'xchan_pubkey')) + $key = $person['xchan_pubkey']; + else { + logger('diaspora_message: unable to find author details'); + return; + } + + if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) { + logger('diaspora_message: verification failed.'); + return; + } + + $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1", + dbesc($message_id), + intval($importer['channel_id']) + ); + if($r) { + logger('diaspora_message: duplicate message already delivered.', LOGGER_DEBUG); + return; + } + + $key = get_config('system','pubkey'); + if($subject) + $subject = str_rot47(base64url_encode($subject)); + if($body) + $body = str_rot47(base64url_encode($body)); + + q("insert into mail ( `channel_id`, `convid`, `conv_guid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_obscured`,`mid`,`parent_mid`,`created`) values ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%d','%s','%s','%s')", + intval($importer['channel_id']), + intval($conversation['id']), + intval($conversation['guid']), + dbesc($person['xchan_hash']), + dbesc($importer['xchan_hash']), + dbesc($subject), + dbesc($body), + intval(1), + dbesc($msg_guid), + dbesc($parent_uri), + dbesc($msg_created_at) + ); + + q("update conv set updated = '%s' where id = %d", + dbesc(datetime_convert()), + intval($conversation['id']) + ); + + return; +} + + +function diaspora_photo($importer,$xml,$msg) { + + $a = get_app(); + + logger('diaspora_photo: init',LOGGER_DEBUG); + + $remote_photo_path = notags(unxmlify($xml->remote_photo_path)); + + $remote_photo_name = notags(unxmlify($xml->remote_photo_name)); + + $status_message_guid = notags(unxmlify($xml->status_message_guid)); + + $guid = notags(unxmlify($xml->guid)); + + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + + $public = notags(unxmlify($xml->public)); + + $created_at = notags(unxmlify($xml_created_at)); + + logger('diaspora_photo: status_message_guid: ' . $status_message_guid, LOGGER_DEBUG); + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$msg['author']); + if(! $contact) { + logger('diaspora_photo: contact record not found: ' . $msg['author'] . ' handle: ' . $diaspora_handle); + return; + } + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream'))) { + logger('diaspora_photo: Ignoring this author.'); + return 202; + } + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `mid` = '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($status_message_guid) + ); + if(! $r) { + logger('diaspora_photo: attempt = ' . $attempt . '; status message not found: ' . $status_message_guid . ' for photo: ' . $guid); + return; + } + +// $parent_item = $r[0]; + +// $link_text = '[img]' . $remote_photo_path . $remote_photo_name . '[/img]' . "\n"; + +// $link_text = scale_external_images($link_text, true, +// array($remote_photo_name, 'scaled_full_' . $remote_photo_name)); + +// if(strpos($parent_item['body'],$link_text) === false) { +// $r = q("update item set `body` = '%s', `visible` = 1 where `id` = %d and `uid` = %d", +// dbesc($link_text . $parent_item['body']), +// intval($parent_item['id']), +// intval($parent_item['uid']) +// ); +// } + + return; +} + + + + +function diaspora_like($importer,$xml,$msg) { + + $a = get_app(); + $guid = notags(unxmlify($xml->guid)); + $parent_guid = notags(unxmlify($xml->parent_guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $target_type = notags(unxmlify($xml->target_type)); + $positive = notags(unxmlify($xml->positive)); + $author_signature = notags(unxmlify($xml->author_signature)); + + $parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : ''); + + // likes on comments not supported here and likes on photos not supported by Diaspora + +// if($target_type !== 'Post') +// return; + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$msg['author']); + if(! $contact) { + logger('diaspora_like: cannot find contact: ' . $msg['author'] . ' for channel ' . $importer['channel_name']); + return; + } + + + if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments'))) { + logger('diaspora_like: Ignoring this author.'); + return 202; + } + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `mid` = '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($parent_guid) + ); + if(! count($r)) { + logger('diaspora_like: parent item not found: ' . $guid); + return; + } + + $parent_item = $r[0]; + + $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `mid` = '%s' LIMIT 1", + intval($importer['channel_id']), + dbesc($guid) + ); + if(count($r)) { + if($positive === 'true') { + logger('diaspora_like: duplicate like: ' . $guid); + return; + } + // Note: I don't think "Like" objects with positive = "false" are ever actually used + // It looks like "RelayableRetractions" are used for "unlike" instead + if($positive === 'false') { + logger('diaspora_like: received a like with positive set to "false"...ignoring'); + // perhaps call drop_item() + // FIXME--actually don't unless it turns out that Diaspora does indeed send out "false" likes + // send notification via proc_run() + return; + } + } + + $i = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($parent_item['author_xchan']) + ); + if($i) + $item_author = $i[0]; + + // Note: I don't think "Like" objects with positive = "false" are ever actually used + // It looks like "RelayableRetractions" are used for "unlike" instead + if($positive === 'false') { + logger('diaspora_like: received a like with positive set to "false"'); + logger('diaspora_like: unlike received with no corresponding like...ignoring'); + return; + } + + + /* How Diaspora performs "like" signature checking: + + - If an item has been sent by the like author to the top-level post owner to relay on + to the rest of the contacts on the top-level post, the top-level post owner should check + the author_signature, then create a parent_author_signature before relaying the like on + - If an item has been relayed on by the top-level post owner, the contacts who receive it + check only the parent_author_signature. Basically, they trust that the top-level post + owner has already verified the authenticity of anything he/she sends out + - In either case, the signature that get checked is the signature created by the person + who sent the salmon + */ + + // 2014-09-10 let's try this: signatures are failing. I'll try and make a signable string from + // the parameters in the order they were presented in the post. This is how D* creates the signable string. + + + $signed_data = $positive . ';' . $guid . ';' . $target_type . ';' . $parent_guid . ';' . $diaspora_handle; + + $key = $msg['key']; + + if($parent_author_signature) { + // If a parent_author_signature exists, then we've received the like + // relayed from the top-level post owner. There's no need to check the + // author_signature if the parent_author_signature is valid + + $parent_author_signature = base64_decode($parent_author_signature); + + if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) { + if (intval(get_config('system','ignore_diaspora_like_signature'))) + logger('diaspora_like: top-level owner verification failed. Proceeding anyway.'); + else { + logger('diaspora_like: top-level owner verification failed.'); + return; + } + } + } + else { + // If there's no parent_author_signature, then we've received the like + // from the like creator. In that case, the person is "like"ing + // our post, so he/she must be a contact of ours and his/her public key + // should be in $msg['key'] + + $author_signature = base64_decode($author_signature); + + if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) { + if (intval(get_config('system','ignore_diaspora_like_signature'))) + logger('diaspora_like: like creator verification failed. Proceeding anyway'); + else { + logger('diaspora_like: like creator verification failed.'); + return; + } + } + } + + logger('diaspora_like: signature check complete.',LOGGER_DEBUG); + + // Phew! Everything checks out. Now create an item. + + // Find the original comment author information. + // We need this to make sure we display the comment author + // information (name and avatar) correctly. + if(strcasecmp($diaspora_handle,$msg['author']) == 0) + $person = $contact; + else { + $person = find_diaspora_person_by_handle($diaspora_handle); + + if(! is_array($person)) { + logger('diaspora_like: unable to find author details'); + return; + } + } + + $uri = $diaspora_handle . ':' . $guid; + + $activity = ACTIVITY_LIKE; + + $post_type = (($parent_item['resource_type'] === 'photo') ? t('photo') : t('status')); + + $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $parent_item['plink'])); + $objtype = (($parent_item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE ); + + $body = $parent_item['body']; + + + $object = json_encode(array( + 'type' => $post_type, + 'id' => $parent_item['mid'], + 'parent' => (($parent_item['thr_parent']) ? $parent_item['thr_parent'] : $parent_item['parent_mid']), + 'link' => $links, + 'title' => $parent_item['title'], + 'content' => $parent_item['body'], + 'created' => $parent_item['created'], + 'edited' => $parent_item['edited'], + 'author' => array( + 'name' => $item_author['xchan_name'], + 'address' => $item_author['xchan_addr'], + 'guid' => $item_author['xchan_guid'], + 'guid_sig' => $item_author['xchan_guid_sig'], + 'link' => array( + array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']), + array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])), + ), + )); + + + $bodyverb = t('%1$s likes %2$s\'s %3$s'); + + $arr = array(); + + $arr['uid'] = $importer['channel_id']; + $arr['aid'] = $importer['channel_account_id']; + $arr['mid'] = $guid; + $arr['parent_mid'] = $parent_item['mid']; + $arr['owner_xchan'] = $parent_item['owner_xchan']; + $arr['author_xchan'] = $person['xchan_hash']; + + $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; + $alink = '[url=' . $parent_item['author-link'] . ']' . $parent_item['author-name'] . '[/url]'; + $plink = '[url='. z_root() .'/display/'.$guid.']'.$post_type.'[/url]'; + $arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink ); + + $arr['app'] = 'Diaspora'; + + // set the route to that of the parent so downstream hubs won't reject it. + $arr['route'] = $parent_item['route']; + + $arr['item_private'] = $parent_item['item_private']; + $arr['verb'] = $activity; + $arr['obj_type'] = $objtype; + $arr['object'] = $object; + + if(! $parent_author_signature) { + $key = get_config('system','pubkey'); + $x = array('signer' => $diaspora_handle, 'body' => $text, + 'signed_text' => $signed_data, 'signature' => base64_encode($author_signature)); + $arr['diaspora_meta'] = json_encode($x); + } + + $x = item_store($arr); + + if($x) + $message_id = $x['item_id']; + + // if the message isn't already being relayed, notify others + // the existence of parent_author_signature means the parent_author or owner + // is already relaying. The parent_item['origin'] indicates the message was created on our system + + if(intval($parent_item['item_origin']) && (! $parent_author_signature)) + proc_run('php','include/notifier.php','comment-import',$message_id); + + return; +} + +function diaspora_retraction($importer,$xml) { + + + $guid = notags(unxmlify($xml->guid)); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + $type = notags(unxmlify($xml->type)); + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$diaspora_handle); + if(! $contact) + return; + + if($type === 'Person') { + require_once('include/Contact.php'); + contact_remove($importer['channel_id'],$contact['abook_id']); + } + elseif($type === 'Post') { + $r = q("select * from item where mid = '%s' and uid = %d limit 1", + dbesc('guid'), + intval($importer['channel_id']) + ); + if(count($r)) { + if(link_compare($r[0]['author_xchan'],$contact['xchan_hash'])) { + drop_item($r[0]['id'],false); + } + } + } + + return 202; + // NOTREACHED +} + +function diaspora_signed_retraction($importer,$xml,$msg) { + + + $guid = notags(unxmlify($xml->target_guid)); + $diaspora_handle = notags(unxmlify($xml->sender_handle)); + $type = notags(unxmlify($xml->target_type)); + $sig = notags(unxmlify($xml->target_author_signature)); + + $parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : ''); + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$diaspora_handle); + if(! $contact) { + logger('diaspora_signed_retraction: no contact ' . $diaspora_handle . ' for ' . $importer['channel_id']); + return; + } + + + $signed_data = $guid . ';' . $type ; + $key = $msg['key']; + + /* How Diaspora performs relayable_retraction signature checking: + + - If an item has been sent by the item author to the top-level post owner to relay on + to the rest of the contacts on the top-level post, the top-level post owner checks + the author_signature, then creates a parent_author_signature before relaying the item on + - If an item has been relayed on by the top-level post owner, the contacts who receive it + check only the parent_author_signature. Basically, they trust that the top-level post + owner has already verified the authenticity of anything he/she sends out + - In either case, the signature that get checked is the signature created by the person + who sent the salmon + */ + + if($parent_author_signature) { + + $parent_author_signature = base64_decode($parent_author_signature); + + if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) { + logger('diaspora_signed_retraction: top-level post owner verification failed'); + return; + } + + } + else { + + $sig_decode = base64_decode($sig); + + if(! rsa_verify($signed_data,$sig_decode,$key,'sha256')) { + logger('diaspora_signed_retraction: retraction owner verification failed.' . print_r($msg,true)); + return; + } + } + + if($type === 'StatusMessage' || $type === 'Comment' || $type === 'Like') { + $r = q("select * from item where mid = '%s' and uid = %d limit 1", + dbesc($guid), + intval($importer['channel_id']) + ); + if($r) { + if($r[0]['author_xchan'] == $contact['xchan_hash']) { + + drop_item($r[0]['id'],false, DROPITEM_PHASE1); + + // Now check if the retraction needs to be relayed by us + // + // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always + // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent. + // The only item with `parent` and `id` as the parent id is the parent item. + $p = q("select item_flags from item where parent = %d and id = %d limit 1", + $r[0]['parent'], + $r[0]['parent'] + ); + if($p) { + if(intval($p[0]['item_origin']) && (! $parent_author_signature)) { + + // the existence of parent_author_signature would have meant the parent_author or owner + // is already relaying. + + logger('diaspora_signed_retraction: relaying relayable_retraction'); + proc_run('php','include/notifier.php','drop',$r[0]['id']); + } + } + } + } + } + else + logger('diaspora_signed_retraction: unknown type: ' . $type); + + return 202; + // NOTREACHED +} + +function diaspora_profile($importer,$xml,$msg) { + + $a = get_app(); + $diaspora_handle = notags(unxmlify($xml->diaspora_handle)); + + + if($diaspora_handle != $msg['author']) { + logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); + return 202; + } + + $contact = diaspora_get_contact_by_handle($importer['channel_id'],$diaspora_handle); + if(! $contact) + return; + + if($contact['blocked']) { + logger('diaspora_post: Ignoring this author.'); + return 202; + } + + $name = unxmlify($xml->first_name) . ((strlen($xml->last_name)) ? ' ' . unxmlify($xml->last_name) : ''); + $image_url = unxmlify($xml->image_url); + $birthday = unxmlify($xml->birthday); + + + $handle_parts = explode("@", $diaspora_handle); + if($name === '') { + $name = $handle_parts[0]; + } + + if( preg_match("|^https?://|", $image_url) === 0) { + $image_url = "http://" . $handle_parts[1] . $image_url; + } + + require_once('include/photo/photo_driver.php'); + + $images = import_xchan_photo($image_url,$contact['xchan_hash']); + + // Generic birthday. We don't know the timezone. The year is irrelevant. + + $birthday = str_replace('1000','1901',$birthday); + + $birthday = datetime_convert('UTC','UTC',$birthday,'Y-m-d'); + + // this is to prevent multiple birthday notifications in a single year + // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year + + if(substr($birthday,5) === substr($contact['bd'],5)) + $birthday = $contact['bd']; + + $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' ", + dbesc($name), + dbesc(datetime_convert()), + dbesc($images[0]), + dbesc($images[1]), + dbesc($images[2]), + dbesc($images[3]), + dbesc(datetime_convert()), + intval($contact['xchan_hash']) + ); + + return; + +} + +function diaspora_share($owner,$contact) { + $a = get_app(); + + $allowed = get_pconfig($owner['channel_id'],'system','diaspora_allowed'); + if($allowed === false) + $allowed = 1; + + if(! intval($allowed)) { + logger('diaspora_share: disallowed for channel ' . $importer['channel_name']); + return; + } + + + + $myaddr = $owner['channel_address'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + + if(! array_key_exists('xchan_hash',$contact)) { + $c = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where xchan_hash = '%s' limit 1", + dbesc($contact['hubloc_hash']) + ); + if(! $c) { + logger('diaspora_share: ' . $contact['hubloc_hash'] . ' not found.'); + return; + } + $contact = $c[0]; + } + + $theiraddr = $contact['xchan_addr']; + + $tpl = get_markup_template('diaspora_share.tpl'); + $msg = replace_macros($tpl, array( + '$sender' => $myaddr, + '$recipient' => $theiraddr + )); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey']))); + return(diaspora_queue($owner,$contact,$slap, false)); +} + +function diaspora_unshare($owner,$contact) { + + $a = get_app(); + $myaddr = $owner['channel_address'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + + $tpl = get_markup_template('diaspora_retract.tpl'); + $msg = replace_macros($tpl, array( + '$guid' => $owner['channel_guid'] . str_replace('.','',get_app()->get_hostname()), + '$type' => 'Person', + '$handle' => $myaddr + )); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey']))); + + return(diaspora_queue($owner,$contact,$slap, false)); +} + + +function diaspora_send_status($item,$owner,$contact,$public_batch = false) { + + $a = get_app(); + $myaddr = $owner['channel_address'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + + if(intval($item['id']) != intval($item['parent'])) { + logger('attempted to send a comment as a top-level post'); + return; + } + + $images = array(); + + $title = $item['title']; + $body = bb2diaspora_itembody($item,true); + +/* + // We're trying to match Diaspora's split message/photo protocol but + // all the photos are displayed on D* as links and not img's - even + // though we're sending pretty much precisely what they send us when + // doing the same operation. + // Commented out for now, we'll use bb2diaspora to convert photos to markdown + // which seems to get through intact. + + $cnt = preg_match_all('|\[img\](.*?)\[\/img\]|',$body,$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $detail = array(); + $detail['str'] = $mtch[0]; + $detail['path'] = dirname($mtch[1]) . '/'; + $detail['file'] = basename($mtch[1]); + $detail['guid'] = $item['guid']; + $detail['handle'] = $myaddr; + $images[] = $detail; + $body = str_replace($detail['str'],$mtch[1],$body); + } + } +*/ + + if(intval($item['item_consensus'])) { + $poll = replace_macros(get_markup_template('diaspora_consensus.tpl'), array( + '$guid_q' => '10000000', + '$question' => t('Please choose'), + '$guid_y' => '00000001', + '$agree' => t('Agree'), + '$guid_n' => '0000000F', + '$disagree' => t('Disagree'), + '$guid_a' => '00000000', + '$abstain' => t('Abstain') + )); + } + elseif($item['resource_type'] === 'event' && $item['resource_id']) { + $poll = replace_macros(get_markup_template('diaspora_consensus.tpl'), array( + '$guid_q' => '1000000', + '$question' => t('Please choose'), + '$guid_y' => '0000001', + '$agree' => t('I will attend'), + '$guid_n' => '000000F', + '$disagree' => t('I will not attend'), + '$guid_a' => '0000000', + '$abstain' => t('I may attend') + )); + } + else + $poll = ''; + + $public = (($item['item_private']) ? 'false' : 'true'); + + require_once('include/datetime.php'); + $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); + + // Detect a share element and do a reshare + // see: https://github.com/Raven24/diaspora-federation/blob/master/lib/diaspora-federation/entities/reshare.rb + if (!$item['item_private'] AND ($ret = diaspora_is_reshare($item["body"]))) { + $tpl = get_markup_template('diaspora_reshare.tpl'); + $msg = replace_macros($tpl, array( + '$root_handle' => xmlify($ret['root_handle']), + '$root_guid' => $ret['root_guid'], + '$guid' => $item['mid'], + '$handle' => xmlify($myaddr), + '$public' => $public, + '$created' => $created, + '$provider' => (($item['app']) ? $item['app'] : t('$projectname')) + )); + } else { + $tpl = get_markup_template('diaspora_post.tpl'); + $msg = replace_macros($tpl, array( + '$body' => xmlify($body), + '$guid' => $item['mid'], + '$poll' => $poll, + '$handle' => xmlify($myaddr), + '$public' => $public, + '$created' => $created, + '$provider' => (($item['app']) ? $item['app'] : t('$projectname')) + )); + } + + logger('diaspora_send_status: '.$owner['channel_name'].' -> '.$contact['xchan_name'].' base message: ' . $msg, LOGGER_DATA); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey'],$public_batch))); + + $qi = diaspora_queue($owner,$contact,$slap,$public_batch,$item['mid']); + +// logger('diaspora_send_status: guid: '.$item['mid'].' result '.$return_code, LOGGER_DEBUG); + + if(count($images)) { + diaspora_send_images($item,$owner,$contact,$images,$public_batch,$item['mid']); + } + + return $qi; +} + +function diaspora_is_reshare($body) { + + $body = trim($body); + + // Skip if it isn't a pure repeated messages + // Does it start with a share? + if(strpos($body, "[share") > 0) + return(false); + + // Does it end with a share? + if(strlen($body) > (strrpos($body, "[/share]") + 8)) + return(false); + + $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body); + // Skip if there is no shared message in there + if ($body == $attributes) + return(false); + + $profile = ""; + preg_match("/profile='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + preg_match('/profile="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + $ret= array(); + + $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); + if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == "")) + return(false); + + $link = ""; + preg_match("/link='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + preg_match('/link="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); + if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == "")) + return(false); + + return($ret); +} + +function diaspora_send_images($item,$owner,$contact,$images,$public_batch = false) { + $a = get_app(); + if(! count($images)) + return; + $mysite = substr($a->get_baseurl(),strpos($a->get_baseurl(),'://') + 3) . '/photo'; + + $tpl = get_markup_template('diaspora_photo.tpl'); + foreach($images as $image) { + if(! stristr($image['path'],$mysite)) + continue; + $resource = str_replace('.jpg','',$image['file']); + $resource = substr($resource,0,strpos($resource,'-')); + + $r = q("select * from photo where `resource_id` = '%s' and `uid` = %d limit 1", + dbesc($resource), + intval($owner['uid']) + ); + if(! $r) + continue; + $public = (($r[0]['allow_cid'] || $r[0]['allow_gid'] || $r[0]['deny_cid'] || $r[0]['deny_gid']) ? 'false' : 'true' ); + $msg = replace_macros($tpl,array( + '$path' => xmlify($image['path']), + '$filename' => xmlify($image['file']), + '$msg_guid' => xmlify($image['guid']), + '$guid' => xmlify($r[0]['resource_id']), + '$handle' => xmlify($image['handle']), + '$public' => xmlify($public), + '$created_at' => xmlify(datetime_convert('UTC','UTC',$r[0]['created'],'Y-m-d H:i:s \U\T\C')) + )); + + + logger('diaspora_send_photo: base message: ' . $msg, LOGGER_DATA); + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey'],$public_batch))); + + return(diaspora_queue($owner,$contact,$slap,$public_batch,$item['mid'])); + } + +} + +function diaspora_send_followup($item,$owner,$contact,$public_batch = false) { + + $a = get_app(); + $myaddr = $owner['channel_address'] . '@' . get_app()->get_hostname(); + $theiraddr = $contact['xchan_addr']; + + // Diaspora doesn't support threaded comments, but some + // versions of Diaspora (i.e. Diaspora-pistos) support + // likes on comments + if(($item['verb'] === ACTIVITY_LIKE || $item['verb'] === ACTIVITY_DISLIKE) && $item['thr_parent']) { + $p = q("select mid, parent_mid from item where mid = '%s' limit 1", + dbesc($item['thr_parent']) + ); + } + else { + // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always + // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent. + // The only item with `parent` and `id` as the parent id is the parent item. + $p = q("select * from item where parent = %d and id = %d limit 1", + intval($item['parent']), + intval($item['parent']) + ); + } + if($p) + $parent = $p[0]; + else + return; + + + if(($item['verb'] === ACTIVITY_LIKE) && ($parent['mid'] === $parent['parent_mid'])) { + $tpl = get_markup_template('diaspora_like.tpl'); + $like = true; + $target_type = 'Post'; + $positive = 'true'; + + if(intval($item['item_deleted'])) + logger('diaspora_send_followup: received deleted "like". Those should go to diaspora_send_retraction'); + } + else { + $tpl = get_markup_template('diaspora_comment.tpl'); + $like = false; + } + + if($item['diaspora_meta'] && ! $like) { + $diaspora_meta = json_decode($item['diaspora_meta'],true); + if($diaspora_meta) { + if(array_key_exists('iv',$diaspora_meta)) { + $key = get_config('system','prvkey'); + $meta = json_decode(crypto_unencapsulate($diaspora_meta,$key),true); + } + else + $meta = $diaspora_meta; + } + $signed_text = $meta['signed_text']; + $authorsig = $meta['signature']; + $signer = $meta['signer']; + $text = $meta['body']; + } + else { + $text = bb2diaspora_itembody($item); + + // sign it + + if($like) + $signed_text = $item['mid'] . ';' . $target_type . ';' . $parent['mid'] . ';' . $positive . ';' . $myaddr; + else + $signed_text = $item['mid'] . ';' . $parent['mid'] . ';' . $text . ';' . $myaddr; + + $authorsig = base64_encode(rsa_sign($signed_text,$owner['channel_prvkey'],'sha256')); + + } + + $msg = replace_macros($tpl,array( + '$guid' => xmlify($item['mid']), + '$parent_guid' => xmlify($parent['mid']), + '$target_type' =>xmlify($target_type), + '$authorsig' => xmlify($authorsig), + '$body' => xmlify($text), + '$positive' => xmlify($positive), + '$handle' => xmlify($myaddr) + )); + + logger('diaspora_followup: base message: ' . $msg, LOGGER_DATA); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey'],$public_batch))); + + + return(diaspora_queue($owner,$contact,$slap,$public_batch,$item['mid'])); +} + + +function diaspora_send_relay($item,$owner,$contact,$public_batch = false) { + + + $a = get_app(); + $myaddr = $owner['channel_address'] . '@' . get_app()->get_hostname(); + + $text = bb2diaspora_itembody($item); + + $body = $text; + + // Diaspora doesn't support threaded comments, but some + // versions of Diaspora (i.e. Diaspora-pistos) support + // likes on comments + + // That version is now dead so detect a "sublike" and + // just send it as an activity. + + $sublike = false; + + if($item['verb'] === ACTIVITY_LIKE) { + if(($item['thr_parent']) && ($item['thr_parent'] !== $item['parent_mid'])) { + $sublike = true; + } + } + + // The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always + // return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent. + // The only item with `parent` and `id` as the parent id is the parent item. + + $p = q("select * from item where parent = %d and id = %d limit 1", + intval($item['parent']), + intval($item['parent']) + ); + + + if($p) + $parent = $p[0]; + else { + logger('diaspora_send_relay: no parent'); + return; + } + + $like = false; + $relay_retract = false; + $sql_sign_id = 'iid'; + + if( intval($item['item_deleted'])) { + $relay_retract = true; + + $target_type = ( ($item['verb'] === ACTIVITY_LIKE && (! $sublike)) ? 'Like' : 'Comment'); + + $sql_sign_id = 'retract_iid'; + $tpl = get_markup_template('diaspora_relayable_retraction.tpl'); + } + elseif(($item['verb'] === ACTIVITY_LIKE) && (! $sublike)) { + $like = true; + + $target_type = ( $parent['mid'] === $parent['parent_mid'] ? 'Post' : 'Comment'); +// $positive = (intval($item['item_deleted']) ? 'false' : 'true'); + $positive = 'true'; + + $tpl = get_markup_template('diaspora_like_relay.tpl'); + } + else { // item is a comment + $tpl = get_markup_template('diaspora_comment_relay.tpl'); + } + + $diaspora_meta = (($item['diaspora_meta']) ? json_decode($item['diaspora_meta'],true) : ''); + if($diaspora_meta) { + if(array_key_exists('iv',$diaspora_meta)) { + $key = get_config('system','prvkey'); + $meta = json_decode(crypto_unencapsulate($diaspora_meta,$key),true); + } + else + $meta = $diaspora_meta; + $sender_signed_text = $meta['signed_text']; + $authorsig = $meta['signature']; + $handle = $meta['signer']; + $text = $meta['body']; + } + else + logger('diaspora_send_relay: original author signature not found'); + + /* Since the author signature is only checked by the parent, not by the relay recipients, + * I think it may not be necessary for us to do so much work to preserve all the original + * signatures. The important thing that Diaspora DOES need is the original creator's handle. + * Let's just generate that and forget about all the original author signature stuff. + * + * Note: this might be more of an problem if we want to support likes on comments for older + * versions of Diaspora (diaspora-pistos), but since there are a number of problems with + * doing that, let's ignore it for now. + * + * + */ +// bug - nomadic identity may/will affect diaspora_handle_from_contact + if(! $handle) { + if($item['author_xchan'] === $owner['channel_hash']) + $handle = $owner['channel_address'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3); + else + $handle = diaspora_handle_from_contact($item['author_xchan']); + } + if(! $handle) { + logger('diaspora_send_relay: no handle'); + return; + } + + if(! $sender_signed_text) { + if($relay_retract) + $sender_signed_text = $item['mid'] . ';' . $target_type; + elseif($like) + $sender_signed_text = $positive . ';' . $item['mid'] . ';' . $target_type . ';' . $parent['mid'] . ';' . $handle; + else + $sender_signed_text = $item['mid'] . ';' . $parent['mid'] . ';' . $text . ';' . $handle; + } + + // Sign the relayable with the top-level owner's signature + // + // We'll use the $sender_signed_text that we just created, instead of the $signed_text + // stored in the database, because that provides the best chance that Diaspora will + // be able to reconstruct the signed text the same way we did. This is particularly a + // concern for the comment, whose signed text includes the text of the comment. The + // smallest change in the text of the comment, including removing whitespace, will + // make the signature verification fail. Since we translate from BB code to Diaspora's + // markup at the top of this function, which is AFTER we placed the original $signed_text + // in the database, it's hazardous to trust the original $signed_text. + + $parentauthorsig = base64_encode(rsa_sign($sender_signed_text,$owner['channel_prvkey'],'sha256')); + + if(! $text) + logger('diaspora_send_relay: no text'); + + $msg = replace_macros($tpl,array( + '$guid' => xmlify($item['mid']), + '$parent_guid' => xmlify($parent['mid']), + '$target_type' =>xmlify($target_type), + '$authorsig' => xmlify($authorsig), + '$parentsig' => xmlify($parentauthorsig), + '$body' => xmlify($text), + '$positive' => xmlify($positive), + '$handle' => xmlify($handle) + )); + + logger('diaspora_send_relay: base message: ' . $msg, LOGGER_DATA); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey'],$public_batch))); + + return(diaspora_queue($owner,$contact,$slap,$public_batch,$item['mid'])); + +} + + + +function diaspora_send_retraction($item,$owner,$contact,$public_batch = false) { + + $a = get_app(); + $myaddr = $owner['channel_address'] . '@' . get_app()->get_hostname(); + + // Check whether the retraction is for a top-level post or whether it's a relayable + if( $item['mid'] !== $item['parent_mid'] ) { + + $tpl = get_markup_template('diaspora_relay_retraction.tpl'); + $target_type = (($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment'); + } + else { + + $tpl = get_markup_template('diaspora_signed_retract.tpl'); + $target_type = 'StatusMessage'; + } + + $signed_text = $item['mid'] . ';' . $target_type; + + $msg = replace_macros($tpl, array( + '$guid' => xmlify($item['mid']), + '$type' => xmlify($target_type), + '$handle' => xmlify($myaddr), + '$signature' => xmlify(base64_encode(rsa_sign($signed_text,$owner['channel_prvkey'],'sha256'))) + )); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey'],$public_batch))); + + return(diaspora_queue($owner,$contact,$slap,$public_batch,$item['mid'])); +} + +function diaspora_send_mail($item,$owner,$contact) { + + $a = get_app(); + $myaddr = $owner['channel_address'] . '@' . get_app()->get_hostname(); + + $r = q("select * from conv where guid = '%s' and uid = %d limit 1", + intval($item['conv_guid']), + intval($item['channel_id']) + ); + + if(! count($r)) { + logger('diaspora_send_mail: conversation not found.'); + return; + } + $cnv = $r[0]; + $cnv['subject'] = base64url_decode(str_rot47($cnv['subject'])); + + $conv = array( + 'guid' => xmlify($cnv['guid']), + 'subject' => xmlify($cnv['subject']), + 'created_at' => xmlify(datetime_convert('UTC','UTC',$cnv['created'],'Y-m-d H:i:s \U\T\C')), + 'diaspora_handle' => xmlify($cnv['creator']), + 'participant_handles' => xmlify($cnv['recips']) + ); + + if(array_key_exists('mail_obscured',$item) && intval($item['mail_obscured'])) { + if($item['title']) + $item['title'] = base64url_decode(str_rot47($item['title'])); + if($item['body']) + $item['body'] = base64url_decode(str_rot47($item['body'])); + } + + + $body = bb2diaspora($item['body']); + $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); + + $signed_text = $item['mid'] . ';' . $cnv['guid'] . ';' . $body . ';' + . $created . ';' . $myaddr . ';' . $cnv['guid']; + + $sig = base64_encode(rsa_sign($signed_text,$owner['channel_prvkey'],'sha256')); + + $msg = array( + 'guid' => xmlify($item['mid']), + 'parent_guid' => xmlify($cnv['guid']), + 'parent_author_signature' => (($item['reply']) ? null : xmlify($sig)), + 'author_signature' => xmlify($sig), + 'text' => xmlify($body), + 'created_at' => xmlify($created), + 'diaspora_handle' => xmlify($myaddr), + 'conversation_guid' => xmlify($cnv['guid']) + ); + + if($item['reply']) { + $tpl = get_markup_template('diaspora_message.tpl'); + $xmsg = replace_macros($tpl, array('$msg' => $msg)); + } + else { + $conv['messages'] = array($msg); + $tpl = get_markup_template('diaspora_conversation.tpl'); + $xmsg = replace_macros($tpl, array('$conv' => $conv)); + } + + logger('diaspora_conversation: ' . print_r($xmsg,true), LOGGER_DATA); + + $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg,$owner,$contact,$owner['channel_prvkey'],$contact['xchan_pubkey'],false))); + + return(diaspora_queue($owner,$contact,$slap,false,$item['mid'])); + + +} + +function diaspora_queue($owner,$contact,$slap,$public_batch,$message_id = '') { + + + $allowed = get_pconfig($owner['channel_id'],'system','diaspora_allowed'); + if($allowed === false) + $allowed = 1; + + if(! intval($allowed)) { + return false; + } + + if($public_batch) + $dest_url = $contact['hubloc_callback'] . '/public'; + else + $dest_url = $contact['hubloc_callback'] . '/users/' . $contact['hubloc_guid']; + + logger('diaspora_queue: URL: ' . $dest_url, LOGGER_DEBUG); + + if(intval(get_config('system','diaspora_test'))) + return false; + + $a = get_app(); + $logid = random_string(4); + + logger('diaspora_queue: ' . $logid . ' ' . $dest_url, LOGGER_DEBUG); + + $hash = random_string(); + + q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", + dbesc($hash), + intval($owner['account_id']), + intval($owner['channel_id']), + dbesc('post'), + dbesc($dest_url), + intval(1), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc(''), + dbesc($slap) + ); + + if($message_id) { + q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ", + dbesc($message_id), + dbesc($dest_url), + dbesc($dest_url), + dbesc('queued'), + dbesc(datetime_convert()), + dbesc($owner['channel_hash']), + dbesc($hash) + ); + } + + return $hash; + +} + + +function diaspora_follow_allow(&$a, &$b) { + + if($b['xchan']['xchan_network'] !== 'diaspora' && $b['xchan']['xchan_network'] !== 'friendica-over-diaspora') + return; + + $allowed = get_pconfig($b['channel_id'],'system','diaspora_allowed'); + if($allowed === false) + $allowed = 1; + $b['allowed'] = $allowed; + +} + + +function diaspora_discover(&$a,&$b) { + + require_once('include/network.php'); + + $result = array(); + $network = null; + $diaspora = false; + + $diaspora_base = ''; + $diaspora_guid = ''; + $diaspora_key = ''; + $dfrn = false; + + $x = old_webfinger($webbie); + if($x) { + logger('old_webfinger: ' . print_r($x,true)); + foreach($x as $link) { + if($link['@attributes']['rel'] === NAMESPACE_DFRN) + $dfrn = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'salmon') + $notify = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === NAMESPACE_FEED) + $poll = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') + $hcard = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') + $profile = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0') + $poco = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') { + $diaspora_base = unamp($link['@attributes']['href']); + $diaspora = true; + } + if($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') { + $diaspora_guid = unamp($link['@attributes']['href']); + $diaspora = true; + } + if($link['@attributes']['rel'] === 'diaspora-public-key') { + $diaspora_key = base64_decode(unamp($link['@attributes']['href'])); + if(strstr($diaspora_key,'RSA ')) + $pubkey = rsatopem($diaspora_key); + else + $pubkey = $diaspora_key; + $diaspora = true; + } + } + + if($diaspora && $diaspora_base && $diaspora_guid) { + $guid = $diaspora_guid; + $diaspora_base = trim($diaspora_base,'/'); + + $notify = $diaspora_base . '/receive'; + + if(strpos($webbie,'@')) { + $addr = str_replace('acct:', '', $webbie); + $hostname = substr($webbie,strpos($webbie,'@')+1); + } + $network = 'diaspora'; + // until we get a dfrn layer, we'll use diaspora protocols for Friendica, + // but give it a different network so we can go back and fix these when we get proper support. + // It really should be just 'friendica' but we also want to distinguish + // between Friendica sites that we can use D* protocols with and those we can't. + // Some Friendica sites will have Diaspora disabled. + if($dfrn) + $network = 'friendica-over-diaspora'; + if($hcard) { + $vcard = scrape_vcard($hcard); + $vcard['nick'] = substr($webbie,0,strpos($webbie,'@')); + if(! $vcard['fn']) + $vcard['fn'] = $webbie; + } + + $r = q("select * from xchan where xchan_hash = '%s' limit 1", + dbesc($addr) + ); + + /** + * + * Diaspora communications are notoriously unreliable and receiving profile update messages (indeed any messages) + * are pretty much random luck. We'll check the timestamp of the xchan_name_date at a higher level and refresh + * this record once a month; because if you miss a profile update message and they update their profile photo or name + * you're otherwise stuck with stale info until they change their profile again - which could be years from now. + * + */ + + if($r) { + $r = q("update xchan set xchan_name = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s' limit 1", + dbesc($vcard['fn']), + dbesc($network), + dbesc(datetime_convert()), + dbesc($addr) + ); + } + else { + + $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", + dbesc($addr), + dbesc($guid), + dbesc($pubkey), + dbesc($addr), + dbesc($profile), + dbesc($vcard['fn']), + dbesc($network), + dbescdate(datetime_convert()) + ); + } + + $r = q("select * from hubloc where hubloc_hash = '%s' limit 1", + dbesc($webbie) + ); + + if(! $r) { + + $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_primary ) values ('%s','%s','%s','%s','%s','%s','%s','%s', 1)", + dbesc($guid), + dbesc($addr), + dbesc($addr), + dbesc($network), + dbesc(trim($diaspora_base,'/')), + dbesc($hostname), + dbesc($notify), + dbescdate(datetime_convert()) + ); + } + $photos = import_xchan_photo($vcard['photo'],$addr); + $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", + dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])), + dbesc($photos[0]), + dbesc($photos[1]), + dbesc($photos[2]), + dbesc($photos[3]), + dbesc($addr) + ); + return true; + + } + + return false; + +/* + $vcard['fn'] = notags($vcard['fn']); + $vcard['nick'] = str_replace(' ','',notags($vcard['nick'])); + + $result['name'] = $vcard['fn']; + $result['nick'] = $vcard['nick']; + $result['guid'] = $guid; + $result['url'] = $profile; + $result['hostname'] = $hostname; + $result['addr'] = $addr; + $result['batch'] = $batch; + $result['notify'] = $notify; + $result['poll'] = $poll; + $result['request'] = $request; + $result['confirm'] = $confirm; + $result['poco'] = $poco; + $result['photo'] = $vcard['photo']; + $result['priority'] = $priority; + $result['network'] = $network; + $result['alias'] = $alias; + $result['pubkey'] = $pubkey; + + logger('probe_url: ' . print_r($result,true), LOGGER_DEBUG); + + return $result; + +*/ + +/* Sample Diaspora result. + +Array +( + [name] => Mike Macgirvin + [nick] => macgirvin + [guid] => a9174a618f8d269a + [url] => https://joindiaspora.com/u/macgirvin + [hostname] => joindiaspora.com + [addr] => macgirvin@joindiaspora.com + [batch] => + [notify] => https://joindiaspora.com/receive + [poll] => https://joindiaspora.com/public/macgirvin.atom + [request] => + [confirm] => + [poco] => + [photo] => https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_fec4e6eef13ae5e56207.jpg + [priority] => + [network] => diaspora + [alias] => + [pubkey] => -----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtihtyIuRDWkDpCA+I1UaQ +jI4S7k625+A7EEJm+pL2ZVSJxeCKiFeEgHBQENjLMNNm8l8F6blxgQqE6ZJ9Spa7f +tlaXYTRCrfxKzh02L3hR7sNA+JS/nXJaUAIo+IwpIEspmcIRbD9GB7Wv/rr+M28uH +31EeYyDz8QL6InU/bJmnCdFvmEMBQxJOw1ih9tQp7UNJAbUMCje0WYFzBz7sfcaHL +OyYcCOqOCBLdGucUoJzTQ9iDBVzB8j1r1JkIHoEb2moUoKUp+tkCylNfd/3IVELF9 +7w1Qjmit3m50OrJk2DQOXvCW9KQxaQNdpRPSwhvemIt98zXSeyZ1q/YjjOwG0DWDq +AF8aLj3/oQaZndTPy/6tMiZogKaijoxj8xFLuPYDTw5VpKquriVC0z8oxyRbv4t9v +8JZZ9BXqzmayvY3xZGGp8NulrfjW+me2bKh0/df1aHaBwpZdDTXQ6kqAiS2FfsuPN +vg57fhfHbL1yJ4oDbNNNeI0kJTGchXqerr8C20khU/cQ2Xt31VyEZtnTB665Ceugv +kp3t2qd8UpAVKl430S5Quqx2ymfUIdxdW08CEjnoRNEL3aOWOXfbf4gSVaXmPCR4i +LSIeXnd14lQYK/uxW/8cTFjcmddsKxeXysoQxbSa9VdDK+KkpZdgYXYrTTofXs6v+ +4afAEhRaaY+MCAwEAAQ== +-----END PUBLIC KEY----- + +) +*/ + + + + + } +} + + +function diaspora_feature_settings_post(&$a,&$b) { + + if($_POST['diaspora-submit']) { + set_pconfig(local_channel(),'system','diaspora_allowed',intval($_POST['dspr_allowed'])); + set_pconfig(local_channel(),'system','diaspora_public_comments',intval($_POST['dspr_pubcomment'])); + set_pconfig(local_channel(),'system','prevent_tag_hijacking',intval($_POST['dspr_hijack'])); + info( t('Diaspora Protocol Settings updated.') . EOL); + } +} + + +function diaspora_feature_settings(&$a,&$s) { + $dspr_allowed = get_pconfig(local_channel(),'system','diaspora_allowed'); + if($dspr_allowed === false) + $dspr_allowed = get_config('diaspora','allowed'); + $pubcomments = get_pconfig(local_channel(),'system','diaspora_public_comments'); + if($pubcomments === false) + $pubcomments = 1; + $hijacking = get_pconfig(local_channel(),'system','prevent_tag_hijacking'); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('dspr_allowed', t('Enable the (experimental) Diaspora protocol for this channel'), $dspr_allowed, '', $yes_no), + )); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('dspr_pubcomment', t('Allow any Diaspora member to comment on your public posts'), $pubcomments, '', $yes_no), + )); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('dspr_hijack', t('Prevent your hashtags from being redirected to other sites'), $hijacking, '', $yes_no), + )); + + + $s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( + '$addon' => array('diaspora', '' . t('Diaspora Protocol Settings'), '', t('Submit')), + '$content' => $sc + )); + + return; + +} diff --git a/sources/addons/diaspora/p.php b/sources/addons/diaspora/p.php new file mode 100644 index 00000000..3df8cd55 --- /dev/null +++ b/sources/addons/diaspora/p.php @@ -0,0 +1,52 @@ +get_hostname(); + + $item = $r[0]; + + $title = $item['title']; + $body = bb2diaspora_itembody($item); + $created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C'); + + $tpl = get_markup_template('diaspora_post.tpl'); + $msg = replace_macros($tpl, array( + '$body' => xmlify($body), + '$guid' => $item['mid'], + '$handle' => xmlify($myaddr), + '$public' => 'true', + '$created' => $created, + '$provider' => (($item['app']) ? $item['app'] : t('$projectname')) + )); + + header('Content-type: text/xml'); + echo $msg; + killme(); +} \ No newline at end of file diff --git a/sources/addons/diaspora/receive.php b/sources/addons/diaspora/receive.php new file mode 100644 index 00000000..fad4ae71 --- /dev/null +++ b/sources/addons/diaspora/receive.php @@ -0,0 +1,75 @@ +argv, true), LOGGER_DEBUG); + + if((argc() == 2) && (argv(1) === 'public')) { + $public = true; + } + else { + + if(argc() != 3 || argv(1) !== 'users') + http_status_exit(500); + + $guid = argv(2); + $hn = str_replace('.','',$a->get_hostname()); + if(($x = strpos($guid,$hn)) > 0) + $guid = substr($guid,0,$x); + + // Diaspora sites *may* provide a truncated guid. + + $r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_guid like '%s' AND channel_removed = 0 LIMIT 1", + dbesc($guid . '%') + ); + + if(! $r) + http_status_exit(500); + + $importer = $r[0]; + } + + // It is an application/x-www-form-urlencoded that has been urlencoded twice. + + logger('mod-diaspora: receiving post', LOGGER_DEBUG); + + $xml = urldecode($_POST['xml']); + + logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA); + + if(! $xml) + http_status_exit(500); + + logger('mod-diaspora: message is okay', LOGGER_DEBUG); + + $msg = diaspora_decode($importer,$xml); + + logger('mod-diaspora: decoded', LOGGER_DEBUG); + + logger('mod-diaspora: decoded msg: ' . print_r($msg,true), LOGGER_DATA); + + if(! is_array($msg)) + http_status_exit(500); + + logger('mod-diaspora: dispatching', LOGGER_DEBUG); + + $ret = 0; + if($public) + diaspora_dispatch_public($msg); + else + $ret = diaspora_dispatch($importer,$msg); + + http_status_exit(($ret) ? $ret : 200); + // NOTREACHED +} + diff --git a/sources/addons/diaspost/diasphp.php b/sources/addons/diaspost/diasphp.php new file mode 100644 index 00000000..d4c31b47 --- /dev/null +++ b/sources/addons/diaspost/diasphp.php @@ -0,0 +1,107 @@ +token_regex = '/content="(.*?)" name="csrf-token/'; + + $this->pod = $pod; + $this->cookiejar = tempnam(sys_get_temp_dir(), 'cookies'); + } + + function _fetch_token() { + $ch = curl_init(); + + curl_setopt ($ch, CURLOPT_URL, $this->pod . "/stream"); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiejar); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $this->cookiejar); + curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt ($ch, CURLOPT_TIMEOUT, 60); + + + $output = curl_exec ($ch); + curl_close($ch); + + // Token holen und zurückgeben + preg_match($this->token_regex, $output, $matches); + return $matches[1]; + } + + function login($username, $password) { + $datatopost = array( + 'user[username]' => $username, + 'user[password]' => $password, + 'authenticity_token' => $this->_fetch_token() + ); + + $poststr = http_build_query($datatopost); + + // Adresse per cURL abrufen + $ch = curl_init(); + + curl_setopt ($ch, CURLOPT_URL, $this->pod . "/users/sign_in"); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiejar); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $this->cookiejar); + curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt ($ch, CURLOPT_POST, true); + curl_setopt ($ch, CURLOPT_POSTFIELDS, $poststr); + curl_setopt ($ch, CURLOPT_TIMEOUT, 60); + + curl_exec ($ch); + $info = curl_getinfo($ch); + curl_close($ch); + + if($info['http_code'] != 302) { + throw new Exception('Login error '.print_r($info, true)); + } + + // Das Objekt zurückgeben, damit man Aurufe verketten kann. + return $this; + } + + function post($text, $provider = "diasphp") { + // post-daten vorbereiten + $datatopost = json_encode(array( + 'aspect_ids' => 'public', + 'status_message' => array('text' => $text, + 'provider_display_name' => $provider) + )); + + // header vorbereiten + $headers = array( + 'Content-Type: application/json', + 'accept: application/json', + 'x-csrf-token: '.$this->_fetch_token() + ); + + // Adresse per cURL abrufen + $ch = curl_init(); + + curl_setopt ($ch, CURLOPT_URL, $this->pod . "/status_messages"); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiejar); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $this->cookiejar); + curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt ($ch, CURLOPT_POST, true); + curl_setopt ($ch, CURLOPT_POSTFIELDS, $datatopost); + curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt ($ch, CURLOPT_TIMEOUT, 60); + + curl_exec ($ch); + $info = curl_getinfo($ch); + curl_close($ch); + + if($info['http_code'] != 201) { + throw new Exception('Post error '.print_r($info, true)); + } + + // Ende der möglichen Kette, gib mal "true" zurück. + return true; + } +} +?> diff --git a/sources/addons/diaspost/diaspora.png b/sources/addons/diaspost/diaspora.png new file mode 100644 index 0000000000000000000000000000000000000000..9666591638cc17fc8bb5a8a7eeed4b7cc83fb9a7 GIT binary patch literal 952 zcmV;p14sOcP)kdg00009a7bBm000fw z000fw0YWI7cmMzZ^JzmvP*7-ZbZ>KLZ*U+zZK3<12uwt~|df*uJ3vUQf-iKjLrpU5Em_ z07>B+2Ydjl2MGdd0rZyZAfN>3t*4U#s3)K+{!su1b!g-2=2rB1nx@(m_0sF>wh>=8 z`m%C$40W{P3*dVL;3$i>)tN0ztCO>Ye>cnL`YXLpQGhzx?7AIy7w>=m>|DSnOB*;a z&P~yh0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0006% zNkl93&HzuCC4jA^gJ;-=G0auAFC}jwX%uJ2G;Kt3iI>xpSDYO$h?(S7 zJPIUtlG(dhF2^GDQR4}jB#i~wMA+(C`$z*L8n|QF=ZLKCG_1a31waUZ!!#R`vSqel zSlvYX;>CS3W}5#5HuKatCuk+g|5yR1Aw&WD1p2~FCi99ibTcGgBTaI0`lrP^BDF0a~(fn*x7wjxYch1nc|9 zOOR5`Zg~({#!FXj{Zz1v-wHX!O0Kv#-&wDV6Z16Gm}@VajHlEY>b+OAhmpX~`ZUK) zx4e-zf#hlb?pZ7467x&QZ&8*1W38i$DWi0b`yBQE$W0dGAoWBkA&kWwGfXhZUG + */ + +function diaspost_load() { + register_hook('post_local', 'addon/diaspost/diaspost.php', 'diaspost_post_local'); + register_hook('notifier_normal', 'addon/diaspost/diaspost.php', 'diaspost_send'); + register_hook('jot_networks', 'addon/diaspost/diaspost.php', 'diaspost_jot_nets'); + register_hook('feature_settings', 'addon/diaspost/diaspost.php', 'diaspost_settings'); + register_hook('feature_settings_post', 'addon/diaspost/diaspost.php', 'diaspost_settings_post'); + +} +function diaspost_unload() { + unregister_hook('post_local', 'addon/diaspost/diaspost.php', 'diaspost_post_local'); + unregister_hook('notifier_normal', 'addon/diaspost/diaspost.php', 'diaspost_send'); + unregister_hook('jot_networks', 'addon/diaspost/diaspost.php', 'diaspost_jot_nets'); + unregister_hook('feature_settings', 'addon/diaspost/diaspost.php', 'diaspost_settings'); + unregister_hook('feature_settings_post', 'addon/diaspost/diaspost.php', 'diaspost_settings_post'); + +} + + +function diaspost_jot_nets(&$a,&$b) { + if((! local_channel()) || (! perm_is_allowed(local_channel(),'','view_stream'))) + return; + + $diaspost_post = get_pconfig(local_channel(),'diaspost','post'); + if(intval($diaspost_post) == 1) { + $diaspost_defpost = get_pconfig(local_channel(),'diaspost','post_by_default'); + $selected = ((intval($diaspost_defpost) == 1) ? ' checked="checked" ' : ''); + $b .= '
' . t('Post to Diaspora') . '
'; + } +} + +function diaspost_queue_hook(&$a,&$b) { + $hostname = $a->get_hostname(); + + $qi = q("SELECT * FROM `queue` WHERE `network` = '%s'", + dbesc(NETWORK_DIASPORA2) + ); + if(! count($qi)) + return; + + require_once('include/queue_fn.php'); + + foreach($qi as $x) { + if($x['network'] !== NETWORK_DIASPORA2) + continue; + + logger('diaspost_queue: run'); + + $r = q("SELECT `user`.* FROM `user` LEFT JOIN `contact` on `contact`.`uid` = `user`.`uid` + WHERE `contact`.`self` = 1 AND `contact`.`id` = %d LIMIT 1", + intval($x['cid']) + ); + if(! count($r)) + continue; + + $userdata = $r[0]; + + $diaspost_username = get_pconfig($userdata['uid'],'diaspost','diaspost_username'); + $diaspost_password = z_unobscure(get_pconfig($userdata['uid'],'diaspost','diaspost_password')); + $diaspost_url = get_pconfig($userdata['uid'],'diaspost','diaspost_url'); + + $success = false; + + if($diaspost_url && $diaspost_username && $diaspost_password) { + require_once("addon/diaspost/diasphp.php"); + + logger('diaspost_queue: able to post for user '.$diaspost_username); + + $z = unserialize($x['content']); + + $post = $z['post']; + + logger('diaspost_queue: post: '.$post, LOGGER_DATA); + + try { + logger('diaspost_queue: prepare', LOGGER_DEBUG); + $conn = new Diasphp($diaspost_url); + logger('diaspost_queue: try to log in '.$diaspost_username, LOGGER_DEBUG); + $conn->login($diaspost_username, $diaspost_password); + logger('diaspost_queue: try to send '.$body, LOGGER_DEBUG); + $conn->post($post, $hostname); + + logger('diaspost_queue: send '.$userdata['uid'].' success', LOGGER_DEBUG); + + $success = true; + + remove_queue_item($x['id']); + } catch (Exception $e) { + logger("diaspost_queue: Send ".$userdata['uid']." failed: ".$e->getMessage(), LOGGER_DEBUG); + } + } else + logger('diaspost_queue: send '.$userdata['uid'].' missing username or password', LOGGER_DEBUG); + + if (!$success) { + logger('diaspost_queue: delayed'); + update_queue_time($x['id']); + } + } +} + +function diaspost_settings(&$a,&$s) { + + if(! local_channel()) + return; + + /* Add our stylesheet to the page so we can make our settings look nice */ + + //$a->page['htmlhead'] .= '' . "\r\n"; + + /* Get the current state of our config variables */ + + $enabled = get_pconfig(local_channel(),'diaspost','post'); + $checked = (($enabled) ? '1' : false); + $css = (($enabled) ? '' : '-disabled'); + + $def_enabled = get_pconfig(local_channel(),'diaspost','post_by_default'); + + $def_checked = (($def_enabled) ? 1 : false); + + $diaspost_username = get_pconfig(local_channel(), 'diaspost', 'diaspost_username'); + $diaspost_password = z_unobscure(get_pconfig(local_channel(), 'diaspost', 'diaspost_password')); + $diaspost_url = get_pconfig(local_channel(), 'diaspost', 'diaspost_url'); + + $status = ""; + + if ($diaspost_username AND $diaspost_password AND $diaspost_url) { + try { + require_once("addon/diaspost/diasphp.php"); + + $conn = new Diasphp($diaspost_url); + $conn->login($diaspost_username, $diaspost_password); + } catch (Exception $e) { + $status = t("Can't login to your Diaspora account. Please check username and password and ensure you used the complete address (including http...)"); + } + } + + /* Add some HTML to the existing form */ + if ($status) { + $sc .= '
'; + $sc .= '' . $status . ''; + $sc .= '
'; + } + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('diaspost', t('Enable Diaspost Post Plugin'), $checked, '', array(t('No'),t('Yes'))), + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('diaspost_username', t('Diaspora username'), $diaspost_username, '') + )); + + $sc .= replace_macros(get_markup_template('field_password.tpl'), array( + '$field' => array('diaspost_password', t('Diaspora password'), $diaspost_password, '') + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('diaspost_url', t('Diaspora site URL'), $diaspost_url, 'Example: https://joindiaspora.com') + )); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('diaspost_bydefault', t('Post to Diaspora by default'), $def_checked, '', array(t('No'),t('Yes'))), + )); + + $s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( + '$addon' => array('diaspost', '' . t('Diaspost Post Settings'), '', t('Submit')), + '$content' => $sc + )); + + return; +} + + +function diaspost_settings_post(&$a,&$b) { + + if(x($_POST,'diaspost-submit')) { + + set_pconfig(local_channel(),'diaspost','post',intval($_POST['diaspost'])); + set_pconfig(local_channel(),'diaspost','post_by_default',intval($_POST['diaspost_bydefault'])); + set_pconfig(local_channel(),'diaspost','diaspost_username',trim($_POST['diaspost_username'])); + set_pconfig(local_channel(),'diaspost','diaspost_password',z_obscure(trim($_POST['diaspost_password']))); + set_pconfig(local_channel(),'diaspost','diaspost_url',trim($_POST['diaspost_url'])); + + } + +} + +function diaspost_post_local(&$a,&$b) { + + if($b['created'] != $b['edited']) + return; + + if(! perm_is_allowed($b['uid'],'','view_stream')) + return; + + + if((! local_channel()) || (local_channel() != $b['uid'])) + return; + + if($b['item_private']) + return; + + $diaspost_post = intval(get_pconfig(local_channel(),'diaspost','post')); + + $diaspost_enable = (($diaspost_post && x($_REQUEST,'diaspost_enable')) ? intval($_REQUEST['diaspost_enable']) : 0); + + if($_REQUEST['api_source'] && intval(get_pconfig(local_channel(),'diaspost','post_by_default'))) + $diaspost_enable = 1; + + if(! $diaspost_enable) + return; + + if(strlen($b['postopts'])) + $b['postopts'] .= ','; + $b['postopts'] .= 'diaspost'; +} + + + + +function diaspost_send(&$a,&$b) { + $hostname = 'hubzilla ' . '(' . $a->get_hostname() . ')'; + + logger('diaspost_send: invoked',LOGGER_DEBUG); + + if($b['mid'] != $b['parent_mid']) + return; + + if((! is_item_normal($b)) || $b['item_private'] || ($b['created'] !== $b['edited'])) + return; + + + if(! perm_is_allowed($b['uid'],'','view_stream')) + return; + + + if(! strstr($b['postopts'],'diaspost')) + return; + + + logger('diaspost_send: prepare posting', LOGGER_DEBUG); + + $diaspost_username = get_pconfig($b['uid'],'diaspost','diaspost_username'); + $diaspost_password = z_unobscure(get_pconfig($b['uid'],'diaspost','diaspost_password')); + $diaspost_url = get_pconfig($b['uid'],'diaspost','diaspost_url'); + + if($diaspost_url && $diaspost_username && $diaspost_password) { + + logger('diaspost_send: all values seem to be okay', LOGGER_DEBUG); + + require_once('include/bb2diaspora.php'); + $tag_arr = array(); + $tags = ''; + $x = preg_match_all('/\#\[(.*?)\](.*?)\[/',$b['tag'],$matches,PREG_SET_ORDER); + + if($x) { + foreach($matches as $mtch) { + $tag_arr[] = $mtch[2]; + } + } + if(count($tag_arr)) + $tags = implode(',',$tag_arr); + + $title = $b['title']; + $body = $b['body']; + // Insert a newline before and after a quote + $body = str_ireplace("[quote", "\n\n[quote", $body); + $body = str_ireplace("[/quote]", "[/quote]\n\n", $body); + + // strip bookmark indicators + + $body = preg_replace('/\#\^\[([zu])rl/i', '[$1rl', $body); + + $body = preg_replace('/\#\^http/i', 'http', $body); + + + if(intval(get_pconfig($item['uid'],'system','prevent_tag_hijacking'))) { + $new_tag = html_entity_decode('⋕',ENT_COMPAT,'UTF-8'); + $new_mention = html_entity_decode('@',ENT_COMPAT,'UTF-8'); + + // #-tags + $body = preg_replace('/\#\[url/i', $new_tag . '[url', $body); + $body = preg_replace('/\#\[zrl/i', $new_tag . '[zrl', $body); + // @-mentions + $body = preg_replace('/\@\!?\[url/i', $new_mention . '[url', $body); + $body = preg_replace('/\@\!?\[zrl/i', $new_mention . '[zrl', $body); + } + + // remove multiple newlines + do { + $oldbody = $body; + $body = str_replace("\n\n\n", "\n\n", $body); + } while ($oldbody != $body); + + // convert to markdown + $body = bb2diaspora($body, false, true); + + // Adding the title + if(strlen($title)) + $body = "## ".html_entity_decode($title)."\n\n".$body; + + require_once("addon/diaspost/diasphp.php"); + + try { + logger('diaspost_send: prepare', LOGGER_DEBUG); + $conn = new Diasphp($diaspost_url); + logger('diaspost_send: try to log in '.$diaspost_username, LOGGER_DEBUG); + $conn->login($diaspost_username, $diaspost_password); + logger('diaspost_send: try to send '.$body, LOGGER_DEBUG); + + //throw new Exception('Test'); + $conn->post($body, $hostname); + + logger('diaspost_send: success'); + } catch (Exception $e) { + logger("diaspost_send: Error submitting the post: " . $e->getMessage()); + +// logger('diaspost_send: requeueing '.$b['uid'], LOGGER_DEBUG); + +// $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", $b['uid']); +// if (count($r)) +// $a->contact = $r[0]["id"]; + +// $s = serialize(array('url' => $url, 'item' => $b['id'], 'post' => $body)); +// require_once('include/queue_fn.php'); +// add_to_queue($a->contact,NETWORK_DIASPORA2,$s); +// notice(t('Diaspost post failed. Queued for retry.').EOL); + } + } +} diff --git a/sources/addons/dirstats/dirstats.php b/sources/addons/dirstats/dirstats.php new file mode 100644 index 00000000..442f10c1 --- /dev/null +++ b/sources/addons/dirstats/dirstats.php @@ -0,0 +1,204 @@ + +*/ + +function dirstats_load() { + register_hook('cron_daily', 'addon/dirstats/dirstats.php', 'dirstats_cron'); +} +function dirstats_unload() { + unregister_hook('cron_daily', 'addon/dirstats/dirstats.php', 'dirstats_cron'); +} +function dirstats_module() {} + + +function dirstats_init() { + if(! get_config('dirstats','hubcount')) + dirstats_cron($a,$b); + +} + +function dirstats_content(&$a) { + + $hubcount = get_config('dirstats','hubcount'); + $zotcount = get_config('dirstats','zotcount'); + $friendicacount = get_config('dirstats','friendicacount'); + $diasporacount = get_config('dirstats','diasporacount'); + $channelcount = get_config('dirstats','channelcount'); + $friendicachannelcount = get_config('dirstats','friendicachannelcount'); + $diasporachannelcount = get_config('dirstats','diasporachannelcount'); + $over35s = get_config('dirstats','over35s'); + $under35s = get_config('dirstats','under35s'); + $average = get_config('dirstats','averageage'); + $chatrooms = get_config('dirstats','chatrooms'); + $tags = get_config('dirstats','tags'); + + $ob = $a->get_observer(); + $observer = $ob['xchan_hash']; + // Requested by Martin + $fountainofyouth = get_xconfig($observer, 'dirstats', 'averageage'); + if (intval($fountainofyouth)) + $average = $fountainofyouth; + +if (argv(1) == 'json') { + $dirstats = array ( + 'hubcount' => $hubcount, + 'zotcount' => $zotcount, + 'friendicacount' => $friendicacount, + 'diasporacount' => $diasporacount, + 'channelcount' => $channelcount, + 'friendicachannelcount' => $friendicachannelcount, + 'diasporachannelcount' => $diasporachannelcount, + 'over35s' => $over35s, + 'under35s' => $under35s, + 'average' => $average, + 'chatrooms' => $chatrooms, + 'tags' => $tags + ); + echo json_return_and_die($dirstats); + } + + // Used by Hubzilla News + elseif (argv(1) == 'genpost' && get_config('dirstats','allowfiledump')) { + $result = '[b]Hub count[/b] : ' . $hubcount . "\xA" . + '[b]Hubzilla Hubs[/b] : ' . $zotcount . "\xA" . + '[b]Friendica Hubs[/b] : ' . $friendicacount . "\xA" . + '[b]Diaspora Pods[/b] : ' . $diasporacount . "\xA" . + '[b]Hubzilla Channels[/b] : ' . $channelcount . "\xA" . + '[b]Friendica Profiles[/b] : ' . $friendicachannelcount . "\xA" . + '[b]Diaspora Profiles[/b] : ' . $diasporachannelcount . "\xA" . + '[b]People aged 35 and above[/b] : ' . $over35s . "\xA" . + '[b]People aged 34 and below[/b] : ' . $under35s . "\xA" . + '[b]Average Age[/b] : ' . $average . "\xA" . + '[b]Known Chatrooms[/b] : ' . $chatrooms . "\xA" . + '[b]Unique Profile Tags[/b] : ' . $tags . "\xA"; + + file_put_contents('genpost', $result); + } +else { + $tpl = get_markup_template( "dirstats.tpl", "addon/dirstats/" ); + return replace_macros($tpl, array( + '$title' => t('Hubzilla Directory Stats'), + '$hubtitle' => t('Total Hubs'), + '$hubcount' => $hubcount, + '$zotlabel' => t('Hubzilla Hubs'), + '$zotcount' => $zotcount, + '$friendicalabel' => t('Friendica Hubs'), + '$friendicacount' => $friendicacount, + '$diasporalabel' => t('Diaspora Pods'), + '$diasporacount' => $diasporacount, + '$zotchanlabel' => t('Hubzilla Channels'), + '$channelcount' => $channelcount, + '$friendicachanlabel' => t('Friendica Channels'), + '$friendicachannelcount' => $friendicachannelcount, + '$diasporachanlabel' => t('Diaspora Channels'), + '$diasporachannelcount' => $diasporachannelcount, + '$over35label' => t('Aged 35 and above'), + '$over35s' => $over35s, + '$under35label' => t('Aged 34 and under'), + '$under35s' => $under35s, + '$averageagelabel' => t('Average Age'), + '$average' => $average, + '$chatlabel' => t('Known Chatrooms'), + '$chatrooms' => $chatrooms, + '$tagslabel' => t('Known Tags'), + '$tags' => $tags, + '$disclaimer' => t('Please note Diaspora and Friendica statistics are merely those **this directory** is aware of, and not all those known in the network. This also applies to chatrooms,') + )); + } +} +function dirstats_cron(&$a, $b) { + // Some hublocs are immortal and won't ever die - they all have null date for hubloc_connected and hubloc_updated + $r = q("SELECT count(distinct hubloc_host) as total FROM `hubloc` where not (hubloc_flags & %d) > 0 and not (hubloc_connected = %d and hubloc_updated = %d)", + intval(HUBLOC_FLAGS_DELETED), + dbesc(NULL_DATE), + dbesc(NULL_DATE) + ); + if ($r) { + $hubcount = $r[0]['total']; + set_config('dirstats','hubcount',$hubcount); + } + + $r = q("SELECT count(distinct hubloc_host) as total FROM `hubloc` where hubloc_network = 'zot' and not (hubloc_flags & %d) > 0 and not (hubloc_connected = %d and hubloc_updated = %d)", + intval(HUBLOC_FLAGS_DELETED), + dbesc(NULL_DATE), + dbesc(NULL_DATE) + + ); + if ($r) { + $zotcount = $r[0]['total']; + set_config('dirstats','zotcount',$zotcount); + } + $r = q("SELECT count(distinct hubloc_host) as total FROM `hubloc` where hubloc_network = 'friendica-over-diaspora'"); + if ($r){ + $friendicacount = $r[0]['total']; + set_config('dirstats','friendicacount',$friendicacount); + } + $r = q("SELECT count(distinct hubloc_host) as total FROM `hubloc` where hubloc_network = 'diaspora'"); + if ($r) { + $diasporacount = $r[0]['total']; + set_config('dirstats','diasporacount',$diasporacount); + } + $r = q("SELECT count(distinct xchan_hash) as total FROM `xchan` where xchan_network = 'zot' and not (xchan_flags & %d) > 0", + intval(XCHAN_FLAGS_DELETED) + ); + if ($r) { + $channelcount = $r[0]['total']; + set_config('dirstats','channelcount',$channelcount); + } + $r = q("SELECT count(distinct xchan_hash) as total FROM `xchan` where xchan_network = 'friendica-over-diaspora'"); + if ($r) { + $friendicachannelcount = $r[0]['total']; + set_config('dirstats','friendicachannelcount',$friendicachannelcount); + } + $r = q("SELECT count(distinct xchan_hash) as total FROM `xchan` where xchan_network = 'diaspora'"); + if ($r) { + $diasporachannelcount = $r[0]['total']; + set_config('dirstats','diasporachannelcount',$diasporachannelcount); + } + $r = q("select count(xprof_hash) as total from `xprof` where xprof_age >=35"); + if ($r) { + $over35s = $r[0]['total']; + set_config('dirstats','over35s',$over35s); + } + $r = q("select count(xprof_hash) as total from `xprof` where xprof_age <=34 and xprof_age >=1"); + if ($r) { + $under35s = $r[0]['total']; + set_config('dirstats','under35s',$under35s); + } + + $r = q("select sum(xprof_age) as sum from xprof"); + if ($r) { + $rr = q("select count(xprof_hash) as total from `xprof` where xprof_age >=1"); + $total = $r[0]['sum']; + $number = $rr[0]['total']; + if($number) + $average = $total / $number; + else + $average = 0; + set_config('dirstats','averageage',$average); + } + + $r = q("select count(distinct xchat_url) as total from `xchat`"); + if ($r) { + $chatrooms = $r[0]['total']; + set_config('dirstats','chatrooms',$chatrooms); + } + $r = q("select count(distinct xtag_term) as total from xtag where xtag_flags = 0"); + if ($r) { + $tags = $r[0]['total']; + set_config('dirstats','tags',$tags); + } +} diff --git a/sources/addons/dirstats/view/tpl/dirstats.tpl b/sources/addons/dirstats/view/tpl/dirstats.tpl new file mode 100644 index 00000000..f1c3a132 --- /dev/null +++ b/sources/addons/dirstats/view/tpl/dirstats.tpl @@ -0,0 +1,20 @@ +
+

{{$title}}

+
    {{$hubtitle}} : {{$hubcount}}
+
    {{$zotlabel}} : {{$zotcount}}
+
    {{$friendicalabel}} : {{$friendicacount}}
+
    {{$diasporalabel}} : {{$diasporacount}}
+

+
    {{$zotchanlabel}} : {{$channelcount}}
+
    {{$friendicachanlabel}} : {{$friendicachannelcount}}
+
    {{$diasporachanlabel}} : {{$diasporachannelcount}}
+

+
    {{$over35label}} : {{$over35s}}
+
    {{$under35label}} : {{$under35s}}
+
    {{$averageagelabel}} : {{$average}}
+

+
    {{$chatlabel}} : {{$chatrooms}}
+
    {{$tagslabel}} : {{$tags}}
+ +

{{$disclaimer}}

+
diff --git a/sources/addons/donate/donate.apd b/sources/addons/donate/donate.apd new file mode 100644 index 00000000..eff602d3 --- /dev/null +++ b/sources/addons/donate/donate.apd @@ -0,0 +1,3 @@ +url: $baseurl/donate +name: Support Hubzilla +photo: $baseurl/addon/donate/donate.png diff --git a/sources/addons/donate/donate.php b/sources/addons/donate/donate.php new file mode 100644 index 00000000..1eb6d57d --- /dev/null +++ b/sources/addons/donate/donate.php @@ -0,0 +1,75 @@ +' . t('The Redmatrix/Hubzilla projects are provided primarily by volunteers giving their time and expertise - and often paying out of pocket for services they share with others.') . '

'; +$text .= '

' . t('There is no corporate funding and no ads, and we do not collect and sell your personal information. (We don\'t control your personal information - you do.)') . '

'; +$text .= '

' . t('Help support our ground-breaking work in decentralisation, web identity, and privacy.') . '

'; + +$text .= '

' . t('Your donations keep servers and services running and also helps us to provide innovative new features and continued development.') . '

'; + +$o = replace_macros(get_markup_template('donate.tpl','addon/donate'),array( + '$header' => t('Donate'), + '$text' => $text, + '$choice' => t('Choose a project, developer, or public hub to support with a one-time donation'), + '$onetime' => t('Donate Now'), + '$repeat' => t('Or become a project sponsor (Hubzilla Project only)'), + '$note' => t('Please indicate if you would like your first name or full name (or nothing) to appear in our sponsor listing'), + '$subscribe' => t('Sponsor'), + '$contributors' => $contributors, + '$sponsors' => $sponsors, + '$thanks' => t('Special thanks to: '), +)); + +call_hooks('donate_plugin',$o); + +return $o; + +} diff --git a/sources/addons/donate/donate.png b/sources/addons/donate/donate.png new file mode 100644 index 0000000000000000000000000000000000000000..d932f0014756c2b094480ee637108d7138fcb63d GIT binary patch literal 7097 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 literal 0 HcmV?d00001 diff --git a/sources/addons/donate/tipping.jpg b/sources/addons/donate/tipping.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f370ece78b8477128765f22b37031c9bb59884b3 GIT binary patch literal 109373 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%0A+jDk|1a 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%0APdv*Ibwp_Z{ew+qC& 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 Rn)`lRz9xTP_x}J{|Jm?DemVdE literal 0 HcmV?d00001 diff --git a/sources/addons/donate/view/tpl/donate.tpl b/sources/addons/donate/view/tpl/donate.tpl new file mode 100644 index 00000000..6382cc6f --- /dev/null +++ b/sources/addons/donate/view/tpl/donate.tpl @@ -0,0 +1,64 @@ +

{{$header}}

+ +
{{$text}}
+ +
+ +Donations + +
+
+ +
+ + +
{{$choice}}
+
+ + +


+ + + + + +
+ +


+ +

+{{$repeat}} +

+

+{{$note}} +

+ +
+ + +
+ + +
+
+
+ + +
+ +

+{{$thanks}} +
    +{{foreach $sponsors as $s}} +
  • {{$s}}
  • +{{/foreach}} +
diff --git a/sources/addons/dwpost/dwpost.css b/sources/addons/dwpost/dwpost.css new file mode 100644 index 00000000..e69de29b diff --git a/sources/addons/dwpost/dwpost.php b/sources/addons/dwpost/dwpost.php new file mode 100644 index 00000000..a4b999f0 --- /dev/null +++ b/sources/addons/dwpost/dwpost.php @@ -0,0 +1,229 @@ + + * Author: Michael Johnston + * Author: Cat Gray + */ + +require_once('include/permissions.php'); + +function dwpost_load() { + register_hook('post_local', 'addon/dwpost/dwpost.php', 'dwpost_post_local'); + register_hook('notifier_normal', 'addon/dwpost/dwpost.php', 'dwpost_send'); + register_hook('jot_networks', 'addon/dwpost/dwpost.php', 'dwpost_jot_nets'); + register_hook('feature_settings', 'addon/dwpost/dwpost.php', 'dwpost_settings'); + register_hook('feature_settings_post', 'addon/dwpost/dwpost.php', 'dwpost_settings_post'); + +} +function dwpost_unload() { + unregister_hook('post_local', 'addon/dwpost/dwpost.php', 'dwpost_post_local'); + unregister_hook('notifier_normal', 'addon/dwpost/dwpost.php', 'dwpost_send'); + unregister_hook('jot_networks', 'addon/dwpost/dwpost.php', 'dwpost_jot_nets'); + unregister_hook('feature_settings', 'addon/dwpost/dwpost.php', 'dwpost_settings'); + unregister_hook('feature_settings_post', 'addon/dwpost/dwpost.php', 'dwpost_settings_post'); + +} + + +function dwpost_jot_nets(&$a,&$b) { + if((! local_channel()) || (! perm_is_allowed(local_channel(),'','view_stream'))) + return; + + $dw_post = get_pconfig(local_channel(),'dwpost','post'); + if(intval($dw_post) == 1) { + $dw_defpost = get_pconfig(local_channel(),'dwpost','post_by_default'); + $selected = ((intval($dw_defpost) == 1) ? ' checked="checked" ' : ''); + $b .= '
' + . t('Post to Dreamwidth') . '
'; + } +} + + +function dwpost_settings(&$a,&$s) { + + if(! local_channel()) + return; + + /* Add our stylesheet to the page so we can make our settings look nice */ + + //$a->page['htmlhead'] .= '' . "\r\n"; + + /* Get the current state of our config variables */ + + $enabled = get_pconfig(local_channel(),'dwpost','post'); + + $checked = (($enabled) ? 1 : false); + + $def_enabled = get_pconfig(local_channel(),'dwpost','post_by_default'); + + $def_checked = (($def_enabled) ? 1 : false); + + $dw_username = get_pconfig(local_channel(), 'dwpost', 'dw_username'); + $dw_password = z_unobscure(get_pconfig(local_channel(), 'dwpost', 'dw_password')); + + + /* Add some HTML to the existing form */ + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('dwpost', t('Enable Dreamwidth Post Plugin'), $checked, '', array(t('No'),t('Yes'))), + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('dw_username', t('Dreamwidth username'), $dw_username, '') + )); + + $sc .= replace_macros(get_markup_template('field_password.tpl'), array( + '$field' => array('dw_password', t('Dreamwidth password'), $dw_password, '') + )); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('dw_bydefault', t('Post to Dreamwidth by default'), $def_checked, '', array(t('No'),t('Yes'))), + )); + + $s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( + '$addon' => array('dwpost',t('Dreamwidth Post Settings'), '', t('Submit')), + '$content' => $sc + )); + +} + + +function dwpost_settings_post(&$a,&$b) { + + if(x($_POST,'dwpost-submit')) { + + set_pconfig(local_channel(),'dwpost','post',intval($_POST['dwpost'])); + set_pconfig(local_channel(),'dwpost','post_by_default',intval($_POST['dw_bydefault'])); + set_pconfig(local_channel(),'dwpost','dw_username',trim($_POST['dw_username'])); + set_pconfig(local_channel(),'dwpost','dw_password',z_obscure(trim($_POST['dw_password']))); + + } + +} + +function dwpost_post_local(&$a,&$b) { + + // This can probably be changed to allow editing by pointing to a different API endpoint + + if($b['edit']) + return; + + if((! local_channel()) || (local_channel() != $b['uid'])) + return; + + if($b['item_private'] || $b['parent']) + return; + + logger('Dreamwidth xpost invoked'); + + $dw_post = intval(get_pconfig(local_channel(),'dwpost','post')); + + $dw_enable = (($dw_post && x($_REQUEST,'dwpost_enable')) ? intval($_REQUEST['dwpost_enable']) : 0); + + if($_REQUEST['api_source'] && intval(get_pconfig(local_channel(),'dwpost','post_by_default'))) + $dw_enable = 1; + + if(! $dw_enable) + return; + + if(strlen($b['postopts'])) + $b['postopts'] .= ','; + $b['postopts'] .= 'dwpost'; +} + + + + +function dwpost_send(&$a,&$b) { + + if((! is_item_normal($b)) || $b['item_private'] || ($b['created'] !== $b['edited'])) + return; + + if(! perm_is_allowed($b['uid'],'','view_stream')) + return; + + if(! strstr($b['postopts'],'dwpost')) + return; + + if($b['parent'] != $b['id']) + return; + + // dreamwidth post in the LJ user's timezone. + // Hopefully the person's Friendica account + // will be set to the same thing. + + $tz = 'UTC'; + + $x = q("select channel_timezone from channel where channel_id = %d limit 1", + intval($b['uid']) + ); + if($x && strlen($x[0]['channel_timezone'])) + $tz = $x[0]['channel_timezone']; + + $dw_username = get_pconfig($b['uid'],'dwpost','dw_username'); + $dw_password = z_unobscure(get_pconfig($b['uid'],'dwpost','dw_password')); + $dw_blog = 'http://www.dreamwidth.org/interface/xmlrpc'; + + if($dw_username && $dw_password && $dw_blog) { + + require_once('include/bbcode.php'); + require_once('include/datetime.php'); + + $title = $b['title']; + $post = bbcode($b['body']); + $post = xmlify($post); + $tags = dwpost_get_tags($b['tag']); + + $date = datetime_convert('UTC',$tz,$b['created'],'Y-m-d H:i:s'); + $year = intval(substr($date,0,4)); + $mon = intval(substr($date,5,2)); + $day = intval(substr($date,8,2)); + $hour = intval(substr($date,11,2)); + $min = intval(substr($date,14,2)); + + $xml = <<< EOT + +LJ.XMLRPC.postevent + + +year$year +mon$mon +day$day +hour$hour +min$min +event$post +username$dw_username +password$dw_password +subject$title +lineendingsunix +ver1 +props + +useragentFriendica +taglist$tags + + + + + +EOT; + + logger('dwpost: data: ' . $xml, LOGGER_DATA); + + if($dw_blog !== 'test') + $x = z_post_url($dw_blog,$xml,array('headers' => array("Content-Type: text/xml"))); + logger('posted to dreamwidth: ' . print_r($x,true), LOGGER_DEBUG); + + } +} + +function dwpost_get_tags($post) +{ + preg_match_all("/\]([^\[#]+)\[/",$post,$matches); + $tags = implode(', ',$matches[1]); + return $tags; +} diff --git a/sources/addons/dwpost/lang/C/messages.po b/sources/addons/dwpost/lang/C/messages.po new file mode 100644 index 00000000..6bed922f --- /dev/null +++ b/sources/addons/dwpost/lang/C/messages.po @@ -0,0 +1,46 @@ +# ADDON dwpost +# Copyright (C) +# This file is distributed under the same license as the Friendica dwpost addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: dwpost.php:39 +msgid "Post to Dreamwidth" +msgstr "" + +#: dwpost.php:70 +msgid "Dreamwidth Post Settings" +msgstr "" + +#: dwpost.php:72 +msgid "Enable dreamwidth Post Plugin" +msgstr "" + +#: dwpost.php:77 +msgid "dreamwidth username" +msgstr "" + +#: dwpost.php:82 +msgid "dreamwidth password" +msgstr "" + +#: dwpost.php:87 +msgid "Post to dreamwidth by default" +msgstr "" + +#: dwpost.php:93 +msgid "Submit" +msgstr "" diff --git a/sources/addons/dwpost/lang/ca/strings.php b/sources/addons/dwpost/lang/ca/strings.php new file mode 100644 index 00000000..6ad56a9b --- /dev/null +++ b/sources/addons/dwpost/lang/ca/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Missatge a Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Configuració d'enviaments a Dreamwidth"; +$a->strings["Enable dreamwidth Post Plugin"] = "Habilitat el plugin d'enviaments a Dreamwidth"; +$a->strings["dreamwidth username"] = "Nom d'usuari a Dreamwidth"; +$a->strings["dreamwidth password"] = "Contrasenya a Dreamwidth"; +$a->strings["Post to dreamwidth by default"] = "Enviar per defecte a Dreamwidth"; +$a->strings["Submit"] = "Enviar"; diff --git a/sources/addons/dwpost/lang/cs/strings.php b/sources/addons/dwpost/lang/cs/strings.php new file mode 100644 index 00000000..e01db0d1 --- /dev/null +++ b/sources/addons/dwpost/lang/cs/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Poslat na Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Nastavení Dreamwidth příspěvků"; +$a->strings["Enable dreamwidth Post Plugin"] = "Povolit dreamwidth Plugin"; +$a->strings["dreamwidth username"] = "dreamwidth uživatelské jméno"; +$a->strings["dreamwidth password"] = "dreamwidth heslo"; +$a->strings["Post to dreamwidth by default"] = "Defaultně umístit na dreamwidth"; +$a->strings["Submit"] = "Odeslat"; diff --git a/sources/addons/dwpost/lang/de/strings.php b/sources/addons/dwpost/lang/de/strings.php new file mode 100644 index 00000000..2e3ba985 --- /dev/null +++ b/sources/addons/dwpost/lang/de/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "In Dreamwidth veröffentlichen"; +$a->strings["Dreamwidth Post Settings"] = "Dreamwidth Veröffentlichungs-Einstellungen"; +$a->strings["Enable dreamwidth Post Plugin"] = "Dreamwidth Post Plugin aktivieren"; +$a->strings["dreamwidth username"] = "Dreamwidth Benutzername"; +$a->strings["dreamwidth password"] = "Dreamwidth Passwort"; +$a->strings["Post to dreamwidth by default"] = "Standardmäßig bei Dreamwidth veröffentlichen"; +$a->strings["Submit"] = "Senden"; diff --git a/sources/addons/dwpost/lang/eo/strings.php b/sources/addons/dwpost/lang/eo/strings.php new file mode 100644 index 00000000..967d4b9b --- /dev/null +++ b/sources/addons/dwpost/lang/eo/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Afiŝi al Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Agordoj por Afiŝoj al Dreamwidth"; +$a->strings["Enable dreamwidth Post Plugin"] = "Ŝalti la Dreamwidth Kromprogramon"; +$a->strings["dreamwidth username"] = "Dreamwidth salutnomo"; +$a->strings["dreamwidth password"] = "Dreamwidth pasvorto"; +$a->strings["Post to dreamwidth by default"] = "Defaŭlte afiŝi al Dreamwidth"; +$a->strings["Submit"] = "Sendi"; diff --git a/sources/addons/dwpost/lang/es/strings.php b/sources/addons/dwpost/lang/es/strings.php new file mode 100644 index 00000000..11e6ff59 --- /dev/null +++ b/sources/addons/dwpost/lang/es/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Publicar en Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Configuración de las publicaciones en Dreamwidth"; +$a->strings["Enable dreamwidth Post Plugin"] = "Activar el módulo de publicación en Dreamwidth"; +$a->strings["dreamwidth username"] = "Nombre de usuario de Dreamwidth"; +$a->strings["dreamwidth password"] = "Contraseña de Dreamwidth"; +$a->strings["Post to dreamwidth by default"] = "Publicar en Dreamwidth por defecto"; +$a->strings["Submit"] = "Envíar"; diff --git a/sources/addons/dwpost/lang/fr/strings.php b/sources/addons/dwpost/lang/fr/strings.php new file mode 100644 index 00000000..729bb028 --- /dev/null +++ b/sources/addons/dwpost/lang/fr/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Poster vers Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Réglages Dreamwidth"; +$a->strings["Enable dreamwidth Post Plugin"] = "Activer \"Poster vers Dreamwidth\""; +$a->strings["dreamwidth username"] = "Nom d'utilisateur Dreamwidth"; +$a->strings["dreamwidth password"] = "Mot de passe"; +$a->strings["Post to dreamwidth by default"] = "Poster vers Dreamwidth par défaut"; +$a->strings["Submit"] = "Envoyer"; diff --git a/sources/addons/dwpost/lang/is/strings.php b/sources/addons/dwpost/lang/is/strings.php new file mode 100644 index 00000000..96f1f78b --- /dev/null +++ b/sources/addons/dwpost/lang/is/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = ""; +$a->strings["Dreamwidth Post Settings"] = ""; +$a->strings["Enable dreamwidth Post Plugin"] = ""; +$a->strings["dreamwidth username"] = ""; +$a->strings["dreamwidth password"] = ""; +$a->strings["Post to dreamwidth by default"] = ""; +$a->strings["Submit"] = "Senda inn"; diff --git a/sources/addons/dwpost/lang/it/strings.php b/sources/addons/dwpost/lang/it/strings.php new file mode 100644 index 00000000..a47497aa --- /dev/null +++ b/sources/addons/dwpost/lang/it/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Posta su Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Impostazioni post Dreamwidth"; +$a->strings["Enable dreamwidth Post Plugin"] = "Abilita il plugin dreamwidth"; +$a->strings["dreamwidth username"] = "dreamwidth username"; +$a->strings["dreamwidth password"] = "Password dreamwidth"; +$a->strings["Post to dreamwidth by default"] = "Invia a dreamwidth per impostazione predefinita"; +$a->strings["Submit"] = "Invia"; diff --git a/sources/addons/dwpost/lang/nb-no/strings.php b/sources/addons/dwpost/lang/nb-no/strings.php new file mode 100644 index 00000000..37677e6d --- /dev/null +++ b/sources/addons/dwpost/lang/nb-no/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = ""; +$a->strings["Dreamwidth Post Settings"] = ""; +$a->strings["Enable dreamwidth Post Plugin"] = ""; +$a->strings["dreamwidth username"] = ""; +$a->strings["dreamwidth password"] = ""; +$a->strings["Post to dreamwidth by default"] = ""; +$a->strings["Submit"] = "Lagre"; diff --git a/sources/addons/dwpost/lang/pl/strings.php b/sources/addons/dwpost/lang/pl/strings.php new file mode 100644 index 00000000..237c95d9 --- /dev/null +++ b/sources/addons/dwpost/lang/pl/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Opublikuj na Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = ""; +$a->strings["Enable dreamwidth Post Plugin"] = ""; +$a->strings["dreamwidth username"] = ""; +$a->strings["dreamwidth password"] = ""; +$a->strings["Post to dreamwidth by default"] = ""; +$a->strings["Submit"] = "Potwierdź"; diff --git a/sources/addons/dwpost/lang/pt-br/strings.php b/sources/addons/dwpost/lang/pt-br/strings.php new file mode 100644 index 00000000..329cf9e3 --- /dev/null +++ b/sources/addons/dwpost/lang/pt-br/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "Publicar no Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Configurações de publicação no Dreamwidth"; +$a->strings["Enable dreamwidth Post Plugin"] = "Habilitar o plugin de publicação no Dreamwidth"; +$a->strings["dreamwidth username"] = "Nome de usuário do Dreamwidth"; +$a->strings["dreamwidth password"] = "Senha do Dreamwidth"; +$a->strings["Post to dreamwidth by default"] = "Publicar no Dreamwidth por padrão"; +$a->strings["Submit"] = "Enviar"; diff --git a/sources/addons/dwpost/lang/ru/strings.php b/sources/addons/dwpost/lang/ru/strings.php new file mode 100644 index 00000000..98b08781 --- /dev/null +++ b/sources/addons/dwpost/lang/ru/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = ""; +$a->strings["Dreamwidth Post Settings"] = "Dreamwidth настройки сообщений"; +$a->strings["Enable dreamwidth Post Plugin"] = "Включить dreamwidth плагин сообщений"; +$a->strings["dreamwidth username"] = "dreamwidth имя пользователя"; +$a->strings["dreamwidth password"] = "dreamwidth пароль"; +$a->strings["Post to dreamwidth by default"] = ""; +$a->strings["Submit"] = "Подтвердить"; diff --git a/sources/addons/dwpost/lang/sv/strings.php b/sources/addons/dwpost/lang/sv/strings.php new file mode 100644 index 00000000..3ec569a7 --- /dev/null +++ b/sources/addons/dwpost/lang/sv/strings.php @@ -0,0 +1,3 @@ +strings["Submit"] = "Spara"; diff --git a/sources/addons/dwpost/lang/zh-cn/strings.php b/sources/addons/dwpost/lang/zh-cn/strings.php new file mode 100644 index 00000000..93e075c6 --- /dev/null +++ b/sources/addons/dwpost/lang/zh-cn/strings.php @@ -0,0 +1,9 @@ +strings["Post to Dreamwidth"] = "转播到Dreamwidth"; +$a->strings["Dreamwidth Post Settings"] = "Dreamwidth转播设置"; +$a->strings["Enable dreamwidth Post Plugin"] = "使Dreamwidth转播插件可用"; +$a->strings["dreamwidth username"] = "Dreamwidth用户名"; +$a->strings["dreamwidth password"] = "Dreamwidth密码"; +$a->strings["Post to dreamwidth by default"] = "默认地转播到Dreamwidth"; +$a->strings["Submit"] = "提交"; diff --git a/sources/addons/embedly/embedly.php b/sources/addons/embedly/embedly.php new file mode 100644 index 00000000..924c21dd --- /dev/null +++ b/sources/addons/embedly/embedly.php @@ -0,0 +1,25 @@ + + * + */ + +function embedly_load() { + register_hook('oembed_probe','addon/embedly/embedly.php','embedly_oembed_probe'); +} + +function embedly_unload() { + unregister_hook('oembed_probe','addon/embedly/embedly.php','embedly_oembed_probe'); +} + +function embedly_oembed_probe($a,$b) { + // try oohembed service + $ourl = "http://oohembed.com/oohembed/?url=".$b['url'].'&maxwidth=' . $b['videowidth']; + $result = z_fetch_url($ourl); + if($result['success']) + $b['embed'] = $result['body']; +} \ No newline at end of file diff --git a/sources/addons/extcron/extcron.php b/sources/addons/extcron/extcron.php new file mode 100755 index 00000000..85169fe1 --- /dev/null +++ b/sources/addons/extcron/extcron.php @@ -0,0 +1,22 @@ + + * + * Notes: External service needs to make a web request to http(s)://yoursite/extcron + */ + +function extcron_load() {} + +function extcron_unload() {} + +function extcron_module() {} + +function extcron_init(&$a) { + proc_run('php','include/poller.php'); + killme(); +} diff --git a/sources/addons/extcron/lang/C/messages.po b/sources/addons/extcron/lang/C/messages.po new file mode 100644 index 00000000..e69de29b diff --git a/sources/addons/flattrwidget/CHANGELOG b/sources/addons/flattrwidget/CHANGELOG new file mode 100644 index 00000000..fd5f3538 --- /dev/null +++ b/sources/addons/flattrwidget/CHANGELOG @@ -0,0 +1,3 @@ +2013-09-22 Version 0.1 Tobias Diekershoff + initial version of the widget + * add a flattr button to left or right aside of the channel view diff --git a/sources/addons/flattrwidget/README.md b/sources/addons/flattrwidget/README.md new file mode 100644 index 00000000..9fc30baf --- /dev/null +++ b/sources/addons/flattrwidget/README.md @@ -0,0 +1,76 @@ +Flattr Widget for The Hubzilla +================================ +This widget is ment to add a [flattr][1] button for one thing to the +left/right aside area of a red# channel. For example this could be the flattr +thing for your blog (on a blog channel). + +What can be configured? + +* static button from your server or dynamic button generated using the flattr + API +* left or right aside area +* URL and Title of the thing you want to be flattred. + + If none are set, the channel URL and the title "_Channel Name_ on The Red + Matrix" will be used. + +There will also be a widget that adds the flattr button to each posting +separetely. + +Screenshots +----------- +_At the moment the screenshots will only show in your red# admin panel._ + +![Dynamic flattr button in channel view](/addon/flattrwidget/img/red-flattr-widget.png) + +Dynamic flattr button generated from the flattr API displaying the number of +flattrs received. + +![Static flattr button in channel view](/addon/flattrwidget/img/red-flattr-widget2.png) + +Static flattr buttton, the image is hosted on your server for privacy of the +visitors. + +Feedback +-------- + +You can send feedback, bug reports etc, for this widget to [my red# stuff +feedback channel][3], you can also leave a flattr there if you like. + +Author +------ + +Original Author: [Tobias Diekershoff][TD] + +License +------- + +This widget id licensed under the [MIT][2] license. + +Copyright (c) 2013, Tobias Diekershoff + +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. + +The _flattr_ button located in the img directory was retrieved from the flattr +homepage. + +[1]: https://flattr.com +[2]: http://opensource.org/licenses/mit-license.php +[3]: https://diekershoff.de/channel/basredstuff +[TD]: https://diekershoff.de/channel/bavatar diff --git a/sources/addons/flattrwidget/flattrwidget.php b/sources/addons/flattrwidget/flattrwidget.php new file mode 100644 index 00000000..e0c0f87e --- /dev/null +++ b/sources/addons/flattrwidget/flattrwidget.php @@ -0,0 +1,129 @@ + + * Maintainer: Tobias Diekershoff + */ + +function flattrwidget_load() { + register_hook('construct_page', 'addon/flattrwidget/flattrwidget.php', 'flattrwidget_construct_page'); + register_hook('feature_settings', 'addon/flattrwidget/flattrwidget.php', 'flattrwidget_settings'); + register_hook('feature_settings_post', 'addon/flattrwidget/flattrwidget.php', 'flattrwidget_settings_post'); +} + +function flattrwidget_unload() { + unregister_hook('construct_page', 'addon/flattrwidget/flattrwidget.php', 'flattrwidget_construct_page'); + unregister_hook('feature_settings', 'addon/flattrwidget/flattrwidget.php', 'flattrwidget_settings'); + unregister_hook('feature_settings_post', 'addon/flattrwidget/flattrwidget.php', 'flattrwidget_settings_post'); +} + +function flattrwidget_construct_page(&$a,&$b) { + if (! $b['module']=='channel') + return; + $id = $a->profile['profile_uid']; + $enable = intval(get_pconfig($id,'flattrwidget','enable')); + if (! $enable) + return; + $a->page['htmlhead'] .= ''; + // get alignment and static/dynamic from the settings + // align is either "aside" or "right_aside" + // sd is either static or dynamic + $lr = get_pconfig( $id, 'flattrwidget', 'align'); + $sd = get_pconfig( $id, 'flattrwidget', 'sd'); + // title of the thing for the things page on flattr + $ftitle = get_pconfig( $id, 'flattrwidget', 'title'); + // URL of the thing + $thing = get_pconfig( $id, 'flattrwidget', 'thing'); + // flattr user the thing belongs to + $user = get_pconfig( $id, 'flattrwidget', 'user'); + // title for the flattr button itself + $title = t('Flattr this!'); + // construct the link for the button + $link = 'https://flattr.com/submit/auto?user_id='.$user.'&url=' . rawurlencode($thing).'&title='.rawurlencode($ftitle); + if ($sd == 'static') { + // static button graphic from the img folder + $img = $a->get_baseurl() .'/addon/flattrwidget/img/flattr-badge-large.png'; + $code = '
'.$title.''; + } else { + $code = ''; + // dynamic button from flattr API + } + // put the widget content together + $flattrwidget = '
'.$code.'
'; + // place the widget into the selected aside area + if ($lr=='right_aside') { + $b['layout']['region_right_aside'] = $flattrwidget . $b['layout']['region_right_aside']; + } else { + $b['layout']['region_aside'] = $flattrwidget . $b['layout']['region_aside']; + } +} +function flattrwidget_settings_post($a,$s) { + if(! local_channel() || (! x($_POST,'flattrwidget-submit'))) + return; + $c = $a->get_channel(); + set_pconfig( local_channel(), 'flattrwidget', 'align', $_POST['flattrwidget-align'] ); + set_pconfig( local_channel(), 'flattrwidget', 'sd', $_POST['flattrwidget-static'] ); + $thing = $_POST['flattrwidget-thing']; + if ($thing == '') { + $thing = $a->get_baseurl().'/channel/'.$c['channel_address']; + } + set_pconfig( local_channel(), 'flattrwidget', 'thing', $thing); + set_pconfig( local_channel(), 'flattrwidget', 'user', $_POST['flattrwidget-user']); + $ftitle = $_POST['flattrwidget-thingtitle']; + if ($ftitle == '') { + $ftitle = $c['channel_name'].' on The Hubzilla'; + } + set_pconfig( local_channel(), 'flattrwidget', 'title', $ftitle); + set_pconfig( local_channel(), 'flattrwidget', 'enable', intval($_POST['flattrwidget-enable'])); + info(t('Flattr widget settings updated.').EOL); +} +function flattrwidget_settings(&$a,&$s) { + $id = local_channel(); + if (! $id) + return; + + //$a->page['htmlhead'] .= ''; + $lr = get_pconfig( $id, 'flattrwidget', 'align'); + $sd = get_pconfig( $id, 'flattrwidget', 'sd'); + $thing = get_pconfig( $id, 'flattrwidget', 'thing'); + $user = get_pconfig( $id, 'flattrwidget', 'user'); + $ftitle = get_pconfig( $id, 'flattrwidget', 'title'); + $enable = intval(get_pconfig(local_channel(),'flattrwidget','enable')); + $enable_checked = (($enable) ? 1 : false); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('flattrwidget-user', t('Flattr user'), $user, '') + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('flattrwidget-thing', t('URL of the Thing to flattr'), $thing, t('If empty channel URL is used')) + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('flattrwidget-thingtitle', t('Title of the Thing to flattr'), $ftitle, t('If empty "channel name on The Hubzilla" will be used')) + )); + + $sc .= replace_macros(get_markup_template('field_select.tpl'), array( + '$field' => array('flattrwidget-static', t('Static or dynamic flattr button'), $sd, '', array('static'=>t('static'), 'dynamic'=>t('dynamic'))) + )); + + $sc .= replace_macros(get_markup_template('field_select.tpl'), array( + '$field' => array('flattrwidget-align', t('Alignment of the widget'), $lr, '', array('aside'=>t('left'), 'right_aside'=>t('right'))) + )); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('flattrwidget-enable', t('Enable Flattr widget'), $enable_checked, '', array(t('No'),t('Yes'))), + )); + + $s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( + '$addon' => array('flattrwidget',t('Flattr Widget Settings'), '', t('Submit')), + '$content' => $sc + )); + + +} diff --git a/sources/addons/flattrwidget/img/flattr-badge-large.png b/sources/addons/flattrwidget/img/flattr-badge-large.png new file mode 100644 index 0000000000000000000000000000000000000000..1105305850621343d54022dd422415ddf1f659e1 GIT binary patch literal 1639 zcmV-t2AKJYP)t_els_}nNMyeFqp|I+&`C*Q)S_473%8C!<642`wf;WpUb9?&s{RBQi9P}iuC*<{RE8g)9KOwr* zeUgCwig=9xJ+fpsgS9-;Gw3PWLx`<&`^S!{ai!P)%~2{B1Qpr-r!^>F0@{&yy#W2( zC0DkMEYi#*^tXaBr};wMSH8i-6SXMxJ7ZVpq1U=e`e=&9A_wMMAt2ipXDb{f?~75p zA|USvdKHUJI;hZCBemfO>U%DV*6_>OE;*NwOLjO>U~RG<;Y*>r6K@cphZpYRpwC?o z!HmjW+;yAr@{t;B&ah9i_>7gfE5eLA+6b9#-JYU@g@9QuBE$EHHZ`2D4ou zLi}Pxjq=W2C~mV`5_)puuZU6amNZpmSJINXu*(kc&fJD0NfyjOMRqKoQ0WaKmJ2D~ z!No^Yw%~Z46^*%?Ug=vwRoD~*{~SwX8=#-KXd~32?TjWbP}TOPv-?6zcMARFK9=je zr^e8;yC&C3`0~(C=Q(lE-{pVFJku4!;<-m%m@3`^{fmBFe^7utoei}p^xGpXNUA@G zXqBs^8Q{*OC39H~ff#u{fDfu@O=bCos_V_*;x|*1ZN&aORW{6r45uv~Lr35K5DHMvg0mxq2T$AN?XCf%HQx+~R) z^VKM*x(D--skNdOh2A%O1qpQr5T$gLG}T2-G!7?hrWSGv0-d(o?SLRs9S_cO1(#5$MCu z228G#@a3TgXZ^_S>67v1%v0^D^YPn9LSN_oJS5j!GK=ZvP%{#0e?er`E=hkRA*bj_ zWbFurGyE=C;%M@>h$!+D#*luYEf!N{H2O-^6>6|?!o9|r8%NdBSBc;p7x-jtr#bed zUmt8XxlY2Dhki1{o&zuuY0f;=l8Pr2_XyyfLSNJEWW=ezrxyQ}aacDGz0yU>hD9YT znG49YLwkQU#*JG7&C`CNEfzEA4L*OTE*mG@YmB*ZifgfWH~kt^-2)ng7Tcq-HxGRe zTTHH#@a3TgrtRRimlvVt7>~5T=v@`$HTH;9eg|ED4jTHBXq!2%)*fQIJ#rNZH3xA{ z;UZ}&MSH@Mxu-8j&^b_pxaxgKR2~Bn&C`CN&Bp?C$-0#tiL@<1W_`w(n@eD>HNwlC zkl)Pqc6Lp!_CmfU%;Y)=UmkiuimeEA3k=^;AxdS3(-m7qt>}&f5qE6RH>5*+wI?FV zoh5Df(&Tc5ni!#7P#=Xuv0p>kk-_57OFL2B&9*$2Kap$0#q-d8CF`augW#REjg2D` z`i!x0erHM?P}QCe?<6aP7wiYs1+70yb#ZjdF}Y5{mxu0`WW)VM`tX(tVU@NxS++&g zm#>{;XEnU^=zY)xxpF_kFFQ+`0oI*alp7oW6XUNRv$pnTf$`Hb+{!-Q*&2VuR_$eD zsMI}aTuhZ*dt|A)^tFW7q~nN$J|Q;FkLK7Hvq5xTtiNZlUYM(t311$%Z-Og{mN~7OnDFJH{}FHfoE~`1&dp#s)b~(_xGGPaEp=M)4l8zqPrU7G?ij#FZg>88 zh8-w)A_9Nfu-)kY-GSH8Rmdwn5mw@~qJ6r^5tM77+`XAQ@CuJTxz<qoN$>h<83Fu9Wj&==)>+1|1j>LP2Jy!k6-ecgoiTfu8Yp?`+C)OMG lo{g*iWN$F=Tq6KC_%D-CKj~#=%!>d3002ovPDHLkV1i<{B$EID literal 0 HcmV?d00001 diff --git a/sources/addons/flattrwidget/img/red-flattr-widget.png b/sources/addons/flattrwidget/img/red-flattr-widget.png new file mode 100644 index 0000000000000000000000000000000000000000..c72263824925bdbd8de91e23aeb0f4bf99e51406 GIT binary patch literal 50194 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≪I<1MPvQ24F00BY% zzA3;|1*}y_StpeSRjviBbCXaWNE@Kb0eK5cM^9q^&9`E`zXnvcCXOf#tqdF-sz!mu zS3s0&rj9B=Ckm|u$P-kSx}nbSP0v0}X(24{o#t)8B#_4#c)c zN#!Nh;KFlu>9t;>nM+7H=W5|lh7H8(;vvS~G>=b5Mg>E68kUr031bYNeDX5*Kyc5fd3$-@6 zGf0wpU?ZHvxEM)Ys+dfS)3i`ovk8?muu3Ce-j74K-iiLD7cs6bqUCBS;Hv4vE@5Gz zpq-wSHFe?-Y==}gsK2w&T1|j*V=SDifU0ah+tvoI0PSjOZa!54-NgkwCq~Y^Jm;Y+ zlJ`TCaK3qeeVtcPcU&bk{TA)|=gA_FR6t$=-7&B@1Z)Z5ulA&;K0@V&EqPA~{ib0$ zjRZW7M2>7-^J14;uPAdSG~vFrB8G)o#}#c!$Fw`u#r2vc&xS zJhr#Daq{Fz96fpzRaN2hpZ`2goH#Kd4p7p-hd=yboIH6FOG`_5$2;DEPk!=~c=+Lm zCn3F;v^{X(0Dk?~e;o%89)z_Pd7k4B|L_m7v9U3=xgc%46KpL=&`JU4EGk#P8HLLi zUc!ZQ&tqX>5!U6XtcFWd*o9T-R*ou7G0@kL07$Yf^7(_v77w6O33}rJHj4^dMS;p% zz*>yU5@}wyb(WRIXk4K`EO7q9C4Bv{Z{gNcr||as--dhcz7t0d9fWZfqoQa$0`F5z znwg6Bdgq<>tvgMs16|kJRR^ml@4&|S7xBu@22zYr7=v+XU>Xtnv|-jkDU|NIyjG?Y zWT}F6w$_?g8f9f*jD<}!v@h^nY^(VjJMXJ z*XyC%?E(O{x3{5`!lys|>B%B?yWPo!T5Hko_wn$<4`XL%2LSL3zwiq%#$ax44#VMa z^8cNk9dSMt?*wwNwMTa~Q_40q-$d0z80>g}3oky0+itxBorMm@<1zA98`c25{tz!; zxPXh#KaHxau(*5xM^ENB*f|K7w=ftF;B-BX*ENz*sjBl=)g;!=IT&kUjK%2MI<~jB z@x&944x^L)fAyc0G^2HdYz9zC9c&SJjH8&ehV)&1hbY6y>;&E0-?d@`dxb{jPl|j6zkE zxODM69)IjB*uM5M>}Ut3Dsk@YWxRN{hx;Gs;=r+!uuj2L4yLk=mQ7lZ3pT!H+*AW> zEpDh&jnY~e=kW5SS8(OpH9YqC864cVA16-Sg5$@J?==?BHSt<^u=QjYU!hh_o2jb{ zjp@QN(4L3WIWm;c04i4_)v0qx;OCB8q&lg4&$UB>x?Jd*L#Z?l)-~0Fvc%bMe+yT7 zecbon58}YFQ*b(M@_j9vx^lA3PXr!m8O=#$267lQ9^5f+pWr%9;amV4XvjGJ;BY*; zaKU~K4sP-O?wCi9mFHrl7hcP!2swQ&_x7}fmWxqJr8XZ$qC`* z1FaK``aL}R^ckEyeFs$1MsKH&?cO%FHn%Yzm6&UFkheM*RwJ|)7Lc@B7?opGw#29$ zVp#NHm4!`Q!)|kA4tsOs8qK#FHLs1funNV_09(Ctce?f z)VM}bxjJfa4pv*(VvMuj`4;Av7O}K6kIvG57}Y}M>Ofu;o(Q4sc1pfZ4IGY?-fR=H zJ8HSRjoMwWRO|}-9i2=|=FSU;lpkY64UWo2h32wJTy*M1Y3R*!_z5kXq2`>NvsXY= z?Fr+jr4!Ks4zJaRPEuc(ZM@HQIV{(B$xSd=KrK8E97t%jn#fnTS$DsR}kZeTs?w{Fo*;he>| zvMB8sofTpdgKgxwhADPn%065*gtHaOa)j})kGZ9NNahYA$(G=B4&@vwQ@}WjVOb$@ z1@cycR9QG(4|{OV*25rRp-s~cZ0nhE)&ivg3S0loHHVEC?xr?d?B|B=2H08rOVuBS|#Jf*dP7p?q8ACSf@@7`Og3Y^Jceb`hh&CdQ*as$z^{Jc2P}EU)fEcl9Wi z4xEHZmeESuc;%&MaPj3AVX6`XQ#ZEcsYa$6qje4zHK=BqrlEQ`Bv7I52QZ$D;xE@Z zz*=Z$G3u@3m6x8z{OSQL-qe9jyRec9>;wdJ(T?W$8hTlllWU`mHT1eU>4ui{ zUN?qrsyaVTlBDhs^EKCIz@hbHlv0CpFFlXj?zkNX4%}o z)3KXy@%&j_e&uCUWrc->Rm{zIu(`Q`r=NKeD+l(Y-H<7U!*SDWk~AZc>yd+NdX;_IF?g+t}IZW1&03mOGDjYZG>qLXUgU zuqdkvND?TdwY;^nlk1s?)OjvDER0n((X6>FUwWgVV3O2B6cSh{JI00QpN8t}!|L%n zZXideqC;TO#*U^%-^6VL9~K=1MBoR`5FY~Juf{pu2fjt^4^A?%Xj z$E2k~gB?TMcZp4>o_prZu2&zu`4pJM2XX@b#--p*MUHbzMJOBW%iEF3V{ecgB0H;o!!V53FfWP>Q zzj#eu`;YzDkKyjS??$K75k($pmn22TX;|%_OVM<0zOYady-=53 z8mdq8i~8FVs(UqVoFoh|4LSXOyY^X|8@`{eo6aNS|9&m3InS3VLQV-al7^cklFA1! zhDu)4)@T$!k$Ncvm!zen2t#Um*<#uup zaS^Rn3rkB&xaF2xcCGu3jx&k@O)lVX9R1Ld;}adYUayC1*RG-0>!B>mV6MT# z1t}e%T{(VXJetS_>iG=}$?ei>SXfxV{{8#moWt7M8g_PeCTbqEXP7Pm-%ufi5PsuB zs4K0V(%1OU=i_w!cUW3l!ph1DwANT(Uq`Rk+f~Y;2Nng1d<4crX1^}9+#;nnyza}_ z*q4yF03l!VPN##>XoPFmu3>w7dslroX1G%R$q!2!4)fR3`znb-aGI#U{v=7TxVVUY z`}SdZd3mC*;GaiPZ`xtzYuR*t_@D*4Zu}6X>^FKC@YIK+?!LRu4}%O%hmpd4{~bgr zDgT1GxjD4k?VuzsKlS(x;t)UWS?4z@gho<>;t1$2IomWvyWNJh7W4D-yYef(iMbrF z1jIHy-yud^6JyD0*+CO~4I;zCO?MUEkRo z8y(l{!`=D$d2~9RJxwB#7m`{)B~}{OSEKuf$|~`kn0`K;e!{1eQi>@3xfgu&@9E{5 zxz0NW(rCM>bin!dqO#1=J&+tFJ?y55VTe^J{sZcP{EhTCpI#VmljH0kx={2vG?be3 z$~Fs2H;|-kNkcJu11Y14dd*OH%B6Dob%wx4i5MZxx{{2Et|0|%_~uBG1g%zUSJ_88 z2>tt0S#9rqeCsdw6cXqfGJI-4(sz+k5l$lE>q8^B5D3igJ6%)0$6~c=N`eXHy3$N@ zDUIX@%CvNZdR}h$QnbiFn|_X88!i~^Apq?DfJXwtWF~F(+j7@&2t}W zwDgP7pM@q@NMBY$I{kZaxvbDekk%&Fp2)*Xssbu`)KFPO0%fGMfg`p2P>od}LUO@8 zWeQCd38gUfUi0YdyG7(_{!8})|2MsM8ohf=OwOJ9LBK(`W>Zf=AfB$ z-O?c}rHnNC;_}TLyWp%hDb?h)_0ZuSYPgYzJh4bql#=4!oEkp$=6=J{;qBZTOJO2C z^(0|C4$yFK;D1g%7GK!dMwU+1P`h< zn@J|2?$U6=SxS1GL(aitF8UxHaNL;ud(bi&J*apz$8Cq!z3B`!eke=#P@3CD*DQ@) zxa8^l2BLy@bc2QTt3t*u$@qj$w2)vQ)zPA;u@{`AMokSnl;3*KBW(mJI`Hq!%TfHm zpld2=)cd*G^cp1s23==bUZd-oW!Xd%pKnk}O@+?}LM}N zc=X0WPkM-PFi)yxaKzs4b$$Scu$@qf!J`B|WI-}iN<{MamjmH+9i^0nN6$eOSn5q_ z=o!kNz87LltQ;eSY&Q_#|oJ&^1oGml7Z+g^xE%fVvR^jU>b%9i|e3AB!L)XA_HT_;=s{H3!aU zM9L3)8cli}CzKY1QrS?NLid7LUXw~Wyq4!ry4cXTSXo7y$|`AJ#mE3WFQhtIy!l@$ z5%R-?1B9W2fNrwb;`7ZBIvnU+Zm;p>siYD(MBkq`Q&7+6JrXB=R8_TW7+|bYArXT@ zSV$~vo)%WeswtsVhNmCiAyLE6^IRNo!0$Ex430HXgPi8v{4hnnk2vth31PgFK=(5J zyR;6{p-aKUG`5K;nMKOW{F{V;kZC8+wAQ;&NX3mm)Q21D_VFBNo)gnWrlE6;NHdMP z$wSW2$s3a#j(HxcNlxF(8#E_}NcZZy@vzc;nx)J$D+m{2$WerwAJCytc^cs3 zsz{=ebU#WVH6@OP$S=}$N$gFj>4v78yV8Le5=l=Pexk)TP0Zk?9V{XKbqFO5Z3?aR zE-Iq;d@)ZX5nra=2nivUHcRYa;6x&tf=IxY6wXTP;T1?Y$U}408!_@2C^rjuHVaTT ztp`EkvGd4{v*%*>J>*!Z0Zlu+qzIOR%M|dG?tLt>lJ=y8Z-p41K||-YM}GoI;TjjK zr)Xg)w+N9HLWc&QW=R1ws{X+NH%{A?>hU3V6d#`(iVkM=Xw!7UB>uic4GxvGq!fz- zL(*gtDMg!hXi0T=9zurl;TS6k8UtcoYtkZePCiG6 zrNc}D*?3MBDuYN&su*E~(qs8e<%c5|JKzR03yDRF%4Vrwhrp~@>J}mjNtFkQ$}7=m zxv@#jG_m!N%4?j9?|)A#A@rIkU0LGA)0#VXbdo*MstX1BqwQ9d~b4k-9V zPggD`FNJ!3a6Bh(_)W}n9?GWUpUF#Rp-mJj(Qt1=y-AGg&TISp;FG+#ba?W*X>9Nx z{Y=^?KpSZI!9;<|7z0nLvcwE7R2~ftMv(d#B%L%VB;~{5PEl}9ik_tJCmoEEF>{VW z2s@GJ%#yLk=(7BpBtClx5T#yD%HKnn1Yaj!DdLB8s7p`E{keQIZ_JT^Th4z7)$jei z4z{V%4d?&lc|IYbgida1B-DfRa503IbH0ZW`DseO^e!k@6H`jaD&?AjT%;_fP7}r{R8< zWpa5f6dLiH!F#Kv#R!Q5NMIhX0dl@Czag|&o`>+#2pej|oHQZtHhLV zBw$h^I7#@+jev_W=Mp;XLZF%l)}-iz-eXBY*53z?QBivmnQ>BS%o`pB6GCV>-FVX$ z0Kh~UhRZ%tBr$|u$7qcbb`WFS@f%GS*%&jK;~w)K5_dbcfo9PKlYl|~9cj8m4TQ=a zake1$M$?*ULS1nZhyO-v^C4h#mX5TLBbb$n8)7fU(lcIBp*g>wwi068h5Graaq_Y# z$F8I_fIG!qh`$8JN%;gty7>*4kUt(?NSa@?jK|vzW1T|0t{U3FQrHxe`H^luEnS4d zxLDU7N8@7*EXf0Mtugw%SgDVCV!q*cq!cO23@sl|yJP-{exMj1Q)ZQ7>r?RC-O!;A7~#l;=uSg;@21hvOj@A3u0$IWEML zra~aolxL*&Whn}fUdPik8s5_qU#yH3>)#IbHqg%rwR}o+>rh%4swVL?g5o6nFy`bm zexOR27`Ks-^j10z&EyCxHGJAu$q{>>KU0HfZ~)leFZxLM%Ul=?&xPKEF}Z@;M32kV;u0j~ly@q2A(9c<6su6a`wX z7FJhR@mhQA?CeagKeT~8?>qG1T>TJ}Pf{id$w|e?K)iomy5GDHoktW@hn)kNF)FPj zC&klXdT7$FMlOmfvHbis`Qa4QyNl&D-e@1HgY)o(3pQ|MHwIpXc+^sN+$^=on1Dh^ z7AY1k(*cCBP&>pN3x()qS-vKX902C$=W+S+AjALqUyMa$IRvmXs$-#!gT9*id_^G<75B?`!$N6?6E24e4Hl4*gJbQ%Le! z0xSLRy~>WHhtJoaONmL>zzv;yUFoos`1PSfN0KY2XuP)v>hZbLqUFz^p@-;%5^61- zX4Gi--}x8gb#sY5mSx$lFBF;p5?Z`a-IFdBy%wqk&TITWXOftD(s0UY2k2`lC!bbR z4r$0sT#As?RER>&4Lu~_$PZUf?&9~JYt2c-muUiwG*6c*L{dAgH$s|*`aTcZ@FJxO zu>lP<5}=?SeZEM6<)}NYWlJRrdNU{^h+d@EnByLwUZ6B4hhOra*K5MNws8sSpR{&zlKm7*_B;0eh! zOPcH<9=kt?cm%`6A$h9Di7^~U;v<}BryH-UOOZ=-Qp>c#>l{g@Xu3z_seDmPOfPgo zb7o$w#w*=O&I9K)O({pGAvz@p@jOY&!9sM-Sru7cs~(+q>q**Y6vN^7j)tDRYl}w; zp|)meG7eV@qS0Aszs2?zms69fJ0W_jKM1*Wm{ifCMk|#MIrc+20}>lDsOv6)BOUWKs8`XW$LhxtsLS`7B%wudlbEt@2vv`bHRAVVT1TTqO5qaB90jLU z9{N4$&=cw;q}Epn1L3J;3{;#Pgt60^egP?@kVGm%eaW1w%X6ww`6L#uhe~PFx|(hMLYG?px=)TjnkQ&6K*HheUmQ+yckehl3B%-5soJnGPC zJgu>Xp7OkWN6RMCO`dg57as#1D((5sHi=O5_mPi3H7IfKVm|qIzIZRn{*!+vIeM%e zH%4soxQq{J{hkWp9a775Xy0-$E;Jc6#ChkR>koK7$tTn==jngna*G9?tY%b+U|vM@*YiBb6zo-gfEm2$g$zM8?ao-aGms8T7p*=3^)wl=5(j zeskcLR-*Vd#;~K1;|MAGNO)BmGA`*$&N9A;&mZHHLMQ@hj6qdZlapMM#o;Y_d~)w?5bfaO>?C@a(T&M@{nHMQR}+kzPZWBU#bRUZ&h(&?xmWGLnPm_{$lFUi zamw)Wj6^<2k%M+Tf}@+AMwn7ZT4)9!j~x8x`Gdlv>|TV@r*r;yk`i%MRg;PoO#?ko zJ(fb!jy8!REY0kTQedS%bZi3N-l*=|9htgSgNmEtN=e+J9S*H+3^Sv0dO@D|NF;vHb+H z?welK9Gw$2LWd;9f&6QH>4-`p)B8dVAS8?^u_}wAK)c=EmCE_w`+Y*ezpAPx2FIg7 zdc6|(>i6GZFxa(!=>gShwJ;iuCTuuKPcNip#|bl%Of&`GytbqNE_)1}Z&G>_xoBc2 zG?hG>G&9}5pM)aLf>?)CV?xabG-ryb!SWMPB7jh|RRTdc%FNN{SMzcAyKlz7edrOq z>A!jp7O{;-9{LuJKk$!V_0XLU^xzvalp9O0iQzIKT!+4vGc>1#{*-AJODRLx5~agR z1TQXqE=4!of$*_lvHef~Pxttw51zl6DqDo=k|ARZp`I~SmuclP>E?!pA4n&#)XpbS zB4cHmX<>LsK}V{wQc2%g(dZj}tlaq_JaF~%_@n>pUtxqcPTl(e{^6@sTH{6_fk~eF zDm81wN~59Am}LlqH*_hb3g!Hqk0E(j>Aj>F+3#*MOso`920QlWnbP{#V73W*GPv4H*Okn zhE$BDLxGC6a8;)u7{@m=KlNycAmubtxj{l#IVdN2Nj?@R79R1r=2QiQ%Q|y8pwOv0 zjQ}C3v{GO)q+H7>kgtb_|8BH`5}KI8D>5-bh}a>?D=ZSKE|FP6m4O%wlQJTC`oOz8 zc?2*`CVU$HFs*vS#Yef&N>x>|N9RQUP`JXwG$|~LX|qvMgcR0EuXQ8mo?TLRmGVtV+ijM4Zr<={LlbvA9)0G$ z7qK)-63pa+l~Rv~ul7h2Y4}tbY3*o^PPy+q#g%M@cMnn?OH}TePkrDsqxrD7(46O4 z6jnlclq3i!0fZ8XpAH+Kkp@47C2)wAV|Ya4%XGZf?)d```dT%1 z+Q}#ZtUN^vO|?>-XXt!AUJKX<^JPgj~h z(w|8aH6+dXY2=dE(_`9HTW?5y&FBFr0lA?K&S&+}!#K8|VvZ!XheG9GnsQ2PHcrHu zRt5~EGZJ1Ex^__7ZW!-a3M~rnWv97XNUR|S_R-LU_ndnpqw~jTIL7I@+@nYb zhScLuKZo}PQ>=h*q?q>HYwaN^vd$_78JZp|O+V%6Iu|3I)!}f13-wG$V~uwKTqI?n zpXH+ndi_*flHaWSnk$}5kJ!I>pwl7{KssCT;&ExB0FJNK@k zdF;{cQb@0r7?ZSgDV4(b9QJ7kc`UsO@zg`(pZPV1Lh}%pCAL2#IyQaJsnb+LAHaLe zxfkTMZr(sLi%>ueA?1ubju~+JV2A}J)hH$T-%xHx!4y8wFNAIIjg;s4WDF4(vJ8c% zA+L4q+O?puudJ+y>nU*}_$X?g^GySZLLh5M{wPFk4fPmEMo+et4q0mC|uv~0{^KohIm{U$e+H2D&fgz-n4u+uDB^f6t z0P$<$8_bt?LXy$afIFUE@DWoK5#|RXy&jL+)1Cva`r}JS5@5Kzyo{=a(ER)Hh6`?>+!IUFbLjn-T2QstlW2(xgNEhGM8X944+6O~5*p_6YGR?xJ;1`?i-^xtM-zL~zVAg~EMlVZ7|FG&hYJ|1=;`${nSHiI;JBzcbyi zG>7x#ozP*jw6qkwx6`J7NCJi-WQCq{|p1hrYlWlyX1^Mh;V*=te=MHi57oS0fhsC*aOK(T+vhAn=#8%(O*PU{Pf zRU=~2iS+$E34~9cp(&9UFqnqm#!5)j22e+X=Np_0Ma1fT)YHYZy*SY&mZ!(S z8UA}N^uRHLS!%(&FP~C8X}BH&;$j-ufE%fsOVy!}n8yuGYLUEvWMq^i67mAGjw+JoQB9kK5-L~R2<0@yC*a*q(|FXO zgDf_Sormdk!_navUWik=@i!uB5o0k;lGjGT2cs+#v0$q zh7S$Ule}|?loQ(YQn)M~rlDpE?|DKfv4jCgIkLnmlnhYfv2!mO!%(xiZ*M4k!N>tofZbe4Eu8lMyjw|I?P zl5>)BQtA0zv`?yeOQ$*Q9FjI?2oMaR$8_OnM-(>>-W(wjgQPH0I%p*E3Vwi5<`}(S zbd&l4ev$-MD3q5xo+MJp?@4Hq2!Ah%Pe_M4-6wni0u>DL{og!H=Ig+JMz#4v`$6)K zvDAnw<4C14+F&KI;-pBAk8ldfQ-@^Tg5r=N`gg^Sq|AOtoI$l!`2Q1F5;$!drr&#J75EX(#$gs2~ zp#zO?at@Nk)P=lrnzim6La(QdQ4Wo9mi91bi2B2f_RdSMqwB?UaSjYhUVSDoP6|_I zq2+~8a0yM9NI27Is*-e0D3p(pIi}@$vw}{s(pd<5_@l4>b5uzm`wq{&#_Zf-*z4hs zzVbWx+4uZ&u|7Wy{EV#=2ex8d^B6cKh3!(LBJG7)b9SjT8d5cqa02d)B@syaeWdRf zqUi=Fweav-%B7{U0S96DDI-z#INK_8BE=eQLi9mN=x-s3m)=by}>4y z4|ZOY?W*nh6dRYX>_VBnfP~a-7>f30;T^>A9g2@|L#1J~6m5k7*lA#Kj4)BUM5YaktjGJapw7F;DSjWQc5W*V+<3gZU2r%N{-Hnuz zVzR?hnQ-qf6<#efx5h##K)ou`(h3f{jf+c+(HxtyBP9SbX6RJPo9Fi-k&BQfKfRvN zzLQ3QNp<&GqrX_UCzr>T_AXCtxJ;TfL^R5b3yrv;h~U=N)}*PzT8nnOjc&KQC*+FN zLg{lTL4gBQbe7w+`l@uAN#833s)UgFSW^zYIeadbgpN~mmgc*E8xLc4dnm0Ew6P4p zqHsIm5Yz!mlW-P*{w`RB+`CeNL$AOil|!X;kAkzb-=BUKB`<|am(+;pzT#pQ)U)zX zJ7)0H+DZ9g=gXoJ$%&5O4x#cC6O$ZN=yhrAG?Ko+3opEY-}sH+z`1khaOu(|9653X z_uqd%e)U&>6-SO75gAb-_S=ojsJ_wPPg9VQgdk?YDPji&mBF4CwM-Co_8v=}LwN9x z{{|=a--|@2^%>wC92{QRdJYdg_9+a@p7@^ovs2fN9wo9o!+obdh_(JXeEp^WC|`%m zkn4Gj+y1ooB`eZ1P5s5L-?vr}1<^68H@92|^;E)QL!A zhq*C^s!ZGgaMWF5{P7l5Is=`zDf3j90_0phHzfTQjOVDB!p6o1zWUX#B282L_HX|- ze(9Hf37`1HCs0)te(Se>3-5gAJMnwJ_j^!E;fr7V;^ZQWqL|3)P_IWrINtC=HwIT) zX4!E#(y5YIrMauN@>)S_%_bra5zza<&^|!!%2DId*1YuICbzoSZ6UT zdZ


kKY#K8xore;xnm9sewN(EZep{s!KE-%sHO@BRmP+imZ~p_QAF=tj}jSeVkF zEDXwV1ydQo0*B^L=&2HI$t(js+TXq8MoV7;fJBcQ zm?OnFS_t6Kj(mjk&VB?&{ ze}3-I@$|*N2DHMyrK32$?_R(G?Q9YIyC<;N-Vd!3T-Zjb8dB{FXBMdcM300PA`qTOtLQ!9= zZ=RQzxuAnIJRzi_BzanT{UPxQiElt7gpgn){dYPI2-8~Q$dM!X>7V{-{J|gm0p9dC ze}nxmzKEabc5&>7eh5!~@r&4b>M5MR=N`N;H-}&R#a~3b-451DX$UgQq>j*FcZyJQ z2Ao92lt8f%I?i)N>F|@*DRk}84mQU^O{K9@?BJ=3kK)3{Q|OO2Fe(RF>K?#iXFrtE z5ui}x&Z9q!gYze_F}#RNy=Uw92heRV;qb~SI18*S9L8-oy&Zq{?f(s(&OEeM$l58K zOOR!4WF|qHr?~t055ZZBv+HM2n(<5;e3WA$d2TK=5h`&?#3|`OpCzS=&33zykeo9^ zdGrzj)k23`Y}n+iRR<|@rQ(#qI(q0Lo_+RNjQ;h%#&HhPzEaqDTkboFt(_4o&{-n)dyUi<<|JD%yQaG)`y zp(gFO8?AWo`xC;JLL-?tYA@*{hAKTAd*bD>kp6-69cd&P0(xU$HpiVPTXJfS&TqoC zYu8{eT);mAPysN1^;h`%&JON)?|bo2n&)mj|2%rVUKF_D_0L#IB$TiD8|$^!c+HU0 z9;N(^(nNWFE-h>biRI`j55H#ZHQsePs|2aeadhPl99TFGYYntcp_CRkAN_M-?P)x9 z@vrgn+LH}}ULOv(9{vIBTR4j6uYDaaubly4Cy4v*gLb#E6pbej{h<+wL~oYZW3f=0 zzmB)saxw@9v3M9C8qOJ`ddE=o5CM$t0eU?&SLZkYcS4fH*)%krI~kwTdrpJ*?lTEb zR8@t3zYhSI1MnrKu=2qV;=g_78EicA2tEqH0Qm0#Y;0^yE}Cn3#W=Y!bUdVxIc))A z`essIMJK;dkWR{lV#JA13KFC0PBx3P*yz84<+($+>*xcxx_u6yOuIzo3Y6mt#i)RFO$4K6 zk4~hKL!t4%G2zTv2s9Kwne{NCdn#6Uj4g={p@tsfbRqF z2)|NF_UQZtpZnbB@VmeJy8wWf0DO3L6`Ozk*Vs-HoPGP-@snwaOU-M4?bm({k390o zo*H5ZV33TChecFcsVvJ$ulsmB#&|pqPK@EiehFBiwQVlr!~qY=MV1yklw*c^*{{F; z`kzZ1&*7!3PvEV`-;X29r*X%TAHe3+;3(-S|4h^?G z0`IShOF&bCODN)_Q3(geLv?-nJ8v8Qd3m0r)oRtB^V~CMcCEtUn{L_lWe0-+KJ}?j z;f_1*z~dkPI1T{#7JyHG^rQILH@}I0RTTK2H#hNvy&gUf;D7k?m+_g;dR(y^&DOH-GQ=z6*hPAqFQe z8B?`bZzEKjep&=e_o?K}`~i?kU<%D^=jP_{iBEh2XU?3#lMgoWm-MHb|H9PMNMoRQ zULWGt`?+jVI7UY`)0^oxR>&JraP2$i{}aA*{y)9uc<(g&3CR+31U+;J#KbDSSClZ7 zP}e12cg~TZ(VSPSp=`XE=%|RXH2E=Yivc%y>A4TuUC-LaQ0+Q`*eA5{0eCR_cPM@CC+C8ODQkRiJCN5#jdG#U0o0k?O z9y2$-5U55sQ>;f_(s!4xlY@LR6VJgq2Zh((WL1Z~*Bzq?OI?DzZ8OvpASu{*;tajl zochW&{V5R3wE!d`kXWgX8z&Xtpp#)aF2$=e(}q5TstB=$uRZ#8F+zcVgJ+(32A}=x zXYsQ?`?L5bpZ+xd^Ido09{{-2>)|IZT)^1}AH>i8&hOyoe(vY+o4@&+6XcyM)A*B( zju+-*WTcDbf)n(HQ7=kgnoNw(JOMG|(^<1PsEJ5AHQhJMqrlY0!q=PT4RN{FFULX!-Rf>NO} zm|qZzUWSlU-h?o1QcG;~GhZYrN8`gPLUO~rSwiB!^BgurzL9v$J{R=3N@yZY2#Jo> zsj0z8ns^dJjP|2TYed&vx+ZGe(%iQgZWE%(QpZB?1CRbfz?rW+@m}z0r8}O7`!(>q z4_-2+DW12FQ0gl&F{S(I54j{s_U7o6&KDyMNFbin(n@a}4dJDHgV#2x6c8`BNi<8E zD@jHX%e7*4T$*lBy|K_J9omac*GDS(al_%APq7)Q6WyY};9z999c}T-9r1kDMx~~S%J?f30A6^ojR}wpwDBOJZ8!eep{XeS(G!igNYc`U zM8J_6SLltB(gEJr%vDOHUVG^v<^24Rx-2yuUWTI2@tt(i=pSi_p=2by3yXVf8p-+J z#ZoAVHq84K`2Lf|c}dsKMImYE%GcH(NL*Xam*YH7gF7*49F`>OMDG~|Ws9N^4;LQl z`_G_+m{9Z=>pSoVOB!P9#FROBDB(YlZn{_(5zp1=;lZb%`dVj*&KLqj=*{6LXoy1` z>Q9fcyy$gIQx}ys{WN`hE|TbZ0z5noaqy+dtl+(bU0Hc!HQ#u=@%Vl~1!X zH3{TPl~^nNU??rVXg_FBgwl${ylfz1X~0Bm4234X(4q;2XlZSr!5A#s3XRy(qG=(i zjWNkKNvWnL9~3GSG)eQ=cC+t!_+irpHN{vrk}Z2b&YZdToWuFgIrrXk@0q``Ec)D> zEMBd7iS_Fqxa*A}7z}ah>uxTMUE!BsuVEMlYwue_(fSA3_RLebT&^@?QnXpdr*8fy zq#y1$%6CH-dHRVhyjW4X>IJT8*vmpVUSaf~1i!WE<5U54`MCf910hL7K~!uUX>D0i zz9Nw*pP%TW-#d(H!sbUdQB_`wB#QrwUdF~J_^9JkZY%^*98N@80YHm{2?rJsFxXwQ zlT90n(x^$z(EZMFK0oi{`;k%X?kvvt4^p~)E2`bTss;Al^yA9Rrt47ivgk`*X~gH7 zTk+ax9iJWJf_DVP89z95wr_w~Ok-Dd)r#w6aCnr~!|gb;b8zS6A&4RtA-;zzi4s^W zI8~LN{vmW-=i!YT(#T0Qpc{8+zrRgRa{SAah?0VAR|!NT9BluD>dG>5J)Tt@!&uQ` zF=m7DT<2pax~P1<G@u!%PMyq6F}k-~e|u=%k^ zS7dCz-_N1;PBJ{X$f^U2AS9~C7@9^nus~s9A;nuB=U`hKKTS-qZteZ)F#c|yqqnqv z$jId%unHogC?Ts(RCgv=EhtVGSAM=q-JT|NUBfVRHWod^-iG?sCGo8TCyR2QICUD` zFsUqE8tjH)fN7$yfJYC7LJWF`nVOkJvO5rDTVlQ-C^9l`&JT^!-Ft!Vo?c$x(}2AA zBS-;>0e1dYJNeC7tg?cvI>2hd)HI^e2wFIdu4_D5T+EKG#q54#AF}Eq913vyTn}Z> zZBL^orGWk~TvdHtEpP5W!1T-vid{vJ;(6$%ZeXEEB-i7izOI(#_TSXp zdfRvJH#Q^@=zwV?__EpToH^G^G#aC-vU~}815D79?9!*Er`gxCAD=&ftU6H~PE5o6 z)5?J)*$@_WdiB~Q$Gg6ws-i5Ze2k8bBPokzn{|_DI7EJ49<|jKxK%qD4wVB(I`R1z zaAanKX>#%MkCZ&SEsdVk3f-4)z=9~!+*r?BAGC3O`Z|InVHkg@$*gG<6cq68YcFG3 z1eV)>$9qk@{qYxnd;ZSOa(?%RlP0i%fuZXOzASp**<@p3{?4xIDRuu_M6%yLOb3lNrAfdUDoB-@pJF n_v8a6f+R6FH%~hMBDLBd2B4iZezh#100000NkvXXu0mjf|68JM literal 0 HcmV?d00001 diff --git a/sources/addons/flattrwidget/img/red-flattr-widget2.png b/sources/addons/flattrwidget/img/red-flattr-widget2.png new file mode 100644 index 0000000000000000000000000000000000000000..84b886e7347dba9af4799b77ba0b20a14a407779 GIT binary patch literal 36619 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 literal 0 HcmV?d00001 diff --git a/sources/addons/flattrwidget/style.css b/sources/addons/flattrwidget/style.css new file mode 100644 index 00000000..e69de29b diff --git a/sources/addons/fortunate/README b/sources/addons/fortunate/README new file mode 100644 index 00000000..8297cf41 --- /dev/null +++ b/sources/addons/fortunate/README @@ -0,0 +1,7 @@ +This addon requires a fortune server. You may use the DB supplied here to create one. + +gunzip the fortunate.sql.gz and import into your database. +Copy cookie.php to the top level Friendica directory. +Edit fortunate.php and change FORTUNATE_SERVER definition to your hostname. Change the http in that file to https if your server doesn't support http. + +Many additional options are available if you examine cookie.php - a clever developer can provide a settings page to tailor this to one's liking. Also several languages are supported, and it would be convenient to set this to the current Friendica language if that is amongst those supported. \ No newline at end of file diff --git a/sources/addons/fortunate/cookie.php b/sources/addons/fortunate/cookie.php new file mode 100644 index 00000000..a4be4ef0 --- /dev/null +++ b/sources/addons/fortunate/cookie.php @@ -0,0 +1,351 @@ +real_escape_string($_GET['lang']); + +if(strlen($_GET['pattern'])) + $pattern = @$db->real_escape_string($_GET['pattern']); + +if(strlen($_GET['regex'])) + $regex = @$db->real_escape_string($_GET['regex']); + +if(strlen($_GET['db'])) + $table = @$db->real_escape_string($_GET['db']); +else + $table = ''; + +if($length < 0) + $length = 0; +if($numlines < 0) + $numlines = 0; + +function do_query($table,$length,$numlines,$adult,$cat,$limit,$lang,$pattern,$regex,$equal) { + global $db; + $rnd = mt_rand(); + $r = array(); + + $typesql = (($table) ? " WHERE `category` = '$table' " : " WHERE 1 "); + $lengthsql = (($length) ? " AND LENGTH(`text`) < $length " : "" ); + + if($adult == 2) + $adultsql = " AND offensive = 1 "; + elseif($adult == 1) + $adultsql = ""; + else + $adultsql = " AND offensive = 0 "; + + + if($numlines) + $lengthsql .= + " AND (LENGTH(`text`) - LENGTH(REPLACE(`text`,\"\n\",\"\"))) <= $numlines "; + + $langsql = (($lang === 'any') ? '' : " AND lang = '$lang' "); + + $patsql = ''; + if(strlen($pattern)) + $patsql = " AND MATCH text AGAINST ('$pattern') "; + + $regexsql = ''; + if(strlen($regex)) + $regexsql = " AND text REGEXP '$regex' "; + + $eqsql = ''; + + if($equal) { + $catsavail = array(); + $res = @$db->query("SELECT DISTINCT ( `category` ) FROM `fortune` + $typesql + $adultsql + $lengthsql + $langsql + $patsql + $regexsql "); + if($res->num_rows) { + while($x = $res->fetch_array(MYSQL_ASSOC)) + $catsavail[] = $x['category']; + + $eqsql = " AND `category` = '" + . $catsavail[mt_rand(0,$res->num_rows - 1)] . "' "; + } + } + + $order = (($patsql && $limit == 1) ? "" : "ORDER BY RAND($rnd)" ); + + $result = @$db->query("SELECT `text`, `category` FROM `fortune` + $typesql + $adultsql + $lengthsql + $langsql + $patsql + $regexsql + $eqsql + $order + LIMIT $limit"); + + if($result->num_rows) { + while($x = $result->fetch_array(MYSQL_ASSOC)) + $r[] = fortune_to_html($x['text']) + .(($cat) ? "
[{$x['category']}]
" : ""); + } + return $r; +} + + +function do_stats($table,$length,$numlines,$adult,$cat,$limit,$lang,$pattern,$regex,$equal) { + global $db; + $rnd = mt_rand(); + $r = array(); + + $typesql = (($table) ? " WHERE `category` = '$table' " : " WHERE 1 "); + $lengthsql = (($length) ? " AND LENGTH(`text`) < $length " : "" ); + + if($adult == 2) + $adultsql = " AND offensive = 1 "; + elseif($adult == 1) + $adultsql = ""; + else + $adultsql = " AND offensive = 0 "; + + + if($numlines) + $lengthsql .= + " AND (LENGTH(`text`) - LENGTH(REPLACE(`text`,\"\n\",\"\"))) <= $numlines "; + + $langsql = " AND lang = '$lang' "; + + $patsql = ''; + if(strlen($pattern)) + $patsql = " AND MATCH text AGAINST ('$pattern') "; + + $regexsql = ''; + if(strlen($regex)) + $regexsql = " AND text REGEXP '$regex' "; + + $eqsql = ''; + + $result = @$db->query("SELECT `text`, `category` FROM `fortune` + $typesql + $adultsql + $lengthsql + $langsql + $patsql + $regexsql + $eqsql"); + + + echo '
' . $result->num_rows . ' matching quotations.
'; + + + $res = @$db->query("SELECT DISTINCT ( `category` ) FROM `fortune` + $typesql + $adultsql + $lengthsql + $langsql + $patsql + $regexsql "); + if($res->num_rows) { + echo '
Matching Databases:
'; + while($x = $res->fetch_array(MYSQL_ASSOC)) + echo $x['category'].'
'; + + } + else + echo '
No matching databases using those search parameters - please refine your options.
'; + + +} + + +function fortune_to_html($s) { + + // First pass - escape all the HTML entities, and while we're at it + // get rid of any MS-DOS end-of-line characters and expand tabs to + // 8 non-breaking spaces, and translate linefeeds to
. + // We also get rid of ^G which used to sound the terminal beep or bell + // on ASCII terminals and were humourous in some fortunes. + // We could map these to autoplay a short sound file but browser support + // is still sketchy and then there's the issue of where to locate the + // URL, and a lot of people find autoplay sounds downright annoying. + // So for now, just remove them. + + $s = str_replace( + array("&", + "<", + ">", + '"', + "\007", + "\t", + "\r", + "\n"), + + array("&", + "<", + ">", + """, + "", + "        ", + "", + "
"), + $s); + // Replace pseudo diacritics + // These were used to produce accented characters. For instance an accented + // e would have been encoded by '^He - the backspace moving the cursor + // backward so both the single quote and the e would appear in the same + // character position. Umlauts were quite clever - they used a double quote + // as the accent mark over a normal character. + + $s = preg_replace("/'\010([a-zA-Z])/","&\\1acute;",$s); + $s = preg_replace("/\"\010([a-zA-Z])/","&\\1uml;",$s); + $s = preg_replace("/\`\010([a-zA-Z])/","&\\1grave;",$s); + $s = preg_replace("/\^\010([a-zA-Z])/","&\\1circ;",$s); + $s = preg_replace("/\~\010([a-zA-Z])/","&\\1tilde;",$s); + + // Ignore multiple underlines for the same character. These were + // most useful when sent to a line printer back in the day as it + // would type over the same character a number of times making it + // much darker (e.g. bold). I think there are only one or two + // instances of this in the current (2008) fortune cookie database. + + $s = preg_replace("/(_\010)+/","_\010",$s); + // Map the characters which sit underneath a backspace. + // If you can come up with a regex to do all of the following + // madness - be my guest. + // It's not as simple as you think. We need to take something + // that has been backspaced over an arbitrary number of times + // and wrap a forward looking matching number of characters in + // HTML, whilst deciding if it's intended as an underline or + // strikeout sequence. + + // Essentially we produce a string of '1' and '0' characters + // the same length as the source text. + // Any position which is marked '1' has been backspaced over. + + $cursor = 0; + $dst = $s; + $bs_found = false; + for($x = 0; $x < strlen($s); $x ++) { + if($s[$x] == "\010" && $cursor) { + $bs_found = true; + $cursor --; + $dst[$cursor] = '1'; + $dst[$x] = '0'; + $continue; + } + else { + if($bs_found) { + $bs_found = false; + $cursor = $x; + } + $dst[$cursor] = '0'; + $cursor ++; + } + + } + + $out = ''; + $strike = false; + $bold = false; + + // Underline sequence, convert to bold to avoid confusion with links. + // These were generally used for emphasis so it's a reasonable choice. + // Please note that this logic will fail if there is an underline sequence + // and also a strikeout sequence in the same fortune. + + if(strstr($s,"_\010")) { + $len = 0; + for($x = 0; $x < strlen($s); $x ++) { + if($dst[$x] == '1') { + $len ++; + $bold = true; + } + else { + if($bold) { + $out .= ''; + while($s[$x] == "\010") + $x ++; + $out .= substr($s,$x,$len); + $out .= ''; + $x = $x + $len - 1; + $len = 0; + $bold = false; + } + else + $out .= $s[$x]; + } + } + } + + // These aren't seen very often these days - simulation of + // backspace/replace. You could occasionally see the original text + // on slower terminals before it got replaced. Once modems reached + // 4800/9600 baud in the late 70's and early 80's the effect was + // mostly lost - but if you find a really old fortune file you might + // encounter a few of these. + + else { + for($x = 0; $x < strlen($s); $x ++) { + if($dst[$x] == '1') { + if($strike) + $out .= $s[$x]; + else + $out .= ''.$s[$x]; + $strike = true; + } + else { + if($strike) + $out .= ''; + $strike = false; + $out .= $s[$x]; + } + } + } + + // Many of the underline sequences are also wrapped in asterisks, + // which was yet another way of marking ASCII as 'bold'. + // So if it's an underline sequence, and there are asterisks + // on both ends, strip the asterisks as we've already emboldened the text. + + $out = preg_replace('/\*([^<]*<\/strong>)\*/',"\\1",$out); + + // Finally, remove the backspace characters which we don't need anymore. + + return str_replace("\010","",$out); +} + +$result1 = do_query($table,$length,$numlines,$adult,$cat,1,$lang,$pattern,$regex,$equal); + +if(count($result1)) + echo $result1[0]; + +if($stats) + do_stats($table,$length,$numlines,$adult,$cat,1,$lang,$pattern,$regex,$equal); + + diff --git a/sources/addons/fortunate/fortunate.apd b/sources/addons/fortunate/fortunate.apd new file mode 100644 index 00000000..d1c72473 --- /dev/null +++ b/sources/addons/fortunate/fortunate.apd @@ -0,0 +1,3 @@ +url: $baseurl/fortunate +name: Fortunate +photo: $baseurl/addon/fortunate/fortunate.png diff --git a/sources/addons/fortunate/fortunate.css b/sources/addons/fortunate/fortunate.css new file mode 100644 index 00000000..61813b7d --- /dev/null +++ b/sources/addons/fortunate/fortunate.css @@ -0,0 +1,7 @@ +.fortunate { + margin-top: 25px; + margin-left: 100px; + margin-bottom: 25px; + color: #000088; + font-size: 14px; +} \ No newline at end of file diff --git a/sources/addons/fortunate/fortunate.php b/sources/addons/fortunate/fortunate.php new file mode 100644 index 00000000..5b0f47ac --- /dev/null +++ b/sources/addons/fortunate/fortunate.php @@ -0,0 +1,43 @@ + + */ + + +function fortunate_load() { + register_hook('page_end', 'addon/fortunate/fortunate.php', 'fortunate_fetch'); + +} + +function fortunate_unload() { + unregister_hook('page_end', 'addon/fortunate/fortunate.php', 'fortunate_fetch'); +} + +function fortunate_module(){} + + +function fortunate_fetch(&$a,&$b) { + + $fort_server = get_config('fortunate','server'); + if(! $fort_server) + return; + + $a->page['htmlhead'] .= '' . "\r\n"; + + $s = z_fetch_url('http://' . $fort_server . '/cookie.php?numlines=4&equal=1&rand=' . mt_rand()); + if($s['success']) + $b .= '
' . $s['body'] . '
'; + +} + +function fortunate_content(&$a) { + +// $o = ''; +// fortunate_fetch($a,$o); +// return $o; + +} \ No newline at end of file diff --git a/sources/addons/fortunate/fortunate.png b/sources/addons/fortunate/fortunate.png new file mode 100644 index 0000000000000000000000000000000000000000..894a94c7b78b36f3ed1d50435b0597e0df213d07 GIT binary patch literal 7010 zcmV-o8=d5dP)dhgRT&9ba03h%wDl61~_?~^3)-ji%LoAUDl_{F*z{C{@)1>j!* z{srJ)0RFkUxqq0C(I=kp_ub2V`}Ditm1B!|Y&ZAs7ZMQJvKi-`%kA6EYhGh7yUbpA z;m>p>Ka)Dl!GMd$c;u-6>;Iwm{2+Y&&cs+}odrNZ01#A!03}E$Awpxy5K3Y4yT9k& z_BOL&!#{Pvx^OW6lRxoaz1=PxN&y!XjMxBxRAGDuATc?~54>N`K1&--Sz5CD_T$g~ zOn&l{xFNZ-#g;A2uYJvI-~LYsFvTaYDuq$FWrXsya&dB)DZexwwQnY&c??+_KybG@7`T}=iB@B2v?c(c*Ml$N5@acgf*=35y#M_Ks2VqDyiEjT z(~2x*GKwYBhL|ZkPApFaPd? zV5r<)SuKwQu#^wYyKZRwhnw6_;pfi}xOi;O({Fmy++a|Tz^sKa5WpB1JNh#MGqx~r z+keM-=jC}`mZhp1V~jD@TIZa#7C-(muDPaqY0O)}LkTE=Q5pk8Ng^m1g8?MPNV^E- z6_?Nb^;e|XeDMMAd*?eRzxk~R5d*?H7^%LNB}v)26Bk{?W>c2hxaS@mJ`87(Wtd&d z&wN@oZaPKS1Nhs&l^bq^2sA(mC8*GVpcQN-LSVnoR!d&}YD~2F=x#pvAOU1G8X?(D zlHRUeo4@iENs|{1@DtZxH~EeKU9V*|h&T&tqe*$ymH5C1@|`>T{k|^>0M=Spt7X<^ zk3K5j{x<&nFVOE}=T20{J4~9raKOC>9(eqcOJ*k~ z(j-lsOPp&?PDq-<7$garP5$2R$xB{>xC_h56v`4uj^KtHF&qLh^e}ST=)EJuW(lUI z^-XU?qeTt!%whTRm(gjX)1?yD$bY(7uDupX0%HI~`}+@m(0}?bkfsy>pg@d;vG*tL z(nC+n3kH1eWtUAn@PMSL5vg0-Oj74;(r6?zGcYk}NzASk!Su8w37=h(2sj@C60;0Q zK%n7x5mrT>^XC63S6(^remERbRg6iJBu&#q6+gI#|LW}s0X_iAETb4uwJ13ls)kq# z2v7h>5E+6cxp(W<%YXdi7YO(VGczrS2n+=R2bsu{Mw;3*P3JejSr~KtE`S(F-0+H5 zjcW-o!byM%RSa|7@>!gHwyGXq$H-#==qq1^XAU7KgHnU4f&m0csuG}zih>f1v{ehT z06Tf%uY3Eh&wOUpfDhk!=fbtuW@#!S5HTu71j4$rQ)yHf`2slg>dY!+}{`#GXAUJ&a&5z|~jdb+5y^b!fGars((i?6cVOIR4-hJa7fS^>>=p$5;3i0HCY(oQC5IMCV7e(H%u#iqotq$-5zx7-8wl6vBVxllG0x?1% zA(*LUDU4k=mu%V$BV0z3Dw>s~`0d{gJGOVb-7?QBk4@98(WqIA&wn1b+yVj&C_Rc2 zzC;+&N|2s93}G>Z0t|!)N-_rnnXC3fXujc^Yrgh3t7{LB z-t+hKVnu|I%1=cIiikkkMVT5qdE}Y$$dURbmxxP7WD8Ylx%StwV>?2qr)fP+V-AmL z767il9*;bNd+&t;Ft7%}A*hBRAxIe_YN~=3mLM5OktJU|>%AvSswX|+1zs7zlE}#t z^dblDxFcU$%1&?OQvmMm+ea~hFajkER0S@wNCJXF!?PtOEc^G}pY7Q0Hq1juZelHN zy%qcR+c*EJJ^%a@S;sv;kgwj3`|gFc5P<{)2M7@)COAi-Qza57B1KvDhQnTw4?+lJ zNqAKc24F~fG5`UhWB~-gQ=Lfv(4o}@TXljT+$)%tT3+&kwI-P9i z&Jm3QoZz0n$6fyis+gJO?2M2+dK8O`VjY}Cl0gHE0R->>Af^fp5t3!EH|%u!y>4E3 zFD!{db*P$C3sp}j5X-s(3ZcNn$7D%%7ZzsXdd^hws5elSARtoz=a8%SM1VB!1U-}2hmt_E|*R3U`0 zzkgxy)Dzy98lYql>G|?#QI@J>8w!pK2V73eA&~f|t0!tezVz(sl9p*Sw7mps?NzUg z%yH`N*A0JgZ~L>i#44)-qe26LAsN6y(1x=d4vTy4vCXEeS!33$k$Php{TLOkvh>G} zg;7^T^; zp(u(pO+{qwhd;ddsZU8(iytAzC<&o~5De5@P2Gx!AkVpQP!|ru7?WnOmH;&{FSICB zLm)NYf{HQyqBu4jc8ZeGVaG0eI+(lWCKQ$pBI7`VaiD-|y#n z4#2Kk*Vwg7RW*ho6wxEAZk0vwg$6MKBN7=HfU?AJfZ+gn4l0enS`$+=qzK{h#l@%E z?OsvHNme}t%;VOr$b(=x1%LnoN$QQ&0d~{V0aRm$2lfw#!)~`*6a|3!KmKDSNh(Q* zO0+d7)hY(1kAWM>j4>vPH)91yM950S*n8~g?!$-kvXnFK>>_A_Ti^Ze^KQO*^5RPX zR^`2N4tNn;%T@_^YEngDj9++K$!@pX?RG;5$>zQ`$Hc-fhp#s%T@_E zo1XQc7nH}2g-0IAi=xx%^!t5?NTUHr)FA^AX)UYdDFl5`AA&Hpgdigerm99!?r5j` z;DG~SS=(^pj-39<&F^~GMSuQjTW^pY4u|by$L6kkyPg0Tu&V{^W~Mz62ubf(S}MLNtP`s}iLomCjvQUpMDv6YukY9a zKvf5WK{W4RFqqo3Y2PP)-$X_LMi=Q-3ttW3bb88z3JU})2&7HY;ei9TR#R0mMkM}q z#!e#64iq#3RS`oWLQs*I-snR()alsg79vhtfdRnQ8vyb=k7)b-zDtt+XK(2}{D_E& zyAOzhHc3}KA2y9<(4Yc^4FClyB%uO|1XT|S0)==~*(fG06%eFC$ufAVY6z-&sNJ?_ zl#b;zzvOVw9tH9|@AvyfQDj**+3Ov=>EGLmY*bZCh)u72#p(c)v?7{j1OpgE0wlI$ z3Iu>6u^Po9tc>FjsW?eRg6NeY1PuyhcQ`y#T5(dkir32I3l2s4_9(heHDhMPt`56i`J#2pC9+gt)m>fl!Q)HaZt1 zP!$HGwWgOB&j;`nUcKx`LgdNc`JF>wy4B9i4)*RX78m0z+M zqClGJU_g=TIjOo_3sMj$78+v54go2EAr+8Ft_ZJ8MFI4Nxt`g{icy!hZ1=}xi!hLU z?-RsNxRP}Xj`!dIT&=bWm!=Y`T9%%w)txF-BKosdcPe9J7}sQ!R5EG~@w1hPWhpiW zs~&kdH~qTTz4GtAzw6OQXRo}HE31|n0W=T*CNg@0z;kFFCt5gmJ?cZq3pz(aRcVZi zJuwA>Fe(`$l&S*DNN=G9R1nKmP(nbkyBfd-q9B3Go_sRhxG|Edmwx^055Dn@i+B95 zQLQBbBaD1DzC~E^fcaOvBAt+2JgUXvK_o=q2Lpv*fCMs<%Ge=AtySZ!06gQ|41h1c>#lTu zK9Z__zu)O}+U@peszzDX0}G=wkCYz38dLTM3|>#)oQy3zYUGtv&1Pmw@0H_*pMg+8 zh-QSSfD!{(qA%%4pBpy}5sj|qNJYAR$JDM}@$G}bprVjPQ64_LvRuiyZkcKqU?8PS ze7~nY$f)Z+HQ;3v_7Dd+(-&OeeHlxvl4R_Ms=}+4H-J)gfg|^Zj#?uH!b<(=ObYRa z_r51$iNZr{OYOwOu}^%$jI>H~QcPH>Fqdf>hI#NoRb{mGr_a(=Q%i`Md)2G*;b7Fq zh7qZVyHZJ(N)l8-Bw@-*%2po7JXSx>5b*5PS1+fK-ENnp-f_oZ_wHpoM>8_=SgR2iJWV@tBH%z3L1WF@bkioPuUsRhs#u>yNCZJtk7L7x_#-${ycjdw8EA4V zF^3RBh#f*a0zchqEq?T)c4ajh%U8#pJm#=8L8uNB#HF0P-Ddd)OEp_CHgPjAfB9I! zIxbp384GgseuyfAs*lI9AW;mcEUdsXJ@I*SwE+A7=#RW=JPni7YE!Du?AjF;7sm^g zWzFQs&N9Z_PE&%aAr2>as=YSL6gChPF~*2Z)A`FU?+youxDY`D9K~?7WC*R-yn6Do z%SJ-DRQVae718jw{VM<# zzwwPn-ul)g$>L!ngG%~26ALeY0m0qxc!#7Zit?oS`f*0NtYMDAH~{H_8!vs0iSlrj zhEHMQL(0F>2CZ3Lnyh!yfWR)p>e@k{{?&;fS5;Tjmj(QcfwG@0cV7GuO%(5 zbkP~n>}Ad4I0IS0Ui?cgi`{?4!B(F7Jb`#r<9j348f#6O*?O%uGri-@Z|*f}vBZ#M zEN>zpl2$*-T3a#piTYQ`(K>%FvxzAnv&2LU#da0^%{ra7^ z-yTkPPPba&`0dA`#s>@F#;dNjE;ZH~BhOJ8%vc|fBNAhcan2=)t2L5lYi8TFv#z^- zsVqmbETPm8B8}=k`bgn@x7&^5n6=kl8+=)1BY~1$!#E1Ybt^u2$*s4pzyA8TkG)>6 z-EJ3a*VayRcGLg_!pbZ(_G$~XH*MZ}`Q;`{V6B)q$u_4n@=3hKSaHszsjFp4vss^= zoxkX!wb%U0(S8pwW5yV1%#qu_N^7HP9YSbccwxx%N}VSa3|v0=TPDh#b@trb-WJgg zhr=jD_WS))tF_DEaizW&O}z&=|Hd1Vdfm9hI48!6mE*@hPX}14ENyM#Y?9b4bB$&) zIWe(u09WjGwhgCs&Ii zQpjGf=i5vDg@eZx?~`_F9KFjicYxaKU%&2x3tYW!vdkulSS!YenCD|!KokHW)+Ekm zSyHdNW~(+mJ+ouSjw`Nc{_?J8hW#q}#WpBOj(*__u3qc)dfjd}05me{A{f9@HJ&Vv zokqOZwr;KO+!-bH*bj9&9q;|{&aazg9Td+1^AOm*dGmR1eM>qy>FV{QRx{2SYsFZ| zsq3LTSr3nui79OeS!k;FHSgD)yEBx2FZJNv-`mofB$bLl_8xek|Ha$VUwu_KtTPIOp8_kw;v!Niq;-)DjzOy!V8F)rPkpez^bCQ(<=2 zdvB9udS<45^UdwQ`RZteRbD(9wgK9}eq%cu=6AgIweuHVIK5>{W9^!3YATzUaP`cl znQ>0U#It2*I(dl4(2OyPL{d7`s+L)V;2gym`;#Qu^Q~`fPt&@!RFzsS-?tBqMihFY zj_Ij!2E%37GsM6Doo(ALzVps(+N<>l(AO>GX7MYC35&T&-r31jfl}6V~Z1JU)77TndN<(m2YGO{ft#Ym(&2 zZ+~ZVSx#7|kzBJna}jmDT%%i60~f69%N}^czo?90WXzbWVS4p3akhn{B9Dor8#m6J zbI#n(oip3Fx7M$(&CJxMr?aW4Y;rPdG;E`8(^OnymY@Axg-efvSz%lfy^Dgn9KTuT zT$UZU>#qK>#r0VdCN0CV6DdJd`*$o@!&pLbU zIcHCA-P&5WE}NOoCMMH~iEMH*Z8np7-PLL)O^r*$7#NWk26&9wP}C)Me8M+=i>y0I zl3MMlyS`f<*uOE$s%a^Nlwt5?R89qnREIWCSV^VnM$MOTPbea7;;_iEX0y3*L$uJ^Hp0xWtGgv8fV) zn8-tIk|d4BlXu_!#G{XHOA>(qS}NPVv{jcaDpDh(Dstj%WptJiM1U*-`^366)6K10 zc5K@=yM6oQ#!dA#v$d(Iv^9~m8fkMPY1Un>Zqw9dnMo3pI5AE}yz05li!-^{vN~UB z1aKyWlMz2LMywTUZJMTy=Kk5)-GBFgw~GW{`WVL5Oo|@xV(PIYuMXYB*>VgNERu)G zqS;L6=htuCIJ0fr^p>ry_3N{l>2zW;Yqeafl{6b!Wzy89sYw#+9IUH?R-PZ~nF1cM z&Pc=(jQ!e}p|xTyoV96Io0@FR%^kY`{&Mf$X=AFsJeDKCgC)=qv7^RKfM==4$YH%M zGcyzO>*qIbnclKxa(=$Pc1<=polZ<7&1TYUq^*{#)m)aDEVW5$oHNcEn@DvSU(OKf zDgduIsBf*2EXpG_W5gP<*1E)IS$%qXYSX48yB|CD(1U*A>C~5rNHR+90X#}tssaP& z23gHcPSn?}+c3X=YUAd~`Ss1Yx!TNh(wa}+$*n#SB*bIqDqU6N)iX*QBZ!!{a8z3#HiW~p(BNmApiaTa37 z4tyrzx{8ZDo=c_}U74e*2xTaJ$n&z_&%52C-Ok%f`BJ-BTFTq)yxlH3ouWU`GLPiT zSm&}VX*QEqv({`St=0%+J!v#-y_q!XF3oH$W~0PdXA&#cidd;Gb$o$1U!Y5m_mu`l z3?(&UFjB&jEOU)U+MFn+ChNVv?+<)F3}s30BaN{(F^RKjX0z00HCL}Ejhd;|U9FbX zYBozvlGr4bDoQPkHSzMs7X#`GwD8L5IY?Cv^dXdG$a5|7a+v$Upd1XsaHvJ8zNBhQ z%MvZ-5}T$r%WRg~G_z@H)5O?uh+1)0#E6&|5$B5l7^7iXrRr(W(rf9}ms%E~@WB`A zy?RfjjIJV!7nvHD7-z*f6YtiEHDV)38>;|+ia`BY0bV&2$>Htp&Y5)KL07*qoM6N<$g2-NG AfB*mh literal 0 HcmV?d00001 diff --git a/sources/addons/frphotos/frphotohelper.php b/sources/addons/frphotos/frphotohelper.php new file mode 100644 index 00000000..c2edc3e3 --- /dev/null +++ b/sources/addons/frphotos/frphotohelper.php @@ -0,0 +1,75 @@ +get_channel(); + + $fr_server = $_REQUEST['fr_server']; + $fr_username = $_REQUEST['fr_username']; + $fr_password = $_REQUEST['fr_password']; + + $cookies = 'store/[data]/frphoto_cookie_' . $channel['channel_address']; + + if($fr_server && $fr_username && $fr_password) { + + $ch = curl_init($fr_server . '/api/friendica/photos/list'); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookies); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookies); + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($ch, CURLOPT_USERPWD, $fr_username . ':' . $fr_password); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_USERAGENT, 'Hubzilla'); + + $output = curl_exec($ch); + curl_close($ch); + + $j = json_decode($output,true); + +// echo print_r($j,true); + + $total = 0; + if(count($j)) { + foreach($j as $jj) { + + $r = q("select uid from photo where resource_id = '%s' and uid = %d limit 1", + dbesc($jj), + intval($channel['channel_id']) + ); + if($r) + continue; + + $total ++; + proc_run('php','addon/frphotos/frphotohelper.php',$jj, $channel['channel_address'], urlencode($fr_server)); + sleep(3); + } + } + if($total) { + set_pconfig(local_channel(),'frphotos','complete','1'); + } + @unlink($cookies); + goaway(z_root() . '/photos/' . $channel['channel_address']); + } +} + + +function frphotos_content(&$a) { + + if(! local_channel()) { + notice( t('Permission denied') . EOL); + return; + } + + if(intval(get_pconfig(local_channel(),'frphotos','complete'))) { + info('Friendica photos have already been imported into this channel.'); + return; + } + + $o = replace_macros(get_markup_template('frphotos.tpl','addon/frphotos'),array( + '$header' => t('Friendica Photo Album Import'), + '$desc' => t('This will import all your Friendica photo albums to this Red channel.'), + '$fr_server' => array('fr_server', t('Friendica Server base URL'),'',''), + '$fr_username' => array('fr_username', t('Friendica Login Username'),'',''), + '$fr_password' => array('fr_password', t('Friendica Login Password'),'',''), + '$submit' => t('Submit'), + )); + return $o; +} diff --git a/sources/addons/frphotos/view/tpl/frphotos.tpl b/sources/addons/frphotos/view/tpl/frphotos.tpl new file mode 100644 index 00000000..b8e97882 --- /dev/null +++ b/sources/addons/frphotos/view/tpl/frphotos.tpl @@ -0,0 +1,13 @@ +

{{$header}}

+ +

{{$desc}}

+ +
+ +{{include file="field_input.tpl" field=$fr_server}} +{{include file="field_input.tpl" field=$fr_username}} +{{include file="field_password.tpl" field=$fr_password}} + + +
+ diff --git a/sources/addons/hexit/hexit.apd b/sources/addons/hexit/hexit.apd new file mode 100644 index 00000000..af0b05fb --- /dev/null +++ b/sources/addons/hexit/hexit.apd @@ -0,0 +1,3 @@ +url: $baseurl/hexit +name: Hexit +photo: $baseurl/addon/hexit/hexit.png diff --git a/sources/addons/hexit/hexit.php b/sources/addons/hexit/hexit.php new file mode 100644 index 00000000..bd9b7204 --- /dev/null +++ b/sources/addons/hexit/hexit.php @@ -0,0 +1,185 @@ + +/** + * A function for converting hex <-> dec w/o loss of precision. + * + * The problem is that parseInt("0x12345...") isn't precise enough to convert + * 64-bit integers correctly. + * + * Internally, this uses arrays to encode decimal digits starting with the least + * significant: + * 8 = [8] + * 16 = [6, 1] + * 1024 = [4, 2, 0, 1] + */ + +// Adds two arrays for the given base (10 or 16), returning the result. +// This turns out to be the only "primitive" operation we need. +function add(x, y, base) { + var z = []; + var n = Math.max(x.length, y.length); + var carry = 0; + var i = 0; + while (i < n || carry) { + var xi = i < x.length ? x[i] : 0; + var yi = i < y.length ? y[i] : 0; + var zi = carry + xi + yi; + z.push(zi % base); + carry = Math.floor(zi / base); + i++; + } + return z; +} + +// Returns a*x, where x is an array of decimal digits and a is an ordinary +// JavaScript number. base is the number base of the array x. +function multiplyByNumber(num, x, base) { + if (num < 0) return null; + if (num == 0) return []; + + var result = []; + var power = x; + while (true) { + if (num & 1) { + result = add(result, power, base); + } + num = num >> 1; + if (num === 0) break; + power = add(power, power, base); + } + + return result; +} + +function parseToDigitsArray(str, base) { + var digits = str.split(''); + var ary = []; + for (var i = digits.length - 1; i >= 0; i--) { + var n = parseInt(digits[i], base); + if (isNaN(n)) return null; + ary.push(n); + } + return ary; +} + +function convertBase(str, fromBase, toBase) { + var digits = parseToDigitsArray(str, fromBase); + if (digits === null) return null; + + var outArray = []; + var power = [1]; + for (var i = 0; i < digits.length; i++) { + // invariant: at this point, fromBase^i = power + if (digits[i]) { + outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase); + } + power = multiplyByNumber(fromBase, power, toBase); + } + + var out = ''; + for (var i = outArray.length - 1; i >= 0; i--) { + out += outArray[i].toString(toBase); + } + return out; +} + +function decToHex(decStr) { + var hex = convertBase(decStr, 10, 16); + return hex ? '0x' + hex : null; +} + +function hexToDec(hexStr) { + if (hexStr.substring(0, 2) === '0x') hexStr = hexStr.substring(2); + hexStr = hexStr.toLowerCase(); + return convertBase(hexStr, 16, 10); +} + + + + function str_or_null(x) { + return x === null ? 'null' : x; + } + + // "1.234e+5" -> "12340" + function expandExponential(x) { + var pos = x.indexOf("e"); + if (pos === -1) pos = x.indexOf("E"); + if (pos === -1) return x; + + var base = x.substring(0, pos); + var pow = parseInt(x.substring(pos + 1), 10); + if (pow < 0) return x; // not supported. + + var dotPos = base.indexOf('.'); + if (dotPos === -1) dotPos = base.length; + + var ret = base.replace('.', ''); + while (ret.length < dotPos + pow) ret += '0'; + return ret; + } + + function boldDifference(correct, actual) { + for (var i = 0, j = 0; i < correct.length && j < actual.length; i++, j++) { + if (correct[i] !== actual[j]) { + break; + } + } + if (j < actual.length) { + return actual.substring(0, j) + '' + actual.substring(j) + ''; + } else { + return actual; + } + } + + function convert() { + var input = document.getElementById("in").value; + if (input) { + var aHex = str_or_null(decToHex(input)); + var aDec = str_or_null(hexToDec(input)); + var bHex = '0x' + (parseInt(input, 10)).toString(16); + var bDec = "" + expandExponential("" +parseInt(input, 16)); + + var html = '

To Decimal(' + input + ') = ' + aDec + '

'; + html += '

To Hex(' + input + ') = ' + aHex + '

'; + document.getElementById('result').innerHTML = html; + } + } + convert(); + + + + +

Hexit

+ +

Type in a hex or decimal string:

+ +

+ + + +EOT; + +return $o; +} diff --git a/sources/addons/hexit/hexit.png b/sources/addons/hexit/hexit.png new file mode 100644 index 0000000000000000000000000000000000000000..990f7ead4f298dbb28e9dec04d6bcbfd05f67355 GIT binary patch literal 6362 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 V-`2_@i{P&b2wYQNqejg(`hUtqbo2lK literal 0 HcmV?d00001 diff --git a/sources/addons/ijpost/ijpost.css b/sources/addons/ijpost/ijpost.css new file mode 100644 index 00000000..e69de29b diff --git a/sources/addons/ijpost/ijpost.php b/sources/addons/ijpost/ijpost.php new file mode 100644 index 00000000..863a2b05 --- /dev/null +++ b/sources/addons/ijpost/ijpost.php @@ -0,0 +1,229 @@ + + * Author: Michael Johnston + * Author: Cat Gray + */ + +require_once('include/permissions.php'); + +function ijpost_load() { + register_hook('post_local', 'addon/ijpost/ijpost.php', 'ijpost_post_local'); + register_hook('notifier_normal', 'addon/ijpost/ijpost.php', 'ijpost_send'); + register_hook('jot_networks', 'addon/ijpost/ijpost.php', 'ijpost_jot_nets'); + register_hook('feature_settings', 'addon/ijpost/ijpost.php', 'ijpost_settings'); + register_hook('feature_settings_post', 'addon/ijpost/ijpost.php', 'ijpost_settings_post'); + +} +function ijpost_unload() { + unregister_hook('post_local', 'addon/ijpost/ijpost.php', 'ijpost_post_local'); + unregister_hook('notifier_normal', 'addon/ijpost/ijpost.php', 'ijpost_send'); + unregister_hook('jot_networks', 'addon/ijpost/ijpost.php', 'ijpost_jot_nets'); + unregister_hook('feature_settings', 'addon/ijpost/ijpost.php', 'ijpost_settings'); + unregister_hook('feature_settings_post', 'addon/ijpost/ijpost.php', 'ijpost_settings_post'); + +} + + +function ijpost_jot_nets(&$a,&$b) { + if((! local_channel()) || (! perm_is_allowed(local_channel(),'','view_stream'))) + return; + + $ij_post = get_pconfig(local_channel(),'ijpost','post'); + if(intval($ij_post) == 1) { + $ij_defpost = get_pconfig(local_channel(),'ijpost','post_by_default'); + $selected = ((intval($ij_defpost) == 1) ? ' checked="checked" ' : ''); + $b .= '
' + . t('Post to Insanejournal') . '
'; + } +} + + +function ijpost_settings(&$a,&$s) { + + if(! local_channel()) + return; + + /* Add our stylesheet to the page so we can make our settings look nice */ + + //$a->page['htmlhead'] .= '' . "\r\n"; + + /* Get the current state of our config variables */ + + $enabled = get_pconfig(local_channel(),'ijpost','post'); + + $checked = (($enabled) ? 1 : false); + + $def_enabled = get_pconfig(local_channel(),'ijpost','post_by_default'); + + $def_checked = (($def_enabled) ? 1 : false); + + $ij_username = get_pconfig(local_channel(), 'ijpost', 'ij_username'); + $ij_password = z_unobscure(get_pconfig(local_channel(), 'ijpost', 'ij_password')); + + + /* Add some HTML to the existing form */ + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('ijpost', t('Enable InsaneJournal Post Plugin'), $checked, '', array(t('No'),t('Yes'))), + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('ij_username', t('InsaneJournal username'), $ij_username, '') + )); + + $sc .= replace_macros(get_markup_template('field_password.tpl'), array( + '$field' => array('ij_password', t('InsaneJournal password'), $ij_password, '') + )); + + $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('ij_bydefault', t('Post to InsaneJournal by default'), $def_checked, '', array(t('No'),t('Yes'))), + )); + + $s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( + '$addon' => array('ijpost',t('InsaneJournal Post Settings'), '', t('Submit')), + '$content' => $sc + )); + +} + + +function ijpost_settings_post(&$a,&$b) { + + if(x($_POST,'ijpost-submit')) { + + set_pconfig(local_channel(),'ijpost','post',intval($_POST['ijpost'])); + set_pconfig(local_channel(),'ijpost','post_by_default',intval($_POST['ij_bydefault'])); + set_pconfig(local_channel(),'ijpost','ij_username',trim($_POST['ij_username'])); + set_pconfig(local_channel(),'ijpost','ij_password',z_obscure(trim($_POST['ij_password']))); + info( t('Insane Journal Settings saved.') . EOL); + } + +} + +function ijpost_post_local(&$a,&$b) { + + // This can probably be changed to allow editing by pointing to a different API endpoint + + if($b['edit']) + return; + + if((! local_channel()) || (local_channel() != $b['uid'])) + return; + + if($b['item_private'] || $b['parent']) + return; + + $ij_post = intval(get_pconfig(local_channel(),'ijpost','post')); + + $ij_enable = (($ij_post && x($_REQUEST,'ijpost_enable')) ? intval($_REQUEST['ijpost_enable']) : 0); + + if($_REQUEST['api_source'] && intval(get_pconfig(local_channel(),'ijpost','post_by_default'))) + $ij_enable = 1; + + if(! $ij_enable) + return; + + if(strlen($b['postopts'])) + $b['postopts'] .= ','; + $b['postopts'] .= 'ijpost'; +} + + + + +function ijpost_send(&$a,&$b) { + + if((! is_item_normal($b)) || $b['item_private'] || ($b['created'] !== $b['edited'])) + return; + + if(! perm_is_allowed($b['uid'],'','view_stream')) + return; + + if(! strstr($b['postopts'],'ijpost')) + return; + + if($b['parent'] != $b['id']) + return; + + logger('Insanejournal xpost invoked'); + + // insanejournal post in the LJ user's timezone. + // Hopefully the person's Friendica account + // will be set to the same thing. + + $tz = 'UTC'; + + $x = q("select channel_timezone from channel where channel_id = %d limit 1", + intval($b['uid']) + ); + if($x && strlen($x[0]['channel_timezone'])) + $tz = $x[0]['channel_timezone']; + + $ij_username = get_pconfig($b['uid'],'ijpost','ij_username'); + $ij_password = z_unobscure(get_pconfig($b['uid'],'ijpost','ij_password')); + $ij_blog = 'http://www.insanejournal.com/interface/xmlrpc'; + + if($ij_username && $ij_password && $ij_blog) { + + require_once('include/bbcode.php'); + require_once('include/datetime.php'); + + $title = $b['title']; + $post = bbcode($b['body']); + $post = xmlify($post); + $tags = ijpost_get_tags($b['tag']); + + $date = datetime_convert('UTC',$tz,$b['created'],'Y-m-d H:i:s'); + $year = intval(substr($date,0,4)); + $mon = intval(substr($date,5,2)); + $day = intval(substr($date,8,2)); + $hour = intval(substr($date,11,2)); + $min = intval(substr($date,14,2)); + + $xml = <<< EOT + +LJ.XMLRPC.postevent + + +year$year +mon$mon +day$day +hour$hour +min$min +event$post +username$ij_username +password$ij_password +subject$title +lineendingsunix +ver1 +props + +useragentHubzilla +taglist$tags + + + + + +EOT; + + logger('ijpost: data: ' . $xml, LOGGER_DATA); + + if($ij_blog !== 'test') + $x = z_post_url($ij_blog,$xml,array('headers' => array("Content-Type: text/xml"))); + logger('posted to insanejournal: ' . print_r($x,true), LOGGER_DEBUG); + + } +} + +function ijpost_get_tags($post) +{ + preg_match_all("/\]([^\[#]+)\[/",$post,$matches); + $tags = implode(', ',$matches[1]); + return $tags; +} diff --git a/sources/addons/ijpost/lang/C/messages.po b/sources/addons/ijpost/lang/C/messages.po new file mode 100644 index 00000000..4f62c23a --- /dev/null +++ b/sources/addons/ijpost/lang/C/messages.po @@ -0,0 +1,46 @@ +# ADDON ijpost +# Copyright (C) +# This file is distributed under the same license as the Friendica ijpost addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ijpost.php:39 +msgid "Post to Insanejournal" +msgstr "" + +#: ijpost.php:70 +msgid "InsaneJournal Post Settings" +msgstr "" + +#: ijpost.php:72 +msgid "Enable InsaneJournal Post Plugin" +msgstr "" + +#: ijpost.php:77 +msgid "InsaneJournal username" +msgstr "" + +#: ijpost.php:82 +msgid "InsaneJournal password" +msgstr "" + +#: ijpost.php:87 +msgid "Post to InsaneJournal by default" +msgstr "" + +#: ijpost.php:93 +msgid "Submit" +msgstr "" diff --git a/sources/addons/ijpost/lang/ca/strings.php b/sources/addons/ijpost/lang/ca/strings.php new file mode 100644 index 00000000..b5382615 --- /dev/null +++ b/sources/addons/ijpost/lang/ca/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Enviament a Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = "Ajustos d'Enviament a Insanejournal"; +$a->strings["Enable InsaneJournal Post Plugin"] = "Habilita el Plugin d'Enviaments a Insanejournal"; +$a->strings["InsaneJournal username"] = "Nom d'usuari de Insanejournal"; +$a->strings["InsaneJournal password"] = "Contrasenya de Insanejournal"; +$a->strings["Post to InsaneJournal by default"] = "Enviar per defecte a Insanejournal"; +$a->strings["Submit"] = "Enviar"; diff --git a/sources/addons/ijpost/lang/cs/strings.php b/sources/addons/ijpost/lang/cs/strings.php new file mode 100644 index 00000000..8e40419a --- /dev/null +++ b/sources/addons/ijpost/lang/cs/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Odeslat na Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = "Nastavení příspěvků pro InsaneJournal"; +$a->strings["Enable InsaneJournal Post Plugin"] = "Povolit Insanejournal plugin"; +$a->strings["InsaneJournal username"] = "Insanejournal uživatelské jméno"; +$a->strings["InsaneJournal password"] = "Insanejournal heslo"; +$a->strings["Post to InsaneJournal by default"] = "Defaultně zasílat příspěvky na InsaneJournal"; +$a->strings["Submit"] = "Odeslat"; diff --git a/sources/addons/ijpost/lang/de/strings.php b/sources/addons/ijpost/lang/de/strings.php new file mode 100644 index 00000000..319a9743 --- /dev/null +++ b/sources/addons/ijpost/lang/de/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Auf InsaneJournal posten."; +$a->strings["InsaneJournal Post Settings"] = "InsaneJournal Beitrags-Einstellungen"; +$a->strings["Enable InsaneJournal Post Plugin"] = "InsaneJournal Plugin aktivieren"; +$a->strings["InsaneJournal username"] = "InsaneJournal Benutzername"; +$a->strings["InsaneJournal password"] = "InsaneJournal Passwort"; +$a->strings["Post to InsaneJournal by default"] = "Standardmäßig auf InsaneJournal posten."; +$a->strings["Submit"] = "Senden"; diff --git a/sources/addons/ijpost/lang/eo/strings.php b/sources/addons/ijpost/lang/eo/strings.php new file mode 100644 index 00000000..11698887 --- /dev/null +++ b/sources/addons/ijpost/lang/eo/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Afiŝi al Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = "Agordoj pri Insaenejournal Afiŝoj"; +$a->strings["Enable InsaneJournal Post Plugin"] = "Ŝalti la InsaneJournal afiŝo kromprogramon."; +$a->strings["InsaneJournal username"] = "Salutnomo ĉe InsaneJournal"; +$a->strings["InsaneJournal password"] = "Pasvorto ĉe InsaneJournal"; +$a->strings["Post to InsaneJournal by default"] = "Defaŭlte afiŝi ĉe InsaneJournal"; +$a->strings["Submit"] = "Sendi"; diff --git a/sources/addons/ijpost/lang/es/strings.php b/sources/addons/ijpost/lang/es/strings.php new file mode 100644 index 00000000..4468be83 --- /dev/null +++ b/sources/addons/ijpost/lang/es/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Publicar en Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = "Configuración de publicación en Insanejournal"; +$a->strings["Enable InsaneJournal Post Plugin"] = "Activar el módulo de publicación en Insanejournal"; +$a->strings["InsaneJournal username"] = "Nombre de usuario de Insanejournal"; +$a->strings["InsaneJournal password"] = "Contraseña de Insanejournal"; +$a->strings["Post to InsaneJournal by default"] = "Publicar en Insanejournal por defecto"; +$a->strings["Submit"] = "Envíar"; diff --git a/sources/addons/ijpost/lang/fr/strings.php b/sources/addons/ijpost/lang/fr/strings.php new file mode 100644 index 00000000..7db58ccf --- /dev/null +++ b/sources/addons/ijpost/lang/fr/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Publier vers InsaneJournal"; +$a->strings["InsaneJournal Post Settings"] = "Réglages InsaneJournal"; +$a->strings["Enable InsaneJournal Post Plugin"] = "Activer le connecteur InsaneJournal"; +$a->strings["InsaneJournal username"] = "Utilisateur InsaneJournal"; +$a->strings["InsaneJournal password"] = "Mot de passe InsaneJournal"; +$a->strings["Post to InsaneJournal by default"] = "Publier sur InsaneJournal par défaut"; +$a->strings["Submit"] = "Envoyer"; diff --git a/sources/addons/ijpost/lang/is/strings.php b/sources/addons/ijpost/lang/is/strings.php new file mode 100644 index 00000000..b79f347e --- /dev/null +++ b/sources/addons/ijpost/lang/is/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = ""; +$a->strings["InsaneJournal Post Settings"] = ""; +$a->strings["Enable InsaneJournal Post Plugin"] = ""; +$a->strings["InsaneJournal username"] = ""; +$a->strings["InsaneJournal password"] = ""; +$a->strings["Post to InsaneJournal by default"] = ""; +$a->strings["Submit"] = "Senda inn"; diff --git a/sources/addons/ijpost/lang/it/strings.php b/sources/addons/ijpost/lang/it/strings.php new file mode 100644 index 00000000..f82132ce --- /dev/null +++ b/sources/addons/ijpost/lang/it/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Invia a Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = "Impostazioni Invio a InsaneJournal "; +$a->strings["Enable InsaneJournal Post Plugin"] = "Abilita il plugin Invio a InsaneJournal"; +$a->strings["InsaneJournal username"] = "Nome utente InsaneJournal"; +$a->strings["InsaneJournal password"] = "Password InsaneJournal"; +$a->strings["Post to InsaneJournal by default"] = "Invia sempre a InsaneJournal"; +$a->strings["Submit"] = "Invia"; diff --git a/sources/addons/ijpost/lang/nb-no/strings.php b/sources/addons/ijpost/lang/nb-no/strings.php new file mode 100644 index 00000000..2eaa62e3 --- /dev/null +++ b/sources/addons/ijpost/lang/nb-no/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = ""; +$a->strings["InsaneJournal Post Settings"] = ""; +$a->strings["Enable InsaneJournal Post Plugin"] = ""; +$a->strings["InsaneJournal username"] = ""; +$a->strings["InsaneJournal password"] = ""; +$a->strings["Post to InsaneJournal by default"] = ""; +$a->strings["Submit"] = "Lagre"; diff --git a/sources/addons/ijpost/lang/pl/strings.php b/sources/addons/ijpost/lang/pl/strings.php new file mode 100644 index 00000000..5b6ec674 --- /dev/null +++ b/sources/addons/ijpost/lang/pl/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Opublikuj na Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = ""; +$a->strings["Enable InsaneJournal Post Plugin"] = ""; +$a->strings["InsaneJournal username"] = ""; +$a->strings["InsaneJournal password"] = ""; +$a->strings["Post to InsaneJournal by default"] = ""; +$a->strings["Submit"] = "Potwierdź"; diff --git a/sources/addons/ijpost/lang/pt-br/strings.php b/sources/addons/ijpost/lang/pt-br/strings.php new file mode 100644 index 00000000..4dce00fc --- /dev/null +++ b/sources/addons/ijpost/lang/pt-br/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "Publicar no InsaneJournal"; +$a->strings["InsaneJournal Post Settings"] = "Configurações da publicação no InsaneJournal"; +$a->strings["Enable InsaneJournal Post Plugin"] = "Habilitar o plugin de publicação no InsaneJournal"; +$a->strings["InsaneJournal username"] = "Nome de usuário do InsaneJournal"; +$a->strings["InsaneJournal password"] = "Senha do InsaneJournal"; +$a->strings["Post to InsaneJournal by default"] = "Publicar no InsaneJournal por padrão"; +$a->strings["Submit"] = "Enviar"; diff --git a/sources/addons/ijpost/lang/ru/strings.php b/sources/addons/ijpost/lang/ru/strings.php new file mode 100644 index 00000000..0109f8a6 --- /dev/null +++ b/sources/addons/ijpost/lang/ru/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = ""; +$a->strings["InsaneJournal Post Settings"] = ""; +$a->strings["Enable InsaneJournal Post Plugin"] = "Включить InsaneJournal плагин сообщений"; +$a->strings["InsaneJournal username"] = ""; +$a->strings["InsaneJournal password"] = ""; +$a->strings["Post to InsaneJournal by default"] = ""; +$a->strings["Submit"] = "Подтвердить"; diff --git a/sources/addons/ijpost/lang/sv/strings.php b/sources/addons/ijpost/lang/sv/strings.php new file mode 100644 index 00000000..3ec569a7 --- /dev/null +++ b/sources/addons/ijpost/lang/sv/strings.php @@ -0,0 +1,3 @@ +strings["Submit"] = "Spara"; diff --git a/sources/addons/ijpost/lang/zh-cn/strings.php b/sources/addons/ijpost/lang/zh-cn/strings.php new file mode 100644 index 00000000..f2a04712 --- /dev/null +++ b/sources/addons/ijpost/lang/zh-cn/strings.php @@ -0,0 +1,9 @@ +strings["Post to Insanejournal"] = "转播到Insanejournal"; +$a->strings["InsaneJournal Post Settings"] = "Insanejournal转播设置"; +$a->strings["Enable InsaneJournal Post Plugin"] = "使InsaneJournal转播插件可用"; +$a->strings["InsaneJournal username"] = "InsaneJournal用户名"; +$a->strings["InsaneJournal password"] = "InsaneJournal密码"; +$a->strings["Post to InsaneJournal by default"] = "默认地转播到InsaneJournal"; +$a->strings["Submit"] = "提交"; diff --git a/sources/addons/irc/irc.apd b/sources/addons/irc/irc.apd new file mode 100644 index 00000000..12189e78 --- /dev/null +++ b/sources/addons/irc/irc.apd @@ -0,0 +1,3 @@ +url: $baseurl/irc +name: IRC Chat +photo: $baseurl/addon/irc/irc.png diff --git a/sources/addons/irc/irc.css b/sources/addons/irc/irc.css new file mode 100644 index 00000000..e69de29b diff --git a/sources/addons/irc/irc.php b/sources/addons/irc/irc.php new file mode 100644 index 00000000..b9d3a4a0 --- /dev/null +++ b/sources/addons/irc/irc.php @@ -0,0 +1,119 @@ + +*/ + +/* enable in admin->plugins + * you will then have "irc chatroom" listed at yoursite/apps + * and the app will run at yoursite/irc + * documentation at http://tonybaldwin.me/hax/doku.php?id=friendica:irc + * admin can set popular chans, auto connect chans in settings->plugin settings + */ + +function irc_load() { + register_hook('app_menu', 'addon/irc/irc.php', 'irc_app_menu'); + register_hook('feature_settings', 'addon/irc/irc.php', 'irc_addon_settings'); + register_hook('feature_settings_post', 'addon/irc/irc.php', 'irc_addon_settings_post'); +} + +function irc_unload() { + unregister_hook('app_menu', 'addon/irc/irc.php', 'irc_app_menu'); + unregister_hook('feature_settings', 'addon/irc/irc.php', 'irc_addon_settings'); + unregister_hook('feature_settings_post', 'addon/irc/irc.php', 'irc_addon_settings_post'); + +} + + +function irc_addon_settings(&$a,&$s) { + + if(! is_site_admin()) + return; + + /* Add our stylesheet to the page so we can make our settings look nice */ + + //$a->page['htmlhead'] .= '' . "\r\n"; + + /* setting popular channels, auto connect channels */ + $sitechats = get_config('irc','sitechats'); /* popular channels */ + $autochans = get_config('irc','autochans'); /* auto connect chans */ + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('autochans', t('Channels to auto connect'), $sitechats, t('Comma separated list')) + )); + + $sc .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('sitechats', t('Popular Channels'), $autochans, t('Comma separated list')) + )); + + $s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( + '$addon' => array('irc', t('IRC Settings'), '', t('Submit')), + '$content' => $sc + )); + + return; + +} + +function irc_addon_settings_post(&$a,&$b) { + if(! is_site_admin()) + return; + + if($_POST['irc-submit']) { + set_config('irc','autochans',trim($_POST['autochans'])); + set_config('irc','sitechats',trim($_POST['sitechats'])); + /* stupid pop-up thing */ + info( t('IRC settings saved.') . EOL); + } +} + +function irc_app_menu($a,&$b) { +$b['app_menu'][] = '
'; +} + + +function irc_module() { +return; +} + + +function irc_content(&$a) { + + $baseurl = $a->get_baseurl() . '/addon/irc'; + $o = ''; + + /* set the list of popular channels */ + $sitechats = get_config('irc','sitechats'); + if($sitechats) + $chats = explode(',',$sitechats); + else + $chats = array('hubzilla','friendica','chat','chatback','hottub','ircbar','dateroom','debian'); + + + $a->page['aside'] .= '

' . t('Popular Channels') . '

    '; + foreach($chats as $chat) { + $a->page['aside'] .= '
  • ' . '#' . $chat . '
  • '; + } + $a->page['aside'] .= '
'; + + /* setting the channel(s) to auto connect */ + $autochans = get_config('irc','autochans'); + if($autochans) + $channels = $autochans; + else + $channels = ((x($_GET,'channels')) ? $_GET['channels'] : 'hubzilla'); + +/* add the chatroom frame and some html */ + $o .= <<< EOT +

IRC chat

+

A beginner's guide to using IRC. [en]

+ +EOT; + +return $o; + +} + + diff --git a/sources/addons/irc/irc.png b/sources/addons/irc/irc.png new file mode 100644 index 0000000000000000000000000000000000000000..0e4b185dc2ac4637bceae56688e46d68a48b4382 GIT binary patch literal 4334 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 czA^3p0V+d0&%)*% + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license +for software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are +designed to take away your freedom to share and change the works. By +contrast, our General Public Licenses are intended to guarantee your +freedom to share and change all versions of a program--to make sure it +remains free software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public +License. + + "Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further restriction, +you may remove that term. If a license document contains a further +restriction but permits relicensing or conveying under this License, you +may add to a covered work material governed by the terms of that license +document, provided that the further restriction does not survive such +relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have permission +to link or combine any covered work with a work licensed under version 3 +of the GNU General Public License into a single combined work, and to +convey the resulting work. The terms of this License will continue to +apply to the part which is the covered work, but the work with which it is +combined will remain governed by version 3 of the GNU General Public +License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may differ +in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero +General Public License "or any later version" applies to it, you have +the option of following the terms and conditions either of that +numbered version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number +of the GNU Affero General Public License, you may choose any version +ever published by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that +proxy's public statement of acceptance of a version permanently +authorizes you to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file diff --git a/sources/addons/jappixmini/jappix/INSTALL b/sources/addons/jappixmini/jappix/INSTALL new file mode 100644 index 00000000..652c1be7 --- /dev/null +++ b/sources/addons/jappixmini/jappix/INSTALL @@ -0,0 +1,23 @@ +Jappix - An open social platform +These are the installation instructions for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 15/09/10 + +------------------------------------------------- + +It's very simple to install Jappix on your webserver, you just have to follow these things: + +# INSTALLATION + - The HTTP server : http://codingteam.net/project/jappix/doc/HttpServer + - The XMPP server : http://codingteam.net/project/jappix/doc/XmppServer + - The BOSH server : http://codingteam.net/project/jappix/doc/BoshServer + - The Jappix app. : http://codingteam.net/project/jappix/doc/JappixApp + +# MORE + - The whole documentation is available at : http://codingteam.net/project/jappix/doc + +Now, you can use Jappix. Happy socializing! diff --git a/sources/addons/jappixmini/jappix/README b/sources/addons/jappixmini/jappix/README new file mode 100644 index 00000000..49cbf974 --- /dev/null +++ b/sources/addons/jappixmini/jappix/README @@ -0,0 +1,20 @@ +Jappix - An open social platform +This is the readme file for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 18/02/11 + +------------------------------------------------- + +Please refer to the installation instructions that are located in the INSTALL file to process the Jappix installation. + +The Jappix Project official service: https://www.jappix.com/ +The Jappix Project website: https://project.jappix.com/ +The Jappix Project panel: http://codingteam.net/project/jappix + +Jappix is released under the terms of the AGPL license. See COPYING for details. + +Have fun with Jappix! diff --git a/sources/addons/jappixmini/jappix/THANKS b/sources/addons/jappixmini/jappix/THANKS new file mode 100644 index 00000000..a5b12227 --- /dev/null +++ b/sources/addons/jappixmini/jappix/THANKS @@ -0,0 +1,27 @@ +Jappix - An open social platform +These are the special thanks for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 16/02/11 + +------------------------------------------------- + +We would like to thanks the authors of these tools, coming from other projects: + +# PROJECTS + - Base64 http://rumkin.com + - DrawSVGChart http://codingteam.net/project/codingteam + - idzXHR http://www.iadvize.com/plugin_strophe_xmpp.html + - JSJaC http://blog.jwchat.org/jsjac/ + - jQuery http://jquery.com/ + - jQuery Form http://jquery.malsup.com/form/ + - jQuery Timers http://plugins.jquery.com/project/timers + - jXHR http://mulletxhr.com/ + - Mobile Detect http://code.google.com/p/php-mobile-detect/ + - JSMin http://github.com/rgrove/jsmin-php/ + - PHP-gettext https://launchpad.net/php-gettext + - Silk icons http://www.famfamfam.com/lab/icons/silk/ + - Smileys http://www.gajim.org/ diff --git a/sources/addons/jappixmini/jappix/VERSION b/sources/addons/jappixmini/jappix/VERSION new file mode 100644 index 00000000..76892598 --- /dev/null +++ b/sources/addons/jappixmini/jappix/VERSION @@ -0,0 +1 @@ +Spaco [0.9] diff --git a/sources/addons/jappixmini/jappix/css/adhoc.css b/sources/addons/jappixmini/jappix/css/adhoc.css new file mode 100644 index 00000000..68d0383f --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/adhoc.css @@ -0,0 +1,26 @@ +/* + +Jappix - An open social platform +This is the Ad-Hoc CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 20/12/10 + +*/ + +#adhoc .content { + padding: 10px 0 10px 0; +} + +#adhoc .adhoc-head { + background-color: #f1f6fd; + border: 1px #9dc4fc solid; + width: 598px; + height: 18px; + font-size: 0.9em; + margin: 0 10px 12px 10px; + padding: 6px 10px; +} diff --git a/sources/addons/jappixmini/jappix/css/anonymous.css b/sources/addons/jappixmini/jappix/css/anonymous.css new file mode 100644 index 00000000..f61a79c6 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/anonymous.css @@ -0,0 +1,29 @@ +/* + +Jappix - An open social platform +This is the anonymous mode CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 06/11/10 + +*/ + +#top-content { + min-width: 500px !important; +} + +#main-content { + min-width: 490px !important; + min-height: 450px !important; +} + +#left-content { + display: none; +} + +#right-content { + left: 0; +} diff --git a/sources/addons/jappixmini/jappix/css/archives.css b/sources/addons/jappixmini/jappix/css/archives.css new file mode 100644 index 00000000..5e60a8be --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/archives.css @@ -0,0 +1,93 @@ +/* + +Jappix - An open social platform +This is the archives CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 19/12/10 + +*/ + +#archives .content { + padding: 10px 0 10px 0; +} + +#archives .filter { + background-color: #e9f1fd; + border-right: 1px solid #9dc4fc; + width: 180px; + padding: 12px; + position: absolute; + top: 0; + left: 0; + bottom: 0; + float: left; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-topleft: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; +} + +#archives .filter .friend { + margin-bottom: 12px; +} + +#archives .filter .friend { + height: 210px; + width: 180px; + float: none; +} + +#archives .current, +#archives .logs { + position: absolute; + bottom: 0; + right: 0; + left: 204px; +} + +#archives .current { + background-color: #e4eef9; + border-bottom: 1px solid #9dc4fc; + font-size: 0.9em; + height: 16px; + padding: 6px; + top: 0; +} + +#archives .current span { + height: 16px; + overflow: hidden; +} + +#archives .current .name { + max-width: 160px; + font-weight: bold; + float: left; +} + +#archives .current .time { + color: #47646a; + font-size: 0.95em; + float: right; +} + +#archives .logs { + color: black; + font-size: 0.9em; + overflow: auto; + padding: 8px 10px 0; + float: left; + position: absolute; + top: 29px; +} + +#archives .logs a { + color: black; + text-decoration: underline; +} diff --git a/sources/addons/jappixmini/jappix/css/board.css b/sources/addons/jappixmini/jappix/css/board.css new file mode 100644 index 00000000..91e6dcf9 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/board.css @@ -0,0 +1,47 @@ +/* + +Jappix - An open social platform +This is the board CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 26/08/11 + +*/ + +#board .one-board { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + height: 18px; + z-index: 10000; + font-size: 0.92em; + padding: 6px 8px; + box-shadow: 0 0 8px #5c5c5c; + -moz-box-shadow: 0 0 8px #5c5c5c; + -webkit-box-shadow: 0 0 8px #5c5c5c; +} + +#board .one-board:hover { + cursor: pointer; +} + +#board .one-board.visible { + display: block; +} + +#board .one-board.error { + background-color: rgb(241,160,160); + background-color: rgba(241,160,160,0.9); + color: #420c0c; +} + +#board .one-board.info { + background-color: rgb(248,246,186); + background-color: rgba(248,246,186,0.9); + color: #2f2a02; +} diff --git a/sources/addons/jappixmini/jappix/css/buddylist.css b/sources/addons/jappixmini/jappix/css/buddylist.css new file mode 100644 index 00000000..3bfa70cb --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/buddylist.css @@ -0,0 +1,530 @@ +/* + +Jappix - An open social platform +This is the buddy-list CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 31/08/11 + +*/ + +#buddy-list { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + color: #919191; + padding: 15px 6px 4px 6px; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + box-shadow: 0 0 6px #5c5c5c; + -moz-box-shadow: 0 0 6px #5c5c5c; + -webkit-box-shadow: 0 0 6px #5c5c5c; +} + +#buddy-list .content { + background: #e8f1f3; + background: -moz-linear-gradient(top, #e8f1f3, #e4edef); + background: -webkit-gradient(linear, left top, left bottom, from(#e8f1f3), to(#e4edef)); + color: #666666; + height: 207px; + padding: 4px 4px 0 4px; + overflow-x: hidden; + overflow-y: auto; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + -moz-border-radius-topleft: 3px; + -moz-border-radius-topright: 3px; + -webkit-border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; +} + +#buddy-list .one-group { + margin-bottom: 10px; +} + +#buddy-list .one-group a.group { + color: #202c2f; + font-size: 0.8em; + margin: 3px 6px; + padding-left: 12px; + max-height: 15px; + text-decoration: none; + overflow: hidden; + display: block; +} + +#buddy-list .one-group a.group.plus { + background-position: -4px -1143px; +} + +#buddy-list .one-group a.group.minus { + background-position: -4px -1162px; +} + +#buddy-list .one-group a.group:hover { + cursor: pointer; +} + +#buddy-list .hidden-buddy, +#buddy-list .foot-edit-finish, +.buddy-conf-more-display-available { + display: none; +} + +#buddy-list .buddy { + width: 100%; + height: 50px; + margin-bottom: 4px; +} + +#buddy-list .buddy-click { + background: #d9e7ea; + width: 100%; + height: 100%; + overflow: hidden; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +#buddy-list .buddy-click:hover, +#buddy-list .buddy-click:focus { + background: #cedee1; + cursor: pointer; +} + +#buddy-list .buddy-click:active { + background: #c3d3d7; +} + +#buddy-list .gateway { + height: 27px; +} + +#buddy-list .gateway .name { + margin-left: 0; +} + +#buddy-list .gateway .buddy-presence { + float: left; + overflow: hidden; + width: 0; + margin: 0 4px; +} + +#buddy-list .avatar-container { + float: left; + text-align: center; + margin: 3px; + width: 46px; + height: 46px; +} + +#buddy-list .avatar { + max-width: 44px; + max-height: 44px; +} + +#buddy-list .name { + margin: 4px 3px 5px 56px; +} + +#buddy-list .buddy-name { + height: 17px; + font-weight: bold; + font-size: 0.8em; + color: #264249; + margin: 5px 0 5px 2px; + overflow: hidden; +} + +#buddy-list .buddy.blocked p.buddy-name { + text-decoration: line-through; +} + +#buddy-list .buddy-presence { + height: 14px; + font-size: 0.7em; + color: #3a585e; + padding: 2px 0 0 16px; + margin-top: -3px; +} + +#buddy-list .unavailable, +#page-switch .unavailable, +#page-engine p.bc-infos span.show.unavailable { + background-position: 0 -153px; +} + +#buddy-list .available, +#page-engine p.bc-infos span.show.available, +#page-engine .list .available, +#page-engine .list .chat, +#page-switch .available, +#my-infos .f-presence a[data-value=available] span { + background-position: 0 -169px; +} + +#buddy-list .away, +#page-engine p.bc-infos span.show.away, +#page-engine .list .away, +#page-switch .away, +#my-infos .f-presence a[data-value=away] span { + background-position: 0 -185px; +} + +#buddy-list .busy, +#page-engine p.bc-infos span.show.busy, +#page-engine .list .xa, +#page-engine .list .dnd, +#page-switch .busy, +#my-infos .f-presence a[data-value=xa] span { + background-position: 0 -201px; +} + +#buddy-list .error, +#page-switch .error, +#page-engine p.bc-infos span.show.error { + background-position: 0 -217px; +} + +#buddy-list .buddy-infos { + position: absolute; + z-index: 100; + width: 337px; + color: white; + font-size: 0.8em; +} + +.buddy-infos-subarrow { + background-position: 0 -241px; + opacity: 0.8; + width: 9px; + height: 20px; + margin-top: 12px; + float: left; +} + +.buddy-infos-subitem { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.8); + padding: 8px 10px; + width: 308px; + text-shadow: 0 1px 1px black; + float: left; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +.manage-infos p.bm-authorize, +#rosterx .oneresult span.action.add { + background-position: 0 -1181px; +} + +.manage-infos p.bm-remove, +#rosterx .oneresult span.action.delete, +#attach div.one-file a.remove { + background-position: 0 -1200px; +} + +.manage-infos p.bm-remove { + margin-bottom: 18px; +} + +.manage-infos p.bm-rename { + background-position: 0 -1216px; +} + +.manage-infos p.bm-group { + background-position: 0 -1241px; +} + +.manage-infos div.bm-choose { + max-height: 95px; + margin: 0 0 8px 102px; + overflow: auto; +} + +.manage-infos div.bm-choose label { + float: left; + clear: both; + margin-bottom: 1px; +} + +.manage-infos div.bm-choose input { + float: left; +} + +.manage-infos div.bm-choose input[type=checkbox] { + margin: 0 6px 0 0; +} + +.manage-infos div.bm-choose div { + clear: both; +} + +.manage-infos p.bm-rename, +.manage-infos p.bm-group { + height: 26px; +} + +.manage-infos p.bm-rename label, +.manage-infos p.bm-group label { + width: 80px; + padding-top: 3px; + float: left; +} + +.manage-infos p.bm-rename input, +.manage-infos p.bm-group input { + float: left; + width: 155px; +} + +.manage-infos a.save { + float: right; + margin: 4px; +} + +.buddy-infos-subitem p { + margin: 6px 0; + padding-left: 22px; + height: 16px; + overflow: hidden; +} + +.buddy-infos-subitem a { + color: white; + text-decoration: underline; +} + +.tune-note { + background-position: 0 -676px; +} + +.location-world { + background-position: 0 -658px; +} + +.view-individual { + background-position: 0 -34px; +} + +.edit-buddy { + background-position: 0 -1008px; +} + +#buddy-list .filter { + background-color: white; + border-top: 1px solid #b8c2c4; + height: 15px; + padding: 2px 4px; + font-size: 0.8em; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; +} + +#buddy-list .filter input { + border: none; + color: #273a3f; + width: 211px; + padding: 0; + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + +#buddy-list .filter a { + display: none; + background-color: #9a2d2d; + color: white; + height: 13px; + width: 13px; + margin-top: 1px; + font-size: 0.8em; + text-align: center; + text-decoration: none; + float: right; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +#buddy-list .filter a:hover, +#buddy-list .filter a:focus { + background-color: #8c2121; +} + +#buddy-list .filter a:active { + background-color: #7e1919; +} + +#buddy-list .foot { + padding: 9px 1px 3px; +} + +#buddy-list .buddy-list-icon { + height: 16px; + width: 16px; + margin: -3px 5px 0 0; + float: left; +} + +#buddy-list .buddy-list-icon a.talk-images { + height: 16px; + width: 16px; + display: block; +} + +#buddy-list .add, +#page-engine .text .tools-add { + background-position: 0 -1047px; +} + +#buddy-list .join { + background-position: 0 -1065px; +} + +#buddy-list .groupchat, +#page-switch .groupchat-default { + background-position: 0 -1082px; +} + +#buddy-list .more { + background-position: 0 -1100px; +} + +#buddy-list .foot-edit-finish a { + color: white; + font-size: 0.8em; + margin: -3px 4px 0 0; + float: right; + display: block; +} + +#buddy-list .foot-edit-finish a:hover, +#buddy-list .foot-edit-finish a:focus { + text-decoration: underline; + cursor: pointer; +} + +.buddy-conf-item { + position: absolute; + width: 263px; + color: white; + z-index: 9998; + text-align: left; + font-size: 0.8em; + margin-left: -10px; +} + +.buddy-conf-item:hover { + cursor: default; +} + +.buddy-conf-subarrow { + background-position: 0 -241px; + opacity: 0.8; + height: 10px; + width: 18px; + margin-left: 9px; +} + +.buddy-conf-subitem { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.8); + padding: 10px; + text-shadow: 0 1px 1px black; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +.buddy-conf-p { + margin-bottom: 4px; + width: 220px; + font-weight: bold; + float: left; +} + +.buddy-conf-input { + padding-top: 2px; +} + +.buddy-conf-text { + font-size: 11px; + clear: both; + margin-bottom: 3px; +} + +.buddy-conf-text a { + color: white; +} + +.buddy-conf-text a:hover, +.buddy-conf-text a:focus { + cursor: pointer; + text-decoration: underline; +} + +.buddy-conf-text a.buddy-conf-add-search { + text-decoration: underline; + margin-top: 6px; + display: block; +} + +.buddy-conf-select { + font-size: 1.1em; + clear: both; + margin-bottom: 8px; + width: 180px; + height: 23px; +} + +.join-jid { + width: 220px; + margin-top: 5px; +} + +.add-contact-jid, +.add-contact-name, +.add-contact-gateway { + width: 156px; + margin-bottom: 4px; +} + +.add-contact-name-get { + font-size: 0.8em; + display: none; +} + +.buddy-conf-subitem label { + clear: both; +} + +.buddy-conf-subitem label span { + width: 76px; + height: 14px; + margin-top: 3px; + overflow: hidden; + float: left; +} + +#buddy-conf-join ul { + width: 224px; + max-height: 160px; + left: 10px; + top: 51px; +} + +.buddy-conf-join-select { + margin: 8px 0 0 0; +} diff --git a/sources/addons/jappixmini/jappix/css/channel.css b/sources/addons/jappixmini/jappix/css/channel.css new file mode 100644 index 00000000..671d25ea --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/channel.css @@ -0,0 +1,545 @@ +/* + +Jappix - An open social platform +This is the channel CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 26/08/11 + +*/ + +#channel .top div.update { + position: absolute; + top: 12px; + left: 115px; + right: 15px; + bottom: 15px; + border-radius: 20px; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; +} + +#channel .top p { + font-size: 0.9em; + margin-bottom: 10px; +} + +#channel .top h2 { + font-size: 1.6em; + margin-bottom: 10px; + color: #232323; +} + +#channel .top a { + font-size: 0.9em; + color: #232323; +} + +#channel .top.individual div.update { + right: 36px; +} + +#channel .top.individual div.shortcuts, +#userinfos .main-infos div.shortcuts { + width: 16px; + float: right; +} + +#channel .top.individual div.shortcuts { + margin: 2px 5px 0 0; +} + +#channel .top.individual div.shortcuts a, +#userinfos .main-infos div.shortcuts a { + height: 16px; + width: 16px; + margin-bottom: 4px; + display: block; +} + +#channel .top.individual div.shortcuts a.message, +#userinfos .main-infos a.message { + background-position: 0 -1717px; +} + +#channel .top.individual div.shortcuts a.chat, +#userinfos .main-infos a.chat { + background-position: 0 -1737px; +} + +#channel .top.individual div.shortcuts a.command, +#userinfos .main-infos a.command { + background-position: 0 -1758px; +} + +#channel .microblog-body { + height: 20px; + margin-right: 50px; +} + +#channel .microblog-body input { + width: 100%; + height: 100%; + padding: 8px; +} + +#channel .one-microblog-icon { + position: absolute; + top: 38px; + right: 0; +} + +#channel div.update .one-microblog-icon, +#channel div.update .postit { + width: 16px; + height: 16px; + display: block; +} + +#channel div.update .attach { + background-position: 0 -79px; + display: none; +} + +#attach { + position: absolute; + width: 263px; + margin-left: -227px; + color: white; + font-size: 0.85em; + z-index: 9998; + text-align: left; + display: none; +} + +#attach p { + margin-bottom: 6px !important; +} + +#attach input[type=submit] { + margin: 8px 0 6px 0; +} + +#attach .wait { + float: right; + margin: 7px 5px; +} + +#attach div.one-file { + height: 16px; + margin-top: 2px; +} + +#attach div.one-file a.link { + color: white; + width: 215px; + height: 14px; + margin-left: 2px; + overflow: hidden; + float: left; +} + +#attach div.one-file a.remove { + width: 16px; + height: 16px; + float: left; +} + +.attach-subarrow { + background-position: 0 -241px; + opacity: 0.8; + height: 10px; + width: 18px; + margin-left: 226px; +} + +.attach-subitem { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.8); + padding: 10px; + text-shadow: 0 1px 1px black; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +.attach-p { + font-weight: bold; + float: left; +} + +#channel .one-update { + margin-bottom: 12px; + padding: 6px 6px 8px 6px; + border-bottom: 1px dotted #d0d0d0; + min-height: 50px; + color: black; + position: relative; + display: none; +} + +#channel .one-update .avatar-container { + text-align: center; + margin-right: 16px; + float: left; + height: 50px; + width: 50px; +} + +#channel .one-update .avatar-container:hover { + cursor: pointer; +} + +#channel .one-update img.avatar { + max-height: 50px; + max-width: 50px; +} + +#channel .one-update div.body { + margin-left: 65px; + opacity: 0.8; +} + +#channel .one-update:hover div.body { + opacity: 1; +} + +#channel .one-update a.repeat { + background-position: 0 -1681px; + height: 16px; + width: 16px; + margin-right: 4px; + float: left; +} + +#channel .one-update span a { + text-decoration: underline; +} + +#channel .one-update p { + display: block; + margin: 0 12px 5px 0; +} + +#channel .one-update p b.name:hover { + cursor: pointer; + text-decoration: underline; +} + +#channel .one-update p.infos { + font-size: 0.9em; +} + +#channel .one-update p.infos a.geoloc { + background-position: 0 -1778px; + color: #363636; + margin-left: 18px; + padding-left: 14px; +} + +#channel .one-update p.infos a.geoloc:hover, +#channel .one-update p.infos a.geoloc:focus, +#channel .one-update p.infos a.geoloc:active { + color: #141414; +} + +#channel .one-update p.file { + font-size: 0.9em; + margin: 6px 0 5px 10px; +} + +#channel .one-update p.file a.link, +#inbox .inbox-new-file a.file { + min-height: 16px; + padding-left: 22px; + text-decoration: underline; + display: block; +} + +#channel .one-update p.file a.link { + margin-top: 4px; +} + +#channel p.file a, +#inbox .inbox-new-file a.file { + background-position: 0 -988px; +} + +#channel p.file a.audio, +#inbox .inbox-new-file a.file.audio { + background-position: 0 -899px; +} + +#channel p.file a.image, +#inbox .inbox-new-file a.file.image { + background-position: 0 -917px; +} + +#channel p.file a.video, +#inbox .inbox-new-file a.file.video { + background-position: 0 -935px; +} + +#channel p.file a.document, +#inbox .inbox-new-file a.file.document { + background-position: 0 -953px; +} + +#channel p.file a.package, +#inbox .inbox-new-file a.file.package { + background-position: 0 -971px; +} + +#channel .one-update p.file a.thumb img { + border: 1px solid #a2a2a2; + max-width: 140px; + max-height: 105px; + margin: 4px 10px 2px 0; + padding: 1px; +} + +#channel .one-update p.file a.thumb img:hover { + border-color: #464646; +} + +#channel .one-update div.comments, +.popup.large div.comments { + width: 410px; + margin: 2px 0 2px 76px; +} + +#channel .one-update div.comments div.arrow, +.popup.large div.comments div.arrow { + background-position: 0 -1702px; + width: 20px; + height: 8px; + margin-left: 20px; + display: block; +} + +#channel .one-update div.comments div.comments-content, +.popup.large div.comments div.comments-content { + background-color: #e5ebec; + color: black; + font-size: 0.9em; + text-shadow: 0 1px 0 white; +} + +#channel .one-update div.comments input, +.popup.large div.comments input { + width: 356px; + margin: 6px 0; + padding: 4px 5px; +} + +#channel .one-update div.comments span.icon, +.popup.large div.comments span.icon { + background-position: 0 -1082px; + height: 16px; + width: 16px; + margin: 10px; + float: left; +} + +#channel .one-update div.comments .one-comment.loading span.icon, +.popup.large div.comments .one-comment.loading span.icon { + margin: 0 10px 0 0; +} + +#channel .one-update div.comments .one-comment, +.popup.large div.comments .one-comment { + border-bottom: 1px solid #f4f4f4; + padding: 4px 8px 0px 8px; + position: relative; + display: block; +} + +#channel .one-update div.comments .one-comment.compose, +.popup.large div.comments .one-comment.compose { + border-bottom: 2px solid #f4f4f4; + height: 36px; + padding: 0; +} + +#channel .one-update div.comments .one-comment.new, +.popup.large div.comments .one-comment.new { + display: none; +} + +#channel .one-update div.comments a.one-comment, +.popup.large div.comments a.one-comment { + text-decoration: none; +} + +#channel .one-update div.comments a.one-comment:hover, +#channel .one-update div.comments a.one-comment:focus, +.popup.large div.comments a.one-comment:hover, +.popup.large div.comments a.one-comment:focus { + text-decoration: underline; +} + +#channel .one-update div.comments .one-comment.loading, +.popup.large div.comments .one-comment.loading { + padding-bottom: 5px; +} + +#channel .one-update div.comments .one-comment div.marker, +.popup.large div.comments .one-comment div.marker { + background-color: #6d8387; + width: 2px; + position: absolute; + top: 0; + left: 0; + bottom: 0; +} + +#channel .one-update div.comments .one-comment .avatar-container, +.popup.large div.comments .one-comment .avatar-container { + text-align: center; + width: 30px; + height: 30px; + margin: 2px 8px 0 0; + float: left; +} + +#channel .one-update div.comments .one-comment .avatar-container:hover, +.popup.large div.comments .one-comment .avatar-container:hover { + cursor: pointer; +} + +#channel .one-update div.comments .one-comment img.avatar, +.popup.large div.comments .one-comment img.avatar { + max-height: 30px; + max-width: 30px; +} + +#channel .one-update div.comments .one-comment .comment-container, +.popup.large div.comments .one-comment .comment-container { + float: left; +} + +#channel .one-update div.comments .one-comment a.name, +.popup.large div.comments .one-comment a.name { + font-weight: bold; + text-decoration: none; + font-size: 0.95em; + padding-bottom: 2px; + float: left; +} + +#channel .one-update div.comments .one-comment a.name:hover, +#channel .one-update div.comments .one-comment a.name:focus, +.popup.large div.comments .one-comment a.name:hover, +.popup.large div.comments .one-comment a.name:focus { + text-decoration: underline; +} + +#channel .one-update div.comments .one-comment span.date, +#channel .one-update div.comments .one-comment a.remove, +.popup.large div.comments .one-comment span.date, +.popup.large div.comments .one-comment a.remove { + font-size: 0.85em; + float: right; +} + +#channel .one-update div.comments .one-comment.me:hover span.date, +.popup.large div.comments .one-comment.me:hover span.date { + display: none; +} + +#channel .one-update div.comments .one-comment.me a.remove, +.popup.large div.comments .one-comment.me a.remove { + display: none; +} + +#channel .one-update div.comments .one-comment.me:hover a.remove, +.popup.large div.comments .one-comment.me:hover a.remove { + display: block; +} + +#channel .one-update div.comments .one-comment p.body, +.popup.large div.comments .one-comment p.body { + clear: both; +} + +#channel a.more { + background-position: 0 -334px; + color: black; + height: 16px; + text-decoration: none; + margin: -2px 0 0 4px; + padding: 0 0 14px 20px; + display: block; + visibility: hidden; +} + +#channel a.more:hover, +#channel a.more:focus { + text-decoration: underline; +} + +#channel a.mbtool { + width: 11px; + height: 11px; + display: none; + position: absolute; + right: 0; +} + +#channel .one-update:hover a.mbtool { + display: block; +} + +#channel a.mbtool:hover, +#channel a.mbtool:focus { + text-decoration: none; +} + +#channel a.mbtool.profile { + background-position: -1px -1333px; + top: 24px; +} + +#channel a.mbtool.repost { + background-position: -1px -1354px; +} + +#channel a.mbtool.remove { + background-position: -1px -1312px; +} + +#channel a.mbtool.repost, +#channel a.mbtool.remove { + top: 6px; +} + +#channel .footer { + bottom: 0; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; +} + +#channel .footer div { + margin-left: 5px; + padding-left: 24px; + min-height: 16px; + font-size: 0.85em; + width: auto !important; +} + +#channel .footer .sync { + background-position: 0 -804px; + display: none; +} + +#channel .footer .unsync { + background-position: 0 -830px; + display: none; +} diff --git a/sources/addons/jappixmini/jappix/css/directory.css b/sources/addons/jappixmini/jappix/css/directory.css new file mode 100644 index 00000000..34b32312 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/directory.css @@ -0,0 +1,16 @@ +/* + +Jappix - An open social platform +This is the directory tool CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 13/02/11 + +*/ + +#directory .content { + padding: 10px 0 10px 0; +} diff --git a/sources/addons/jappixmini/jappix/css/discovery.css b/sources/addons/jappixmini/jappix/css/discovery.css new file mode 100644 index 00000000..f66456b6 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/discovery.css @@ -0,0 +1,61 @@ +/* + +Jappix - An open social platform +This is the discovery CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 13/02/11 + +*/ + +#discovery .content { + padding: 10px 0 10px 0; +} + +#discovery .content p { + margin: 5px 10px 5px 10px; + text-align: justify; + font-size: 0.85em; +} + +#discovery .discovery-head, +#directory .directory-head, +#rosterx .rosterx-head, +#privacy .privacy-head { + width: 606px; + height: 24px; + margin: 0 10px 10px 10px; + padding: 6px; + background: #f1f6fd; + border: 1px #9dc4fc solid; +} + +#discovery .disco-server-text, +#directory .directory-server-text { + float: left; + font-size: 0.9em; + margin: 3px; +} + +#discovery .disco-server-input, +#directory .directory-server-input { + float: right; + width: 200px; + padding: 2px; + height: 18px; + float: right; + margin-right: 10px; + padding: 2px; +} + +#discovery .disco-category { + display: none; + margin-bottom: 22px; +} + +#discovery .disco-category-title { + font-weight: bold; +} diff --git a/sources/addons/jappixmini/jappix/css/favorites.css b/sources/addons/jappixmini/jappix/css/favorites.css new file mode 100644 index 00000000..5d3fd51d --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/favorites.css @@ -0,0 +1,179 @@ +/* + +Jappix - An open social platform +This is the favorites CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 28/12/10 + +*/ + +#favorites .content { + padding: 10px 0 10px 0; +} + +#favorites .fedit-head-select { + min-width: 190px; + max-width: 210px; +} + +#favorites .switch-fav { + margin: 0 10px 0 10px; + width: 200px; + height: 355px; + border-right: 1px #c0c0c0 dotted; + float: left; +} + +#favorites .room-switcher { + width: 188px; + height: 18px; + border-bottom: 1px #9dc4fc solid; + float: left; + padding: 10px 6px; + font-size: 0.9em; +} + +#favorites .room-switcher:hover { + background-color: #e9f1fd; + cursor: pointer; +} + +#favorites .room-switcher:active { + background-color: #f1f6fd; +} + +#favorites .switch-fav .icon { + float: left; + height: 16px; + width: 16px; + margin: 0 8px 0 0; +} + +#favorites .switch-fav .room-list .list-icon { + background-position: 0 -855px; +} + +#favorites .switch-fav .room-search .search-icon { + background-position: 0 -876px; +} + +#favorites .static-fav { + width: 385px; + height: 335px; + margin: 0 10px 0 0; + padding: 10px; + float: right; +} + +#favorites .favorites-search { + display: none; +} + +#favorites .static-fav-head { + width: 393px; + margin: -10px; +} + +#favorites .static-fav-results { + width: 406px; + height: 314px; + margin: 10px -10px -10px -10px; + padding: 6px 0 0 0; +} + +#favorites .fedit-line { + height: 30px; + font-size: 0.9em; + padding: 10px 0 4px 4px; + border-bottom: 1px #9dc4fc solid; +} + +#favorites .fedit-line:hover { + background: #e9f1fd; +} + +#favorites label { + width: 140px; + margin-top: 3px; +} + +#favorites input { + height: 18px; + width: 186px; + margin-top: 0; + padding: 2px; +} + +#favorites .fedit-select { + min-width: 160px; +} + +#favorites .fedit-actions { + margin: 10px 0 0; + font-size: 0.9em; + float: right; +} + +#favorites input[type=checkbox] { + margin-top: 5px; +} + +#favorites .fedit-terminate { + float: right; +} + +#favorites .fedit-add { + display: block; +} + +#favorites .fedit-edit { + background-position: 2px -1240px; +} + +#favorites .fedit-remove { + margin: 0 8px 0 0; +} + +#favorites .add, +.popup .results .one-button.one-add { + background-position: 3px -1177px; +} + +#favorites .remove, +#inbox .remove { + background-position: 3px -1196px; +} + +#favorites .join, +#inbox .reply, +#inbox .send, +.popup .results .one-button.one-chat { + background-position: 3px -124px; +} + +#favorites .one-button, +#inbox .one-button, +.popup .results .one-button { + padding-left: 20px !important; + font-size: 0.98em; +} + +#favorites .fsearch-results { + overflow: auto; +} + +#favorites .room-name { + margin: 4px 2px 5px; + max-width: 210px; + float: left; +} + +#favorites .fsearch-noresults { + display: none; + font-size: 0.9em; + font-weight: bold; +} diff --git a/sources/addons/jappixmini/jappix/css/home.css b/sources/addons/jappixmini/jappix/css/home.css new file mode 100644 index 00000000..789ea4d9 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/home.css @@ -0,0 +1,579 @@ +/* + +Jappix - An open social platform +This is the home CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 15/01/12 + +*/ + +#home { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + min-height: 550px; + min-width: 875px; +} + +#home .corporation, +#home .corporation .corp_network, +#home .locale, +#home .obsolete { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.70); + color: white; + position: absolute; + top: 0; + text-shadow: 0 0 1px black; + z-index: 100; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; +} + +#home .corporation { + background-position: 9px -357px; + left: 12px; + height: 26px; + width: 34px; +} + +#home .corporation.hovered { + height: 28px; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; +} + +#home .corporation .corp_network { + width: 180px; + padding: 10px 12px; + top: 28px; + display: none; + border-top-right-radius: 3px; + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; +} + +#home .corporation.hovered .corp_network { + display: block; +} + +#home .corporation .corp_network h2 { + font-size: 1.1em; + margin: 14px 0 4px 0; +} + +#home .corporation .corp_network h2.nomargin { + margin-top: 0; +} + +#home .corporation .corp_network a { + font-size: 0.8em; + margin: 2px 0; + padding: 2px 6px; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +#home .corporation .corp_network a span { + margin: 2px 0; + display: block; +} + +#home .corporation .corp_network a span.name { + font-weight: bold; +} + +#home .corporation .corp_network a span.desc { + font-size: 0.9em; + margin-left: 2px; +} + +#home .locale { + left: 52px; + font-size: 0.8em; +} + +#home .locale .current { + height: 19px; + padding: 3px 12px 4px 12px; + font-weight: bold; +} + +#home .locale .current:hover { + cursor: default; +} + +#home .locale .current .current_align { + height: 19px; + vertical-align: middle; + display: table-cell; +} + +#home .locale .list { + margin: 2px 0 2px; +} + +#home .locale .list a, +#home .corporation .corp_network a { + color: white; + text-decoration: none; + display: block; +} + +#home .locale .list a { + padding: 3px 10px; +} + +#home .locale .list a:hover, +#home .locale .list a:focus, +#home .corporation .corp_network a:hover, +#home .corporation .corp_network a:focus { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.1); + cursor: pointer; +} + +#home .locale .list a:active, +#home .corporation .corp_network a:active { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.14); +} + +#home .obsolete { + height: 60px; + padding: 4px 10px; + right: 12px; + font-size: 0.9em; + font-weight: bold; + display: none; +} + +#home .obsolete a { + height: 33px; + width: 33px; + margin: 5px 2px 0 0; + float: left; +} + +#home .obsolete a:hover, +#home .obsolete a:focus { + opacity: 0.8; +} + +#home .obsolete a:active { + opacity: 0.6; +} + +#home .obsolete a.firefox { + background-position: 1px 0; +} + +#home .obsolete a.chrome { + background-position: -34px 0; +} + +#home .obsolete a.safari { + background-position: -68px 0; +} + +#home .obsolete a.opera { + background-position: -101px 0; +} + +#home .obsolete a.ie { + background-position: -135px 0; +} + +#home .plane { + background-position: 0 -384px; + width: 507px; + height: 328px; + position: absolute; + left: 0; + top: 60px; +} + +#home .main { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + position: absolute; + top: 50%; + margin-top: -200px; + width: 800px; + height: 400px; + left: 50%; + margin-left: -400px; + z-index: 50; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + box-shadow: 0 0 35px #5c5c5c; + -moz-box-shadow: 0 0 35px #5c5c5c; + -webkit-box-shadow: 0 0 35px #5c5c5c; +} + +#home .left { + float: left; + width: 350px; + height: 370px; + margin: 15px 0 15px 15px; + color: white; + text-align: center; + text-shadow: 0 1px 1px black; +} + +#home .left .logo { + background-position: 0 0; + float: left; + margin: 30px 20px; + width: 311px; + height: 113px; +} + +#home .left p.upper { + margin: 12px 0 20px 0; +} + +#home .left p.secondary { + margin: 8px 0 0 16px; + font-size: 0.9em; + width: 320px; +} + +#home .right { + background: #e4eef9; + background: -moz-linear-gradient(top, #e4eef9, #C5E1FF); + background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#C5E1FF)); + float: right; + width: 385px; + height: 350px; + margin: 15px 15px 15px 0; + padding: 10px; + font-size: 13px; + text-align: justify; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + box-shadow: 0 0 20px black; + -moz-box-shadow: 0 0 20px black; + -webkit-box-shadow: 0 0 20px black; +} + +#home .right h1 { + font-size: 16px; + padding-bottom: 4px; + border-bottom: 1px black dotted; +} + +#home .right p { + margin-bottom: 4px; +} + +#home .right p a { + border-width: 0 0 1px 0; + border-style: dotted; + border-color: black; +} + +#home .right p a:hover, +#home .right p a:focus { + border-style: solid; + text-decoration: none; +} + +#home .right button { + display: block; + margin-left: 22px; + width: 342px; + height: 64px; + text-decoration: none; + font-weight: bold; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; +} + +#home .right button:hover { + cursor: pointer; +} + +#home .right button span { + float: left; +} + +#home .right button span.home-images { + height: 16px; + width: 16px; + margin: 5px 7px 7px 24px; +} + +#home .right button span.text { + padding-left: 20px; + font-size: 1.5em; +} + +#home .right .login { + background-color: #72d071; + background-position: 0 0; + border: 1px solid #5cb55c; + margin-top: 22px; + box-shadow: 0 0 10px #89e389; + -moz-box-shadow: 0 0 10px #89e389; + -webkit-box-shadow: 0 0 10px #89e389; +} + +#home .right .login:hover, +#home .right .login:focus { + border: 1px solid #419141; + box-shadow: 0 0 15px #72d071; + -moz-box-shadow: 0 0 15px #72d071; + -webkit-box-shadow: 0 0 15px #72d071; +} + +#home .right .login:active { + background-color: #97e896; + background-position: 0 -80px; +} + +#home .right .login span.text { + color: #2d612d; + text-shadow: 1px 1px 1px #5cb55c; +} + +#home .right .login span.home-images { + background-position: 0 -230px; +} + +#home .right .register { + background-color: #f6ef82; + background-position: 0 -160px; + border: 1px solid #e3db56; + margin-top: 15px; + box-shadow: 0 0 15px #f1e968; + -moz-box-shadow: 0 0 15px #f1e968; + -webkit-box-shadow: 0 0 15px #f1e968; +} + +#home .right .register:hover, +#home .right .register:focus { + border: 1px solid #d2c93f; + box-shadow: 0 0 15px #e0d743; + -moz-box-shadow: 0 0 15px #e0d743; + -webkit-box-shadow: 0 0 15px #e0d743; +} + +#home .right .register:active { + background-color: #fdf7af; + background-position: 0 -240px; +} + +#home .right .register span.text { + color: #6d6813; + text-shadow: 1px 1px 1px #dbd56e; +} + +#home .right .register span.home-images { + background-position: 0 -204px; +} + +#home .right p.notice { + margin-top: 24px; + font-size: 0.9em; +} + +#home .right .navigation { + clear: both; + width: 385px; + border-top: 1px black dotted; + position: absolute; + text-align: right; + bottom: 25px; + right: 25px; + padding-top: 6px; +} + +#home .right .navigation a { + margin-left: 9px; + color: black; + text-decoration: none; + font-size: 0.9em; + height: 12px; + padding: 0 0 4px 20px; + float: right; +} + +#home .right .navigation a:hover, +#home .right .navigation a:focus { + text-decoration: underline; +} + +#home .right .navigation a.unencrypted { + background-position: 0 -256px; +} + +#home .right .navigation a.encrypted { + background-position: 0 -282px; +} + +#home .right .navigation a.project { + background-position: 0 -126px; +} + +#home .right .navigation a.manager { + background-position: 0 -152px; +} + +#home .right .navigation a.mobile { + background-position: 0 -178px; +} + +#home a.advanced { + background-position: 0 -334px; + font-size: 0.9em; + height: 16px; + margin-bottom: 10px; + padding-left: 16px; + display: block; +} + +#home fieldset.advanced { + display: none; +} + +#home .anonymouser input[type=text] { + width: 160px; +} + +#home .homediv.registerer .success a { + font-weight: bold; + text-decoration: underline; +} + +#home fieldset { + border: 1px solid black; + margin: 12px 0 12px 0; + padding: 5px 0 4px 0; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +#home legend { + font-size: 0.9em; + margin: 0 0 0 15px; + padding: 0 2px; + text-transform: uppercase; +} + +#home label { + width: 110px; + display: block; + float: left; + clear: both; + margin: 0 0 5px 12px; +} + +#home input, +#home select { + float: left; + margin-bottom: 5px; +} + +#home input[type=text], +#home input[type=password], +#home select { + width: 140px; + margin-top: -2px; +} + +#home input[type=submit] { + min-width: 120px; + float: right; +} + +#home span.jid { + display: block; + float: left; + margin: 0 4px; +} + +#home input.nick, #home input.server { + width: 110px; +} + +#home .info { + padding: 6px; + position: absolute; + bottom: 62px; + right: 35px; + border-width: 1px; + border-style: dotted; + clear: both; + width: 350px; +} + +#home .info.success { + background-color: #aee578; + border-color: #85b05c; + display: none; +} + +#home .info.fail { + background-color: #f19d9d; + border-color: #b34f4f; +} + +#home .info.report { + background-color: #f3f48b; + border-color: #c9c66b; + display: none; +} + +#home .info.report span { + text-decoration: underline; +} + +#home .notice.simple { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.7); + color: white; + font-size: 0.9em; + text-decoration: none; + text-shadow: 0 1px 0 black; + position: fixed; + bottom: 0; + left: 0; + right: 0; + padding: 8px 20px; + z-index: 100; + box-shadow: 0 0 25px #ababab; + -moz-box-shadow: 0 0 25px #ababab; + -webkit-box-shadow: 0 0 25px #ababab; +} + +#home .notice.simple .title { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.4); + background-position: 8px -299px; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #141414; + font-weight: bold; + padding: 8px 8px 8px 30px; +} + +#home .notice.simple .text { + margin-left: 20px; +} diff --git a/sources/addons/jappixmini/jappix/css/ie.css b/sources/addons/jappixmini/jappix/css/ie.css new file mode 100644 index 00000000..8808b50b --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/ie.css @@ -0,0 +1,146 @@ +/* + +Jappix - An open social platform +These are all the IE compliant CSS classes + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 22/04/11 + +*/ + +/* rgba(255,255,255,0.9) */ +.search ul { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#edffffff,endColorstr=#edffffff); +} + +/* rgba(255,255,255,0.3) */ +a.finish:active, +#manager-buttons input:active, +#install-buttons input:active { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#49ffffff,endColorstr=#49ffffff); +} + +/* rgba(255,255,255,0.2) */ +a.finish:hover, +a.finish:focus, +#manager-buttons input:hover, +#manager-buttons input:focus, +#install-buttons input:hover, +#install-buttons input:focus, +.notifications-content .one-notification:active { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#33ffffff,endColorstr=#33ffffff); +} + +/* rgba(255,255,255,0.14) */ +#home .locale .list a:active { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#2fffffff,endColorstr=#2fffffff); +} + +/* rgba(255,255,255,0.1) */ +#home .locale .list a:hover, +#home .locale .list a:focus, +a.finish, +a.finish.disabled:hover, +a.finish.disabled:focus, +a.finish.disabled:active, +#manager-buttons input, +#install-buttons input, +.notifications-content .one-notification:hover, +.notifications-content .one-notification:focus { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#20ffffff,endColorstr=#20ffffff); +} + +/* rgba(255,239,104,0.8) */ +.popup .infos { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#deffef68,endColorstr=#deffef68); +} + +/* rgba(225,160,20,0.3) */ +.search ul li.hovered { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#46e1a014,endColorstr=#46e1a014); +} + +/* rgba(248,246,186,0.9) */ +#board .one-board.info { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#edf8f6ba,endColorstr=#edf8f6ba); +} + +/* rgba(241,160,160,0.9) */ +#board .one-board.error { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#edf1a0a0,endColorstr=#edf1a0a0); +} + +/* rgba(234,234,234,0.8) */ +#page-engine .chatstate { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#deeaeaea,endColorstr=#deeaeaea); +} + +/* rgba(20,20,20,0.6) */ +#home .locale, +#home .obsolete, +#home .notice.simple { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#a0141414,endColorstr=#a0141414); +} + +/* rgba(20,20,20,0.8) */ +#home .main, +#reconnect .pane, +#my-infos, +#right-content, +#buddy-list, +#manager, +#install { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#de141414,endColorstr=#de141414); +} + +/* rgba(20,20,20,0.9) */ +.popup { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ed141414,endColorstr=#ed141414); +} + +/* rgba(0,0,0,0.2) */ +#install-top .step { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#33000000,endColorstr=#33000000); +} + +/* rgba(0,0,0,0.6) */ +.lock { + background: url(../img/others/lock.png) repeat !important; +} + +/* rgba(0,0,0,0.8) */ +#page-engine .tooltip-subitem, +.attach-subitem, +.buddy-infos-subitem, +.buddy-conf-subitem, +.tools-content-subitem { + background: transparent; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#de000000,endColorstr=#de000000); +} + +/* Fix a fieldset padding bug */ +legend { + margin-bottom: 5px !important; +} + +/* Fix an opacity bug */ +a.finish.disabled { + filter: alpha(opacity = 20) !important; +} diff --git a/sources/addons/jappixmini/jappix/css/images.css b/sources/addons/jappixmini/jappix/css/images.css new file mode 100644 index 00000000..2dfb756f --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/images.css @@ -0,0 +1,89 @@ +/* + +Jappix - An open social platform +This is the images CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 16/01/12 + +*/ + +.body-images { + background-image: url(../img/sprites/background.png); + background-repeat: repeat; + background-color: #93c5fa; +} + +.install-images { + background-image: url(../img/sprites/install.png); + background-repeat: no-repeat; +} + +.home-images { + background-image: url(../img/sprites/home.png); + background-repeat: no-repeat; +} + +.browsers-images { + background-image: url(../img/sprites/browsers.png); + background-repeat: no-repeat; +} + +.buttons-images { + background-image: url(../img/sprites/buttons.png); + background-repeat: repeat-x; +} + +.talk-images { + background-image: url(../img/sprites/talk.png); + background-repeat: no-repeat; +} + +.smileys-images { + background-image: url(../img/sprites/smileys.png); + background-repeat: no-repeat; +} + +.welcome-images { + background-image: url(../img/sprites/welcome.png); + background-repeat: no-repeat; +} + +.me-images { + background-image: url(../img/sprites/me.png); + background-repeat: no-repeat; +} + +.manager-images { + background-image: url(../img/sprites/manager.png); + background-repeat: no-repeat; +} + +.mobile-images { + background-image: url(../img/sprites/mobile.png); + background-repeat: no-repeat; +} + +.wait-small { + background-image: url(../img/wait/wait-small.gif); + background-repeat: no-repeat; + height: 16px; + width: 16px; +} + +.wait-medium { + background-image: url(../img/wait/wait-medium.png); + background-repeat: no-repeat; + height: 24px; + width: 24px; +} + +.wait-big { + background-image: url(../img/wait/wait-big.gif); + background-repeat: no-repeat; + height: 30px; + width: 30px; +} diff --git a/sources/addons/jappixmini/jappix/css/inbox.css b/sources/addons/jappixmini/jappix/css/inbox.css new file mode 100644 index 00000000..1ef05886 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/inbox.css @@ -0,0 +1,202 @@ +/* + +Jappix - An open social platform +This is the inbox CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 28/12/10 + +*/ + +#inbox .content { + padding: 10px 0 10px 0; +} + +#inbox .content p { + margin: 3px 10px; + text-align: justify; + font-size: 0.9em; +} + +#inbox .inbox-results { + height: 310px; + width: 620px; + margin: -5px 0 0 10px; + padding: 6px 0 0 0; + overflow: auto; +} + +#inbox .message-unread { + background-color: #E9F1FD; +} + +#inbox .one-message { + font-size: 0.9em; + border-bottom: 1px #b2c7cb solid; +} + +#inbox .message-head { + padding: 6px 0 7px 4px; + overflow: hidden; +} + +#inbox .message-head:hover { + background-color: #e9f1fd; + cursor: pointer; +} + +#inbox .message-head:active { + background-color: #f1f6fd; +} + +#inbox .one-message.message-reading, +#inbox .one-message.message-reading .message-head { + background-color: #f1f6fd; +} + +#inbox .avatar-container { + float: left; + width: 40px; + height: 40px; + margin-right: 7px; + text-align: center; + background-repeat: no-repeat; +} + +#inbox .avatar { + max-width: 40px; + max-height: 40px; +} + +#inbox .message-jid, +#inbox .message-subject { + float: left; + margin: 0 2px; + overflow: hidden; +} + +#inbox .message-jid { + width: 165px; + font-weight: bold; +} + +#inbox .message-subject { + width: 355px; +} + +#inbox .message-truncated { + color: #42646b; + font-size: 0.8em; + margin: 23px 0 0 49px; +} + +#inbox .message-body { + padding: 8px 5px 5px 5px; +} + +#inbox .message-body a { + text-decoration: underline; +} + +#inbox .message-meta { + margin-top: 6px; + padding: 3px 4px; + border-top: 1px #b2c7cb dotted; +} + +#inbox .message-meta span.date { + color: #28474e; + font-size: 0.8em; + margin: 10px 0 0 4px; + float: left; +} + +#inbox .message-meta a { + font-size: 0.98em; + margin: 5px; + float: right; + display: block; +} + +#inbox .inbox-noresults { + font-weight: bold; + display: none; +} + +#inbox .a-show-messages { + display: none; +} + +#inbox .inbox-new { + display: none; + height: 300px; + width: 620px; + margin: -5px 0 0 10px; + padding: 16px 0 0 0; +} + +#inbox .inbox-new-block { + border-top: 1px #686868 dotted; + padding-top: 9px; + min-height: 32px; + clear: both; +} + +#inbox .inbox-new-text { + float: left; + width: 100px; +} + +#inbox .inbox-new-textarea { + width: 460px; + height: 109px; + margin-bottom: 10px; + float: left; +} + +#inbox .inbox-new input { + float: left; +} + +#inbox .inbox-new-to ul { + width: 264px; + max-height: 168px; + font-size: 0.9em; + left: 120px; + top: 31px; +} + +#inbox .inbox-new-to-input { + width: 260px; +} + +#inbox .inbox-new-subject-input { + width: 380px; +} + +#inbox .inbox-new-file a { + display: block; + float: left; +} + +#inbox .inbox-new-file a.file { + font-size: 0.85em; + height: 16px; + max-width: 320px; + margin: 3px 0 15px 013px; + overflow: hidden; +} + +#inbox .inbox-new-file a.one-button { + font-size: 0.85em; + margin: -2px 0 0 25px; +} + +#inbox .inbox-new-send a { + font-size: 0.85em; + float: right; + display: block; +} diff --git a/sources/addons/jappixmini/jappix/css/install.css b/sources/addons/jappixmini/jappix/css/install.css new file mode 100644 index 00000000..9dbde3fc --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/install.css @@ -0,0 +1,285 @@ +/* + +Jappix - An open social platform +This is the install CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 08/06/11 + +*/ + +body { + color: white; +} + +#install { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + width: 800px; + margin: 35px auto; + padding-bottom: 17px; + border-radius: 6px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + box-shadow: 0 0 35px #5c5c5c; + -moz-box-shadow: 0 0 35px #5c5c5c; + -webkit-box-shadow: 0 0 35px #5c5c5c; +} + +#install a { + color: black; + text-decoration: underline; +} + +#install .clear { + clear: both; +} + +#install fieldset { + border: 1px solid black; + margin: 22px 0 15px 0; + padding: 7px 2px 5px 2px; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +#install legend { + font-size: 0.9em; + margin: 0 0 0 15px; + padding: 0 2px; + text-transform: uppercase; +} + +#install label { + width: 200px; + display: block; + float: left; + clear: both; + margin: 0 0 9px 12px; +} + +#install input { + float: left; + margin-bottom: 5px; +} + +#install input[type=text], +#install input[type=url], +#install input[type=password] { + margin-top: -2px; + padding: 3px; + font-size: 0.95em; + min-width: 220px; +} + +#install input.icon { + padding-left: 24px; + min-width: 199px; + max-height: 18px; +} + +#install input.icon#user_name { + background-position: 4px -204px; +} + +#install input.icon#user_password { + background-position: 4px -226px; +} + +#install input.icon#user_repassword { + background-position: 4px -248px; +} + +#install-top { + padding: 30px 45px; +} + +#install-top .logo { + background-position: 0 0; + min-width: 88px; + height: 36px; + padding: 32px 0 0 66px; + font-size: 32px; + color: white; + text-transform: lowercase; + float: left; + text-shadow: 0 1px 1px black; +} + +#install-top .step { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.2); + border: 2px solid white; + padding: 6px 21px; + font-size: 2.7em; + text-shadow: 0 1px 1px black; + float: right; + border-radius: 40px; + -moz-border-radius: 40px; + -webkit-border-radius: 40px; + box-shadow: 0 0 10px #202020; + -moz-box-shadow: 0 0 10px #202020; + -webkit-box-shadow: 0 0 10px #202020; +} + +#install-top .step span { + font-size: 0.6em; +} + +#install-content { + background: #e4eef9; + background: -moz-linear-gradient(top, #e4eef9, #d0e5fa); + background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#d0e5fa)); + color: black; + font-size: 0.9em; + margin: 0 10px; + padding: 20px 24px; + min-height: 260px; + clear: both; + right: 10px; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 20px #202020; + -moz-box-shadow: 0 0 20px #202020; + -webkit-box-shadow: 0 0 20px #202020; +} + +#install-content h3 { + padding-left: 24px; + margin-bottom: 15px; +} + +#install-content h3.start { + background-position: 0 -73px; +} + +#install-content h3.storage { + background-position: 0 -95px; +} + +#install-content h3.account { + background-position: 0 -117px; +} + +#install-content h3.main { + background-position: 0 -139px; +} + +#install-content h3.hosts { + background-position: 0 -161px; +} + +#install-content h3.services { + background-position: 0 -183px; +} + +#install-content p { + margin-bottom: 10px; +} + +#install-content .info { + color: black; + border-width: 1px; + border-style: dashed; + padding: 6px 8px; + display: block; + text-decoration: none; +} + +#install-content .info.smallspace { + margin: 14px 0 10px 0; +} + +#install-content .info.bigspace { + margin: 35px 0 20px 0; +} + +#install-content .info.first { + margin-top: 28px; +} + +#install-content .info.last { + margin-bottom: 28px; +} + +#install-content .info.neutral { + background-color: #f0f19d; + border-color: #b3ad4f; +} + +#install-content a.info.neutral:hover, +#install-content a.info.neutral:focus { + background-color: #eced96; +} + +#install-content a.info.neutral:active { + background-color: #e9ea93; +} + +#install-content .info.success { + background-color: #a8dca9; + border-color: #5e9f5f; +} + +#install-content a.info.success:hover, +#install-content a.info.success:focus { + background-color: #a0d5a1; +} + +#install-content a.info.success:active { + background-color: #9ad09b; +} + +#install-content .info.fail { + background-color: #f19d9d; + border-color: #b34f4f; +} + +#install-content ol { + margin: 20px 30px; +} + +#install-content ol li { + margin-bottom: 1px; +} + +#install-buttons { + margin-top: 22px; +} + +#install-buttons input { + border: 1px solid white; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.1); + color: white; + padding: 4px 8px; + margin-right: 20px; + text-shadow: 0 1px 1px black; + float: right; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 5px #202020; + -moz-box-shadow: 0 0 5px #202020; + -webkit-box-shadow: 0 0 5px #202020; +} + +#install-buttons input:hover, +#install-buttons input:focus { + cursor: pointer; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.2); + box-shadow: 0 0 15px #202020; + -moz-box-shadow: 0 0 15px #202020; + -webkit-box-shadow: 0 0 15px #202020; +} + +#install-buttons input:active { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.3); +} diff --git a/sources/addons/jappixmini/jappix/css/integratebox.css b/sources/addons/jappixmini/jappix/css/integratebox.css new file mode 100644 index 00000000..b5cb9c9f --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/integratebox.css @@ -0,0 +1,34 @@ +/* + +Jappix - An open social platform +This is the integratebox CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 06/11/10 + +*/ + +#integratebox .top { + height: 40px; +} + +#integratebox .content { + text-align: center; + height: 385px; +} + +#integratebox .one-media img { + max-height: 385px; + max-width: 640px; +} + +#integratebox .one-media a img { + border: none; +} + +#integratebox .one-media audio { + margin-top: 170px; +} diff --git a/sources/addons/jappixmini/jappix/css/jquery.datepicker.css b/sources/addons/jappixmini/jappix/css/jquery.datepicker.css new file mode 100644 index 00000000..264cd544 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/jquery.datepicker.css @@ -0,0 +1,148 @@ +/* + +Jappix - An open social platform +This is the datepicker CSS stylesheet + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 28/12/10 + +*/ + +div.datepicker { + position: relative; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + width: 196px; + height: 147px; + position: absolute; + cursor: default; + top: 0; + left: 0; + display: none; +} + +.datepickerHidden { + display: none; +} + +div.datepicker table { + border-collapse:collapse; +} + +div.datepicker a { + text-decoration: none; + cursor: default; + outline: none; +} + +div.datepicker table td { + text-align: right; + padding: 0; + margin: 0; +} + +div.datepicker th { + text-align: center; + color: #47646a; + font-weight: normal; +} + +div.datepicker tbody th { + text-align: left; +} + +div.datepicker tbody a { + display: block; +} + +.datepickerDays a { + width: 20px; + line-height: 16px; + height: 16px; + padding-right: 2px; +} + +.datepickerYears a, +.datepickerMonths a { + width: 44px; + line-height: 36px; + height: 36px; + text-align: center; +} + +td.datepickerNotInMonth { + background: #c7d1d4; +} + +tbody.datepickerDays td.datepickerSelected { + background: #b0bdc1; +} + +tbody.datepickerYears td.datepickerSelected, +tbody.datepickerMonths td.datepickerSelected { + background: #9daaae; +} + +div.datepicker a:hover, +div.datepicker a:focus { + color: #3d7682; +} + +div.datepicker tbody th { + text-align: left; +} + +.datepickerSpace div { + width: 20px; +} + +.datepickerGoNext a, +.datepickerGoPrev a, +.datepickerMonth a { + text-align: center; + height: 20px; + line-height: 20px; +} + +.datepickerGoNext a { + float: right; + width: 20px; +} + +.datepickerGoPrev a { + float: left; + width: 20px; +} + +table.datepickerViewDays tbody.datepickerMonths, +table.datepickerViewDays tbody.datepickerYears { + display: none; +} + +table.datepickerViewMonths tbody.datepickerDays, +table.datepickerViewMonths tbody.datepickerYears, +table.datepickerViewMonths tr.datepickerDoW { + display: none; +} + +table.datepickerViewYears tbody.datepickerDays, +table.datepickerViewYears tbody.datepickerMonths, +table.datepickerViewYears tr.datepickerDoW { + display: none; +} + +td.datepickerDisabled a, +td.datepickerDisabled.datepickerNotInMonth a { + color: #333; +} + +td.datepickerSpecial a { + background: #700; +} + +td.datepickerSpecial.datepickerSelected a { + background: #a00; +} diff --git a/sources/addons/jappixmini/jappix/css/main.css b/sources/addons/jappixmini/jappix/css/main.css new file mode 100644 index 00000000..68254814 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/main.css @@ -0,0 +1,131 @@ +/* + +Jappix - An open social platform +This is the main CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 05/10/11 + +*/ + +* { + margin: 0; + padding: 0; +} + +body { + font: normal 14.4px Helvetica, Verdana, sans-serif; + text-shadow: 0 0 5px white; +} + +h1 { + margin-bottom: 15px; +} + +a { + text-decoration: none; + color: black; + outline-style: none; +} + +a:hover, +a:focus { + cursor: pointer; + text-decoration: underline; +} + +legend { + color: black; +} + +input, +textarea { + background-color: white; + border: 1px solid #636363; + font-size: 0.95em; + padding: 2px; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + box-shadow: inset 0 3px 10px #dcdcdc; + -moz-box-shadow: inset 0 3px 10px #dcdcdc; + -webkit-box-shadow: inset 0 3px 10px #dcdcdc; +} + +textarea { + font-size: 1.1em; +} + +input:focus, +input[type=submit]:hover, +input[type=reset]:hover, +textarea:focus { + border: 1px solid #e1a014; + box-shadow: inset 0 3px 10px #edd9bc; + -moz-box-shadow: inset 0 3px 10px #edd9bc; + -webkit-box-shadow: inset 0 3px 10px #edd9bc; +} + +input[type=submit], +input[type=reset] { + cursor: pointer; +} + +input[type=submit]:active, +input[type=reset]:active { + box-shadow: inset 0 3px 15px #e1a753; + -moz-box-shadow: inset 0 3px 15px #e1a753; + -webkit-box-shadow: inset 0 3px 15px #e1a753; +} + +input[disabled], +textarea[disabled] { + background-color: #f3f3f3; + border: 1px solid #989898; +} + +input:placeholder { + color: #67787c !important; +} + +input:-moz-placeholder { + color: #67787c !important; +} + +input::-webkit-input-placeholder { + color: #67787c !important; +} + +input.placeholder { + color: #67787c !important; +} + +input[type=checkbox] { + margin-top: 2px; +} + +input[type=checkbox], +input[type=radio] { + background: transparent none !important; + border: 0 none !important; +} + +.please-complete, +.please-complete:hover, +.please-complete:focus { + border: 1px #ac2525 solid !important; + box-shadow: inset 0 3px 10px #f39c9c !important; + -moz-box-shadow: inset 0 3px 10px #f39c9c !important; + -webkit-box-shadow: inset 0 3px 10px #f39c9c !important; +} + +.hidden { + display: none !important; +} + +.clear { + clear: both !important; +} diff --git a/sources/addons/jappixmini/jappix/css/manager.css b/sources/addons/jappixmini/jappix/css/manager.css new file mode 100644 index 00000000..c1dd358c --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/manager.css @@ -0,0 +1,543 @@ +/* + +Jappix - An open social platform +This is the manager CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 31/08/11 + +*/ + +#manager { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + width: 945px; + margin: 0 auto 25px; + padding-bottom: 17px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + box-shadow: 0 0 35px #5c5c5c; + -moz-box-shadow: 0 0 35px #5c5c5c; + -webkit-box-shadow: 0 0 35px #5c5c5c; +} + +#manager a { + color: black; + text-decoration: underline; +} + +#manager .clear { + clear: both; +} + +#manager fieldset { + border: 1px solid black; + margin: 22px 0 15px 0; + padding: 7px 2px 5px 2px; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +#manager legend { + font-size: 0.9em; + margin: 0 0 0 15px; + padding: 0 2px; + text-transform: uppercase; +} + +#manager label { + width: 200px; + display: block; + float: left; + clear: both; + margin: 0 0 9px 12px; +} + +#manager label.master { + text-decoration: underline; +} + +#manager input, +#manager select { + float: left; + margin-bottom: 5px; +} + +#manager input[type=radio] { + margin: 2px 8px 5px 0; +} + +#manager input[type=text], +#manager input[type=url], +#manager input[type=password], +#manager select { + margin-top: -2px; + font-size: 0.95em; +} + +#manager input[type=text], +#manager input[type=url], +#manager input[type=password] { + padding: 3px; + min-width: 220px; +} + +#manager input.icon { + padding-left: 24px; + min-width: 199px; + max-height: 18px; +} + +#manager input.icon#admin_name { + background-position: 4px -510px; +} + +#manager input.icon#admin_password, +#manager input.icon#user_repassword { + background-position: 4px -532px; +} + +#manager input.icon#user_name, +#manager input.icon#music_artist { + background-position: 4px -554px; +} + +#manager input.icon#user_password { + background-position: 4px -576px; +} + +#manager input.icon#music_title { + background-position: 4px -598px; +} + +#manager input.icon#music_album { + background-position: 4px -620px; +} + +#manager input.icon#background_image_color, +#manager input.icon#background_color_color { + background-position: 4px -641px; +} + +#manager select { + min-width: 160px; + max-width: 230px; +} + +#manager-top { + padding: 25px 45px 30px; +} + +#manager-top .logo { + background-position: 0 0; + min-width: 89px; + height: 40px; + padding: 28px 0 0 65px; + font-size: 32px; + color: white; + text-transform: lowercase; + float: left; + text-shadow: 0 1px 1px black; +} + +#manager-top .meta { + background-color: #e0eaec; + font-size: 0.9em; + padding: 12px 7px 12px 14px; + float: right; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 10px #202020; + -moz-box-shadow: 0 0 10px #202020; + -webkit-box-shadow: 0 0 10px #202020; +} + +#manager-top .meta span { + margin-right: 10px; + color: black; +} + +#manager-top .meta a { + background-color: #f1f6fd; + border: 1px solid #b9cbcf; + color: #224249; + padding: 4px 8px 4px 21px; + margin-left: 2px; + text-decoration: none; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +#manager-top .meta a:hover, +#manager-top .meta a:focus { + border: 1px solid #95b1b7; +} + +#manager-top .meta a:active { + border: 1px solid #77989f; +} + +#manager-top .meta a.logout { + background-position: 3px -69px; +} + +#manager-top .meta a.close { + background-position: 3px -90px; +} + +#manager-tabs { + margin-left: 12px; +} + +#manager-tabs a { + background-color: #d9e7ea; + color: #204249; + width: 107px; + height: 17px; + padding: 4px 4px 4px 16px; + margin-left: 4px; + font-size: 0.94em; + text-decoration: none; + overflow: hidden; + float: left; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-topleft: 3px; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; +} + +#manager-tabs a:hover, +#manager-tabs a:focus { + background-color: #cedee1; + text-decoration: none; +} + +#manager-tabs a:active { + background-color: #c3d3d7; + text-decoration: none; +} + +#manager-tabs a.tab-active { + background-color: #e4eef9 !important; +} + +#manager-content { + background: #e4eef9; + background: -moz-linear-gradient(top, #e4eef9, #d0e5fa); + background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#d0e5fa)); + color: black; + font-size: 0.9em; + margin: 0 10px; + padding: 20px 24px; + min-height: 260px; + clear: both; + right: 10px; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 20px #202020; + -moz-box-shadow: 0 0 20px #202020; + -webkit-box-shadow: 0 0 20px #202020; +} + +#manager-content h3 { + padding-left: 24px; + margin-bottom: 15px; +} + +#manager-content h3.login { + background-position: 0 -466px; +} + +#manager-content h3.statistics { + background-position: 0 -203px; +} + +#manager-content h3.configuration { + background-position: 0 -224px; +} + +#manager-content h3.hosts { + background-position: 0 -246px; +} + +#manager-content h3.storage { + background-position: 0 -268px; +} + +#manager-content h3.design { + background-position: 0 -290px; +} + +#manager-content h3.users { + background-position: 0 -312px; +} + +#manager-content h3.updates { + background-position: 0 -334px; +} + +#manager-content h4 { + border-top: 1px dotted black; + padding-top: 5px; + margin: 20px 0 14px; + clear: both; +} + +#manager-content ul, +#manager-content ol { + width: 380px; + margin: 8px 0 20px 18px; +} + +#manager-content li { + margin-bottom: 3px; +} + +#manager-content li.total { + margin-bottom: 14px; +} + +#manager-content li b { + width: 190px; + float: left; +} + +#manager-content li span { + margin-left: 10px; + float: left; +} + +#manager-content ul.stats, +#manager-content ol.stats { + float: left; +} + +#manager-content object.stats { + border: 1px dotted #bed4d9; + width: 450px; + height: 270px; + margin-bottom: 20px; + float: right; +} + +#manager-content p, +#manager-content div { + margin-bottom: 10px; +} + +#manager-content .info { + color: black; + border-width: 1px; + border-style: dashed; + padding: 6px 8px; + display: block; + text-decoration: none; +} + +#manager-content .info.bottomspace { + margin-bottom: 16px; +} + +#manager-content .info.smallspace { + margin: 14px 0 10px 0; +} + +#manager-content .info.bigspace { + margin: 35px 0 20px 0; +} + +#manager-content .info.neutral { + background-color: #f0f19d; + border-color: #b3ad4f; +} + +#manager-content a.info.neutral:hover, +#manager-content a.info.neutral:focus { + background-color: #eced96; +} + +#manager-content a.info.neutral:active { + background-color: #e9ea93; +} + +#manager-content .info.success { + background-color: #a8dca9; + border-color: #5e9f5f; +} + +#manager-content a.info.success:hover, +#manager-content a.info.success:focus { + background-color: #a0d5a1; +} + +#manager-content a.info.success:active { + background-color: #9ad09b; +} + +#manager-content .info.fail { + background-color: #f19d9d; + border-color: #b34f4f; +} + +#manager-content a.info.fail:hover, +#manager-content a.info.fail:focus { + background-color: #ea9595; +} + +#manager-content a.info.fail:active { + background-color: #e59090; +} + +#manager-content .browse { + margin: 2px 0 6px; + max-height: 243px; + overflow: auto; +} + +#manager-content .browse .one-browse { + padding: 5px 10px 5px 34px; + height: 17px; +} + +#manager-content .browse .user { + background-position: 9px -111px; +} + +#manager-content .browse .other { + background-position: 9px -133px; +} + +#manager-content .browse .folder { + background-position: 9px -178px; +} + +#manager-content .browse .audio { + background-position: 9px -154px; +} + +#manager-content .browse .alert { + background-position: 9px -353px; +} + +#manager-content .browse .image { + background-position: 9px -374px; +} + +#manager-content .browse .video { + background-position: 9px -397px; +} + +#manager-content .browse .document { + background-position: 9px -418px; +} + +#manager-content .browse .package { + background-position: 9px -441px; +} + +#manager-content .browse .previous { + background-position: 9px -485px; + margin-bottom: 4px; +} + +#manager-content .browse div { + margin: 0; +} + +#manager-content .browse input { + float: right; + margin: 1px 0; +} + +#manager-content .browse .odd { + background-color: #e9f1fd; +} + +#manager-content .browse .even { + background-color: #f1f6fd; +} + +#manager-content .sub { + border-left: 1px solid black; + margin: 5px 0 20px 22px; + padding-left: 12px; + clear: both; +} + +#manager span.logo_links a { + width: 16px; + height: 16px; + margin-right: 6px; + float: left; +} + +#manager span.logo_links a.remove { + background-position: 0 -688px; +} + +#manager span.logo_links a.view { + background-position: 0 -666px; +} + +#manager-content .clear { + margin: 0; +} + +#manager-content textarea.notice-text { + height: 70px; + width: 600px; + margin-left: 4px; + padding: 5px; + font-size: 1.2em; +} + +#manager-buttons { + margin-top: 22px; +} + +#manager-buttons input { + border: 1px solid white; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.1); + color: white; + padding: 4px 8px; + margin-left: -12px; + margin-right: 20px; + font-size: 1em; + text-shadow: 0 1px 1px black; + float: right; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 5px #202020; + -moz-box-shadow: 0 0 5px #202020; + -webkit-box-shadow: 0 0 5px #202020; +} + +#manager-buttons input:hover, +#manager-buttons input:focus { + cursor: pointer; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.2); + box-shadow: 0 0 15px #202020; + -moz-box-shadow: 0 0 15px #202020; + -webkit-box-shadow: 0 0 15px #202020; +} + +#manager-buttons input:active { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.3); +} diff --git a/sources/addons/jappixmini/jappix/css/me.css b/sources/addons/jappixmini/jappix/css/me.css new file mode 100644 index 00000000..2ff74fbd --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/me.css @@ -0,0 +1,49 @@ +/* + +Jappix - An open social platform +This is the Jappix Me tool CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 16/01/12 + +*/ + +#me .content { + padding: 10px 0; +} + +#me .logo { + background-position: 0 0; + width: 300px; + height: 61px; + margin: 20px auto 0 auto; + display: block; +} + +#me .infos { + margin-top: 30px; +} + +#me .infos p { + margin-top: 8px; +} + +#me .infos p.infos-title { + margin-top: 0; +} + +#me .infos a { + text-decoration: underline; +} + +#me a.go { + text-align: center; + font-weight: bold; + width: 300px; + margin: 30px auto 0 auto; + padding: 8px 12px; + display: block; +} \ No newline at end of file diff --git a/sources/addons/jappixmini/jappix/css/mini-ie.css b/sources/addons/jappixmini/jappix/css/mini-ie.css new file mode 100644 index 00000000..d8f4b908 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/mini-ie.css @@ -0,0 +1,73 @@ +/* + +Jappix - An open social platform +This is the Jappix Mini legacy IE CSS stylesheet + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 20/03/11 + +*/ + +#jappix_mini { + width: expression(document.documentElement.clientWidth - 150 + 'px') !important; + position: absolute !important; + bottom: auto !important; + right: auto !important; + top: expression(((document.documentElement.clientHeight - this.offsetHeight) + (ignoreMiniTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop)) + 'px') !important; + left: expression((150 + this.offsetWidth - (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth) + (ignoreMiniLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft)) + 'px') !important; +} + +#jappix_mini .jm_images { + background-image: url(../img/sprites/mini.gif) !important; +} + +#jappix_mini .jm_images_animate { + background-image: url(../img/sprites/animate.gif) !important; +} + +#jappix_mini a.jm_button { + width: 1px !important; +} + +#jappix_mini div.jm_roster { + right: -1px !important; + bottom: 23px !important; +} + +#jappix_mini div.jm_roster div.jm_buddies { + height: expression(this.scrollHeight > (document.documentElement.clientHeight - 70) ? (document.documentElement.clientHeight - 70) + 'px' : 'auto') !important; +} + +#jappix_mini a.jm_pane { + height: 12px !important; + overflow-y: hidden !important; +} + +#jappix_mini a.jm_button.jm_clicked { + background-image: none !important; +} + +#jappix_mini div.jm_conversations a.jm_clicked { + border-right: none !important; + padding: 7px 6px 6px 6px !important; +} + +#jappix_mini div.jm_chat-content { + bottom: 23px !important; + right: -2px !important; +} + +#jappix_popup { + height: expression(document.documentElement.clientHeight + 'px') !important; + width: expression(document.documentElement.clientWidth + 'px') !important; + position: absolute !important; + top: expression(((ignorePopupTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop)) + 'px') !important; + left: expression(((ignorePopupLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft)) + 'px') !important; +} + +#jappix_popup div.jm_prompt { + position: absolute !important; +} diff --git a/sources/addons/jappixmini/jappix/css/mini.css b/sources/addons/jappixmini/jappix/css/mini.css new file mode 100644 index 00000000..7ad6058b --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/mini.css @@ -0,0 +1,540 @@ +/* + +Jappix - An open social platform +This is the Jappix Mini CSS stylesheet + +------------------------------------------------- + +License: AGPL +Authors: Vanaryon, Julien +Last revision: 16/01/12 + +*/ + +#jappix_mini, +#jappix_popup { + font: normal 11px helvetica, "Lucida Grande", "Lucida Sans", "Lucida Sans Unicode", Arial, sans-serif; +} + +#jappix_mini { + margin-left: 130px; + position: fixed; + bottom: 0; + right: 20px; + z-index: 999; +} + +#jappix_mini *, +#jappix_popup * { + border: none; + color: black; + width: auto; + height: auto; + margin: 0; + padding: 0; + overflow: visible; + font-size: 11px; + text-align: left; + text-transform: none; + text-shadow: none; + opacity: 1.0; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + +#jappix_mini .jm_images { + background-image: url(../img/sprites/mini.png); + background-repeat: no-repeat; +} + +#jappix_mini .jm_images_animate { + background-image: url(../img/sprites/animate.png); + background-repeat: no-repeat; +} + +#jappix_mini a { + text-decoration: none; + cursor: pointer; +} + +#jappix_mini a:hover { + cursor: pointer; +} + +#jappix_mini div.jm_position { + float: right; +} + +#jappix_mini a.jm_pane { + background-color: #f4f4f4; + background-position: 0 -100px; + background-repeat: repeat-x; + border-color: #999999; + border-style: solid; + border-width: 1px 1px 0 1px; + font-weight: bold; + outline-style: none; + display: block; + padding: 6px; + height: 24px; +} + +#jappix_mini a.jm_pane:hover { + background: white; +} + +#jappix_mini a.jm_pane:hover, +#jappix_mini a.jm_pane:focus { + border-color: #666666; +} + +#jappix_mini div.jm_starter, +#jappix_mini div.jm_conversations, +#jappix_mini div.jm_conversation { + float: left; + position: relative; +} + +#jappix_mini div.jm_conversation { + width: 153px; +} + +#jappix_mini a.jm_chat-tab { + border-width: 1px 0 0 1px; + width: 140px; + float: right; + overflow: hidden; +} + +#jappix_mini a.jm_chat-tab.jm_clicked { + background: white; + position: relative; + border-top: none; + border-left: 1px solid #999999; + padding-top: 7px; +} + +#jappix_mini a.jm_chat-tab span.jm_notify { + position: absolute; + top: 6px; + right: 9px; +} + +#jappix_mini a.jm_chat-tab span.jm_notify span { + float: left; +} + +#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_left { + background-position: 0 -360px; +} + +#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_right { + background-position: -7px -360px; +} + +#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_left, +#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_right { + height: 16px; + width: 7px; +} + +#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_middle { + background-color: #c60505; + color: white; + font-size: 0.85em; + height: 14px; + padding-top: 2px; +} + +#jappix_mini div.jm_conversation.jm_type_groupchat span.jm_name { + margin-left: 4px; +} + +#jappix_mini div.jm_chat-content { + background-color: white; + border: 1px solid #999999; + height: 300px; + width: 260px; + position: absolute; + right: -1px; + bottom: 25px; + display: none; +} + +#jappix_mini div.jm_actions { + background-color: #565d5e; + border-bottom: 1px solid #3a3a3a; + height: 24px; + padding: 4px 6px; + font-weight: bold; + overflow: hidden; +} + +#jappix_mini div.jm_actions span.jm_nick { + color: white; + height: 16px; + width: 225px; + overflow: hidden; + float: left; +} + +#jappix_mini div.jm_actions a.jm_one-action { + background-color: #727879; + margin: 0 -2px 0 5px; + height: 15px; + width: 15px; + outline-style: none; + float: right; +} + +#jappix_mini div.jm_actions a.jm_one-action:hover, +#jappix_mini div.jm_actions a.jm_one-action:focus { + background-color: #7f8788; +} + +#jappix_mini div.jm_actions a.jm_one-action:active { + background-color: #8c9293; +} + +#jappix_mini div.jm_actions a.jm_logo { + background-position: 7px 2px; + width: 81px; + height: 22px; + margin: -4px 0 0 -2px; + outline-style: none; + float: left; +} + +#jappix_mini div.jm_actions a.jm_logo:hover, +#jappix_mini div.jm_actions a.jm_logo:focus { + background-color: #636a6b; +} + +#jappix_mini div.jm_actions a.jm_logo:active { + background-color: #707677; +} + +#jappix_mini div.jm_actions a.jm_close { + background-position: 1px -341px; +} + +#jappix_mini div.jm_actions a.jm_join { + background-position: 0 -327px; +} + +#jappix_mini div.jm_received-messages { + background-color: white; + padding: 5px 0 4px; + height: 242px; + overflow: auto; +} + +#jappix_mini div.jm_received-messages p { + margin: 3px 0; + word-wrap: break-word; +} + +#jappix_mini div.jm_received-messages p, +#jappix_mini div.jm_received-messages a { + color: black !important; +} + +#jappix_mini div.jm_received-messages div.jm_group { + margin: 2px 6px 9px 6px; + padding-bottom: 8px; + border-bottom: 1px solid #eaeaea; +} + +#jappix_mini div.jm_received-messages div.jm_system-message p, +#jappix_mini div.jm_received-messages div.jm_system-message a { + color: #053805 !important; + font-style: italic !important; +} + +#jappix_mini div.jm_received-messages p a { + text-decoration: underline; +} + +#jappix_mini div.jm_received-messages b { + margin-bottom: 3px; + display: block; +} + +#jappix_mini div.jm_received-messages b.jm_me { + color: #123a5c; +} + +#jappix_mini div.jm_received-messages b.jm_him { + color: #801e1e; +} + +#jappix_mini div.jm_received-messages span.jm_date { + font-size: 0.8em; + float: right; + display: none; +} + +#jappix_mini div.jm_received-messages div.jm_group:hover span.jm_date { + display: block; +} + +#jappix_mini input.jm_send-messages { + background-color: white; + border-color: #999999; + border-style: solid; + border-width: 1px 0 0 0; + padding: 5px; + width: 250px; + min-height: 14px; +} + +#jappix_mini div.jm_disabled div.jm_chat-content, +#jappix_mini div.jm_disabled input.jm_send-messages, +#jappix_mini div.jm_disabled a.jm_pane { + background: #f3f3f3 !important; +} + +#jappix_mini div.jm_disabled input.jm_send-messages { + color: #9d9d9d; +} + +#jappix_mini div.jm_roster { + background-color: white; + border: 1px solid #999999; + width: 160px; + position: absolute; + right: 0; + bottom: 25px; + display: none; +} + +#jappix_mini div.jm_roster div.jm_buddies { + width: 100%; + max-height: 300px; + padding: 5px 0; + overflow: auto; +} + +#jappix_mini div.jm_roster div.jm_grouped { + margin: 2px 0; +} + +#jappix_mini div.jm_roster div.jm_grouped div.jm_name { + margin-bottom: 2px; + padding: 4px 8px 0; + font-weight: bold; +} + +#jappix_mini a.jm_friend { + border-color: white; + border-style: solid; + border-width: 1px 0; + outline-style: none; + padding: 6px; + display: block; +} + +#jappix_mini a.jm_friend.jm_offline { + display: none; +} + +#jappix_mini a.jm_friend:hover, +#jappix_mini a.jm_friend:focus { + background-color: #888888; + border-color: #494949; + color: white; +} + +#jappix_mini a.jm_friend:hover span.jm_presence, +#jappix_mini a.jm_friend:focus span.jm_presence { + background-position: 0 -84px; +} + +#jappix_mini a.jm_button { + padding: 6px 10px; + position: relative; + z-index: 1; +} + +#jappix_mini a.jm_button.jm_clicked { + background: white; + border-top: none; + border-left: 1px solid #999999; + border-right: 1px solid #999999; + padding: 7px 10px 6px 10px; +} + +#jappix_mini span.jm_animate { + background-position: 0 0; + width: 111px; + height: 102px; + position: absolute; + top: -100px; + left: -74px; + z-index: 1; + display: block; +} + +#jappix_mini span.jm_counter { + background-position: 0 -288px; + color: #333333; + height: 16px; + padding-left: 25px; + display: block; +} + +#jappix_mini span.jm_counter.jm_error { + background-position: 0 -305px; +} + +#jappix_mini span.jm_presence { + display: block; + height: 16px; + width: 16px; + margin-right: 4px; + float: left; +} + +#jappix_mini span.jm_name { + color: #272727; + height: 14px; + width: 105px; + overflow: hidden; + float: left; +} + +#jappix_mini .jm_available, +#jappix_mini .jm_chat { + background-position: 0 -20px; +} + +#jappix_mini .jm_away { + background-position: 0 -36px; +} + +#jappix_mini .jm_xa, +#jappix_mini .jm_dnd { + background-position: 0 -52px; +} + +#jappix_mini .jm_unavailable { + background-position: 0 -68px; +} + +#jappix_mini .jm_smiley { + border: 0 none; + height: 16px; + width: 16px; + vertical-align: bottom; +} + +#jappix_mini .jm_smiley-wink { + background-position: 0 -148px; +} + +#jappix_mini .jm_smiley-waii { + background-position: 0 -164px; +} + +#jappix_mini .jm_smiley-unhappy { + background-position: 0 -180px; +} + +#jappix_mini .jm_smiley-tongue { + background-position: 0 -196px; +} + +#jappix_mini .jm_smiley-surprised { + background-position: 0 -212px; +} + +#jappix_mini .jm_smiley-smile { + background-position: 0 -228px; +} + +#jappix_mini .jm_smiley-happy { + background-position: 0 -244px; +} + +#jappix_mini .jm_smiley-grin { + background-position: 0 -260px; +} + +#jappix_popup { + background: url(../img/others/blank.gif) repeat; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 999; +} + +#jappix_popup div.jm_prompt { + background-color: #565d5e; + border: 1px solid #3a3a3a; + width: 346px; + position: fixed; + top: 50%; + left: 50%; + margin-left: -175px; + padding: 16px 2px 2px 2px; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + box-shadow: 0 0 35px #232323; + -moz-box-shadow: 0 0 35px #232323; + -webkit-box-shadow: 0 0 35px #232323; +} + +#jappix_popup div.jm_prompt form { + background-color: white; + border: 1px solid #3a3a3a; + width: 332px; + padding: 6px; +} + +#jappix_popup div.jm_prompt form input { + background-color: #f9f9f9; + border: 1px solid #666666; + font-size: 1.1em; + padding: 1px 2px; +} + +#jappix_popup div.jm_prompt form input:hover, +#jappix_popup div.jm_prompt form input:focus { + border: 1px solid #202020; +} + +#jappix_popup div.jm_prompt form input.jm_text { + width: 326px; + margin: 6px 0; + display: block; +} + +#jappix_popup div.jm_prompt form input.jm_submit { + text-align: center; + margin-left: 3px; + float: right; +} + +#jappix_popup div.jm_prompt form input.jm_submit:hover, +#jappix_popup div.jm_prompt form input.jm_submit:focus { + background-color: #f3f3f3; + cursor: pointer; +} + +#jappix_popup div.jm_prompt form input.jm_submit:active { + background-color: #e8e8e8; +} + +#jappix_popup div.jm_prompt div.jm_clear { + clear: both; +} diff --git a/sources/addons/jappixmini/jappix/css/mobile.css b/sources/addons/jappixmini/jappix/css/mobile.css new file mode 100644 index 00000000..ed44cc03 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/mobile.css @@ -0,0 +1,288 @@ +/* + +Jappix - An open social platform +This is the Jappix Mobile CSS stylesheet + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 05/10/11 + +*/ + +/* BEGIN GENERAL STYLE */ + +* { + margin: 0; + padding: 0; +} + +body { + font: normal 14.4px Helvetica, Verdana, sans-serif; + background-color: #dcdcdc; + margin: 0 auto; + text-align: center; + min-width: 200px; + min-height: 260px; +} + +a { + color: black; +} + +/* END GENERAL STYLE */ + +/* BEGIN HEADER STYLE */ + +.header { + background-color: #2d2d2d; + border-bottom: 1px solid #6d6d6d; + color: #405964; + padding: 6px 0; + height: 30px; +} + +.header div { + background-position: 0 0; + width: 83px; + height: 30px; +} + +/* END HEADER STYLE */ + +/* BEGIN HOME STYLE */ + +#home .header div { + margin: 0 auto; +} + +#home .notification { + padding: 2px; + margin-top: -1px; +} + +#noscript { + background: #86a2ff; + border-bottom: 1px solid #5890d6; + color: #1e4b82; +} + +#error { + background: #ff8686; + border-bottom: 1px solid #d65858; + color: #821e1e; + display: none; +} + +#info { + background: #f3eba7; + border-bottom: 1px solid #d9d085; + color: #5e5616; + display: none; +} + +#home .login { + padding: 8px 0; + margin: 30px 0 30px 0; +} + +#home .login input { + margin-top: 5px; + padding: 2px; +} + +#home .login input.xid, +#home .login input.password { + display: block; + margin: 4px auto; + font-size: 0.85em; + padding: 4px; + background-color: white; + border: 1px solid #636363; + width: 150px; + padding-left: 24px; +} + +#home .login input.xid { + background-position: 4px -30px; +} + +#home .login input.password { + background-position: 4px -53px; +} + +#home .login label { + margin-bottom: 12px; + display: block; +} + +#home .login label input { + margin-right: 4px; +} + +#home a { + font-size: 0.8em; +} + +/* END HOME STYLE */ + +/* BEGIN TALK STYLE */ + +#talk .header div, +#chat .header div { + float: left; + margin-left: 7px; +} + +#talk .header button, +#chat .header button { + float: right; + margin-right: 7px; + padding: 2px; +} + +#talk a.one-buddy { + display: none; + background-color: #87a5ab; + border-bottom: 1px solid #5b8088; + text-shadow: 1px 1px 1px #5b8088; + text-decoration: none; + color: white; + outline-style: none; + padding: 10px 0; +} + +#talk a.one-buddy:hover { + cursor: pointer; +} + +#talk a.available, +#talk a.chat { + background-color: #83b187; + border-bottom: 1px solid #4d8252; + text-shadow: 1px 1px 1px #4d8252; +} + +#talk a.available:hover, +#talk a.chat:hover, +#talk a.available:focus, +#talk a.chat:focus { + background-color: #89c68e; +} + +#talk a.available:active, +#talk a.chat:active { + background-color: #90d496; +} + +#talk a.away { + background-color: #e0be7b; + border-bottom: 1px solid #ae8941; + text-shadow: 1px 1px 1px #ae8941; +} + +#talk a.away:hover, +#talk a.away:focus { + background-color: #eac784; +} + +#talk a.away:active { + background-color: #f3d294; +} + +#talk a.xa, +#talk a.dnd { + background-color: #db8989; + border-bottom: 1px solid #a24343; + text-shadow: 1px 1px 1px #a24343; +} + +#talk a.xa:hover, +#talk a.dnd:hover, +#talk a.xa:focus, +#talk a.dnd:focus { + background-color: #e89797; +} + +#talk a.xa:active, +#talk a.dnd:active { + background-color: #ef9f9f; +} + +/* END TALK STYLE */ + +/* BEGIN CHAT STYLE */ + +#chat { + display: none; +} + +#chat .one-chat, +#chat .one-chat p, +#chat .one-chat div, +#chat .one-chat input { + position: absolute; + bottom: 0; + right: 0; +} + +#chat .one-chat { + top: 43px; + left: 0; +} + +#chat .one-chat p { + background-color: #87a5ab; + border-bottom: 1px solid #5b8088; + text-shadow: 1px 1px 1px #5b8088; + color: white; + top: 0; + left: 0; + height: 18px; + padding: 2px 0; + font-size: 0.9em; +} + +#chat .one-chat div { + border-bottom: 1px solid #cbcbcb; + top: 23px; + left: 0; + bottom: 25px; + overflow: auto; + text-align: left; +} + +#chat .one-chat span { + display: block; + font-size: 0.85em; + margin: 4px 6px; + word-wrap: break-word; +} + +#chat .one-chat b { + margin-right: 3px; +} + +#chat .one-chat b.me { + color: #123a5c; +} + +#chat .one-chat b.him { + color: #801e1e; +} + +#chat .one-chat input { + background-color: white; + bottom: 0; + height: 25px; + width: 100%; + border: none; +} + +#chat .one-chat input.submit { + right: 0; + width: 35px; +} + +/* END CHAT STYLE */ diff --git a/sources/addons/jappixmini/jappix/css/mucadmin.css b/sources/addons/jappixmini/jappix/css/mucadmin.css new file mode 100644 index 00000000..3fe1c754 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/mucadmin.css @@ -0,0 +1,91 @@ +/* + +Jappix - An open social platform +This is the mucadmin CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 11/05/11 + +*/ + +#mucadmin .content { + padding: 10px 0 10px 0; +} + +#mucadmin .content p { + margin: 5px 10px 5px 10px; + text-align: justify; +} + +#mucadmin .mucadmin-head-jid { + text-decoration: underline; + font-size: 0.9em; + float: right; + margin: 1px 4px 1px 1px; +} + +#mucadmin .mucadmin-forms { + height: 310px; + width: 620px; + margin: -5px 0 0 10px; + padding: 6px 0 0 0; + overflow: auto; +} + +#mucadmin .mucadmin-forms label { + width: 260px; +} + +#mucadmin .mucadmin-topic label, +#mucadmin .mucadmin-aut label, +#mucadmin .mucadmin-others label { + font-size: 0.9em; +} + +#mucadmin .mucadmin-forms textarea { + height: 60px; + width: 300px; + margin: 5px 12px 10px 0; +} + +#mucadmin .results { + height: auto; + width: auto; + overflow: visible; + margin: 5px; +} + +#mucadmin .aut-group { + float: left; + padding-bottom: 4px; +} + +#mucadmin .one-aut { + clear: both; + margin: 0 10px 5px 0; +} + +#mucadmin .aut-add { + clear: both; + float: left; + margin-bottom: 5px; + font-size: 0.9em; +} + +#mucadmin .aut-remove { + float: left; +} + +#mucadmin .aut-remove:hover, +#mucadmin .aut-remove:focus { + font-weight: bold; + text-decoration: none; +} + +#mucadmin .mucadmin-others a { + float: left; + font-size: 0.9em; +} diff --git a/sources/addons/jappixmini/jappix/css/myinfos.css b/sources/addons/jappixmini/jappix/css/myinfos.css new file mode 100644 index 00000000..83262268 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/myinfos.css @@ -0,0 +1,330 @@ +/* + +Jappix - An open social platform +This is the my-infos CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 31/08/11 + +*/ + +#my-infos { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + color: #919191; + margin-top: 8px; + padding: 15px 6px 6px 6px; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + box-shadow: 0 0 6px #5c5c5c; + -moz-box-shadow: 0 0 6px #5c5c5c; + -webkit-box-shadow: 0 0 6px #5c5c5c; +} + +#my-infos .content { + background: #e8f1f3; + background: -moz-linear-gradient(top, #e4edef, #e8f1f3); + background: -webkit-gradient(linear, left top, left bottom, from(#e4edef), to(#e8f1f3)); + color: #919191; + max-height: 140px; + padding: 1px 0; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +#my-infos .element { + height: 24px; + margin: 6px 0; + position: relative; +} + +#my-infos .element .icon { + background-color: white; + border-color: #636363; + border-width: 1px; + border-style: solid; + margin-left: 6px; + height: 22px; + width: 25px; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +#my-infos .element div.bubble a { + width: 100%; + height: 20px; +} + +#my-infos .element .icon:hover, +#my-infos .element div.bubble a:hover { + background-color: #f4f4f4; +} + +#my-infos .element .icon:active, +#my-infos .element div.bubble a:active { + background-color: #ededed; +} + +#my-infos .f-presence div.bubble a[data-value=available] { + background-position: 4px -167px; +} + +#my-infos .f-presence div.bubble a[data-value=away] { + background-position: 4px -183px; +} + +#my-infos .f-presence div.bubble a[data-value=xa] { + background-position: 4px -199px; +} + +#my-infos .f-mood div.bubble a[data-value=crazy] { + background-position: 4px -296px; +} + +#my-infos .f-mood div.bubble a[data-value=excited] { + background-position: 4px -314px; +} + +#my-infos .f-mood div.bubble a[data-value=playful] { + background-position: 4px -332px; +} + +#my-infos .f-mood div.bubble a[data-value=happy] { + background-position: 4px -350px; +} + +#my-infos .f-mood div.bubble a[data-value=shocked] { + background-position: 4px -368px; +} + +#my-infos .f-mood div.bubble a[data-value=hot] { + background-position: 4px -386px; +} + +#my-infos .f-mood div.bubble a[data-value=sad] { + background-position: 4px -404px; +} + +#my-infos .f-mood div.bubble a[data-value=amorous] { + background-position: 4px -422px; +} + +#my-infos .f-mood div.bubble a[data-value=confident] { + background-position: 4px -440px; +} + +#my-infos .f-mood a[data-value] span { + background-position: 0 -352px; +} + +#my-infos .f-mood a[data-value=crazy] span, +.mood-one { + background-position: 0 -298px; +} + +#my-infos .f-mood a[data-value=excited] span, +.mood-two { + background-position: 0 -316px; +} + +#my-infos .f-mood a[data-value=playful] span, +.mood-three { + background-position: 0 -334px; +} + +#my-infos .f-mood a[data-value=happy] span, +.mood-four { + background-position: 0 -352px; +} + +#my-infos .f-mood a[data-value=shocked] span, +.mood-five { + background-position: 0 -370px; +} + +#my-infos .f-mood a[data-value=hot] span, +.mood-six { + background-position: 0 -388px; +} + +#my-infos .f-mood a[data-value=sad] span, +.mood-seven { + background-position: 0 -406px; +} + +#my-infos .f-mood a[data-value=amorous] span, +.mood-eight { + background-position: 0 -424px; +} + +#my-infos .f-mood a[data-value=confident] span, +.mood-nine { + background-position: 0 -442px; +} + +#my-infos .f-activity div.bubble a[data-value=doing_chores] { + background-position: 4px -458px; +} + +#my-infos .f-activity div.bubble a[data-value=drinking] { + background-position: 4px -476px; +} + +#my-infos .f-activity div.bubble a[data-value=eating] { + background-position: 4px -494px; +} + +#my-infos .f-activity div.bubble a[data-value=exercising] { + background-position: 4px -512px; +} + +#my-infos .f-activity div.bubble a[data-value=grooming] { + background-position: 4px -548px; +} + +#my-infos .f-activity div.bubble a[data-value=having_appointment] { + background-position: 4px -566px; +} + +#my-infos .f-activity div.bubble a[data-value=inactive] { + background-position: 4px -530px; +} + +#my-infos .f-activity div.bubble a[data-value=relaxing] { + background-position: 4px -620px; +} + +#my-infos .f-activity div.bubble a[data-value=talking] { + background-position: 4px -602px; +} + +#my-infos .f-activity div.bubble a[data-value=traveling] { + background-position: 4px -584px; +} + +#my-infos .f-activity div.bubble a[data-value=working] { + background-position: 4px -638px; +} + +#my-infos .f-activity a[data-value] span { + background-position: 0 -514px; +} + +#my-infos .f-activity a[data-value=doing_chores] span, +.activity-doing_chores { + background-position: 0 -460px; +} + +#my-infos .f-activity a[data-value=drinking] span, +.activity-drinking { + background-position: 0 -478px; +} + +#my-infos .f-activity a[data-value=eating] span, +.activity-eating { + background-position: 0 -496px; +} + +#my-infos .f-activity a[data-value=exercising] span, +.activity-exercising { + background-position: 0 -514px; +} + +#my-infos .f-activity a[data-value=grooming] span, +.activity-grooming { + background-position: 0 -550px; +} + +#my-infos .f-activity a[data-value=having_appointment] span, +.activity-having_appointment { + background-position: 0 -568px; +} + +#my-infos .f-activity a[data-value=inactive] span, +.activity-inactive { + background-position: 0 -532px; +} + +#my-infos .f-activity a[data-value=relaxing] span, +.activity-relaxing { + background-position: 0 -622px; +} + +#my-infos .f-activity a[data-value=talking] span, +.activity-talking { + background-position: 0 -604px; +} + +#my-infos .f-activity a[data-value=traveling] span, +.activity-traveling { + background-position: 0 -586px; +} + +#my-infos .f-activity a[data-value=working] span, +.activity-working { + background-position: 0 -640px; +} + +#my-infos .element .icon.picker { + border-width: 1px 0 1px 1px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-topright: 0; + -moz-border-radius-bottomright: 0; + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-right-radius: 0; +} + +#my-infos .element .icon.disabled { + background-color: #f3f3f3; + border-color: #989898; + cursor: default; +} + +#my-infos .element div.bubble { + background-color: white; + border-color: #636363; + border-width: 1px 1px 0 1px; + border-style: solid; + width: 25px; + padding: 1px 0; + position: absolute; + bottom: 21px; + left: 6px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + -moz-border-radius-topleft: 2px; + -moz-border-radius-topright: 2px; + -webkit-border-top-left-radius: 2px; + -webkit-border-top-right-radius: 2px; +} + +#my-infos .element a { + float: left; +} + +#my-infos .element .icon span { + height: 16px; + width: 16px; + margin: 3px 4px; + display: block; +} + +#my-infos .element input { + height: 18px; + width: 190px; + font-size: 0.85em; + padding-left: 4px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-topleft: 0; + -moz-border-radius-bottomleft: 0; + -webkit-border-top-left-radius: 0; + -webkit-border-top-bottom-radius: 0; +} diff --git a/sources/addons/jappixmini/jappix/css/options.css b/sources/addons/jappixmini/jappix/css/options.css new file mode 100644 index 00000000..6dc4ecdb --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/options.css @@ -0,0 +1,97 @@ +/* + +Jappix - An open social platform +This is the options CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 26/04/11 + +*/ + +#options label { + width: 190px; + font-size: 0.94em; +} + +#options .forms { + width: 610px; + height: 328px; + margin: 15px 15px 15px 15px; + float: left; +} + +#options .forms select { + margin-top: -3px; + min-width: 120px; + float: left; +} + +#options .forms a.linked { + font-size: 0.9em; + float: left; +} + +#options fieldset.privacy { + display: none; +} + +#options .sub-ask-delete, #options .sub-ask-pass, #options .sub-ask-pass-success { + display: none; +} + +#options .sub-ask { + display: none; + width: 592px; + padding: 8px; + float: left; + border: 1px #879da2 dotted; + background: #cbdde1; +} + +#options .sub-ask-top { + font-size: 0.9em; + margin-top: -3px; +} + +#options .sub-ask-title { + margin-bottom: 4px; + float: left; +} + +#options .sub-ask-close { + float: right; +} + +#options .sub-ask-close:hover { + cursor: pointer; +} + +#options .sub-ask-content { + clear: both; + height: 25px; + font-size: 0.9em; + border-top: 1px #416972 solid; + padding: 12px 0; +} + +#options .sub-ask-content label { + width: 125px; +} + +#options .sub-ask-content input { + width: 125px; +} + +#options .sub-ask-bottom { + clear: both; + font-size: 0.9em; + float: right; + text-decoration: underline; +} + +#options .sub-ask-bottom:hover { + cursor: pointer; +} diff --git a/sources/addons/jappixmini/jappix/css/others.css b/sources/addons/jappixmini/jappix/css/others.css new file mode 100644 index 00000000..f3e2461f --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/others.css @@ -0,0 +1,118 @@ +/* + +Jappix - An open social platform +This is the others CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 31/08/11 + +*/ + +#audio { + display: none; +} + +#top-content { + position: absolute; + right: 5px; + left: 5px; + top: 0; + min-width: 860px; + z-index: 50; +} + +#main-content { + position: absolute; + top: 34px; + left: 5px; + right: 5px; + bottom: 5px; + min-width: 850px; + min-height: 450px; +} + +#left-content { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 248px; +} + +#right-content { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 260px; + z-index: 10; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + box-shadow: 0 0 6px #5c5c5c; + -moz-box-shadow: 0 0 6px #5c5c5c; + -webkit-box-shadow: 0 0 6px #5c5c5c; +} + +#general-wait { + background: url(../img/others/blank.gif) repeat; + z-index: 10000; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.general-wait-content { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.9); + background-position: 8px 8px; + padding: 8px; + position: absolute; + right: 5px; + bottom: 5px; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + box-shadow: 0 0 2px #000; + -moz-box-shadow: 0 0 2px #000; + -webkit-box-shadow: 0 0 2px #000; +} + +.inbox-hidable, +.options-hidable, +.pep-hidable, +.pubsub-hidable, +.archives-hidable, +.commands-hidable, +.privacy-hidable, +.xmpplinks-hidable { + display: none; +} + +#reconnect .pane { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.85); + color: white; + padding: 25px; + z-index: 10000; + text-shadow: 0 1px 1px black; + position: absolute; + left: 0; + right: 0; + top: 0; + box-shadow: 0 0 35px #232323; + -moz-box-shadow: 0 0 35px #232323; + -webkit-box-shadow: 0 0 35px #232323; +} + +#reconnect .pane a { + margin-top: -4px; + float: right; +} diff --git a/sources/addons/jappixmini/jappix/css/pageengine.css b/sources/addons/jappixmini/jappix/css/pageengine.css new file mode 100644 index 00000000..75038b6c --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/pageengine.css @@ -0,0 +1,601 @@ +/* + +Jappix - An open social platform +This is the page-engine CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 31/08/11 + +*/ + +#page-engine { + background-color: #f4f4f4; + position: absolute; + top: 40px; + bottom: 6px; + right: 6px; + left: 6px; + z-index: 8; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +#page-engine .top { + background: #e8f1f3; + background: -moz-linear-gradient(top, #e8f1f3, #dee8ea); + background: -webkit-gradient(linear, left top, left bottom, from(#e8f1f3), to(#dee8ea)); + border-bottom: 1px solid #d0d0d0; + color: black; + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 6px; + height: 80px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-topleft: 3px; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; +} + +#page-engine .top .avatar-container { + text-align: center; + margin: 2px 0 0 10px; + height: 76px; + width: 76px; + float: left; +} + +#page-engine .top .avatar { + max-height: 76px; + max-width: 76px; +} + +#page-engine .top .name { + text-align: right; + padding: 7px; +} + +#page-engine p.bc-name { + font-size: 2.3em; + margin-bottom: 5px; +} + +#page-engine p.bc-infos { + font-size: 0.85em; + height: 16px; + overflow: hidden; + position: absolute; + left: 115px; + right: 12px; +} + +#page-engine .page-engine-chan[data-type=groupchat] p.bc-infos { + left: 12px; +} + +#page-engine p.bc-infos span.show { + padding-left: 18px; +} + +#page-engine p.bc-infos a { + text-decoration: underline; +} + +#page-engine div.bc-pep { + float: right; +} + +#page-engine div.bc-pep a { + height: 16px; + width: 16px; + margin-left: 4px; + float: left; +} + +#page-engine div.bc-pep a:hover { + cursor: default; +} + +#page-engine div.bc-pep a[href]:hover { + cursor: pointer; +} + +#page-engine .content, +#page-engine .list { + font-size: 0.9em; + position: absolute; + top: 93px; + right: 0; + bottom: 29px; + overflow: auto; + box-shadow: inset 0 3px 10px #e8e8e8; + -moz-box-shadow: inset 0 3px 10px #e8e8e8; + -webkit-box-shadow: inset 0 3px 10px #e8e8e8; +} + +#page-engine .content { + left: 0; + padding: 12px 14px 0; +} + +#page-engine .content a { + text-decoration: underline; +} + +#page-engine .page-engine-chan { + display: none; +} + +#page-engine .chat .content, +#page-engine .chat .list { + bottom: 93px; +} + +#page-engine .chat .content { + padding-bottom: 24px; +} + +#page-engine .groupchat-content { + padding-bottom: 16px !important; + right: 191px !important; +} + +#page-engine .list { + border-left: 1px solid #c8c8c8; + padding: 8px 0 0; + width: 190px; + right: 0; +} + +#page-engine .list .role { + display: none; + margin-bottom: 10px; +} + +#page-engine .list .title { + font-weight: bold; + color: #383838; + margin-left: 8px; +} + +#page-engine .list .user { + background: #eff2f2; + background: -moz-linear-gradient(top, #eff2f2, #ecefef); + background: -webkit-gradient(linear, left top, left bottom, from(#eff2f2), to(#ecefef)); + border-color: #c8c8c8; + border-width: 1px 0; + border-style: solid; + color: #383838; + margin-bottom: 3px; + height: 32px; + overflow: hidden; +} + +#page-engine .list .user:hover { + background: #e9ecec; + cursor: pointer; +} + +#page-engine .list .user:active { + background: #e3e7e7; +} + +#page-engine .list .user.myself { + background-color: #eff2f2; + cursor: default; +} + +#page-engine .list .user .name { + float: left; + height: 18px; + overflow: hidden; + margin: 7px 0 7px 3px; + padding-left: 18px; +} + +#page-engine .list .user .avatar-container { + text-align: center; + float: right; + height: 32px; + width: 32px; +} + +#page-engine .list .user .avatar { + max-height: 32px; + max-width: 32px; +} + +#page-engine .one-group, +#archives .one-group { + border-bottom: 1px dotted #d0d0d0; + padding-bottom: 8px; + margin-bottom: 10px; +} + +#page-engine .one-line, +#archives .one-line, +#page-engine .one-group b.name, +#archives .one-group b.name { + padding-left: 50px; + word-wrap: break-word; +} + +#page-engine .one-group b.name, +#archives .one-group b.name { + display: block; + margin-bottom: 4px; +} + +#page-engine .one-group b.name.me, +#archives .one-group b.name.me { + color: #123a5c; +} + +#page-engine .one-group b.name.him, +#archives .one-group b.name.him { + color: #801e1e; +} + +#page-engine .one-group span.date, +#archives .one-group span.date { + float: right; + font-size: 0.9em; +} + +#page-engine .one-group .avatar-container, +#archives .one-group .avatar-container { + text-align: center; + margin: 4px 0 0 6px; + height: 30px; + width: 30px; + float: left; +} + +#page-engine .one-group .avatar, +#archives .one-group .avatar { + max-height: 30px; + max-width: 30px; +} + +#page-engine b.name.talk-images { + background-position: 50px -99px; + padding-left: 68px; +} + +#page-engine .user-message, +#archives .user-message { + margin-bottom: 3px; +} + +#page-engine .system-message { + color: #053805 !important; + margin-bottom: 3px !important; + padding-left: 0 !important; +} + +#page-engine .system-message a { + color: #053805 !important; +} + +#page-engine .system-message p.help b { + margin-bottom: 5px; + text-decoration: underline; + display: block; +} + +#page-engine .system-message p.help em { + width: 240px; + text-decoration: underline; + margin-left: 5px; + float: left; +} + +#page-engine .my-nick { + font-weight: bold; +} + +#page-engine .old-message { + font-size: 11px !important; + margin-bottom: 1px !important; +} + +#page-engine .chatstate { + background-color: rgb(234,234,234); + background-color: rgba(234,234,234,0.8); + color: #2c2c2c; + padding: 3px 10px 2px 8px; + position: absolute; + bottom: 93px; + left: 0; + font-size: 0.75em; + border-top-right-radius: 3px; + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; +} + +#page-engine .text { + height: 93px; + position: absolute; + bottom: 0; + left: 0; + right: 0; +} + +#page-engine .footer { + background: #e8f1f3; + background: -moz-linear-gradient(top, #dee8ea, #e8f1f3); + background: -webkit-gradient(linear, left top, left bottom, from(#dee8ea), to(#e8f1f3)); + border-color: #d0d0d0; + border-width: 1px 0 0; + border-style: solid; + color: black; + position: absolute; + left: 0; + right: 0; + padding: 6px; + height: 16px; +} + +#page-engine .chat .footer { + border-width: 1px 0; + position: static; +} + +#page-engine .chat-tools-content { + height: 16px; + width: 16px; + margin-right: 8px; + float: left; +} + +#page-engine .tools-tooltip { + display: block; + height: 16px; + width: 16px; + overflow: hidden; + float: left; +} + +#page-engine .text .chat-tools-smileys { + margin-left: 4px; +} + +#page-engine .text .chat-tools-file { + display: none; +} + +#page-engine .text .chat-tools-file.mini .bubble-file { + z-index: 39; +} + +#page-engine .text .chat-tools-file.mini .tooltip-subitem { + width: 22px; + height: 20px; +} + +#page-engine .text .chat-tools-file.mini .wait { + margin: -2px 0 0 -1px; +} + +#page-engine .text .tools-smileys { + background-position: 0 -388px; +} + +#page-engine .text .tools-style { + background-position: 0 -700px; +} + +#page-engine .text .tools-file { + background-position: 0 -1956px; +} + +#page-engine .text .tools-save { + background-position: 0 -719px; +} + +#page-engine .text .tools-clear { + background-position: 0 -739px; +} + +#page-engine .text .tools-infos, +#channel .top div.shortcuts a.profile { + background-position: 0 -758px; +} + +#page-engine .text .tools-add, +#page-engine .text .tools-archives, +#page-engine .text .tools-mucadmin { + display: none; +} + +#page-engine .text .tools-mucadmin { + background-position: 0 -777px; +} + +#page-engine .bubble-style label.bold { + font-weight: bold; +} + +#page-engine .bubble-style label.italic { + font-style: italic; +} + +#page-engine .bubble-style label.underline { + text-decoration: underline; +} + +#page-engine .bubble-style a.color { + height: 18px; + width: 18px; + border-color: white; + border-width: 1px; + border-style: solid; + margin: 6px 5px 0 0; + float: left; + opacity: 0.6; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 5px black; + -moz-box-shadow: 0 0 5px black; + -webkit-box-shadow: 0 0 5px black; +} + +#page-engine .bubble-style a.color:hover, +#page-engine .bubble-style a.color:focus { + opacity: 0.7; +} + +#page-engine .bubble-style a.color.selected { + opacity: 1; + border-color: #ffb20d; +} + +#page-engine .bubble-file .tooltip-subitem { + width: 240px; +} + +#page-engine .bubble-file input[type=file] { + width: 220px; +} + +#page-engine .bubble-file input[type=submit], +#page-engine .bubble-file input[type=reset] { + margin: 4px 4px 0 0; +} + +#page-engine .text .compose, +#page-engine .muc-ask { + position: absolute; + left: 0; +} + +#page-engine .text .compose { + top: 29px; + right: 12px; + bottom: 12px; +} + +#page-engine .muc-ask { + right: 0; + bottom: 0; +} + +#page-engine .text textarea { + border: 1px solid #c8c8c8; + padding: 5px; + height: 100%; + width: 100%; + font-size: 1.1em; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-top-right-radius: 0; + border-top-left-radius: 0; + -moz-border-radius-topright: 0; + -moz-border-radius-topleft: 0; + -webkit-border-top-right-radius: 0; + -webkit-border-top-left-radius: 0; +} + +#page-engine .muc-ask { + background-color: #e8f1f3; + height: 64px; + font-size: 0.9em; + right: 0; + z-index: 2; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; +} + +#page-engine .muc-ask label { + color: #224249; + margin: 23px 10px 0 16px; + font-weight: bold; +} + +#page-engine .muc-ask input { + width: 200px; + margin: 19px 10px 0 10px; + padding: 3px; +} + +#page-engine .tooltip { + position: absolute; + bottom: 84px; + margin-left: -13px; + z-index: 40; + font-size: 0.8em; + color: white; +} + +#page-engine .tooltip a { + color: white; + text-decoration: underline; +} + +#page-engine .tooltip-subitem { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.8); + padding: 10px; + width: 200px; + height: 110px; + text-shadow: 0 1px 1px black; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +#page-engine .tooltip-subarrow { + background-position: 0 -251px; + opacity: 0.8; + height: 10px; + width: 18px; + margin-left: 12px; +} + +#page-engine .tooltip .tooltip-top { + margin-bottom: 8px; + font-weight: bold; +} + +#page-engine .tooltip label { + margin-bottom: 4px; + float: left; + clear: both; +} + +#page-engine .tooltip label input[type=checkbox] { + margin: 0 6px 0 0; + float: left; +} + +#page-engine .tooltip label.select { + margin-top: 5px; +} + +#page-engine .tooltip input, +#page-engine .tooltip select { + float: left; +} + +#page-engine .tooltip select { + width: 100px; +} + +#page-engine .tooltip .tooltip-actionlog:hover, +#page-engine .tooltip .tooltip-actionlog:focus { + cursor: pointer; + text-decoration: underline; +} diff --git a/sources/addons/jappixmini/jappix/css/pageswitch.css b/sources/addons/jappixmini/jappix/css/pageswitch.css new file mode 100644 index 00000000..59830049 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/pageswitch.css @@ -0,0 +1,209 @@ +/* + +Jappix - An open social platform +This is the page-switch CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 22/05/11 + +*/ + +#page-switch { + position: absolute; + top: 15px; + left: 10px; + right: 10px; + z-index: 9; +} + +#page-switch .chans { + position: absolute; + left: 0; + right: 40px; + top: 0; + height: 25px; + overflow: hidden; +} + +#page-switch .more { + position: absolute; + right: 0; + top: 0; +} + +#page-switch .more-button { + background-position: 6px -1372px; + background-color: #d9e7ea; + width: 7px; + height: 17px; + padding: 1px 6px; + font-size: 0.9em; + text-decoration: none; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +#page-switch .more-content { + background-color: #d9e7ea; + width: 200px; + max-height: 400px; + overflow: auto; + position: absolute; + margin: -2px 0 0 -181px; + padding: 4px 0; + font-size: 0.95em; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topleft: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; +} + +#page-switch .switcher { + background-color: #d9e7ea; + color: #17353b; + height: 15px; + padding: 5px 10px 5px 5px; + margin: 0 2px; + font-size: 0.85em; + float: left; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-topleft: 3px; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; +} + +#page-switch .more-content .switcher { + background-color: #d9e7ea; + float: none; + margin: 0; + font-size: 0.9em; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; +} + +#page-switch .more-content .switcher .exit { + display: block; +} + +#page-switch .more-button:hover, +#page-switch .more-button:focus, +#page-switch .switcher:hover, +#page-switch .switcher:focus, +#page-switch .more-content .switcher:hover, +#page-switch .more-content .switcher:focus { + background-color: #cedee1; + cursor: pointer; +} + +#page-switch .more-button:active, +#page-switch .switcher:active, +#page-switch .more-content .switcher:active { + background-color: #c3d3d7; +} + +#page-switch .switcher.activechan { + background-color: #e8f1f3; +} + +#page-switch .more-content .switcher.activechan { + background-color: #d1e0e3; +} + +#page-switch .icon { + height: 16px; + width: 16px; + float: left; +} + +#page-switch .name { + float: left; + margin-left: 4px; + max-height: 16px; + max-width: 140px; + overflow: hidden; +} + +#page-switch .exit { + display: none; + background-color: #bdd9dc; + border: 1px solid #80aab0; + color: #355e64; + height: 14px; + width: 13px; + margin-left: 10px; + font-size: 0.85em; + text-align: center; + text-decoration: none; + float: right; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +#page-switch .exit:hover, +#page-switch .exit:focus { + background-color: #aac7cb; +} + +#page-switch .exit:active { + background-color: #9bbdc1; +} + +#page-switch .activechan .exit { + display: block; + float: right; +} + +#page-switch .chan-newmessage { + background-color: #f6edc3 !important; +} + +#page-switch .chan-newmessage:hover, +#page-switch .chan-newmessage:focus { + background-color: #f1eac0 !important; +} + +#page-switch .chan-newmessage:active { + background-color: #ede4b8 !important; +} + +#page-switch .composing, +#page-engine .list .user.composing { + color: #217021 !important; +} + +#page-switch .paused, +#page-switch .chan-unread .name, +#page-engine .list .user.paused { + color: #2431ac !important; +} + +#page-switch .active, +#page-engine .list .user.active { + color: #353535 !important; +} + +#page-switch .inactive, +#page-engine .list .user.inactive { + color: #585858 !important; +} + +#page-switch .gone { + color: #851313 !important; +} + +#page-switch .channel .icon { + background-position: 0 -55px; +} diff --git a/sources/addons/jappixmini/jappix/css/popup.css b/sources/addons/jappixmini/jappix/css/popup.css new file mode 100644 index 00000000..e5b3eb92 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/popup.css @@ -0,0 +1,612 @@ +/* + +Jappix - An open social platform +This is the popup CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 02/05/11 + +*/ + +.lock { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.6); + left: 0; + right: 0; + top: 0; + bottom: 0; + position: fixed; + z-index: 9999; +} + +.popup { + background-color: rgb(20,20,20); + background-color: rgba(20,20,20,0.95); + margin-top: -250px; + margin-left: -330px; + width: 640px; + height: 500px; + padding: 0 10px; + position: absolute; + z-index: 10000; + left: 50%; + top: 50%; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + box-shadow: 0 0 35px #232323; + -moz-box-shadow: 0 0 35px #232323; + -webkit-box-shadow: 0 0 35px #232323; +} + +.popup.large { + margin-left: -460px; + width: 920px; +} + +.popup .top { + width: 600px; + height: 45px; + font-size: 1.2em; + padding-top: 9px; + color: white; + margin: 14px 0 0 40px; + text-transform: uppercase; + text-decoration: none; + font-weight: bold; + text-shadow: 0 2px 2px black; +} + +.popup .tab { + width: 620px; + height: 25px; + margin: -5px 10px 0 10px; + position: relative; + z-index: 1; +} + +.popup .tab a { + background-color: #d9e7ea; + color: #204249; + width: 180px; + height: 17px; + padding: 4px 4px 4px 16px; + margin-left: 5px; + font-size: 0.94em; + overflow: hidden; + float: left; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-topleft: 3px; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; +} + +.popup .tab a:hover, +.popup .tab a:focus { + background-color: #cedee1; + text-decoration: none; +} + +.popup .tab a:active { + background-color: #c3d3d7; + text-decoration: none; +} + +.popup .tab a.tab-active { + background-color: #e4eef9 !important; +} + +.popup .one-lap { + display: none; +} + +.popup .one-lap.lap-active { + display: block; +} + +.popup .content { + background: #e4eef9; + background: -moz-linear-gradient(top, #e4eef9, #D0E5FA); + background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#D0E5FA)); + height: 358px; + width: 640px; + position: absolute; + left: 10px; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 20px black; + -moz-box-shadow: 0 0 20px black; + -webkit-box-shadow: 0 0 20px black; +} + +.popup .content, +.popup .content a { + color: #112a2f; +} + +.popup.large div.comments { + background-color: #f4f4f4; + width: 272px; + margin: 0; + position: absolute; + right: 10px; + top: 63px; + bottom: 10px; + overflow-x: hidden; + overflow-y: auto; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +.popup.large div.comments div.comments-content { + font-size: 0.8em; +} + +.popup.large div.comments input { + width: 185px; + min-width: 0; +} + +.popup.large div.comments .one-comment { + padding-bottom: 4px; +} + +.popup.large div.comments .one-comment a { + text-decoration: underline; +} + +.popup.large div.comments div.comments-content { + border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-topleft: 3px; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; +} + +.popup .head { + background: #f1f6fd; + border: 1px #9dc4fc solid; + width: 606px; + height: 24px; + margin: 0 10px 10px 10px; + padding: 6px; +} + +.popup .head-text { + float: left; + font-size: 0.9em; + margin: 3px; +} + +.popup .head-actions { + float: right; + margin-top: 2px; +} + +.popup .head-actions a { + font-size: 0.9em; + margin: 0 4px; +} + +.popup .actions a { + color: #30575f; + font-size: 0.9em; + margin-left: 5px; +} + +.popup .head .head-input { + float: right; + width: 200px; + padding: 2px; +} + +.popup .head .head-select { + float: right; + height: 24px; +} + +.popup .forms { + width: 390px; + height: 328px; + margin: 15px; + float: left; +} + +.popup fieldset { + border: 1px #547177 solid; + margin: 0 0 15px 0; + padding: 8px 2px 3px 2px; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} + +.popup legend { + font-size: 0.9em; + margin: 0 0 0 15px; + padding: 0 2px; + text-transform: uppercase; +} + +.popup label { + color: #1b1b1b; + width: 150px; + margin: 0 0 10px 12px; + clear: both; + float: left; +} + +.popup input, +.popup select { + margin: 0 10px 10px 0; + float: left; +} + +.popup input[type=text] { + min-width: 174px; +} + +.popup select { + min-height: 20px; +} + +.popup .results { + height: 310px; + width: 620px; + margin: -5px 0 0 10px; + padding: 6px 0 0 0; + overflow: auto; +} + +.popup .results .no-results { + margin: 6px 0; + font-size: 0.85em; + font-weight: bold; +} + +.popup .results label { + width: 180px; + margin: 6px 4px 4px 4px; +} + +.popup .results input, +.popup .results textarea, +.popup .results select { + margin: 4px; +} + +.popup .results input, +.popup .results select { + min-width: 180px; +} + +.popup .results input[type=checkbox], +.popup .results input[type=radio] { + margin-top: 7px; +} + +.popup .results textarea { + width: 380px; +} + +.popup .results .avatar-container { + float: left; + width: 60px; + height: 60px; + margin: 5px 12px 5px 9px; + text-align: center; + background-repeat: no-repeat; +} + +.popup .results img.avatar { + max-width: 60px; + max-height: 60px; +} + +.popup .results .one-icon { + height: 16px; + width: 16px; + margin: 10px 3px 0 8px; + float: left; +} + +.popup .results .one-icon.account, +.popup .results .one-icon.auth { + background-position: 0 -777px; +} + +.popup .results .one-icon.automation, +.popup .results .one-icon.client { + background-position: 0 -1500px; +} + +.popup .results .one-icon.collaboration { + background-position: 0 -1520px; +} + +.popup .results .one-icon.proxy, +.popup .results .one-icon.server, +.popup .results .one-icon.others { + background-position: 0 -1540px; +} + +.popup .results .one-icon.component, +.popup .results .one-icon.gateway { + background-position: 0 -1560px; +} + +.popup .results .one-icon.conference { + background-position: 0 -1082px; +} + +.popup .results .one-icon.directory { + background-position: 0 -876px; +} + +.popup .results .one-icon.headline, +.popup .results .one-icon.hierarchy { + background-position: 0 -1580px; +} + +.popup .results .one-icon.pubsub, +.popup .results .one-icon.store { + background-position: 0 -1600px; +} + +.popup .results .one-icon.loading { + background-position: 0 -1620px; +} + +.popup .results .one-icon.down { + background-position: 0 -1640px; +} + +.popup .results .one-host { + font-weight: bold; + width: 170px; +} + +.popup .results .one-type { + width: 210px; +} + +.popup .results .one-type, +.popup .results .one-host { + float: left; + overflow: hidden; + margin: 9px 8px; +} + +.popup .results .one-jid, +.popup .results .one-ctry, +.popup .results .one-fn { + margin: 4px; + width: 400px; +} + +.popup .results .one-fn { + font-weight: bold; +} + +.popup .results .one-jid { + margin-top: 8px; + font-size: 0.9em; +} + +.popup .results .one-name { + float: left; + margin: 4px; +} + +.popup a.one-button { + display: none; + background-color: #f1f6fd; + border: 1px solid #b9cbcf; + margin-top: 1px; + padding: 4px 8px; + text-decoration: none; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +.popup a.one-button:hover, +.popup a.one-button:focus { + border: 1px solid #95b1b7; +} + +.popup a.one-button:active { + border: 1px solid #77989f; +} + +.popup .results .oneresult:hover a.one-button { + display: block; +} + +.popup .results a.one-button, +#inbox .one-message a.one-button { + float: right; + padding: 3px 6px; + margin-right: 4px; +} + +.popup .results a.one-vjud { + position: absolute; + right: 4px; +} + +.popup .results a.one-add { + top: 8px; +} + +.popup .results a.one-chat { + top: 42px; +} + +.popup .results .one-next { + float: right; + margin: 4px 8px 4px 4px; + font-weight: bold; +} + +.popup .results .one-actions { + width: 148px; + margin: 4px; + float: left; +} + +.popup .results .one-actions a { + width: 16px; + height: 16px; + padding: 2px 2px 4px 5px !important; + margin-top: 2px; +} + +.popup .results .one-actions a.browse { + background-position: 3px -1396px; +} + +.popup .results .one-actions a.command { + background-position: 3px -1415px; +} + +.popup .results .one-actions a.subscribe { + background-position: 4px -1435px; +} + +.popup .results .one-actions a.join { + background-position: 3px -1455px; +} + +.popup .results .one-actions a.search { + background-position: 4px -1475px; +} + +.popup .results a.submit, +.popup .results a.cancel, +.popup .results a.back { + margin-right: 8px; + float: right; +} + +.popup .onetitle { + font-size: 0.9em; + padding: 4px; + font-weight: bold; +} + +.popup .oneinstructions { + font-size: 0.9em; + padding: 4px; + margin: 8px 0; +} + +.popup .oneresult { + font-size: 0.9em; + padding: 3px 0 4px 4px; + border-bottom: 1px #9dc4fc solid; + overflow: hidden; + position: relative; +} + +.popup .oneresult:hover { + background: #e9f1fd; +} + +.popup .oneresult[onclick]:hover { + cursor: pointer; +} + +.popup .oneresult[onclick]:active { + background: #f1f6fd; +} + +.popup .infos { + background-color: rgb(255,239,104); + background-color: rgba(255,239,104,0.8); + border: 1px #decb2f solid; + color: #3f3f3f; + padding: 8px; + margin: 10px; + font-size: 0.8em; +} + +.popup .infos p { + margin-top: 10px; +} + +.popup .infos p.infos-title { + font-weight: bold; +} + +.popup .bottom { + width: 640px; + height: 40px; + position: absolute; + bottom: 8px; +} + +.popup .wait { + display: none; + margin: 8px 0 0 3px; + float: left; +} + +a.finish { + border: 1px solid white; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.1); + color: white; + padding: 4px 8px; + margin-right: 7px; + font-size: 0.95em; + text-align: center; + text-decoration: none; + text-shadow: 0 1px 1px black; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 5px black; + -moz-box-shadow: 0 0 5px black; + -webkit-box-shadow: 0 0 5px black; +} + +a.finish:hover, +a.finish:focus { + cursor: pointer; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.2); + box-shadow: 0 0 15px black; + -moz-box-shadow: 0 0 15px black; + -webkit-box-shadow: 0 0 15px black; +} + +a.finish:active { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.3); +} + +a.finish.disabled { + opacity: 0.2; +} + +a.finish.disabled:hover, +a.finish.disabled:focus, +a.finish.disabled:active { + cursor: default; + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.1); +} + +.popup a.finish { + margin-top: 6px; + float: right; +} diff --git a/sources/addons/jappixmini/jappix/css/privacy.css b/sources/addons/jappixmini/jappix/css/privacy.css new file mode 100644 index 00000000..521be322 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/privacy.css @@ -0,0 +1,197 @@ +/* + +Jappix - An open social platform +This is the privacy CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 16/02/11 + +*/ + +#privacy .content { + padding: 10px 0 10px 0; +} + +#privacy .privacy-head div.list-left, +#privacy .privacy-head div.list-center, +#privacy .privacy-head div.list-right, +#privacy .privacy-first { + float: left; +} + +#privacy .privacy-head div.list-left { + margin-left: 5px; +} + +#privacy .privacy-head div.list-center { + border-right: 1px dotted #1b393f; + height: 24px; + width: 1px; + margin-right: 15px; + padding-left: 18px; +} + +#privacy .privacy-head span, +#privacy .privacy-head a, +#privacy .privacy-item span, +#privacy .privacy-item a { + float: left; +} + +#privacy .privacy-head span { + font-size: 0.9em; + font-weight: bold; + margin: 3px 10px 0 0; +} + +#privacy .privacy-head input, +#privacy .privacy-head select { + width: 180px; +} + +#privacy .privacy-head input { + margin-top: 1px; +} + +#privacy .privacy-head select, +#privacy .privacy-item select { + margin-top: -2px; +} + +#privacy .privacy-head span.left-space { + margin-left: 16px; +} + +#privacy .privacy-head a, +#privacy .privacy-item a { + width: 20px; + height: 20px; + padding: 0; + display: block; +} + +#privacy .privacy-item a.item-add { + background-position: 2px -1178px; +} + +#privacy .privacy-head a.list-remove, +#privacy .privacy-item a.item-remove { + background-position: 2px -1197px; +} + +#privacy .privacy-item a.item-save { + background-position: 3px -126px; + width: auto; + height: 19px; + padding: 1px 7px 0 21px; +} + +#privacy .privacy-item, +#privacy form, +#privacy .privacy-active { + clear: both; +} + +#privacy .privacy-item { + margin: 17px 12px; + font-size: 0.9em; +} + +#privacy .privacy-item span { + font-weight: bold; +} + +#privacy .privacy-item select { + width: 300px; + margin: -4px 30px 0 10px; +} + +#privacy .privacy-item a { + margin: -2px 6px 0 0; +} + +#privacy .privacy-first, +#privacy .privacy-second, +#privacy .privacy-third { + height: 195px; + font-size: 0.9em; + margin: 10px 0 0 10px; + float: left; +} + +#privacy .privacy-first, +#privacy .privacy-second { + border-right: 1px dotted #1b393f; + padding-right: 14px; +} + +#privacy .privacy-first { + width: 125px; +} + +#privacy .privacy-first label { + margin: 50px 0 0 15px; +} + +#privacy .privacy-first label input { + margin-top: 2px; +} + +#privacy .privacy-second { + width: 205px; +} + +#privacy .privacy-second label { + margin: 2px 0 0 12px; +} + +#privacy .privacy-second input[type=radio], +#privacy .privacy-third input[type=checkbox] { + margin-top: 2px; + margin-bottom: 2px; +} + +#privacy .privacy-second input[type=text], +#privacy .privacy-second select { + width: 170px; + margin: 2px 0 11px 12px; + float: none; +} + +#privacy .privacy-third label { + width: auto; + margin-top: 11px; +} + +#privacy .privacy-third { + width: 240px; +} + +#privacy .privacy-active { + margin: 34px 16px 0 16px; + font-size: 0.9em; +} + +#privacy .privacy-active-elements { + float: right; +} + +#privacy .privacy-active input[type=text] { + width: 30px; + margin: 0 0 0 8px; + float: none; +} + +#privacy .privacy-active input[type=checkbox] { + margin: 2px 8px 0 0; + float: left; +} + +#privacy .privacy-active label { + width: auto; + margin: 0 15px 0 0; + clear: none; +} diff --git a/sources/addons/jappixmini/jappix/css/rosterx.css b/sources/addons/jappixmini/jappix/css/rosterx.css new file mode 100644 index 00000000..4f159ac8 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/rosterx.css @@ -0,0 +1,53 @@ +/* + +Jappix - An open social platform +This is the Roster Item Exchange tool CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 05/02/11 + +*/ + +#rosterx .content { + padding: 10px 0 10px 0; +} + +#rosterx .rosterx-head a { + font-size: 0.9em; + margin: 3px 4px; + float: left; +} + +#rosterx .oneresult:hover { + cursor: pointer; +} + +#rosterx .oneresult span { + margin: 2px 5px 0 5px; + overflow: hidden; + float: left; +} + +#rosterx .oneresult span.name { + width: 230px; + font-weight: bold; +} + +#rosterx .oneresult span.xid { + width: 270px; + font-size: 0.9em; +} + +#rosterx .oneresult span.action { + width: 16px; + height: 16px; + margin-top: 4px; + float: right; +} + +#rosterx .oneresult span.action.modify { + background-position: 0 -1244px; +} diff --git a/sources/addons/jappixmini/jappix/css/search.css b/sources/addons/jappixmini/jappix/css/search.css new file mode 100644 index 00000000..505b17d9 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/search.css @@ -0,0 +1,60 @@ +/* + +Jappix - An open social platform +This is the search tool CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 23/01/11 + +*/ + +.search { + position: relative; +} + +.search input.suggested { + border-bottom: 1px solid white; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 0; + -moz-border-radius-bottomleft: 0; + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 0; +} + +.search ul { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.9); + border-color: #e1a014; + border-style: solid; + border-width: 0 1px 1px 1px; + position: absolute; + z-index: 1; + padding: 3px 0; + list-style: none; + overflow: auto; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + -moz-border-radius-bottomright: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 3px; +} + +.search ul li { + padding: 2px 6px; + color: #3d3d3d; + text-shadow: none; +} + +.search ul li:hover { + cursor: pointer; +} + +.search ul li.hovered { + background-color: rgb(225,160,20); + background-color: rgba(225,160,20,0.3); +} diff --git a/sources/addons/jappixmini/jappix/css/smileys.css b/sources/addons/jappixmini/jappix/css/smileys.css new file mode 100644 index 00000000..faad478b --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/smileys.css @@ -0,0 +1,196 @@ +/* + +Jappix - An open social platform +This is the smileys CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 16/02/11 + +*/ + +.emoticon { + width: 16px; + height: 16px; +} + +a.emoticon { + margin: 2px; + float: left; +} + +a.emoticon:hover, +a.emoticon:focus { + opacity: 0.8; +} + +a.emoticon:active { + opacity: 0.7; +} + +img.emoticon { + border: 0 none; + vertical-align: bottom; +} + +.emoticon-biggrin { + background-position: 0 0; +} + +.emoticon-devil { + background-position: -16px 0; +} + +.emoticon-coolglasses { + background-position: -32px 0; +} + +.emoticon-tongue { + background-position: -48px 0; +} + +.emoticon-smile { + background-position: -64px 0; +} + +.emoticon-wink { + background-position: -80px 0; +} + +.emoticon-blush { + background-position: -96px 0; +} + +.emoticon-stare { + background-position: -112px 0; +} + +.emoticon-frowning { + background-position: -128px 0; +} + +.emoticon-oh { + background-position: -144px 0; +} + +.emoticon-unhappy { + background-position: -160px 0; +} + +.emoticon-cry { + background-position: -176px 0; +} + +.emoticon-angry { + background-position: -192px 0; +} + +.emoticon-puke { + background-position: -208px 0; +} + +.emoticon-hugright { + background-position: -224px 0; +} + +.emoticon-hugleft { + background-position: -240px 0; +} + +.emoticon-lion { + background-position: -256px 0; +} + +.emoticon-pussy { + background-position: -272px 0; +} + +.emoticon-bat { + background-position: -288px 0; +} + +.emoticon-kiss { + background-position: -304px 0; +} + +.emoticon-heart { + background-position: -320px 0; +} + +.emoticon-brheart { + background-position: -336px 0; +} + +.emoticon-flower { + background-position: -352px 0; +} + +.emoticon-brflower { + background-position: -368px 0; +} + +.emoticon-thumbup { + background-position: -384px 0; +} + +.emoticon-thumbdown { + background-position: -400px 0; +} + +.emoticon-lamp { + background-position: -416px 0; +} + +.emoticon-coffee { + background-position: -432px 0; +} + +.emoticon-drink { + background-position: -448px 0; +} + +.emoticon-beer { + background-position: -464px 0; +} + +.emoticon-boy { + background-position: -480px 0; +} + +.emoticon-girl { + background-position: -496px 0; +} + +.emoticon-phone { + background-position: -512px 0; +} + +.emoticon-photo { + background-position: -528px 0; +} + +.emoticon-music { + background-position: -544px 0; +} + +.emoticon-cuffs { + background-position: -560px 0; +} + +.emoticon-mail { + background-position: -576px 0; +} + +.emoticon-rainbow { + background-position: -592px 0; +} + +.emoticon-star { + background-position: -608px 0; +} + +.emoticon-moon { + background-position: -624px 0; +} diff --git a/sources/addons/jappixmini/jappix/css/stats-svg.css b/sources/addons/jappixmini/jappix/css/stats-svg.css new file mode 100644 index 00000000..f512a939 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/stats-svg.css @@ -0,0 +1,71 @@ +/* + +Jappix - An open social platform +This is the SVG stats CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Erwan Briand, Vanaryon +Last revision: 20/11/10 + +*/ + +svg { + background-color: #e8f1f3; +} + +.refline { + stroke: #596171; + stroke-width: 2px; +} + +.refleft { + fill: #000000; + font-family: "Inconsolata", "DejaVu Serif sans", Verdana, sans-serif; + font-size: 8px; +} + +.reftext { + fill: #586070; + font-family: "Inconsolata", "DejaVu Serif sans", Verdana, sans-serif; + font-size: 10px; +} + +.bubbletextblue, +.bubbletextred { + fill: none; + font-family: "Inconsolata", "DejaVu Serif sans", Verdana, sans-serif; + font-size: 8px; + text-anchor: end; +} + +.bluebar { + fill: "#6C84C0"; + fill-opacity: "0.6"; +} + +.gbar:hover .bluebar { + fill: #2A3F73; +} + +.gbar:hover .redbar { + fill: #C70705; +} + +.gbar:hover #bubble { + fill: white; + stroke: grey; +} + +.gbar:hover .bubbletextblue { + fill: #2A3F73; +} + +.gbar:hover .bubbletextred { + fill: #C70705; +} + +.gbar:hover .reftext { + fill: #000000; +} diff --git a/sources/addons/jappixmini/jappix/css/tools.css b/sources/addons/jappixmini/jappix/css/tools.css new file mode 100644 index 00000000..8b689f54 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/tools.css @@ -0,0 +1,346 @@ +/* + +Jappix - An open social platform +This is the tools CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 27/08/11 + +*/ + +#top-content .tools { + background-color: rgb(232,241,243); + background-color: rgba(232,241,243,0.6); + padding: 3px 8px 5px 8px; + min-width: 10px; + height: 17px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; +} + +#top-content .tools a { + color: black; + padding: 0 3px; + margin: 0 1.5px; +} + +#top-content .tools a:hover, +#top-content .tools a:focus { + cursor: pointer; + text-decoration: underline; +} + +#top-content .tools-logo { + background-position: 9px 2px; + width: 74px; + float: left; +} + +#top-content .tools-all { + float: right; + text-align: right; + margin-left: 8px; + font-size: 0.9em; + color: black; +} + +#top-content .notifications { + background-position: 7px -1264px; +} + +#top-content .music { + background-position: 6px -1286px; +} + +#top-content .notifications:hover, +#top-content .music:hover { + cursor: pointer; +} + +#top-content .music:hover, +#top-content .notifications:hover, +#top-content .music:focus, +#top-content .notifications:focus { + background-color: rgb(232,241,243); + background-color: rgba(232,241,243,0.7); +} + +#top-content .music:active, +#top-content .notifications:active { + background-color: rgb(232,241,243); + background-color: rgba(232,241,243,0.8); +} + +#top-content .actived, +#top-content .actived:hover, +#top-content .actived:focus, +#top-content .actived:active { + background-color: rgb(232,241,243) !important; + background-color: rgba(232,241,243,0.9) !important; +} + +#top-content .notify { + background-color: #c60505; + color: white; + font-size: 0.7em; + font-weight: bold; + margin-left: -10px; + padding: 1px 4px; + position: absolute; + bottom: -2px; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; +} + +#top-content .tools-content { + display: none; + position: absolute; + top: 25px; + margin-left: -8px; +} + +.tools-content-subarrow { + background-position: 0 -241px; + opacity: 0.8; + height: 10px; + width: 18px; + margin-left: 12px; +} + +.tools-content-subitem { + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.8); + padding: 14px 6px 6px 6px; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +.notifications-content { + width: 240px; +} + +.notifications-content .tools-content-subitem { + max-height: 250px; + color: white; + text-shadow: 0 1px 1px black; + text-align: left; + overflow-x: none; + overflow-y: auto; +} + +.notifications-content .empty { + color: white; + font-size: 0.9em; + text-decoration: underline; + margin: -8px 4px 2px 0; + display: none; + float: right; +} + +.notifications-content .nothing { + font-size: 0.9em; + margin: 5px; +} + +.notifications-content .one-notification { + padding: 6px 4px; + font-size: 0.85em; + clear: both; + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +.notifications-content .one-notification:hover, +.notifications-content .one-notification:focus { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.1); +} + +.notifications-content .one-notification:active { + background-color: rgb(255,255,255); + background-color: rgba(255,255,255,0.2); +} + +.notifications-content .avatar-container { + float: left; + width: 40px; + height: 40px; + margin: 0 8px 8px 0; + text-align: center; + background-repeat: no-repeat; +} + +.notifications-content .avatar { + max-width: 40px; + max-height: 40px; +} + +.notifications-content .notification-text, +.notifications-content .notification-actions { + margin-left: 48px; + overflow: hidden; +} + +.notifications-content .notification-actions { + margin-top: 3px; +} + +.notifications-content .notification-actions a { + color: white; + font-weight: bold; + font-size: 0.9em; + text-decoration: underline; + margin-right: 8px; +} + +.notifications-content .one-notification .notification-actions span.talk-images { + background-position: 0 -1828px; + width: 16px; + height: 16px; + margin: -1px 6px 0 0; + float: left; +} + +.notifications-content .one-notification[data-type=subscribe] .notification-actions span.talk-images { + background-position: 0 -1796px; +} + +.notifications-content .one-notification[data-type=invite_room] .notification-actions span.talk-images { + background-position: 0 -1812px; +} + +.notifications-content .one-notification[data-type=send] .notification-actions span.talk-images, +.notifications-content .one-notification[data-type=send_accept] .notification-actions span.talk-images, +.notifications-content .one-notification[data-type=send_reject] .notification-actions span.talk-images, +.notifications-content .one-notification[data-type=send_fail] .notification-actions span.talk-images { + background-position: 0 -1956px; +} + +.notifications-content .one-notification[data-type=rosterx] .notification-actions span.talk-images { + background-position: 0 -1844px; +} + +.notifications-content .one-notification[data-type=comment] .notification-actions span.talk-images { + background-position: 0 -1860px; +} + +.notifications-content .one-notification[data-type=like] .notification-actions span.talk-images { + background-position: 0 -1876px; +} + +.notifications-content .one-notification[data-type=quote] .notification-actions span.talk-images { + background-position: 0 -1892px; +} + +.notifications-content .one-notification[data-type=wall] .notification-actions span.talk-images { + background-position: 0 -1908px; +} + +.notifications-content .one-notification[data-type=photo] .notification-actions span.talk-images { + background-position: 0 -1924px; +} + +.notifications-content .one-notification[data-type=video] .notification-actions span.talk-images { + background-position: 0 -1940px; +} + +.music-content { + width: 220px; +} + +.music-content .tools-content-subitem { + height: 247px; +} + +.music-content .player { + background: #b5d5db; + background: -moz-linear-gradient(top, #b5d5db, #adced4); + background: -webkit-gradient(linear, left top, left bottom, from(#b5d5db), to(#adced4)); + height: 20px; + padding: 2px 5px; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; +} + +.music-content .player a { + margin: 2px; + height: 16px; + width: 16px; + float: left; +} + +.music-content .player a:hover, +.music-content .player a:focus { + opacity: 0.8; +} + +.music-content .player a:active { + opacity: 0.6; +} + +.music-content .stop { + display: none; + background-position: 0 -270px; +} + +.music-content .list { + background-color: #e8f1f3; + height: 188px; + padding: 5px; + text-align: left; + overflow-y: auto; + overflow-x: hidden; +} + +.music-content p.no-results { + display: none; + color: black; + font-size: 0.9em; +} + +.music-content div.special { + padding-bottom: 2px; + margin-bottom: 6px; + border-bottom: 1px solid #c3d4d7; +} + +.music-content .song { + display: block; + margin: 3px 0; + font-size: 0.8em; +} + +.music-content .playing { + font-weight: bold; +} + +.music-content .search { + background-color: #e8f1f3; + height: 25px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; +} + +.music-content .search input { + margin: 2px; + width: 198px; + height: 15px; +} diff --git a/sources/addons/jappixmini/jappix/css/userinfos.css b/sources/addons/jappixmini/jappix/css/userinfos.css new file mode 100644 index 00000000..59bab655 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/userinfos.css @@ -0,0 +1,100 @@ +/* + +Jappix - An open social platform +This is the user-infos CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 27/03/11 + +*/ + +#userinfos .content { + overflow: auto; +} + +#userinfos .one-lap a { + text-decoration: underline; +} + +#userinfos .main-infos { + margin: 20px 20px 8px 20px; + height: 120px; + background: white; + position: relative; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; +} + +#userinfos .avatar-container { + float: left; + text-align: center; + margin: 20px 35px; + width: 80px; + height: 80px; +} + +#userinfos .avatar { + max-width: 80px; + max-height: 80px; +} + +#userinfos h1, +#userinfos h2, +#userinfos h3 { + width: 410px; + overflow: hidden; +} + +#userinfos h1 { + font-size: 2em; + padding-top: 12px; + margin-bottom: 4px; +} + +#userinfos h2 { + color: #447079; + font-size: 1.1em; + margin-bottom: 10px; +} + +#userinfos h3 { + color: #6e8388; + font-size: 0.8em; +} + +#userinfos .main-infos div.shortcuts { + position: absolute; + top: 10px; + right: 12px; +} + +#userinfos .block-infos { + margin: 7px 20px; + float: left; +} + +#userinfos .one-line { + margin: 4px 0; + font-size: 0.9em; + float: left; +} + +#userinfos .one-line b { + width: 120px; + float: left; +} + +#userinfos .one-line span.reset-info { + float: left; + width: 460px; +} + +#userinfos textarea { + margin: 30px 0 0 30px; + width: 572px; + height: 292px; +} diff --git a/sources/addons/jappixmini/jappix/css/vcard.css b/sources/addons/jappixmini/jappix/css/vcard.css new file mode 100644 index 00000000..59dfc486 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/vcard.css @@ -0,0 +1,106 @@ +/* + +Jappix - An open social platform +This is the vCard CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 16/01/12 + +*/ + +#vcard label { + font-size: 0.94em; + margin-top: 2px; +} + +#vcard #vcard-avatar input[type=file] { + margin-left: 15px; +} + +#vcard .avatar-container { + float: left; + text-align: center; + margin: 20px 0 35px 35px; + max-width: 96px; + max-height: 96px; +} + +#vcard .avatar { + max-width: 96px; + max-height: 96px; +} + +#vcard .avatar-delete { + background-position: 3px -1195px; + margin: 12px 25px 0 025px; + padding-left: 20px; + font-size: 0.9em; + float: right; +} + +#vcard .no-avatar { + width: 300px; + color: #7c2222; + padding: 10px; + margin: 15px 0 20px 40px; + background: #f8cece; + border: 1px #ba6d6d solid; + font-size: 0.8em; +} + +#vcard .forms textarea { + height: 111px; + width: 358px; + margin: 5px 12px 10px 12px; +} + +#vcard .forms .avatar-info { + border-width: 1px; + border-style: solid; + display: none; + width: 370px; + height: 15px; + font-size: 0.85em; + padding: 10px; +} + +#vcard .forms .avatar-wait { + background-color: #9bcbed; + color: #0a3858; + border-color: #306780; +} + +#vcard .forms .avatar-ok { + background-color: #c4ed9b; + color: #325213; + border-color: #578030; +} + +#vcard .forms .avatar-error { + background-color: #e79595; + color: #6a0b0b; + border-color: #7c1010; +} + +#vcard .infos { + width: 179px; + height: 328px; + margin: 15px 15px 15px 0; + padding: 0 8px; + float: right; +} + +#vcard .infos a { + text-decoration: underline; +} + +#vcard .send { + float: right; +} + +#vcard .send:hover { + cursor: pointer; +} diff --git a/sources/addons/jappixmini/jappix/css/welcome.css b/sources/addons/jappixmini/jappix/css/welcome.css new file mode 100644 index 00000000..71b31ef2 --- /dev/null +++ b/sources/addons/jappixmini/jappix/css/welcome.css @@ -0,0 +1,170 @@ +/* + +Jappix - An open social platform +This is the welcome tool CSS stylesheet for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 26/04/11 + +*/ + +#welcome .infos { + margin: 15px; +} + +#welcome .infos p { + margin-top: 6px; +} + +#welcome .infos p.infos-title { + margin-top: 0; +} + +#welcome a.box { + background-color: #e4eef9; + border: 1px solid #ccdbde; + margin: 12px 11px 4px 15px; + padding: 10px; + width: 270px; + text-decoration: none; + float: left; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; +} + +#welcome a.box.share { + width: 350px; + margin: 4px 130px; + padding: 4px 10px; + clear: both; +} + +#welcome a.box.share.first { + margin-top: 0; +} + +#welcome a.box.share:hover span.go { + display: block; +} + +#welcome a.box:hover, +#welcome a.box:focus { + border: 1px solid #93c5fa; +} + +#welcome a.box:active { + border: 1px solid #419afa; +} + +#welcome a.box.enabled { + background-color: #f1f6fd; + border: 1px solid #9dc4fc; +} + +#welcome a.box span { + margin: 3px 0; + display: block; +} + +#welcome a.box span.logo { + height: 35px; + width: 35px; + margin-right: 15px; + float: left; +} + +#welcome a.box span.logo.facebook { + background-position: 0 0; +} + +#welcome a.box span.logo.twitter { + background-position: -35px 0; +} + +#welcome a.box span.logo.buzz { + background-position: -70px 0; +} + +#welcome a.box span.logo.identica { + background-position: -105px 0; +} + +#welcome a.box span.option, +#welcome a.box span.name { + font-size: 0.9em; + font-weight: bold; +} + +#welcome a.box span.description { + font-size: 0.7em; + margin-top: 7px; +} + +#welcome a.box.share span.description { + margin-top: 4px; +} + +#welcome a.box span.image { + height: 16px; + width: 16px; + margin: -30px 12px 0 0; + float: right; +} + +#welcome a.box span.image.sound { + background-position: 0 -900px; +} + +#welcome a.box span.image.geolocation { + background-position: 0 -658px; +} + +#welcome a.box span.image.xmpp { + background-position: 0 -990px; +} + +#welcome a.box span.image.archives, +#page-engine .text .tools-archives { + background-position: 0 -1025px; +} + +#welcome a.box span.image.offline { + background-position: 0 -80px; +} + +#welcome a.box span.tick, +#welcome a.box span.go { + height: 16px; + width: 16px; + display: none; + float: right; +} + +#welcome a.box span.tick { + background-position: 0 -1661px; + margin: -52px -15px 0 0; +} + +#welcome a.box span.go { + background-position: 0 -1120px; + margin: -28px 5px 0 0; +} + +#welcome a.box.enabled span.tick { + display: block; +} + +#welcome div.results { + margin: -7px 15px; + padding: 0; + height: 272px; + overflow: auto; +} + +#welcome .bottom .finish.save { + display: none; +} diff --git a/sources/addons/jappixmini/jappix/img/others/blank.gif b/sources/addons/jappixmini/jappix/img/others/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..35d42e808f0a8017b8d52a06be2f8fec0b466a66 GIT binary patch literal 43 scmZ?wbhEHbWMp7uXkcLY|NlP&1B2pE7Dgb&paUX6G7L;iE{qJ;0LZEa`2YX_ literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/others/default-avatar.png b/sources/addons/jappixmini/jappix/img/others/default-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..7cda4c64b8c5eea35bdd7f1f5d54515578e3cb62 GIT binary patch literal 1436 zcmV;N1!MY&P)38p0aN4mY5#{O{9=IUH$Pl-36pp#n|Jr z>Ru6vhv!Sv+$pOrQ)m}?ksm;-U0teZI|1n4`ncWRBoYrsxw~+Hbe$LUVI?*F1ZeAE z?1;+pJx69|dqv{@$eMj$>9uX)W zq+7gD|A!>f-L6{F*bxADOvDaM&b^?}HhG`Ew-ClH^N9wK&hv9&()R4+eoA z&ntAl@&rNKch;OOP4KgaT9w-EkId=PltR12+fBvTZvp8lPu5pSbia&N8!w6&fGX{h zNGs(U?OS)gVaT?R>gE#>#BS&{h3=w4I?59ZNfK%LbW>;-c+jy)VqOZt>5lSXV-y%`h3|kSiq`;iF@%4>53w3R8Cvw)`A(gC zRw4bygN;bx!dEz@7rOxf-4)>@ zTvedZE^hz>ED0YeYZ~GKZUEi#uDA=T`5OvtXJZ(^f$#}cwQnoqmUwU*L0nQJd_fv} zNNKtq|H9ivW$1fpXojn`g%1F_0q8EiMEA9<=Et~1JkAKH%e<|2P@0ASsjkrd80U$H zI-FSY^rb7`BaOSxNozn_kZA8j_}07PeL4Gy6YlXfe?S*w3c7XGQ0P7nr1)xf7ob~= z$N(2W69iInp7%+ltC5}cS75TSP52I&b1x|!X9A|8?IGbiN)unKxD9BpM0WzxM1fqq zXl)%g3(tUY-^G^wQZ?EuLZPf_Bqd)8LYaIx#*l4`AQOK_faSn5`feaF#^W-26a zvtNMrrZOZI(s)-F0IBm|{{Z$|-aA%RYYc(!IbTD|B}4tg7hA3exM5bTiBkgm$wXv>T43 zjj$U4Lw5q(dgetetiLG+r7Go_@xX z0g9HPQ=Dr~1}IV{m&pLd=5p)F00j!Py_5`4@a=U@rY8dwsIeKlGZ~=RmNB0u0~Fgr q_+TrX+877l!}s{b%+Ad7K3vk;M!Q z+`=Ht$S`Y;1W-`2#5JPCIX^cyHLrxhxhOTUBsE2$JhLQ2!QIn0AiR-J9H@xf)5S4_ fLpC{K1}6i<9EMrzTxQ(>3Nv`R`njxgN@xNApadXJ literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/animate.gif b/sources/addons/jappixmini/jappix/img/sprites/animate.gif new file mode 100644 index 0000000000000000000000000000000000000000..cbf55da59291fb1d338d446756a4fca56916cd34 GIT binary patch literal 1898 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 IM6N<$f}^<@cK`qY literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/background.png b/sources/addons/jappixmini/jappix/img/sprites/background.png new file mode 100644 index 0000000000000000000000000000000000000000..4ae286d83f610c67efd5fa2d55ba92478bfcc363 GIT binary patch literal 8782 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 literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/browsers.png b/sources/addons/jappixmini/jappix/img/sprites/browsers.png new file mode 100644 index 0000000000000000000000000000000000000000..8fadb7b3836c59c35eccbe8aa7cb7814366017be GIT binary patch literal 10955 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 literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/buttons.png b/sources/addons/jappixmini/jappix/img/sprites/buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..4c32b14dcc2a7862a7e2f4a2bdb2793ac5300698 GIT binary patch literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^j6kHs!3JbmMD17#q}Y|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8prB-lYeb22er|4RUI~M9QEFmIYKlU6W=V#EyQgnJcq5-UP|-I} z7sn8b-m{Z8hO!y*G}~t;OEfAb@VX`PSXs&O3cBj~75x{TGX2o`z8p*aX_dcgdYNZ% zPk!Q>ct-qcs?mJ9e)IP4BI(6wM%?kiT1(ayfy?ZJ}JxUDwJdnSCoyvkk5-1fY@ z|4x~sQzy2xZeU?c{=U0WNq)tmKttYJE5z&)wMs6QYx(IU_=fDOxbMf$zSn*6?0NU+ ze>dds-LI5jve!3pk*wE}_h%-&&|JURYhsw>+O|7xy0b4_pW=C6tF>KjrOn38S5|Gb z{j==(@7GWN|Gvm7lPGXbsq#9@@(ZzBlM8okm)6y&Ua@yuSsJ6+G@Y8|Zuc5G>~A}+ V4b^@BNdy=I44$rjF6*2UngE;PlMVm? literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/home.png b/sources/addons/jappixmini/jappix/img/sprites/home.png new file mode 100644 index 0000000000000000000000000000000000000000..cd3ca4a19cd96c4e89f91ffa2183d180275c3e91 GIT binary patch literal 28465 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 T=SkqzK5L81=ii+3O!8-hKDmv*&F8 zxN^Eq*RAfSs=A)O(dw#lm}takFfcHf3i80u(0eWn3@jQ767&g$Tjx6r41K=>P*T%t z`P2v*l&aM{UXp}Vf+NKkO+{I#$bt45F6c9rere0OoC^knz0|Yw^4{dj|K@_DqxJlr@6KxT1D-|(WF-ruYCGLe zv}?61*S@EvrK!lmh4?*e_J)pJA541kT|Iatkc$$hBqr9LZ}mq?54@Y&2JdeV#Qvrb z59lB^bUB{=DN$DiG`S2%CnBb$rzfYvOU%jfyIyT|i;MAUu;(yp`;--QddlE4)U}SY z()%Gn$o;sb@V*(%m<=&6VNjKbOXRykY zMb73b47pCzo&(bna}m&~@_~z*ntHpg$}#%G8u%m6Dh@3v6*?6=J3I5IPqY1lUM<0$ zZ60Sn-cL72%ZZ7J=nvh(hx){}NYY5lV?<;W4OcN;kiUZ_Za4tYP{e zR@QX6KAhBaKW*{Yr6ea)_edX3WV}Bf2pqf`g;QUf|mh8yA;LcNb~;3pG%i#+W8j5c^pOg&gNm`G(cW@BQ_D;xTt+ zt=-dP@a>HyYN7BwXXEx{fh5+#RQ&I?0?pEThj&BVL(W6j1NzSAop`WnR1&csA)a1GiiB7BC(4v0$L(}5}BY8Jm zY}O*VOA;MC*qmI|HI^&v89+CdaO@eZ+KTx%?2u7Pq>vcXqp~IH(ito`g;F>ev)4|$g=$LCEy26frG`q{AZ3&X zWNx@xAA?JEqZ^re*S%30NQ=kWaz4)LS7sPJ7}gA`Eib2yF3}KxL6iMbe^UD-)E5Gi zCWPJRDzxHmYB03}gt<&{dEnvUiA;Ud${mhQ17B|!Y%RY+6fpV?U=5QXK5#{!@h zoc9&|^@H}p+HlrEf&`BKs)?%{O&7~yK=9k4Nsrh^k%W&KjTe;(SFm6eT8sVUW|F+Qm6WJ6{^ zDh%em98^%j>q6CcC53&c46mp`H<9^Aq#P{#^pFCzXt7RuHE2{ern*UTIym3|Zi%H< zK&VM%DUO7{E9UIFr*Ko=`6KXJf^hxq^;u4VaDdQnqK6Sp(#G>@y?ImM(%m_$v-6b$ zosd;NnS!3!fkJ`ttMx?ABks}G@m!@|EjQ8C8=N!Xf&Rf|AclbEDu<_JhyG8VXm(`V zKZ0CQ-FEFNeUi=cuXsIckABlA>1+n`FqoX-fZC8NKTL8Y-q780c+!=7s#*w~vMb+g z=Lfd-VL=wCvx!Fu#r*=$Rq9ZfDOtxHlJ*h~8##myDD~X^edy*t97@U)eqeo=Z{7$X z;c)l1hR8=YzPHs!A((jYrHKouXu#j>PWpzbgz0uYpSJ@?mW@(nIGQAu za8`{w76^U~9%$u}7}d77Kg;HPq32S~6KRdAVH2N56$mDiOCa}8157E?hcv1`$FmfHUoB}{#vU-O=6*7MyigN+EI}4U?6{pbU|Hnnk^vD1 zEVA`9KNk8NujvYN;@n%O%_3TFNaLAHP;jI1*ll3-KH9`-7R$!*L*ThJK=n8s0u>FS0WV&H zKo5s$0}MPS?2f$a6{qeqiCF~*fYVfhWSu|u+@#0#)EeD3L#?mrY=1o4A}Scg3rk#+ zaIKsA?)o~r7jAyn#s7Ts#2K5rRQ3@LU5sOTB(6exJd1asZ*P=u(f1jiT zsxoNKgJ3gtyZw_Mna4GMdAXikfp}U@yDX$fI8?Qo0T9s3dxPPT&7)y6Y!Lz(Or{mq z>@P33`fCn97J;Er0rh=eoWrQ4r;uL(W|+;${KSma@3OW!F>M+;^!VwD%^yl3VUfkc zTJxWpC}1+-JC!EgRv^^1I@M_+vX~_RBvHYGzRDo?ry}Vm85Y(g+=b%=kSab`A{Hu9 z7UyRWaUJILrBHGZD0*UJquVH8VLSGmGF=%#>fc0ot;d|Rd7U;iMpE6RBAu$>=8_ft z)_79TiQ*&)mSL{=+6diD^yjxH{J4Xy<~2B$imVGCrfZW7MRMoqL-VD~d!|Ahy1O%#Oei5~{Z=t?`=k4Sblm zl5Gnvl}`1J0Jt4YtkD_>3HAqd7+!|}BdxD6WQ{&YPZvr@_73U`ts+|kD;Y|km65&( zA*rLo4O8Q}?2V?`4a$bgk2f-~z_!X9FVy7Aqcmp_hcgwq0mUkLxPY{JrHW~yr=J$~ zKw(7XLaT`cUZ@e2EGE-+I|(lbbROr|AxLk3-CD{p-r{$W_v4MRDa1NjU~pHca6Zam zkctzm7<0~)H^>o@vm@J%XY+SQb{JNqKKo+mQ1&EVhHgF_4FjWcvTb+=HQ8D9>Mh~) zU^8o_Yr39}Ra8}dLWp^yCcaJ=$y~^HrC_bRMGlxV1O`6-+nd9&bPh^tKHObhhMG5c zK-AgyjXV*UHvBz6PTE^2N|az^x#L$Z5)(n7ZYzK(swL!%H!jMU*Q=&#cpTRPnsBjY zj6WzGq+MP$LRY^`y4_ak6@6Nk&p9h0CoesRp~Oz%}yp)67c^< z|JKoUB~Vo!Jn*>I1?K~@Qd~jiyXNV*-a>JV5i%Ar)PqY6*5SS12gEGxz(4bo<;*WT zhK~7ZO)Pu)6QeirvimD0(6gwdBW4Ht<*CqNiCA(@Qqc&QPxshsl0m)uIJqnUaFn>r zv8?%YTR&CI`X(g?_SpDE!J zGJDBOX&M?3cCjqtDg2@3#{JRuPz93@!8Lj$tjD1Y`=y#IwASY$X1xJ1+Az=TFNe1) z^7H5LW44%JBI)|vwELj8r>E5ljHGJ7;D$SyuTpaL@Oaal2puWf*`z12{RyXr6M~Pq zMV>I?L&$k|90~!ID+dAG_WwL8vF{vQdn2v=`q4W^i)2iZ?ElSx6GyNJGe?h|dn%-{ z<)hX=SADYxhW-!V*PKFq6Q?_U?~$9DnhacWU`>Nk(cxp*g&KG5%|WM&Twz~`9ZhR` zLyZlu+|>ABw;Q}y4b^JsJo=3y+^ja`U!6t@zlK-@&mt=JIVqMz84Mhta3eQbVbYoL;47>p zQk2_jqwNE@ zmz5T|v0bJdV!kT)q^SKMZFX!wMNA8a+$4VhhJG1gic`XenhVTK1s<6Vfx6a5WyOSNv zh`g;pWVtu*J4u7!9l?WpUI8LfSU&hpOu9r&uspCq;I#+mQq&o>1wRK7i?JZ7E#$0+ zi`7`1GfJts?DDZQQH`L9%|t2CnfrjfJ!J1jd>8XhiVngq5HNCxb!ZD8J;f@}>QY@@ zEoBocC}6{yhAWuaKumyFA)1XO zKZbNs|E9NFfXTYGR)E)e{UR7QHx&a`}BqzPX>UQgQL3^f-Y0Dgltn-v2C zxfI22EI=Pe+}_vDkbh7GdE|&FM~U0-r_-azY3d;>I%e!-N_##1rj2el3XtlfB~<~& z3)eGu6|I{+n*jCR%+44`cSpjx=1Q%Zbdup4hW(4$n@03RTkSzWE4<@`2QA6C;}z#K z<40Vr7I`iCw~*g8b@T$kAK{)}@tByWMMX~z&?5YxrFQf1ADfM?S3>en&4HuyYq4w{ zDd80QQ%N*(jns1?-Kalq9L!@52ch*QsztK`q_sClrTtpO?S6vMwEMWw^cmm9h8>zskC~m zA8Lw!cH*EfnM@p{(b^HwDi%Q{!nVf+9~lwD{cwU<{Yk&0W)g_=G9Z^1B<3G-_SDeu z6slzN`MZ*OA|gfFFFZ4n#y)W2r`_h_3lqAK!Wyb-DcDz8(gi z417g~2Wua=x|UH^P^r!cS`Tfig*jYJoD>s02U_UkhZBvWTuE&tU>7pW+YiU4#vmfc z^Qh!&fKN=&q!-Capoku#QQ>Zgb;&~5=7$l4C^QRYO$D3f#v_xE%*12}`Y=ARF3UYa z*NSv>&2As=+VSTv3z(A0_aD^Yj$rQ)tlL^zPKWFZfSTKcbN`HbJHokiZ>Q&E3xU1p zMkjRKu)4S+dDb7bkc=`3yaW1A6;kL$xn1JzNVSplgC4Wqm`B+@{s{T5u3-sxDU4)2 z067zxAFIN8<3J;Hx1<56}g zon8UZO{C>L?*f*RidGc?z%e39;*YQ|*|WnGtT?odYJ# z42h&Jbsx2Yb<`vM{KjRi2BUT@d_JPMWTzpxZcNei>nI=(;Gn$c#P-W6*{U}Uw(E<# z_W=68)yWZPbuXTfT#T<<){)#CR$5ggBLviEsiK^PWIDp>q2Pc(s+`5@tZc?~oCrA= zo14y!GO>i75m;oz4Cy%`8yR5)ycV^fc`oBN=2{%YOxOp(B4JA^Qy{HYiFK-zj-S7X zwd&10vUG3KCdips0Kp#1r$IhW=4**IHLEUXBE2C3UE4Oc0bzmgA)8Gfw-LE6`~^G$ zMf$&^5B}&2&X|209_%rzGCnjbFoxFml4k|#x7KG!*r{N0eqPd zpHGKBUj)NnHZhv|e7ZKkB>e1cj0A)7NtQI$UMBdlA+QCxaUmhNClzx@Lpzb29%e2l zzFS*cBM(fI%HXhF-WIhV%p;Hrn5(?JJY;XGQ)|uU3U$DuOS3Na>A1EXjTdPLigCIZ zDi~oQ6i-0%tdun;gb6l+MK_5}hpiS%S0_QTKpcHe^3fUX|7~iCekDn6|B?hdbre#7qC^tH1F*vPNIT>AW`2GgV54pf2|-!Ias>_tH_wF+rGGly|+gr`%y5Q zU!OY_7ntHslU2M1jJCd|`g~IBEQS#IH_fuVQ@jwYxcr5u&?q$0HsueL(?{&7?NLWgtwbl{cY>B&98)sGTOk24_ zTb&d6>F!KPmycS`ITK$c(@4f#7&1?6zQSZY!fdb3#H&gTfJ*n3-d0Us&9aXBALYdxeT(!QhgCSfbbh zN$Bgpp2qI0BBk4_D~*sZ>i>Ux5WhPYEjzvj!#{ASWPubc8Z7O;HB{?0vGUqwG*z~o zer}Ez$TqI3YG|_S9h;Ay7@PI!*ET=^w&LU9YDmT~M!~`LZBcuwJNCg&U}EVop^%JQE9T*k3*jCj3Ay4Mdvs%kXZB zS*m5!dD>#ujI6Ln#&i`we!46a&{2o`%Fo|BbBL_ee^5JnF`&N2PQ3CH?yfiSX(p38 ztP*1+wyJ5w$#h!Q^ame|zs!4|r3rynvqrV6r%B|y!O>sSbv*oIOp~v6|UKp0ph(a=hBNq2Bz}5tc7^hJP_|c0%s|;3EF*DBf;*J zh&&rPMYV`#_5R}YD%sAw&+w;U{kU$#Zo~_kz(E~3lSZcheEp2YvKd*pJ10DkKdR;$ zHP@WNTvc4<3Q~zxM{MZGdP_wd@b%0v%!Y59gKE+&da|z=Iz^m7);w2zHvAR=<@+$R ziXBQsM`3!56VCO2?DI%I)Ky&gw&NzjWaBGAi5=Z;hn6t})zirD$4%~wpG4Mu*0~%- z;<)-$3!b*s0ATeCV(deuje4rGp?K}O6~e@yi-94Qp4 z|9$Bq>4H*;a+6Rh@)Al_@j@C zmUb6+PYfB0)GLgcG&v=u4odERkcnzNWW17{S%R4Yp=GI>jq1T)|Gu9}Z-uL}b?N~f zX*JTa^`Eb`3pxvUn8JgmIfnIxw%X#&ITnX1HUaIZ2PK4=_OOHQJs@FB9!|3${}QD6 zUUS`x-O6IY7orbP*}Fb$CQw=?*G1Tl2jvtA>P-$p1Up=)f`rZ|t1J)GUr+vE%`QZ{ zd?b~j0Q&zR(oXveU1bm079EMV(sbk=$;V>qdkcUJwFWk~P(IEem@KKXz#|lqUHb4q zJYx!V;rG{?F#i_PzfW<_pmXFdRK%wuGqG#xnb38a!QbOEnDncayss*YtaO=<>p{W4 z7JklD!JY$)c#pklDSY7V5?E6lIk$}cJin1J_i647)spbTisr+HQuWy2cSb1jXF7{p z%;cMrFhYQ9&w!SHa=NY?VWnP}tb4|_sR2=??|zDHyz>&B4vN?=fF zcHU-z+0RM5%e6*{GVTAu5Q;^=h1CvkHzOGt8LBFJcG?qss{MW_lSVif7%Y*S(k&IDS9U2Bxl4^ht3XE^8<@!I`ugPd-W(_&bFCGY z8Cze^Esh27yw%at3idTs%M}`6i#B}h$u)o-1V_L=45+E3Sv zcl$$X8X8e=CDdw=NatrQ&G+?{6$2>-a#GQ^AB9H^u}w%M6_u4cn^*2+7kZynjo$NS zuWD3lrbl`g172#r@h@gc*9dI9?WQHAvFME6FdNGKEvHyh{=tv_qKF;oar+=bz%LnQ#IAkshnR0(O+cmTA@9Dwe zI8VLM5BHrCYTLUJwQF9omkkUQuW+0#{PjYwsOVJiqvV5(48hcqO2?q86vOKLIJR;9 zL~(I3UMYUdj~{qZ;N34cG&qEJ1X%`PKlR)&)fVI$!X{l-{1&X=_l2321}=1Hv7;L5 zx=1Pks99NofytV$+XRY%+p z%#-GG;mt0wQgWiT&>%*h!C^88%>%P1tz~8DOULQ%RWLP>S3)J~bV_y_VuQYgA8V!; zfsc{XI-c*Y-Oy~^Ql3VU=6p!}TV;5^=PS|XH*GQQ>Tk}U&TFC3;65fHVd(O*)`w<# zszAny5Rsh+`v||K@y5^#Q637ChRn>&3NRSMJ(9km75*{&>+tZOp|nQQlCnK$cP7P+ z*DkNmr_U;6?~H6L<+j=h%R+45zL8x0OV1x(GBtmjB0J_@4y-mCiYHrab7yf%4&{HZ z)0{xU+YmcK!uy~62Js|4Q}E2}Dm*N!8OjlP5DhFt;i5P^tr_AlY%v}1f8c@cXBA{n z__g_Xw0My**Nu$Uwl}t%dmNjK>*_RK!GS}8{ediLYJX6*>TFj-wX-irB0DZPvCloV z#M_D9DWE=GQdX8%2)n+U#X^F;{x3}j?>giCKbi)$CaoHNTFYO)N5{pfXofkPu>`KH z?RCrZ!I+>vT05yB!-D~E=RZI?rV)YU7FLOksFyv}iD zWo1(kC{?X$zsKeMrnq%C+`euNcT$neff`30gTN^c5dE}ut__Iz!?E}t}IuDt3JkN z^;!F0(;XqSF=gO*emI~b+*pBbTWsO40t6J}WDQMH6?jAhwBmtJGz4RmL`1sjC*DHV zLlijykOsallh*sfzHdR+6YUr6&wqrY3~(alk-Jz*NPanuw9h~fdxyz%y``xlRgLw% z`2l(n+Lit^!otD|LcVq>?4>E849M#1z*b3+CMJJ%u5vB0moXlete{b7@vg zExl(ZK1mc$8>&~%?KSZE;MZfy+K1x)PkSAzy7LpI7oDo+p*iIJ0q20TV_|2wd!ERM zqt~bC+0J$>*knErCw!W+Kjz&epJy9-yIvC`X>qoLKwWAZVqcKfSC$--PD-1=mTVe0-F0#sDG3qZ8~G;PDKRp|Qe^DBEl2s5C+Zg2zDEXBdst$Ct}Fe)|m_v}^S zQST(Drj2vAJ;O1&#WaYS;HgZ1x5j71`E~P{3N9(ROZP^#wd={QaTdSuB+}0o?a$=X zvY+2?Kjk=yk`gmXZ;tr9dLjP6D&#i1yZ%|{RS~0&gRMnbZ19z_`)sfH30<%}Di+Um z)fqf?WCDgrLPUEmBRDHG3@Z?xvPKh>MS;QMLCYetMKX#CJSsRS`(|NWv4$ zk=3o}k=enRm=azDI8SV~r=Mzn9|HJnLdG3xA5q21df0ZFP=TR)LL9!;8*x&4QyITdDWYh?bCO_FgmF`Re&xK_>FU@nVyku_%Hp z=8t$hwz+sKrX?L^A(w?KVrq?nc8&^VJB^|DIWGx-T(}tD+?N=ip+6?8LwtZbOj+Q6 z+s#F*XP+7yCV7HBr4J!=Bl4z2j+Bt6u?coRv>lfU1v2D6Qj$Pj2KH zQD+9%7NFGADdm)^4Ke-OHL%aOm<+Ln=V^+MBaF(sBZ|yRrv|NNhBh(lfDX(0Kyu;V z(z3-w=X56d08B3tzG23%sG#-B@UEGUxp9BZ+OlKpY#p)H%9KSKX_qD;P@#`)ck4~u zfaA`B8fV!B4!4pXxvI#u@!2#2QoIA?s?P=oi?DHO?J@;;$LAF(Ki6Y6?N1@( z{P?nCb4KpAh*tfTa_2>M*HFt$%NRx^rRsT*R+r1G#E^tlQ+S=UCHH_j(Z>oiSvAtk zR{>>PtqQomhrlW(fLLr1P97}(lW(zzl?Y$knzDwQOi)L2xLQ6bq?tHt>pdcBnI)u*i2BvIba zGM#H<9U_X?kcz`^frgRN71J5lQls=#U~ H(~$oKZFmFf literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/logs.png b/sources/addons/jappixmini/jappix/img/sprites/logs.png new file mode 100644 index 0000000000000000000000000000000000000000..bae4fb18c3702250359427a2bd095dfcb461c945 GIT binary patch literal 1947 zcmV;M2W0q(P)eBmqcn>XF3Cc8v7I;Ud(S@L zm}|#$kV4iE_y5Uy{G9(e_kW-BJkL2cm@r|&gb5QSCP4fzhX9qOz|+7JfDb4DB+w6Z z0Pg^ARS~>s$~j4~15{22eg}Nx4!QOM&s7n;ZpwNWVh5-`SRaLcF zO6iy+$4pgKcc`lRs+4lZl#88+=ocr1zs-sz$Bo6E#Ykrt0xKZNUR;jForT4n#f_eR zg($#y8~wf>wyi8jg5U%Dt01AXI!|jSP&Kq0MXN(2&_nS za%&$=`iym7ny^U%RJ!lex~(>w4ZGcrl+raB0x6|pwOX;;?Eto^5Zh|_+?=u)G$iqx z5nNWD%0jU+4lf6s8$VK~o}n?kO%_y!ey0wzdZWrLV8=^kg`^ zUax=Kwr$%-Mn-0JcXv-+fecVt0;J5C_nlg1{_MNRn1;P@2DYL+07m}VjXpXCQsSzZ zlk^`7o8#zzSXW9HSWrc9z$}lqBKzs|FKh+V$(r}jgaOVur5TA_m2+?ACC7vv z`2?^hQIu@J4}m_f*Sl9$)pfwjKo9Vo*Xuo<@S6|p0zANLx~~7KxVSiGC~otB<$(3V zg$vuNtE-1pRhW(w(zlb z6dZuSvur`qu0@9t*bvwr@g&>LqkKuSJtdq^OThGZGdUhrZIc=>|cLo4mIPw zh(t%CVav}=S|fky06-^3PR;zJJ$~gn68)|wK6maM!0P~)E?v^$CP6$Nr>m>$j|SJj zjiB5ZjiPDV`SHz>e4&vDfH4->XmB&(=K42l>lrFL<1he|(&2jw7bb2C=IMhJZJddv17? z*uYgRIk&Dht{i-i*tP4#E?>d!%^%4md@X7o*pxIBhRLP>3FC( z`T6SG#}Np0;>pvZyb%Ze6Vu`Iro8pCfIt$*HUHt89`QI* zyRFz&RRp6GYnKp;qKtP1#w>3!*i+W1C<;ny9ZA{@{zkt{B z6ef#!aP18Qt+uQ3**iJS#H+PPXj+TZ(A!W+N zP6+-|fXb5s>*1dI9rV<{meOii$fBd-Tc6Z^-1cWNA%tF3R8(72Q=>SYPIm6xnS6s~ zWo5r#y?XT+Yqw#4J{C@z;vCTycimoA-GSXijI-EKK$SFD*}{@^=>VjDy^|H@#( hgb5QSOqjTT_%HdNql1~c6^Z}=002ovPDHLkV1nqkp@aYc literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/manager.png b/sources/addons/jappixmini/jappix/img/sprites/manager.png new file mode 100644 index 0000000000000000000000000000000000000000..d63a3fec408a13548eaec1181dbc51e45cebe48e GIT binary patch literal 21102 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 literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/me.png b/sources/addons/jappixmini/jappix/img/sprites/me.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8bc0fb3b8be42ac326d9b209b5815a641e546a GIT binary patch literal 5100 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 O0000C}^ zg+hbDhKghyc=)MZlUv!I?_km;%n3G5Cdk*q9;Vn*jfi7xa#b z-JdAIp=sly0N0^8!=r1*rDxQrD~Ybp&ZkhysZi^v0NJQM->5I$s7TzZIOD4+*{(v@ zu2Al=0pYSD*0Vm*uzJ<9Tadzt=CUvHv;c+5fa0}3^|k=kvW?WVfY!EY(X@?-%!&88 z0Oz?h)wYSEzSZ8jXZpJW`mCq!y(HwmK<~dX-N0S#zC!-BZtuT4n9!52!`$q`GwHuz z=)Z^X#Wv`{cB0as@5Mjy$2joEN$AK||Gs+vzjEoxQ18k)`?|OA$WrLaXYR*)@XSQ- z%W%KW;`z=%@y}QP#)$3EW%bTx^wCk|&ZPg!g7MFKvE8@v(r@a{tntx>|ICo{)>QD( zkL1y_;?cSF*G}xzknq)n`qXmr*lYFKUi8^!_1Aj$+E~Hhyv*6@^VXX5+iv>Xclh0E z_1|Ok-G18K+4SIQ@!XyG-+BMotm53;_}-K7-mCWBn)cv_-QV2c-s1M-boJk%-r(K% z;GE^)-r(Zj_~m`};;H!Lk@@4K{@}Uy;=SYL;rQr={^gnE=HvM1px@~5@#fg(=;iq9 zmip+m=jrC+>htdC=lbia_Ug&$>*)FHvFhyU?d$LQ@TT|e((Ui;`|!Kx@c8fX?)>w_ z^YZEH^ZW7h@bvQb`}5fM^W^XJ_VV=c`}WiJ^!W1k`Sthn{Py+#`Q!fj>;L-r_x%6; z{PX?){Qv*|A^8LW3IP8AEC2ui07C$H0RRa80RIUbNT8s>fd~^ST*$DY!-WPT9(+i# zqQ!&;A3S+da0Z@&7ek6v7;%L^NCX~u+cz=fxkC?Mj{GNahChxJ{QZh3QWlGcK4%)7 z@dVOIkN&VdSpjmUQ-=}p`I}0W>c^%7&v6?#ZY$S>=f-727*41`3NyUno3X+uTM84o zA**&s7dL6d>MR>8a2(8R(w5Z;R888za4$c9V77BV|Bb8D_is4P zlevMetTsH<;>iwNe~!LR_D-(|9!q)n!uA^*!;2k^~)bVrIIPbMt0b? z=D*T%?|wegARc!6jI)!94l=rWKrpa@jW8UIwHOK#PG z7Tr@RJrSU9GdzgZK%fbf8z`C4C?i5a{ZmI~PDv!-Q$SwiV~|7^Y2=YeCaL6-Og8D{ zlTb!k5fC`w5QCIN0s)9DvH$`CmO$drWgLfO0OnITfD(rqhg5K;Qzrm&2q0%P@TOBB zR8WDPclPP$pMVA`=%9oaYUrVeCW@sKP83muq6s;X2{h0!as#9TIRT9)jgW!@rUDh= zOCybB;sL1t+`tGanfMU_s{a3=;DHAaz-sHQxaO+suDtf@>#hqdkU#>kE-(ZnkPLwU zstQ1|L=8_EfNBDG)Ud)61x!1{Ml%cms{sWN;O(#EmTT_0=%%agx`7JdZUC?fAOQ<3 zH~;{u0bu@}#Zy+HAM&_S8Pi!`s%E=?)o_7#4h{nwAXI??YQTzJ2~O>?)&e+2QU2a z#20UTINl_${PN5<@BH)7M=!lM+*EJ<_1I^x{r22#r!gfIU1<-fe?(K1Sd#A zWz6h?7|fssH^{*bdhmlYD~1S1NWv1D@PsH#p$b=64C1)(g)oev3};Bg8rqOJy2zmp zcgVvY`tXPTKn$V~he*UC8u5roOrjE($iyZ(@rh83q7TiOrsjt$i_Ch(Pq7pgB;m_DmmEV8|XmCGgu)8NL_*&hdgLAorUsdE>y|YJVXMW ziCSkn-x<$&*7KhE+$TXH_0NC~)S!4B2tpN#DTd~8k9}0s9|JkaLLM@ai)`d0Q~A+K zj?xyGyoC<5ssosUQj~=vr72OVN>;kEmxTJ|E*`m6LF^K=gZiZ_9N~i$qyPqU$o_*d zk?BiiV&Vm4Sfv$2FotJFvryA?1}7W=(|78@tK016H_0l9uAUXFhEl6L;VDmgD$1Vt z)F(gv2~dH~HLnHTYaQ?S*M|x=qJ^a>Vj1a3S1=Z&kB#hPIZ;_kT(+f~b#G@|X;WX$ zk`If(1SdFw2tBOfv^O;d7Ld?`7GU55AHcwDlex@Pf}sN@*uVpPi`8nXat#*P00k!S zRppMA5`~~aYPx_{b+U81ZMANqup8IyVydp*1utI3yHN5vG_Z*ptV9i4QA;Maz3+8w zW+B_i`PTQonJwih^}9;`qE=9%)r1|YPz5vS!L&d1FEHPL3U;sq6%+~6@HM?@yni{(UPLn>d&T9&0z&TlHK{MiJLR;$GY^OXbjOWcmS5WAf)n{S)jN9?w@b0$=9 zU7?89iU0;o(tlz{$GvEOaVeCQBE?z5jnLT4?C;GeCJp*JpLMA7)!iq7%K$4>ULoBix)PrJED!1lJY9a1E)ggxd?_jCk; z1c@SnJ>=1jzPBSC^5_QM5vBLPr{nO47ku9BVR%arK?RU^```yff^_iX@I;V1-RExi z$qVWVv)~6mRIqoy|2^=Y7gXgfQFz27Uh##BJKGuW`fj8H_Jn$ScQ-zypYa2K}%Ou@DQmfC;6L3fd447HBAFKnwaX3>#R0sgMfrKnNvZ zD1*=s;;@0GP=m3sg07$sMo=hU5DopH4?q}%Lf8+YZ~=t!1zf-dPyhu?(1bkT0xnPj z8lV9eV1(3ng;{42kTQvu zNQsDYiIbQpnrMlc*ol&OD4^(xg))kpSc<0jh=!7is+Iye1?%Df1`#JYM=f)a7(Y$|;?j8UDxUa3HW{k0_001z601xAl z0@TVe2G34cQw?zU_sZ`qO~s55dT2fO1^|dC|K31ARt^nj5Z^~zUmbrLkBNX6r_=jI z5CA|eqOGQE60oqJ8|?FJCU;12D<>FaCCLiJp%lgfmvQqN5ShO~_gc7@3b>S8GVanj zHhyuq`nUs2a4*jFldjD5bAhtA)fF~bi2a5oLLi1j1CLlZfhrWjgn`M?a)aGaETO+q8MMAe;C!C-izL(cbrp+c|BjvN$h?d^-*mOD_Txw*MQ=Vxb)9adWyY9hTv3q`$|(Ahg5bUF7%ihKo?i6+@gO|IxX#FX!jy6y(o8 ze0y!BS31QEya$^V*C}6pEsC;Qkz0wZsHkWP@iBRk;X4b@mG$R0uglj`+iZrxe*E~syams#TwGYtaa*+74zwCdpcSKg;tOwaIURI8$X`QWtTg(t=}h^eqZlmj z=%-hNDWZL@k1|gcV7S@+PMHRqwTBOqk+O+X3zL&x&AV;>fOhru^X28`_n-7O@s&oI zZ;#%&0@c>}n%qJ2%^)PBy1IHMwn6dKjw&M~W0H@*e>nc!z7#whYp$tNPc6^I$*C+< zmSTIpQ1T$M@A2)FBzf_1lF#wv)?F?;vWs&6T??9I>T=-4_B9IIoI|sHY}7h^O$yfB zY%o`6+xHu@cH6}!M~e*KHC0mi)2W`G9&drshA5WHTB9W(m_7Z+DB;t*ZlY%d|5r^J<>%A2RNI>vj=uBok;r?gtN!|^CH zwc4HISpZ$ee!|5afs(Z~vL2H&e@#k1!~P7_bqHE)+V6Qw^pFW~T~JT}rU!L+=B-Js z9w)M~D-s~wZLe1!##JJ}p%xKe4sXIW1Kez2;Y)-g3+MH>w_&3V{J7l63r^y`iNWWKO;0oI z)6Fx^;)K*(bB%NYU$NtRgdm%daGAB_iR_=c``bT<5#&CnD~vK=5{)p(L04ZubuPsC z75eUknl>;8m!M`QdCLRD= ze#SiTdbg-SmqsO4hiXkl_|Rw8?`jrGQd3i(;gc{7!(gz0dAE$--rnV_t1EaY`g~(# zWW=PaDd1|QCkkNe=;)~G?p}>VA`jCuGMLJ$tG`P~NNnop>f+|Nx3||fHAzg(%xoCs z$~4;E-QL_(S66>(4*gs*975Oc$Bj42nx@Q8QK&vEd}Ki+zFU;D0{C4N&6pUgBVPg) z-@IK%+)-p6U3<~Cv$aP{(h%cC^?3aLonW-w==_}8BbEEPI=7QG0#b@_x4uycP8-m| zP!Dvqerm8JDjCX@cOo?xypj=o{u8%OV#F??{VLhe^gEAqX6H@g-tVP>=w7e>XO#sC zdV>%95U;_u4Ph~c_yM*g>CgI&i8m^;GOx0vIz4!w8b76>W8m06b}bMbY>`%NcUh7b zs?uzAN%x{wuC*?_0{c32iTqQXjWEq^PQtF^a8ijGQ1Wx{vu!{~ZOm6o$57RQsd1Z$ zhi_~b2J+>c0yi^$QX;`pSG3zU)Kh}s!f};RQ!NA5H3|boY$5zNim&lmPQTJSaMR!9 zh;-2?H^nq98HzH-@qO-&g1_pY8b4aHu{^IoT)C>E^ZQ&0%{s73fZ7WGr-qy$4()V~ z=ky$9qf*mn3svrKD_Y{}O+&q_ak7~o-c2C2?hxIA==#|~ubJOOm8U1VhT}JpHoK`D zrB56PWb?veDwWSj^YQSKbKWt*g(0f^1H(%C=L4O>p?IR5S&_G_3tAe><1`4enxUGJ zullq(&s5D}sZ~2{^#=}k3;!Pq;?f2NsI<2Orc<*)>Bey^1TG;+YXk!EaQueW?4{>` zfSAJ=3$bceR@R%=!!9&SB3dlXxYA+lqw>?Il<14Y(zZ6b@jt(I9C4H*X0uobj^s#- zsdNTTJ7Tv2#WD1>8BCzf@rFxJBM{gVNT`S)Cnx8#auXK;_N3(U(XF@ux?T)pFij!G z>*IO#Qn9eQ+I_u)u!@3Qtw=*{_L-U4&>lsI@iFo!_kb zYsG8Pzz{;H9v6A?M+HUpyHoY*v*QcRT2HFN!9Q}wF+_$on9+|92QOcN~Y0 zjq^e){)ls;YC4OPjU{Uf=1}MqX6Ps0S5L-1*K1$UI$CjiqE{J0n36?MK-P>u(@bBx z8vL$tGbWaKqg*SVT<)8-Hp-rKzBHVICof`zNh!Ef>mzn0S-XdXsm)sB^opQB!;5!`mqPS5WGQt>RL%#P0YM2}@prC{wdZuUSA*L!41PmYALlu-;-qsHd>WuZ;L4RNE8gYVAOm&VgP|oYAA~ zji_k>6_M?F(d4jDX`k@xAQT8lTKtjr+c4RCK3l=J_mojN^#S7M<&<=Brc{|`qNjUN zEa2G*^sW$l@@FZ%6)PMbHTj`rcl2Jj8N}Nc|R~)0B)q#(<=ijGSXgrR_ zUR3TidrT4pWi#?)ePbXNIbJwHrRw>j>EK0Qbn#rd*in)K7~#pha0u6ojz=~EYj13e zR#aq~LS3bfS_B%@5fj#bj{BVtD|xDJxusO2L&pn$`f-fea_V^M2&ss~cVW|S%eHvV z^wu6DlLdzs4>v+BJcGXlTIYSrdQ2+o97RGXuU@jol4}rt=s|PTs&4K0ivNL&fPeCA zoRI5xonmu}D>6K}hj?zp*j>$+^b?k4w8Vqs!eKGTVz)VAgR^Mn;`ToKgKI(-m78T{ zE+`&fjTCd~3OL}B_Dxg#ZC|$5g5cquA-N_UT55879Ia@g#*6Dx_TXafVEBr*&^48> zI<9#8b1s#66#q*sT^|g5ZulhE8S(8YV`8JD)a6f>R9@;Shf?-kM~=Zu+K10_q@nR6mK-!HUI_$wgGjXliuw6j&lG?MUCd!pC8;i=wH)4nK$NlWGldh z*_3jn%I$Y*9dDe@-o||0iounfa=#{CbEHx1v-yv`qy^26O9h6Gpvkfc(Silo%V#}oYWR?QEvF5(YQb8fRVz&E~_b8ECwHM9v#9S7221tsuL%$`JJz@MTvDT`Alq2 zBn@nY!GU&Zt#Z$w{=>lOwUc6PLJ@`~01IFLhE5 zAkfcpC1%AR%>!B0E99-vVmYU+MezY|p+-duo;nWnihY-~|L~&czf1fZ50<|yV^jo9 z&V(csuxXX3P+V$lQw9KA6MDaYEs7O65o>#aKTLwUlvXEm0z2r-*hV$b`n{z_;2%qa zyq166<2e2BV`F>O_KK8Rc)o$)W&EsyWZ0Iz8cK`i1FuQIJj1W6XjMU(P^Ls?~5WQ(>B^d`cqaFn@) z81oBY@mPzRy&w0-w_OZA?=wJwcW9@o!&l!X z8v=4Ac?5S>Qgj^~E>M|s-KEqfO4`W-DV&ttJbu5n9LrX3oVu9_<$a`N8o^IRWhcX8 zFbMvG*}s)6n=1Cnk@_S+Cze(l_Bu{9Noh;r(YTpMxa(UBhGc<<&p9 zJDwWct*?P?>Ij3FAy6o}Lzd@AEywdNfZD1rs1MYMUFwuI54Ao2y9xixg#^XSzhfV7 zXdS{aZ?u0w|6gSOS3}X*L4230>BoU@u;4-I64Ex5NBuXhrcG+k6L5~^vlRkvQSqC4 zf%Ds`nL<`%CC!MY+M4;<0KC6KbMEVyx_3!FPFjp%WG${Wp;ehSCndi^Fz?r@GSbw3 zCme`U87{dp4vfG8;N#|{fmO#(1dCY5Ed$A$o)3$?ga2mo(5=qYeBX62``&B=Z6DDd z*?wsK8tgC5PJq@t6+qL5&BbXJ!8d+*33bsk5z z>j6r1nd^bQvCOyiNvhn?PbrcgH3cCiSe@bDM`W#?q=H8MUH#6^?+3drO=*z*raaLq z6W1Y(oW#*N>T}v8r(d}h=WE73$WxX7+30KySbqX%FC={Cs_fcRFA(v1y}t!hp8D7R zv!ug6k=^*BUA5W|WgZcv)Ct^6m7tvB!72uJ495bCA}zme9aw*90JiKNJi2&_4B87| z`t&l3jX)))fr-@3b)|CGzvXM2R{C1)d9QEto0qsh1JPSZ%k!~Y!Gi^uL4;}qksGkf z^DZkLyPij-rrr0|O^Ky|7p6Vlh^4mUUuEIlwbZoE`S-PeqZpXH%%%tGtk)X7Ra#_C)OxfoI9M1Q&A^3Y@lO$I-O5#C)v(L2Qhf(BB*@#wWbJ3P^(vFw zC@;WLk-R&&)2UlCD?HTpaNiS{bXV&5}&`ts>IDN#Kb5UkgHg{ z4RaaU470QNNc1MrZDQtjIAy-z>~@6ojXw8P`-YcRzbqoC-T))ENpoUhrD#a;uB+!YpH z8%^B?>c1ZwtMHvcH@?&|w`yY)RhVWN;CbN=+g%dFII}qqZ|0pqsPBtz(g|soWU}IB zKhWKEshTrvGNH3V>2pWK4lu#xam5x0b+ZY`O3tx;^$7Vi||g_+LP0uYAb02X%<6&xqK(_O-Dr z3mX-R8gCP37ZP<%EPTm>w4Hv&B~T&p>)BgA91)L-@oIChm7qITsUE!9F^z{}*y zaWX@SOa{ecYeq@m8?nv~JcDeksmDP0lNR;7^l$0SP`jj>-Wm!jHL<#CR8G~qgJWFj zfswp_CO$XL`daLQ=lF+VvyB$J{&`d)nQ>a~dk@@d&r_51)&4mY9zFVVPs~wM^b=kU zR?T?$w$)0qy|OR^pNJnvDijcQ#_Mh-LL6rN$0l5%}ezZA? zLFAMRovtDBZVvSt<K%#mWZzWY|vdoJA91i>Sr)Kw6|PD+IGOG7+z`0S8zwDu>waaOiB$hdwU^FI}! Mt^P!P^ruufGRjh$%;SQJD=5U5mz5MC0ffII{wA%tLF3)$W5CcF3EuYbf`5_W|IgJp($ z{z}fC``vqg-#Ono-}!c>jEoF{E!`rrjlhO^O^SM{4|@e+lt(7rCy^46=wW~Wyegb_ z3J&!U?2j`!uh}30q)2OKi~$c`)|D;nP`+a7h}(C0-*d?3#nVW9)Oko3_eLR zui68rr>8S{@?=z1<@MKJCm0NNd5pxwL>_wRAq>NyxVRXP$J4!QX1Z4j0|_8$DoT7T zlBy6mQjUZQ2zuO_ff5@7K=5>pWq+%=_ z1`HrCFAsoo=g#r=+i!PYHjgp*&d`<=1xaaz?Av<;2^E1!!qnR=o0d~&J6!YBNtGz$ z>UgH2C}^67!{I_98G4=&c?&A_JsWz5mM-m;@1o z=$SXkviE;o4j9Np(Pmt5R$+Nc_Y*BDD&oL_14xp@$&)9qXpDmg5Aw`2&kz+AMQv?u z_pOnj=#m zr=|RirT@+F5I&XbM%0lJ${($FPh!%Cgz2MG2SyykHD*}rn&Ip?Dd}E`-93dBp7-8+ zFK)M+Pe1*X+}vE|%$Y-7T^&o7EaCX^;{e=z^UXZ@)!)Kp|y zCMhY2*Is*#($Z2YD=V2bYZj6uA%vi?u#m#SLJA5Btc*Kt+B9a&n1QOQoIQJ%l9Cd# zv$L5!dp0>aIV2_~5*HVTEX$at$-H^$$ou0S#yl2Y2S> zW$chf@_AggrK^AUV@jpr?2txsD0{A@|641nzHY#w;v0jjF1ShQ#nOO`CLu9-i7KBj42cG3qA9!z3lBCA%dV*dR3 z6crU&$)>ot7^l2$Jkg?-*<8b$26zt`+G=j~=C= zp`mrWZ$Sd+y3WCa2Q9l3Cr()2bHfccbZYF~yLVgR46tt9I_p0D`}e=P3CN>DuTZ;W zl9@{EEh7-RLHv{nmcHk-N%WYIf!PwI$8Do5ee#1-ku;V1cRxmVcic%ds*wwKpU+22 zOG~R~w@WTwueU>@sIRXlH8m9>1e(^lZi=q!*5m-x)YM#+kd6rRj8o7nbm1lmd6T&D zFOP*8-uS}f5eK;Gt!G+8w{(9P%<`DXFiq2pxCRO#I)G^ZcW0&j(oNwt5-7$|n z$vKqu&Lwa-d^d8a$Mw}gQr(VL4{GaOn*L@?e={*7E)?zVbtQz(HzEO!{>g1IhuUF7W%Feb_R!8D7fO+H>$f2xVWL~R9TC*w66?{beg@Z@$N+u?UKyl! zD37932ek|HhI#w-ZGCTp>9q<113B7>cjo~_$UwBqkj8lr-s)QPhQ^4Vxw4-Tv6t!h z`+4JyH;9jqr@Fe@0%4ja3l=P3*sx)Ez1|LOwKv~kii?ZUG>xjNDyz<2x^yWHhl7fWimTIUZ);9m=xvG!sakwz z`o7$;g%IMZ*Lwd?u@BU)Hq17$k9xZirY+yQ(P4`X^I8aVaV6aZTWrs?VcIZln6}t3 zuN_fJzKMIz?eUY+w+HbqSEnxeYF`;It=`3db{!^nLYhtSTTw-PJilF0LTO+z(=%@6 zmVpyV?=vO5NnwQWzW+R@x38n2HppUM0e}8!u1&CgnBViGaVUNJVW45iRg_h)j(7-V zdg^H2R!pzpIlQV1rB7e-Cl0p>wud?A_B3J#^ru;*Q0wsn;0rZ`85*?}0O&1H7MI54 zTSt)AKhY-G9%e$c#ti@ z!-h_vUQfc?669$8w(#|G_xtEAf<3**@@VdOGLv04y+|+>36^E`!JqI1drviRzPXCZ z#sij-_mj7fef87?7e&b*%+dk?m$ zbrz<-p^liuOL@vz`W^ zYIP0+AN&Ys%`Ogq@R&`oGhr@*6$qpCfKBKPz)|{6ewu`lQwf}UkU_IwMmx2`CfJz- zBx!w+6c@s10%0IRwdlGVp>HSTYb2^~1A2XnP4H5lDTIk@P(JRxMF=xMu;DYzKsh2* zhwj;j5oo|QIGxhMi#^l*#ot8R4yX6TpA&R1LvQ>VwMQ>hS3ZY7_z0hpKyuA7WT!&YpfQY@ zwbUjT$unC$@;!9V7J{{}5;}hdM|?jN*WDahy8#B@$?f^i*`zuHQ&OYRy?Y3pUWnm4 zhqKR6B*z2}f3N{<=v`#o^*ftVXJHCGfTX!Viy^9aJVG1Cq1Bs+9x;vd+^1|pU4f~@ z4nYr?Xs$^}+8_?C`UkO@_cH9xU)yxLnt;yycd0nP|6M}OEtnyLgt0$iaMmwuGFKq~ Y0|T~+DS7e@$p8QV07*qoM6N<$g5<|)p8x;= literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/smileys.png b/sources/addons/jappixmini/jappix/img/sprites/smileys.png new file mode 100644 index 0000000000000000000000000000000000000000..1c33243dc15949ad31951af21b9495d6b52c9801 GIT binary patch literal 19253 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 literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/talk.png b/sources/addons/jappixmini/jappix/img/sprites/talk.png new file mode 100644 index 0000000000000000000000000000000000000000..a307e19ebceb827a0be5f7c7a848500ea8c3d4a3 GIT binary patch literal 43207 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 literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/sprites/welcome.png b/sources/addons/jappixmini/jappix/img/sprites/welcome.png new file mode 100644 index 0000000000000000000000000000000000000000..9044bd9c8a3b325fb38841b406c3a01540ad1e0f GIT binary patch literal 4356 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 Yj+&U0O}1jCP0zkL>&zYuN5M<~1^P+;)&Kwi literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/wait/wait-medium.png b/sources/addons/jappixmini/jappix/img/wait/wait-medium.png new file mode 100644 index 0000000000000000000000000000000000000000..4b9a780bd92b919df6391e5ba0048ff9425d5ed6 GIT binary patch literal 4129 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 literal 0 HcmV?d00001 diff --git a/sources/addons/jappixmini/jappix/img/wait/wait-small.gif b/sources/addons/jappixmini/jappix/img/wait/wait-small.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4b5787e474c3ddf5cbae8f8cc49368642fd2fc2 GIT binary patch literal 847 zcmZ?wbhEHb6krfw_`<-jZQC|uW8+PmHu?Memz9;7nwq+~xh-6{u(Pw%*48#ZKR-P^ zeZ`6u4Gj%5X3Pi=508tBV;}`6{^#~{4GDI33~)8lGhk)}>Q($F+Z`3#dv5WDCfV46FeP3VkV=^OhQj* zDbt1zY&Sa^qI+3vm@-=fCJMANcD63+TcfGd;2HH}kxJ5sT^^GrShTD#RgfP#Y{ zm(PKQ56OY<%}h>Po^A^;ouOc}$}}`3aGUlErG1Ojrx>gdTeoOozhkz*d1XfiZkqse z19lrumIed9NHz;CUe0!9MQoNQ0DY+Zd4k3*5f3e{BLO0ux=Y#(-y1h_Svj9J^xopp z()5tcLvM!4&5e}|90L0;o?*R_#jV#E?&5HVFOp%Afd{8ptBygR(-p41Yyq!lZ+SxP zP0N{CYE-g$V>J1By0Kas1PRs#g(*yiB1auoG&{?&tr0(#-Q6^YQPJs1f;~gycBXw3 zlwF%Fs+|Qd+3+^3dXh#)LNBP`720MRz3mmKMC${G9f`0jo72zX4-! zg#(YPp}?V&61lMw$9GD2^jv7Wp}{WD#bUyw@LWSjVwsy_q6b4n@C=T|T+=068IxQ* zwy-g*+L@T7!_}wSP+%;Ud_;MJ`VZbWO6(?P<^gJ25&8`pJ-sSeEscj->H+i^$1(>K zhC`c' + _e("Commands") + '' + + + '
' + + '
' + + + '
' + + '
' + + + '
'; + + // Create the popup + createPopup('adhoc', html); + + // Associate the events + launchAdHoc(); + + return false; +} + +// Quits the adhoc popup +function closeAdHoc() { + // Destroy the popup + destroyPopup('adhoc'); + + return false; +} + +// Retrieves an entity adhoc command +function retrieveAdHoc(xid) { + // Open the popup + openAdHoc(); + + // Add a XID marker + $('#adhoc .adhoc-head').html('' + getBuddyName(xid).htmlEnc() + ' (' + xid.htmlEnc() + ')'); + + // Get the highest entity resource + var highest = getHighestResource(xid); + + if(highest) + xid = highest; + + // Start a new adhoc command + dataForm(xid, 'command', '', '', 'adhoc'); + + return false; +} + +// Starts an adhoc command on the user server +function serverAdHoc(server) { + // Open the popup + openAdHoc(); + + // Add a XID marker + $('#adhoc .adhoc-head').html('' + server.htmlEnc() + ''); + + // Start a new adhoc command + dataForm(server, 'command', '', '', 'adhoc'); +} + +// Plugin launcher +function launchAdHoc() { + // Click event + $('#adhoc .bottom .finish').click(closeAdHoc); +} diff --git a/sources/addons/jappixmini/jappix/js/anonymous.js b/sources/addons/jappixmini/jappix/js/anonymous.js new file mode 100644 index 00000000..88eaa7dc --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/anonymous.js @@ -0,0 +1,131 @@ +/* + +Jappix - An open social platform +These are the anonymous mode JS script for Jappix + +------------------------------------------------- + +License: AGPL +Authors: Vanaryon, LinkMauve +Last revision: 02/10/11 + +*/ + +// Connected to an anonymous session +function anonymousConnected(con) { + logThis('Jappix (anonymous) is now connected.', 3); + + // Connected marker + CONNECTED = true; + CURRENT_SESSION = true; + RECONNECT_TRY = 0; + RECONNECT_TIMER = 0; + + // Not resumed? + if(!RESUME) { + // Create the app + createTalkPage(); + + // Send our first presence + firstPresence(''); + + // Set last activity stamp + LAST_ACTIVITY = getTimeStamp(); + + // Create the new groupchat + checkChatCreate(generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat'); + + // Remove some nasty elements for the anonymous mode + $('.tools-mucadmin, .tools-add').remove(); + } + + // Resumed + else { + // Send again our presence + presenceSend(); + + // Change the title + updateTitle(); + } + + // Remove the waiting icon + removeGeneralWait(); +} + +// Disconnected from an anonymous session +function anonymousDisconnected() { + logThis('Jappix (anonymous) is now disconnected.', 3); +} + +// Logins to a anonymous account +function anonymousLogin(server) { + try { + // We define the http binding parameters + oArgs = new Object(); + + if(HOST_BOSH_MAIN) + oArgs.httpbase = HOST_BOSH_MAIN; + else + oArgs.httpbase = HOST_BOSH; + + // We create the new http-binding connection + con = new JSJaCHttpBindingConnection(oArgs); + + // And we handle everything that happen + con.registerHandler('message', handleMessage); + con.registerHandler('presence', handlePresence); + con.registerHandler('iq', handleIQ); + con.registerHandler('onconnect', anonymousConnected); + con.registerHandler('onerror', handleError); + con.registerHandler('ondisconnect', anonymousDisconnected); + + // We set the anonymous connection parameters + oArgs = new Object(); + oArgs.domain = server; + oArgs.authtype = 'saslanon'; + oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')'; + oArgs.secure = true; + oArgs.xmllang = XML_LANG; + + // We connect ! + con.connect(oArgs); + + // Change the page title + pageTitle('wait'); + } + + catch(e) { + // Logs errors + logThis('Error while anonymous loggin in: ' + e, 1); + + // Reset Jappix + anonymousDisconnected(); + + // Open an unknown error + openThisError(2); + } + + finally { + return false; + } +} + +// Plugin launcher +function launchAnonymous() { + logThis('Anonymous mode detected, connecting...', 3); + + // We add the login wait div + showGeneralWait(); + + // Get the vars + if(LINK_VARS['r']) + ANONYMOUS_ROOM = LINK_VARS['r']; + if(LINK_VARS['n']) + ANONYMOUS_NICK = LINK_VARS['n']; + + // Fire the login action + anonymousLogin(HOST_ANONYMOUS); +} + +// Launch this plugin! +$(document).ready(launchAnonymous); diff --git a/sources/addons/jappixmini/jappix/js/archives.js b/sources/addons/jappixmini/jappix/js/archives.js new file mode 100644 index 00000000..387a379f --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/archives.js @@ -0,0 +1,418 @@ +/* + +Jappix - An open social platform +These are the archives functions for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 03/03/11 + +*/ + +// Opens the archive tools +function openArchives() { + // Popup HTML content + var html = + '
' + _e("Message archives") + '
' + + + '
' + + '
' + + '' + + + '
' + + '
' + + + '
' + + '' + + '' + _e("Please select a friend to view the chat history.") + '' + + '
' + + + '
' + + '
' + + + '
' + + '
' + + + '' + _e("Close") + '' + + '
'; + + // Create the popup + createPopup('archives', html); + + // Associate the events + launchArchives(); + + // Get all the buddies in our roster + var buddies = getAllBuddies(); + var options = ''; + + for(i in buddies) { + var current = buddies[i]; + + // Add the current buddy + options += ''; + } + + // Can append the buddy HTML code? + if(options) + $('#archives .filter .friend').append(options); + + return false; +} + +// Closes the archive tools +function closeArchives() { + // Destroy the popup + destroyPopup('archives'); + + return false; +} + +// Gets the archives list for a buddy +function getListArchives(xid) { + // Reset the archives viewer + $('#archives .logs').empty(); + + // Show the waiting icon + $('#archives .wait').show(); + + // Apply the ID + var id = genID(); + $('#archives').attr('data-session', id); + + // New IQ + var iq = new JSJaCIQ(); + iq.setType('get'); + iq.setID(id); + + var list = iq.appendNode('list', {'xmlns': NS_URN_ARCHIVE, 'with': xid}); + var set = list.appendChild(iq.buildNode('set', {'xmlns': NS_RSM})); + set.appendChild(iq.buildNode('max', {'xmlns': NS_RSM}, '0')); + + con.send(iq, handleListArchives); + + logThis('Getting archives list for: ' + xid + '...'); +} + +// Handles the archives list for a buddy +function handleListArchives(iq) { + // Hide the waiting icon + $('#archives .wait').hide(); + + // Any error? + if(handleErrorReply(iq) || !exists('#archives[data-session=' + iq.getID() + ']')) + return; + + // Get the last archive date + var last = $(iq.getNode()).find('list set changed').text(); + + // Any last archive? + if(last) { + // Read the date + var date = Date.jab2date(last); + + // Change the datepicker value + $('#archives .filter .date').DatePickerSetDate(date, true); + + // Retrieve the archives + checkChangeArchives(); + } + + logThis('Got archives list.', 2); +} + +// Gets the archives for a day +function getDayArchives(xid, date) { + // Reset the archives viewer + $('#archives .logs').empty(); + + // Show the waiting icon + $('#archives .wait').show(); + + // Apply the ID + var id = genID(); + $('#archives').attr('data-session', id); + + // New IQ + var iq = new JSJaCIQ(); + iq.setType('get'); + iq.setID(id); + + iq.appendNode('list', {'xmlns': NS_URN_ARCHIVE, 'with': xid, 'start': date + 'T00:00:00Z', 'end': date + 'T23:59:59Z'}); + + con.send(iq, handleDayArchives); + + logThis('Getting day archives (' + date + ') for: ' + xid + '...'); +} + +// Handles the archives for a day +function handleDayArchives(iq) { + // Hide the waiting icon + $('#archives .wait').hide(); + + // Any error? + if(handleErrorReply(iq) || !exists('#archives[data-session=' + iq.getID() + ']')) + return; + + // Get each archive thread + $(iq.getNode()).find('chat').each(function() { + // Current values + var xid = $(this).attr('with'); + var start = $(this).attr('start'); + + if(xid && start) + $('#archives .logs').append(''); + }); + + // Display the day + var date = parseDay($('#archives .filter .date').DatePickerGetDate(true) + 'T00:00:00Z' + getDateTZO()); + + // Try to get the first thread + var pending = '#archives input.archives-pending:first'; + + if(!exists(pending)) + date = printf(_e("Nothing found for: %s"), date); + + else { + retrieveArchives($(pending).attr('data-with'), $(pending).attr('data-start')); + $(pending).remove(); + } + + $('#archives .current .time').text(date); + + logThis('Got day archives.', 2); +} + +// Retrieves a specified archive collection +function retrieveArchives(xid, start) { + // Show the waiting icon + $('#archives .wait').show(); + + // Apply the ID + var id = genID(); + $('#archives').attr('data-session', id); + + // New IQ + var iq = new JSJaCIQ(); + iq.setType('get'); + iq.setID(id); + + var list = iq.appendNode('retrieve', {'xmlns': NS_URN_ARCHIVE, 'with': xid, 'start': start}); + + con.send(iq, handleRetrieveArchives); + + logThis('Retrieving archives (start: ' + start + ') for: ' + xid + '...'); +} + +// Handles a specified archive collection +function handleRetrieveArchives(iq) { + // Hide the waiting icon + $('#archives .wait').hide(); + + // Any error? + if(handleErrorReply(iq) || !exists('#archives[data-session=' + iq.getID() + ']')) + return; + + // Get the node + var chat = $(iq.getNode()).find('chat:first'); + + // Get the buddy XID + var xid = bareXID(chat.attr('with')); + + // Get the start date & stamp + var start_date = Date.jab2date(chat.attr('start')); + var start_stamp = extractStamp(start_date); + + // Parse the result chat + chat.find('to, from').each(function() { + var node = (this).nodeName; + var stamp = start_stamp + parseInt($(this).attr('secs')); + var date = extractTime(new Date(stamp * 1000)); + var body = $(this).find('body').text(); + + // Is it my message? + if((node == 'to') && body) + displayMessage('chat', getXID(), 'archives', getBuddyName(getXID()).htmlEnc(), body, date, start_stamp, 'user-message', true, '', 'me'); + + // Is it a buddy message? + else if((node == 'from') && body) + displayMessage('chat', xid, 'archives', getBuddyName(xid).htmlEnc(), body, date, start_stamp, 'user-message', true, '', 'him'); + }); + + // Not the latest thread? + var pending = '#archives input.archives-pending:first'; + + if(exists(pending)) { + retrieveArchives($(pending).attr('data-with'), $(pending).attr('data-start')); + $(pending).remove(); + } + + // Everything has been retrieved, get the avatars + else { + getAvatar(getXID(), 'cache', 'true', 'forget'); + getAvatar(xid, 'cache', 'true', 'forget'); + } + + logThis('Got archives.', 2); +} + +// Gets the archiving configuration +function getConfigArchives() { + // Lock the archiving options + $('#archiving').attr('checked', false).attr('disabled', true); + + // Get the archiving configuration + var iq = new JSJaCIQ(); + iq.setType('get'); + + iq.appendNode('pref', {'xmlns': NS_URN_ARCHIVE}); + + con.send(iq, handleGetConfigArchives); +} + +// Handles the archiving configuration +function handleGetConfigArchives(iq) { + // Reset the options stuffs + waitOptions('archives'); + + // Unlock the archiving options + $('#archiving').removeAttr('disabled'); + + // End if not a result + if(!iq || (iq.getType() != 'result')) + return; + + // Extract the preferences from the IQ + var enabled = $(iq.getNode()).find('pref auto').attr('save'); + + // Define the input enabling/disabling vars + var checked = true; + + if(enabled != 'true') + checked = false; + + // Apply the values + $('#archiving').attr('checked', checked); +} + +// Configures the archiving on the server +function configArchives(enabled) { + // Configure the auto element + var iq = new JSJaCIQ(); + iq.setType('set'); + + iq.appendNode('auto', {'xmlns': NS_URN_ARCHIVE, 'save': enabled}); + + con.send(iq, handleConfigArchives); + + // Configure the default element + var iq = new JSJaCIQ(); + iq.setType('set'); + + var pref = iq.appendNode('pref', {'xmlns': NS_URN_ARCHIVE}); + pref.appendChild(iq.appendNode('default', {'xmlns': NS_URN_ARCHIVE, 'otr': 'concede', 'save': 'body'})); + + con.send(iq); + + // Configure the method element + var iq = new JSJaCIQ(); + iq.setType('set'); + + var mType = new Array('auto', 'local', 'manual'); + var mUse = new Array('prefer', 'concede', 'concede'); + + var pref = iq.appendNode('pref', {'xmlns': NS_URN_ARCHIVE}); + + for(i in mType) + pref.appendChild(iq.appendNode('method', {'xmlns': NS_URN_ARCHIVE, 'type': mType[i], 'use': mUse[i]})); + + con.send(iq); + + // Logger + logThis('Configuring archives...', 3); +} + +// Handles the archives configuration +function handleConfigArchives(iq) { + if(!iq || (iq.getType() != 'result')) + logThis('Archives not configured.', 2); + else + logThis('Archives configured.', 3); +} + +// Checks if the datepicker has changed +function checkChangeArchives() { + var xid = $('#archives .filter .friend').val(); + var date = $('#archives .filter .date').DatePickerGetDate(true); + + // No XID? + if(!xid || !xid.length) + return; + + // Too many value? + if(xid.length > 1) { + $('#archives .filter .friend').val(xid[0]); + + return; + } + + // Get the first XID + xid = xid[0]; + + // Get the archives + getDayArchives(xid, date); +} + +// Update the archives with the selected XID +function updateArchives() { + // Read the values + var xid = $('#archives .filter .friend').val(); + var date = $('#archives .filter .date').DatePickerGetDate(true); + + // No XID? + if(!xid || !xid.length) + return; + + // Too many value? + if(xid.length > 1) { + $('#archives .filter .friend').val(xid[0]); + + return; + } + + // Get the first XID + xid = xid[0]; + + // Apply the current marker + $('#archives .current .name').text(getBuddyName(xid)); + $('#archives .current .time').text(parseDay(date + 'T00:00:00Z' + getDateTZO())); + + // Get the archives + getListArchives(xid, date); +} + +// Plugin launcher +function launchArchives() { + // Current date + var current_date = explodeThis('T', getXMPPTime(), 0); + + // Datepicker + $('#archives .filter .date').DatePicker({ + flat: true, + date: current_date, + current: current_date, + calendars: 1, + starts: 1, + onChange: checkChangeArchives + }); + + // Click events + $('#archives .bottom .finish').click(function() { + return closeArchives(); + }); + + // Change event + $('#archives .filter .friend').change(updateArchives); +} diff --git a/sources/addons/jappixmini/jappix/js/audio.js b/sources/addons/jappixmini/jappix/js/audio.js new file mode 100644 index 00000000..f83583a9 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/audio.js @@ -0,0 +1,46 @@ +/* + +Jappix - An open social platform +These are the audio JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 10/08/11 + +*/ + +// Plays the given sound ID +function soundPlay(num) { + try { + // Not supported! + if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) + return false; + + // If the sounds are enabled + if(getDB('options', 'sounds') == '1') { + // If the audio elements aren't yet in the DOM + if(!exists('#audio')) { + $('body').append( + '
' + + '
' + ); + } + + // We play the target sound + var playThis = document.getElementById('audio').getElementsByTagName('audio')[num]; + playThis.load(); + playThis.play(); + } + } + + catch(e) {} + + finally { + return false; + } +} diff --git a/sources/addons/jappixmini/jappix/js/autocompletion.js b/sources/addons/jappixmini/jappix/js/autocompletion.js new file mode 100644 index 00000000..52d3c47e --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/autocompletion.js @@ -0,0 +1,99 @@ +/* + +Jappix - An open social platform +These are the autocompletion tools JS script for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 12/11/10 + +*/ + +// Sort an array with insensitivity to the case +function caseInsensitiveSort(a, b) { + // Put the two strings into lower case + a = a.toLowerCase(); + b = b.toLowerCase(); + + // Process the sort + if(a > b) + return 1; + if(a < b) + return -1; +} + +// Creates an array with the autocompletion results +function processAutocompletion(query, id) { + // Replace forbidden characters in regex + query = escapeRegex(query); + + // Create an empty array + var results = new Array(); + + // Search in the roster + $('#' + id + ' .user').each(function() { + var nick = $(this).find('.name').text(); + var regex = new RegExp('(^)' + query, 'gi'); + + if(nick.match(regex)) + results.push(nick); + }); + + // Sort the array + results = results.sort(caseInsensitiveSort); + + // Return the results array + return results; +} + +// Resets the autocompletion tools +function resetAutocompletion(hash) { + $('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer').removeAttr('data-autocompletion-query'); +} + +// Autocompletes the chat input nick +function createAutocompletion(hash) { + // Initialize + var vSelector = $('#' + hash + ' .message-area'); + var value = vSelector.val(); + if(!value) + resetAutocompletion(hash); + var query = vSelector.attr('data-autocompletion-query'); + + // The autocompletion has not been yet launched + if(query == undefined) { + query = value; + vSelector.attr('data-autocompletion-query', query); + } + + // Get the pointer + var pointer = vSelector.attr('data-autocompletion-pointer'); + var i = 0; + + if(pointer) + i = parseInt(pointer); + + // We get the nickname + var nick = processAutocompletion(query, hash)[i]; + + // Shit, this is my nick! + if((nick != undefined) && (nick.toLowerCase() == getMUCNick(hash).toLowerCase())) { + // Increment + i++; + + // Get the next nick + nick = processAutocompletion(query, hash)[i]; + } + + // We quote the nick + if(nick != undefined) { + // Increment + i++; + quoteMyNick(hash, nick); + + // Put a pointer + vSelector.attr('data-autocompletion-pointer', i); + } +} diff --git a/sources/addons/jappixmini/jappix/js/avatar.js b/sources/addons/jappixmini/jappix/js/avatar.js new file mode 100644 index 00000000..4234ffc7 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/avatar.js @@ -0,0 +1,205 @@ +/* + +Jappix - An open social platform +These are the avatar JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 01/03/11 + +*/ + +// Requests the avatar of a given user +var AVATAR_PENDING = []; + +function getAvatar(xid, mode, enabled, photo) { + /* REF: http://xmpp.org/extensions/xep-0153.html */ + + // No need to get the avatar, another process is yet running + if(existArrayValue(AVATAR_PENDING, xid)) + return false; + + // Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests + var xml = XMLFromString(getPersistent('avatar', xid)); + var forced = false; + + // Retrieving forced? + if($(xml).find('forced').text() == 'true') + forced = true; + + // No avatar in presence + if(!photo && !forced && (enabled == 'true')) { + // Pending marker + AVATAR_PENDING.push(xid); + + // Reset the avatar + resetAvatar(xid, hex_md5(xid)); + + logThis('No avatar for: ' + xid, 2); + } + + // Try to catch the avatar + else { + // Define some stuffs + var type = $(xml).find('type').text(); + var binval = $(xml).find('binval').text(); + var checksum = $(xml).find('checksum').text(); + var updated = false; + + // Process the checksum of the avatar + if((checksum == photo) || (photo == 'forget') || forced) + updated = true; + + // If the avatar is yet stored and a new retrieving is not needed + if((mode == 'cache') && type && binval && checksum && updated) { + // Pending marker + AVATAR_PENDING.push(xid); + + // Display the cache avatar + displayAvatar(xid, hex_md5(xid), type, binval); + + logThis('Read avatar from cache: ' + xid, 3); + } + + // Else if the request has not yet been fired, we get it + else if((!updated || (mode == 'cache' && !updated) || (mode == 'force') || (photo = 'forget')) && (enabled != 'false')) { + // Pending marker + AVATAR_PENDING.push(xid); + + // Get the latest avatar + var iq = new JSJaCIQ(); + iq.setType('get'); + iq.setTo(xid); + + iq.appendNode('vCard', {'xmlns': NS_VCARD}); + + con.send(iq, handleAvatar); + + logThis('Get avatar from server: ' + xid, 3); + } + } + + return true; +} + +// Handles the avatar +function handleAvatar(iq) { + // Extract the XML values + var handleXML = iq.getNode(); + var handleFrom = fullXID(getStanzaFrom(iq)); + + // Is this me? Remove the resource! + if(bareXID(handleFrom) == getXID()) + handleFrom = bareXID(handleFrom); + + // Get some other values + var hash = hex_md5(handleFrom); + var find = $(handleXML).find('vCard'); + var aChecksum = 'none'; + var oChecksum = null; + + // Read our own checksum + if(handleFrom == getXID()) { + oChecksum = getDB('checksum', 1); + + // Avoid the "null" value + if(!oChecksum) + oChecksum = ''; + } + + // vCard not empty? + if(find.size()) { + // We get our profile details + if(handleFrom == getXID()) { + // Get the names + var names = generateBuddyName(iq); + + // Write the values to the database + setDB('profile', 'name', names[0]); + setDB('profile', 'nick', names[1]); + } + + // We get the avatar + var aType = find.find('TYPE:first').text(); + var aBinval = find.find('BINVAL:first').text(); + + // No binval? + if(!aBinval) { + aType = 'none'; + aBinval = 'none'; + } + + // Enough data + else { + // No type? + if(!aType) + aType = 'image/png'; + + // Process the checksum + else + aChecksum = hex_sha1(Base64.decode(aBinval)); + } + + // We display the user avatar + displayAvatar(handleFrom, hash, aType, aBinval); + + // Store the avatar + setPersistent('avatar', handleFrom, '' + aType + '' + aBinval + '' + aChecksum + 'false'); + + logThis('Avatar retrieved from server: ' + handleFrom, 3); + } + + // vCard is empty + else + resetAvatar(handleFrom); + + // We got a new checksum for us? + if(((oChecksum != null) && (oChecksum != aChecksum)) || !FIRST_PRESENCE_SENT) { + // Define a proper checksum + var pChecksum = aChecksum; + + if(pChecksum == 'none') + pChecksum = ''; + + // Update our temp. checksum + setDB('checksum', 1, pChecksum); + + // Send the stanza + if(FIRST_PRESENCE_SENT) + presenceSend(pChecksum); + else + getStorage(NS_OPTIONS); + } +} + +// Reset the avatar of an user +function resetAvatar(xid, hash) { + // Store the empty avatar + setPersistent('avatar', xid, 'nonenonenonefalse'); + + // Display the empty avatar + displayAvatar(xid, hash, 'none', 'none'); +} + +// Displays the avatar of an user +function displayAvatar(xid, hash, type, binval) { + // Initialize the vars + var container = hash + ' .avatar-container'; + var code = ''; + + // Replace with the new avatar (in the roster and in the chat) + $('.' + container).html(code); + + // We can remove the pending marker + removeArrayValue(AVATAR_PENDING, xid); +} diff --git a/sources/addons/jappixmini/jappix/js/base64.js b/sources/addons/jappixmini/jappix/js/base64.js new file mode 100644 index 00000000..1cf2dc74 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/base64.js @@ -0,0 +1,80 @@ +// This code was written by Tyler Akins and has been placed in the +// public domain. It would be nice if you left this header intact. +// Base64 code from Tyler Akins -- http://rumkin.com + +var Base64 = (function () { + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + + var obj = { + /** + * Encodes a string in base64 + * @param {String} input The string to encode in base64. + */ + encode: function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + do { + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + + keyStr.charAt(enc3) + keyStr.charAt(enc4); + } while (i < input.length); + + return output; + }, + + /** + * Decodes a base64 string. + * @param {String} input The string to decode. + */ + decode: function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + do { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + } while (i < input.length); + + return output; + } + }; + + return obj; +})(); diff --git a/sources/addons/jappixmini/jappix/js/board.js b/sources/addons/jappixmini/jappix/js/board.js new file mode 100644 index 00000000..1d26acee --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/board.js @@ -0,0 +1,141 @@ +/* + +Jappix - An open social platform +These are the notification board JS script for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 12/03/11 + +*/ + +// Creates a board panel +function createBoard(type, id) { + // Text var + var text = ''; + + // Info + if(type == 'info') { + switch(id) { + // Password change + case 1: + text = _e("Your password has been changed, now you can connect to your account with your new login data."); + + break; + + // Account deletion + case 2: + text = _e("Your XMPP account has been removed, bye!"); + + break; + + // Account logout + case 3: + text = _e("You have been logged out of your XMPP account, have a nice day!"); + + break; + + // Groupchat join + case 4: + text = _e("The room you joined seems not to exist. You should create it!"); + + break; + + // Groupchat removal + case 5: + text = _e("The groupchat has been removed, now someone else will be able to recreate it."); + + break; + + // Non-existant groupchat user + case 6: + text = _e("The user that you want to reach is not present in the room."); + + break; + } + } + + // Error + else { + switch(id) { + // Custom error + case 1: + text = '' + _e("Error") + ' » '; + + break; + + // Network error + case 2: + text = _e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."); + + break; + + // List retrieving error + case 3: + text = _e("The element list on this server could not be obtained!"); + + break; + + // Attaching error + case 4: + text = printf(_e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD); + + break; + } + } + + // No text? + if(!text) + return false; + + // Append the content + $('#board').append('
' + text + '
'); + + // Events (click and auto-hide) + $('#board .one-board.' + type + '[data-id=' + id + ']') + + .click(function() { + closeThisBoard(this); + }) + + .oneTime('5s', function() { + closeThisBoard(this); + }) + + .slideDown(); + + return true; +} + +// Destroys the existing board notifications +function destroyBoard() { + $('#board').empty(); +} + +// Executes a given action on the notification board +function actionBoard(id, type) { + // In a first, we destroy other boards + destroyBoard(); + + // Then we display the board + createBoard(type, id); +} + +// Opens a given error ID +function openThisError(id) { + actionBoard(id, 'error'); +} + +// Opens a given info ID +function openThisInfo(id) { + actionBoard(id, 'info'); +} + +// Closes a given board +function closeThisBoard(board) { + $(board).slideUp('normal', function() { + $(this).remove(); + }); +} diff --git a/sources/addons/jappixmini/jappix/js/browser-detect.js b/sources/addons/jappixmini/jappix/js/browser-detect.js new file mode 100644 index 00000000..39edaf2b --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/browser-detect.js @@ -0,0 +1,124 @@ +/* BROWSER DETECT + * http://www.quirksmode.org/js/detect.html + */ + +var BrowserDetect = { + init: function () { + this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; + this.version = this.searchVersion(navigator.userAgent) + || this.searchVersion(navigator.appVersion) + || "an unknown version"; + this.OS = this.searchString(this.dataOS) || "an unknown OS"; + }, + + searchString: function (data) { + for (var i=0;i ' + _e("no subject defined for this room.") + '

'; + specialCode = '

' + _e("Moderators") + '

' + _e("Participants") + '

' + _e("Visitors") + '

' + _e("Others") + '

'; + specialLink = ''; + specialStyle = ''; + + // Is this a gateway? + if(xid.match(/%/)) + specialDisabled = ''; + else + specialDisabled = ' disabled=""'; + } + + // Chat (or other things?!) special code + else { + specialAttributes = ' data-type="chat"'; + specialAvatar = '
'; + specialName = '

'; + specialCode = '
'; + specialLink = ''; + specialStyle = ' style="display: none;"'; + specialDisabled = ''; + } + + // Not a groupchat private chat, we can use the buddy add icon + if((type == 'chat') || (type == 'groupchat')) { + var addTitle; + + if(type == 'chat') + addTitle = _e("Add this contact to your friends"); + else + addTitle = _e("Add this groupchat to your favorites"); + + specialLink += ''; + } + + // IE DOM parsing bug fix + var specialStylePicker = '
' + + '' + + '
'; + + if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) + specialStylePicker = ''; + + // Append the chat HTML code + $('#page-engine').append( + '
' + + '
' + + specialAvatar + + + '
' + + '

' + nick.htmlEnc() + '

' + + specialName + + '
' + + '
' + + + specialCode + + + '
' + + '' + + + '
' + + '' + + '
' + + '
' + + '
' + ); + + // Click event: chat cleaner + $(path + 'tools-clear').click(function() { + cleanChat(id); + }); + + // Click event: user-infos + $(path + 'tools-infos').click(function() { + openUserInfos(xid); + }); +} + +// Generates the chat switch elements +function generateSwitch(type, id, xid, nick) { + // Path to the element + var chat_switch = '#page-switch .'; + + // Special code + var specialClass = ' unavailable'; + var show_close = true; + + // Groupchat + if(type == 'groupchat') { + specialClass = ' groupchat-default'; + + if(isAnonymous() && (xid == generateXID(ANONYMOUS_ROOM, 'groupchat'))) + show_close = false; + } + + // Generate the HTML code + var html = '
' + + '
' + + + '
' + nick.htmlEnc() + '
'; + + // Show the close button if not MUC and not anonymous + if(show_close) + html += '
x
'; + + // Close the HTML + html += '
'; + + // Append the HTML code + $(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html); +} + +// Cleans given the chat lines +function cleanChat(chat) { + $('#page-engine #' + chat + ' .content .one-group').remove(); + + $(document).oneTime(10, function() { + $('#page-engine #' + chat + ' .text .message-area').focus(); + }); +} + +// Creates a new chat +function chatCreate(hash, xid, nick, type) { + logThis('New chat: ' + xid, 3); + + // Create the chat content + generateChat(type, hash, xid, nick); + + // Create the chat switcher + generateSwitch(type, hash, xid, nick); + + // If the user is not in our buddy-list + if(type == 'chat') { + // Add button + if(!exists('#buddy-list .buddy[data-xid=' + escape(xid) + ']')) + $('#' + hash + ' .tools-add').click(function() { + // Hide the icon (to tell the user all is okay) + $(this).hide(); + + // Send the subscribe request + addThisContact(xid, nick); + }).show(); + + // Archives button + else if(enabledArchives() || enabledArchives('auto') || enabledArchives('manual') || enabledArchives('manage')) + $('#' + hash + ' .tools-archives').click(function() { + // Open the archives popup + openArchives(); + + // Get the archives for this user + $('#archives .filter .friend').val(xid); + updateArchives(); + }).show(); + } + + // We catch the user's informations (like this avatar, vcard, and so on...) + getUserInfos(hash, xid, nick, type); + + // The icons-hover functions + tooltipIcons(xid, hash); + + // The event handlers + var inputDetect = $('#page-engine #' + hash + ' .message-area'); + + inputDetect.focus(function() { + chanCleanNotify(hash); + }) + + inputDetect.keypress(function(e) { + // Enter key + if(e.keyCode == 13) { + // Add a new line + if(e.shiftKey) + inputDetect.val(inputDetect.val() + '\n'); + + // Send the message + else { + // Send the message + sendMessage(hash, 'chat'); + + // Reset the composing database entry + setDB('chatstate', xid, 'off'); + } + + return false; + } + }); + + // Chatstate events + eventsChatState(inputDetect, xid, hash); +} diff --git a/sources/addons/jappixmini/jappix/js/chatstate.js b/sources/addons/jappixmini/jappix/js/chatstate.js new file mode 100644 index 00000000..de7e7966 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/chatstate.js @@ -0,0 +1,174 @@ +/* + +Jappix - An open social platform +These are the chatstate JS script for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 25/08/11 + +*/ + +// Sends a given chatstate to a given entity +function chatStateSend(state, xid, hash) { + var user_type = $('#' + hash).attr('data-type'); + + // If the friend client supports chatstates and is online + if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !exists('#page-switch .' + hash + ' .unavailable'))) { + // Already sent? + if(getDB('currentchatstate', xid) == state) + return; + + // Write the state + setDB('currentchatstate', xid, state); + + // New message stanza + var aMsg = new JSJaCMessage(); + aMsg.setTo(xid); + aMsg.setType(user_type); + + // Append the chatstate node + aMsg.appendNode(state, {'xmlns': NS_CHATSTATES}); + + // Send this! + con.send(aMsg); + } +} + +// Displays a given chatstate in a given chat +function displayChatState(state, hash, type) { + // Groupchat? + if(type == 'groupchat') { + resetChatState(hash, type); + + // "gone" state not allowed + if(state != 'gone') + $('#page-engine .page-engine-chan .user.' + hash).addClass(state); + } + + // Chat + else { + // We change the buddy name color in the page-switch + resetChatState(hash, type); + $('#page-switch .' + hash + ' .name').addClass(state); + + // We generate the chatstate text + var text = ''; + + switch(state) { + // Active + case 'active': + text = _e("Your friend is paying attention to the conversation."); + + break; + + // Composing + case 'composing': + text = _e("Your friend is writing a message..."); + + break; + + // Paused + case 'paused': + text = _e("Your friend stopped writing a message."); + + break; + + // Inactive + case 'inactive': + text = _e("Your friend is doing something else."); + + break; + + // Gone + case 'gone': + text = _e("Your friend closed the chat."); + + break; + } + + // We reset the previous state + $('#' + hash + ' .chatstate').remove(); + + // We create the chatstate + $('#' + hash + ' .content').after('
' + text + '
'); + } +} + +// Resets the chatstate switcher marker +function resetChatState(hash, type) { + // Define the selector + var selector; + + if(type == 'groupchat') + selector = $('#page-engine .page-engine-chan .user.' + hash); + else + selector = $('#page-switch .' + hash + ' .name'); + + // Reset! + selector.removeClass('active') + selector.removeClass('composing') + selector.removeClass('paused') + selector.removeClass('inactive') + selector.removeClass('gone'); +} + +// Adds the chatstate events +function eventsChatState(target, xid, hash) { + target.keyup(function(e) { + if(e.keyCode != 13) { + // Composing a message + if($(this).val() && (getDB('chatstate', xid) != 'on')) { + // We change the state detect input + setDB('chatstate', xid, 'on'); + + // We send the friend a "composing" chatstate + chatStateSend('composing', xid, hash); + } + + // Stopped composing a message + else if(!$(this).val() && (getDB('chatstate', xid) == 'on')) { + // We change the state detect input + setDB('chatstate', xid, 'off'); + + // We send the friend an "active" chatstate + chatStateSend('active', xid, hash); + } + } + }); + + target.change(function() { + // Reset the composing database entry + setDB('chatstate', xid, 'off'); + }); + + target.focus(function() { + // Not needed + if(target.is(':disabled')) + return; + + // Nothing in the input, user is active + if(!$(this).val()) + chatStateSend('active', xid, hash); + + // Something was written, user started writing again + else + chatStateSend('composing', xid, hash); + }); + + target.blur(function() { + // Not needed + if(target.is(':disabled')) + return; + + // Nothing in the input, user is inactive + if(!$(this).val()) + chatStateSend('inactive', xid, hash); + + // Something was written, user paused + else + chatStateSend('paused', xid, hash); + }); +} diff --git a/sources/addons/jappixmini/jappix/js/common.js b/sources/addons/jappixmini/jappix/js/common.js new file mode 100644 index 00000000..ab10d6e7 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/common.js @@ -0,0 +1,311 @@ +/* + +Jappix - An open social platform +These are the common JS script for Jappix + +------------------------------------------------- + +License: AGPL +Authors: Vanaryon, olivierm +Last revision: 24/06/11 + +*/ + +// Checks if an element exists in the DOM +function exists(selector) { + if(jQuery(selector).size() > 0) + return true; + else + return false; +} + +// Checks if Jappix is connected +function isConnected() { + if((typeof con != 'undefined') && con && con.connected()) + return true; + + return false; +} + +// Checks if Jappix has focus +function isFocused() { + try { + if(document.hasFocus()) + return true; + + return false; + } + + catch(e) { + return true; + } +} + +// Generates the good XID +function generateXID(xid, type) { + // XID needs to be transformed + if(xid && (xid.indexOf('@') == -1)) { + // Groupchat + if(type == 'groupchat') + return xid + '@' + HOST_MUC; + + // One-to-one chat + if(xid.indexOf('.') == -1) + return xid + '@' + HOST_MAIN; + + // It might be a gateway? + return xid; + } + + // Nothing special (yet bare XID) + return xid; +} + +// Gets the asked translated string +function _e(string) { + return string; +} + +// Replaces '%s' to a given value for a translated string +function printf(string, value) { + return string.replace('%s', value); +} + +// Properly explodes a string with a given character +function explodeThis(toEx, toStr, i) { + // Get the index of our char to explode + var index = toStr.indexOf(toEx); + + // We split if necessary the string + if(index != -1) { + if(i == 0) + toStr = toStr.substr(0, index); + else + toStr = toStr.substr(index + 1); + } + + // We return the value + return toStr; +} + +// Cuts the resource of a XID +function cutResource(aXID) { + return explodeThis('/', aXID, 0); +} + +// Gets the resource of a XID +function thisResource(aXID) { + // Any resource? + if(aXID.indexOf('/') != -1) + return explodeThis('/', aXID, 1); + + // No resource + return ''; +} + +// Does stringprep on a string +function stringPrep(string) { + // Replacement arrays + var invalid = new Array('Š', 'š', 'Đ', 'đ', 'Ž', 'ž', 'Č', 'č', 'Ć', 'ć', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ý', 'þ', 'ÿ', 'Ŕ', 'ŕ'); + + var valid = new Array('S', 's', 'Dj', 'dj', 'Z', 'z', 'C', 'c', 'C', 'c', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'B', 'Ss', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'o', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'y', 'b', 'y', 'R', 'r'); + + // Compute a new string + for(i in invalid) + string = string.replace(invalid[i], valid[i]); + + return string; +} + +// Encodes quotes in a string +function encodeQuotes(str) { + return (str + '').replace(/"/g, '"'); +} + +// Gets the bare XID from a XID +function bareXID(xid) { + // Cut the resource + xid = cutResource(xid); + + // Launch the stringprep + xid = stringPrep(xid); + + // Set the XID to lower case + xid = xid.toLowerCase(); + + return xid; +} + +// Gets the full XID from a XID +function fullXID(xid) { + // Normalizes the XID + var full = bareXID(xid); + var resource = thisResource(xid); + + // Any resource? + if(resource) + full += '/' + resource; + + return full; +} + +// Gets the nick from a XID +function getXIDNick(aXID) { + return explodeThis('@', aXID, 0); +} + +// Gets the host from a XID +function getXIDHost(aXID) { + return explodeThis('@', aXID, 1); +} + +// Checks if we are in developer mode +function isDeveloper() { + if(DEVELOPER == 'on') + return true; + + return false; +} + +// Checks if anonymous mode is allowed +function allowedAnonymous() { + if(ANONYMOUS == 'on') + return true; + + return false; +} + +// Checks if host is locked +function lockHost() { + if(LOCK_HOST == 'on') + return true; + + return false; +} + +// Gets the full XID of the user +function getXID() { + // Return the XID of the user + if(con.username && con.domain) + return con.username + '@' + con.domain; + + return ''; +} + +// Generates the colors for a given user XID +function generateColor(xid) { + var colors = new Array( + 'ac0000', + 'a66200', + '007703', + '00705f', + '00236b', + '4e005c' + ); + + var number = 0; + + for(var i = 0; i < xid.length; i++) + number += xid.charCodeAt(i); + + var color = '#' + colors[number % (colors.length)]; + + return color; +} + +// Checks if the XID is a gateway +function isGateway(xid) { + if(xid.indexOf('@') != -1) + return false; + + return true; +} + +// Gets the from attribute of a stanza (overrides some servers like Prosody missing from attributes) +function getStanzaFrom(stanza) { + var from = stanza.getFrom(); + + // No from, we assume this is our XID + if(!from) + from = getXID(); + + return from; +} + +// Logs a given data in the console +function logThis(data, level) { + // Console not available + if(!isDeveloper() || (typeof(console) == 'undefined')) + return false; + + // Switch the log level + switch(level) { + // Debug + case 0: + console.debug(data); + + break; + + // Error + case 1: + console.error(data); + + break; + + // Warning + case 2: + console.warn(data); + + break; + + // Information + case 3: + console.info(data); + + break; + + // Default log level + default: + console.log(data); + + break; + } + + return true; +} + +// Gets the current Jappix app. location +function getJappixLocation() { + var url = window.location.href; + + // If the URL has variables, remove them + if(url.indexOf('?') != -1) + url = url.split('?')[0]; + if(url.indexOf('#') != -1) + url = url.split('#')[0]; + + // No "/" at the end + if(!url.match(/(.+)\/$/)) + url += '/'; + + return url; +} + +// Removes spaces at the beginning & the end of a string +function trim(str) { + return str.replace(/^\s+/g,'').replace(/\s+$/g,''); +} + +// Adds a zero to a date when needed +function padZero(i) { + // Negative number (without first 0) + if(i > -10 && i < 0) + return '-0' + (i * -1); + + // Positive number (without first 0) + if(i < 10 && i >= 0) + return '0' + i; + + // All is okay + return i; +} diff --git a/sources/addons/jappixmini/jappix/js/connection.js b/sources/addons/jappixmini/jappix/js/connection.js new file mode 100644 index 00000000..85a718c5 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/connection.js @@ -0,0 +1,526 @@ +/* + +Jappix - An open social platform +These are the connection JS script for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 29/08/11 + +*/ + +// Does the user login +var CURRENT_SESSION = false; + +function doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember) { + try { + // We remove the not completed class to avoid problems + $('#home .loginer input').removeClass('please-complete'); + + // We add the login wait div + showGeneralWait(); + + // We define the http binding parameters + oArgs = new Object(); + + if(HOST_BOSH_MAIN) + oArgs.httpbase = HOST_BOSH_MAIN; + else + oArgs.httpbase = HOST_BOSH; + + // We create the new http-binding connection + con = new JSJaCHttpBindingConnection(oArgs); + + // And we handle everything that happen + setupCon(con); + + // Generate a resource + var random_resource = getDB('session', 'resource'); + + if(!random_resource) + random_resource = lResource + ' (' + (new Date()).getTime() + ')'; + + // We retrieve what the user typed in the login inputs + oArgs = new Object(); + oArgs.domain = trim(lServer); + oArgs.username = trim(lNick); + oArgs.resource = random_resource; + oArgs.pass = lPass; + oArgs.secure = true; + oArgs.xmllang = XML_LANG; + + // Store the resource (for reconnection) + setDB('session', 'resource', random_resource); + + // Generate a session XML to be stored + session_xml = 'true' + lServer.htmlEnc() + '' + lNick.htmlEnc() + '' + lResource.htmlEnc() + '' + lPass.htmlEnc() + '' + lPriority.htmlEnc() + ''; + + // Save the session parameters (for reconnect if network issue) + CURRENT_SESSION = session_xml; + + // Remember me? + if(lRemember) + setDB('remember', 'session', 1); + + // We store the infos of the user into the data-base + setDB('priority', 1, lPriority); + + // We connect ! + con.connect(oArgs); + + // Change the page title + pageTitle('wait'); + + logThis('Jappix is connecting...', 3); + } + + catch(e) { + // Logs errors + logThis('Error while logging in: ' + e, 1); + + // Reset Jappix + destroyTalkPage(); + + // Open an unknown error + openThisError(2); + } + + finally { + return false; + } +} + +// Handles the user registration +function handleRegistered() { + logThis('A new account has been registered.', 3); + + // We remove the waiting image + removeGeneralWait(); + + // Reset the title + pageTitle('home'); + + // We show the success information + $('#home .registerer .success').fadeIn('fast'); + + // We quit the session + logout(); +} + +// Does the user registration +function doRegister(username, domain, pass) { + logThis('Trying to register an account...', 3); + + try { + // We define the http binding parameters + oArgs = new Object(); + + if(HOST_BOSH_MAIN) + oArgs.httpbase = HOST_BOSH_MAIN; + else + oArgs.httpbase = HOST_BOSH; + + // We create the new http-binding connection + con = new JSJaCHttpBindingConnection(oArgs); + + // We setup the connection ! + con.registerHandler('onconnect', handleRegistered); + con.registerHandler('onerror', handleError); + + // We retrieve what the user typed in the register inputs + oArgs = new Object(); + oArgs.domain = trim(domain); + oArgs.username = trim(username); + oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')'; + oArgs.pass = pass; + oArgs.register = true; + oArgs.secure = true; + oArgs.xmllang = XML_LANG; + + con.connect(oArgs); + + // We change the registered information text + $('#home .homediv.registerer').append( + '
' + + _e("You have been registered, here is your XMPP address:") + ' ' + con.username.htmlEnc() + '@' + con.domain.htmlEnc() + ' - ' + _e("Login") + '' + + '
' + ); + + // Login link + $('#home .homediv.registerer .success a').click(function() { + return doLogin(con.username, con.domain, con.pass, con.resource, '10', false); + }); + + // Show the waiting image + showGeneralWait(); + + // Change the page title + pageTitle('wait'); + } + + catch(e) { + // Logs errors + logThis(e, 1); + } + + finally { + return false; + } +} + +// Does the user anonymous login +function doAnonymous() { + logThis('Trying to login anonymously...', 3); + + var aPath = '#home .anonymouser '; + var room = $(aPath + '.room').val(); + var nick = $(aPath + '.nick').val(); + + // If the form is correctly completed + if(room && nick) { + // We remove the not completed class to avoid problems + $('#home .anonymouser input').removeClass('please-complete'); + + // Redirect the user to the anonymous room + window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick; + } + + // We check if the form is entirely completed + else { + $(aPath + 'input[type=text]').each(function() { + var select = $(this); + + if(!select.val()) + $(document).oneTime(10, function() { + select.addClass('please-complete').focus(); + }); + else + select.removeClass('please-complete'); + }); + } + + return false; +} + +// Handles the user connected event +var CONNECTED = false; + +function handleConnected() { + logThis('Jappix is now connected.', 3); + + // Connection markers + CONNECTED = true; + RECONNECT_TRY = 0; + RECONNECT_TIMER = 0; + + // We hide the home page + $('#home').hide(); + + // Not resumed? + if(!RESUME) { + // Remember the session? + if(getDB('remember', 'session')) + setPersistent('session', 1, CURRENT_SESSION); + + // We show the chatting app. + createTalkPage(); + + // We reset the homepage + switchHome('default'); + + // We get all the other things + getEverything(); + + // Set last activity stamp + LAST_ACTIVITY = getTimeStamp(); + } + + // Resumed + else { + // Send our presence + presenceSend(); + + // Change the title + updateTitle(); + } + + // Remove the waiting item + removeGeneralWait(); +} + +// Handles the user disconnected event +function handleDisconnected() { + logThis('Jappix is now disconnected.', 3); + + // Normal disconnection + if(!CURRENT_SESSION && !CONNECTED) + destroyTalkPage(); +} + +// Setups the normal connection +function setupCon(con) { + // We setup all the necessary handlers for the connection + con.registerHandler('message', handleMessage); + con.registerHandler('presence', handlePresence); + con.registerHandler('iq', handleIQ); + con.registerHandler('onconnect', handleConnected); + con.registerHandler('onerror', handleError); + con.registerHandler('ondisconnect', handleDisconnected); +} + +// Logouts from the server +function logout() { + // We are not connected + if(!isConnected()) + return false; + + // Disconnect from the XMPP server + con.disconnect(); + + logThis('Jappix is disconnecting...', 3); +} + +// Terminates a session +function terminate() { + if(!isConnected()) + return; + + // Clear temporary session storage + resetConMarkers(); + + // Show the waiting item (useful if BOSH is sloooow) + showGeneralWait(); + + // Change the page title + pageTitle('wait'); + + // Disconnect from the XMPP server + logout(); +} + +// Quitss a session +function quit() { + if(!isConnected()) + return; + + // We show the waiting image + showGeneralWait(); + + // Change the page title + pageTitle('wait'); + + // We disconnect from the XMPP server + logout(); +} + +// Creates the reconnect pane +var RECONNECT_TRY = 0; +var RECONNECT_TIMER = 0; + +function createReconnect(mode) { + logThis('This is not a normal disconnection, show the reconnect pane...', 1); + + // Reconnect pane not yet displayed? + if(!exists('#reconnect')) { + // Blur the focused input/textarea/select + $('input, select, textarea').blur(); + + // Create the HTML code + var html = '
' + + '
' + + _e("Due to a network issue, you were disconnected. What do you want to do now?"); + + // Can we cancel reconnection? + if(mode == 'normal') + html += '' + _e("Cancel") + ''; + + html += '' + _e("Reconnect") + '' + + '
'; + + // Append the code + $('body').append(html); + + // Click events + if(mode == 'normal') + $('#reconnect a.finish.cancel').click(function() { + return cancelReconnect(); + }); + + $('#reconnect a.finish.reconnect').click(function() { + return acceptReconnect(mode); + }); + + // Try to reconnect automatically after a while + if(RECONNECT_TRY < 5) + RECONNECT_TIMER = 5 + (5 * RECONNECT_TRY); + else + RECONNECT_TIMER = 120; + + // Change the try number + RECONNECT_TRY++; + + // Fire the event! + $('#reconnect a.finish.reconnect').everyTime('1s', function() { + // We can reconnect! + if(RECONNECT_TIMER == 0) + return acceptReconnect(mode); + + // Button text + if(RECONNECT_TIMER <= 10) + $(this).text(_e("Reconnect") + ' (' + RECONNECT_TIMER + ')'); + + // Remove 1 second + RECONNECT_TIMER--; + }); + + // Page title + updateTitle(); + } +} + +// Reconnects the user if he was disconnected (network issue) +var RESUME = false; + +function acceptReconnect(mode) { + logThis('Trying to reconnect the user...', 3); + + // Resume marker + RESUME = true; + + // Show waiting item + showGeneralWait(); + + // Reset some various stuffs + var groupchats = '#page-engine .page-engine-chan[data-type=groupchat]'; + $(groupchats + ' .list .role').hide(); + $(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove(); + $(groupchats).attr('data-initial', 'false'); + + // Stop the timer + $('#reconnect a.finish.reconnect').stopTime(); + + // Remove the reconnect pane + $('#reconnect').remove(); + + // Try to login again + if(mode == 'normal') + loginFromSession(XMLFromString(CURRENT_SESSION)); + else if(mode == 'anonymous') + anonymousLogin(HOST_ANONYMOUS); + + return false; +} + +// Cancel the reconnection of user account (network issue) +function cancelReconnect() { + logThis('User has canceled automatic reconnection...', 3); + + // Stop the timer + $('#reconnect a.finish.reconnect').stopTime(); + + // Remove the reconnect pane + $('#reconnect').remove(); + + // Destroy the talk page + destroyTalkPage(); + + // Renitialize the previous session parameters + resetConMarkers(); + + return false; +} + +// Clears session reminder database +function clearLastSession() { + // Clear temporary storage + resetConMarkers(); + + // Clear persistent storage + if($(XMLFromString(getPersistent('session', 1))).find('stored').text() == 'true') + removePersistent('session', 1); +} + +// Resets the connection markers +function resetConMarkers() { + CURRENT_SESSION = false; + CONNECTED = false; + RESUME = false; + RECONNECT_TRY = 0; + RECONNECT_TIMER = 0; +} + +// Logins from a saved session +function loginFromSession(data) { + // Select the data + var session = $(data); + + // Fire the login event + doLogin( + session.find('username').text(), + session.find('domain').text(), + session.find('password').text(), + session.find('resource').text(), + session.find('priority').text(), + false + ); +} + +// Quits a session normally +function normalQuit() { + // Reset our database + clearLastSession(); + + // We quit the current session + quit(); + + // We show an info + openThisInfo(3); + + return false; +} + +// Gets all the users stuffs +function getEverything() { + getFeatures(); + getRoster(); + listPrivacy(); + getStorage(NS_ROSTERNOTES); +} + +// Plugin launcher +function launchConnection() { + // Logouts when Jappix is closed + $(window).bind('beforeunload', terminate); + + // Nothing to do when anonymous! + if(isAnonymous()) + return; + + // Try to resume a stored session, if not anonymous + var session = XMLFromString(getPersistent('session', 1)); + + if($(session).find('stored').text() == 'true') { + // Hide the homepage + $('#home').hide(); + + // Show the waiting icon + showGeneralWait(); + + // Login! + loginFromSession(session); + + logThis('Saved session found, resuming it...', 3); + } + + // Not connected, maybe a XMPP link is submitted? + else if((parent.location.hash != '#OK') && LINK_VARS['x']) { + switchHome('loginer'); + + logThis('A XMPP link is set, switch to login page.', 3); + } +} + +// Launch this plugin! +$(document).ready(launchConnection); diff --git a/sources/addons/jappixmini/jappix/js/constants.js b/sources/addons/jappixmini/jappix/js/constants.js new file mode 100644 index 00000000..bc59bd75 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/constants.js @@ -0,0 +1,211 @@ +/* + +Jappix - An open social platform +These are the constants JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Authors: Stefan Strigler, Vanaryon +Last revision: 26/08/11 + +*/ + +// XMPP XMLNS attributes +var NS_PROTOCOL = 'http://jabber.org/protocol/'; +var NS_FEATURES = 'http://jabber.org/features/'; +var NS_CLIENT = 'jabber:client'; +var NS_IQ = 'jabber:iq:'; +var NS_X = 'jabber:x:'; +var NS_IETF = 'urn:ietf:params:xml:ns:xmpp-'; +var NS_XMPP = 'urn:xmpp:'; + +var NS_STORAGE = 'storage:'; +var NS_BOOKMARKS = NS_STORAGE + 'bookmarks'; +var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes'; + +var NS_JAPPIX = 'jappix:'; +var NS_INBOX = NS_JAPPIX + 'inbox'; +var NS_OPTIONS = NS_JAPPIX + 'options'; + +var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items'; +var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info'; +var NS_VCARD = 'vcard-temp'; +var NS_VCARD_P = NS_VCARD + ':x:update'; +var NS_AUTH = NS_IQ + 'auth'; +var NS_AUTH_ERROR = NS_IQ + 'auth:error'; +var NS_REGISTER = NS_IQ + 'register'; +var NS_SEARCH = NS_IQ + 'search'; +var NS_ROSTER = NS_IQ + 'roster'; +var NS_PRIVACY = NS_IQ + 'privacy'; +var NS_PRIVATE = NS_IQ + 'private'; +var NS_VERSION = NS_IQ + 'version'; +var NS_TIME = NS_IQ + 'time'; +var NS_LAST = NS_IQ + 'last'; +var NS_IQDATA = NS_IQ + 'data'; +var NS_XDATA = NS_X + 'data'; +var NS_IQOOB = NS_IQ + 'oob'; +var NS_XOOB = NS_X + 'oob'; +var NS_DELAY = NS_X + 'delay'; +var NS_EXPIRE = NS_X + 'expire'; +var NS_EVENT = NS_X + 'event'; +var NS_XCONFERENCE = NS_X + 'conference'; +var NS_STATS = NS_PROTOCOL + 'stats'; +var NS_MUC = NS_PROTOCOL + 'muc'; +var NS_MUC_USER = NS_MUC + '#user'; +var NS_MUC_ADMIN = NS_MUC + '#admin'; +var NS_MUC_OWNER = NS_MUC + '#owner'; +var NS_MUC_CONFIG = NS_MUC + '#roomconfig'; +var NS_PUBSUB = NS_PROTOCOL + 'pubsub'; +var NS_PUBSUB_EVENT = NS_PUBSUB + '#event'; +var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner'; +var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info'; +var NS_PUBSUB_NC = NS_PUBSUB + '#node_config'; +var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items'; +var NS_COMMANDS = NS_PROTOCOL + 'commands'; +var NS_BOSH = NS_PROTOCOL + 'httpbind'; +var NS_STREAM = 'http://etherx.jabber.org/streams'; +var NS_URN_TIME = NS_XMPP + 'time'; +var NS_URN_PING = NS_XMPP + 'ping'; +var NS_URN_ADATA = NS_XMPP + 'avatar:data'; +var NS_URN_AMETA = NS_XMPP + 'avatar:metadata'; +var NS_URN_MBLOG = NS_XMPP + 'microblog:0'; +var NS_URN_INBOX = NS_XMPP + 'inbox'; +var NS_URN_ARCHIVE = NS_XMPP + 'archive'; +var NS_URN_AR_PREF = NS_URN_ARCHIVE + ':pref'; +var NS_URN_AR_AUTO = NS_URN_ARCHIVE + ':auto'; +var NS_URN_AR_MANUAL = NS_URN_ARCHIVE + ':manual'; +var NS_URN_AR_MANAGE = NS_URN_ARCHIVE + ':manage'; +var NS_URN_DELAY = NS_XMPP + 'delay'; +var NS_URN_RECEIPTS = NS_XMPP + 'receipts'; +var NS_RSM = NS_PROTOCOL + 'rsm'; +var NS_IPV6 = 'ipv6'; +var NS_XHTML = 'http://www.w3.org/1999/xhtml'; +var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im'; +var NS_CHATSTATES = NS_PROTOCOL + 'chatstates'; +var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth'; +var NS_ROSTERX = NS_PROTOCOL + 'rosterx'; +var NS_MOOD = NS_PROTOCOL + 'mood'; +var NS_ACTIVITY = NS_PROTOCOL + 'activity'; +var NS_TUNE = NS_PROTOCOL + 'tune'; +var NS_GEOLOC = NS_PROTOCOL + 'geoloc'; +var NS_NICK = NS_PROTOCOL + 'nick'; +var NS_NOTIFY = '+notify'; +var NS_CAPS = NS_PROTOCOL + 'caps'; +var NS_ATOM = 'http://www.w3.org/2005/Atom'; + +var NS_STANZAS = NS_IETF + 'stanzas'; +var NS_STREAMS = NS_IETF + 'streams'; + +var NS_TLS = NS_IETF + 'tls'; +var NS_SASL = NS_IETF + 'sasl'; +var NS_SESSION = NS_IETF + 'session'; +var NS_BIND = NS_IETF + 'bind'; + +var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth'; +var NS_FEATURE_IQREGISTER = NS_FEATURES + 'iq-register'; +var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress'; + +var NS_COMPRESS = NS_PROTOCOL + 'compress'; + +// Available locales +var LOCALES_AVAILABLE_ID = new Array(); +var LOCALES_AVAILABLE_NAMES = new Array(); + +// XML lang +var XML_LANG = null; + +// Jappix parameters +var JAPPIX_STATIC = null; +var JAPPIX_VERSION = null; +var JAPPIX_MAX_FILE_SIZE = null; +var JAPPIX_MAX_UPLOAD = null; + +// Jappix main configuration +var SERVICE_NAME = null; +var SERVICE_DESC = null; +var JAPPIX_RESOURCE = null; +var LOCK_HOST = null; +var ANONYMOUS = null; +var REGISTRATION = null; +var BOSH_PROXY = null; +var MANAGER_LINK = null; +var GROUPCHATS_JOIN = null; +var ENCRYPTION = null; +var HTTPS_STORAGE = null; +var HTTPS_FORCE = null; +var COMPRESSION = null; +var MULTI_FILES = null; +var DEVELOPER = null; + +// Jappix hosts configuration +var HOST_MAIN = null; +var HOST_MUC = null; +var HOST_PUBSUB = null; +var HOST_VJUD = null; +var HOST_ANONYMOUS = null; +var HOST_BOSH = null; +var HOST_BOSH_MAIN = null; +var HOST_BOSH_MINI = null; +var HOST_STATIC = null; +var HOST_UPLOAD = null; + +// Anonymous mode +var ANONYMOUS_ROOM = null; +var ANONYMOUS_NICK = null; + +// Node parameters +var JAPPIX_LOCATION = getJappixLocation(); + +// XMPP error stanzas +function STANZA_ERROR(code, type, cond) { + if (window == this) + return new STANZA_ERROR(code, type, cond); + + this.code = code; + this.type = type; + this.cond = cond; +} + +var ERR_BAD_REQUEST = + STANZA_ERROR('400', 'modify', 'bad-request'); +var ERR_CONFLICT = + STANZA_ERROR('409', 'cancel', 'conflict'); +var ERR_FEATURE_NOT_IMPLEMENTED = + STANZA_ERROR('501', 'cancel', 'feature-not-implemented'); +var ERR_FORBIDDEN = + STANZA_ERROR('403', 'auth', 'forbidden'); +var ERR_GONE = + STANZA_ERROR('302', 'modify', 'gone'); +var ERR_INTERNAL_SERVER_ERROR = + STANZA_ERROR('500', 'wait', 'internal-server-error'); +var ERR_ITEM_NOT_FOUND = + STANZA_ERROR('404', 'cancel', 'item-not-found'); +var ERR_JID_MALFORMED = + STANZA_ERROR('400', 'modify', 'jid-malformed'); +var ERR_NOT_ACCEPTABLE = + STANZA_ERROR('406', 'modify', 'not-acceptable'); +var ERR_NOT_ALLOWED = + STANZA_ERROR('405', 'cancel', 'not-allowed'); +var ERR_NOT_AUTHORIZED = + STANZA_ERROR('401', 'auth', 'not-authorized'); +var ERR_PAYMENT_REQUIRED = + STANZA_ERROR('402', 'auth', 'payment-required'); +var ERR_RECIPIENT_UNAVAILABLE = + STANZA_ERROR('404', 'wait', 'recipient-unavailable'); +var ERR_REDIRECT = + STANZA_ERROR('302', 'modify', 'redirect'); +var ERR_REGISTRATION_REQUIRED = + STANZA_ERROR('407', 'auth', 'registration-required'); +var ERR_REMOTE_SERVER_NOT_FOUND = + STANZA_ERROR('404', 'cancel', 'remote-server-not-found'); +var ERR_REMOTE_SERVER_TIMEOUT = + STANZA_ERROR('504', 'wait', 'remote-server-timeout'); +var ERR_RESOURCE_CONSTRAINT = + STANZA_ERROR('500', 'wait', 'resource-constraint'); +var ERR_SERVICE_UNAVAILABLE = + STANZA_ERROR('503', 'cancel', 'service-unavailable'); +var ERR_SUBSCRIPTION_REQUIRED = + STANZA_ERROR('407', 'auth', 'subscription-required'); +var ERR_UNEXPECTED_REQUEST = + STANZA_ERROR('400', 'wait', 'unexpected-request'); diff --git a/sources/addons/jappixmini/jappix/js/dataform.js b/sources/addons/jappixmini/jappix/js/dataform.js new file mode 100644 index 00000000..7fbea89d --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/dataform.js @@ -0,0 +1,921 @@ +/* + +Jappix - An open social platform +These are the dataform JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 28/08/11 + +*/ + +// Gets the defined dataform elements +function dataForm(host, type, node, action, target) { + // Clean the current session + cleanDataForm(target); + + // We tell the user that a search has been launched + $('#' + target + ' .wait').show(); + + // If we have enough data + if(host && type) { + // Generate a session ID + var sessionID = Math.round(100000.5 + (((900000.49999) - (100000.5)) * Math.random())); + var id = target + '-' + sessionID + '-' + genID(); + $('.' + target + '-results').attr('data-session', target + '-' + sessionID); + + // We request the service item + var iq = new JSJaCIQ(); + iq.setID(id); + iq.setTo(host); + iq.setType('get'); + + // MUC admin query + if(type == 'muc') { + iq.setQuery(NS_MUC_OWNER); + con.send(iq, handleDataFormMuc); + } + + // Browse query + else if(type == 'browse') { + var iqQuery = iq.setQuery(NS_DISCO_ITEMS); + + if(node) + iqQuery.setAttribute('node', node); + + con.send(iq, handleDataFormBrowse); + } + + // Command + else if(type == 'command') { + var items; + + if(node) + items = iq.appendNode('command', {'node': node, 'xmlns': NS_COMMANDS}); + + else { + items = iq.setQuery(NS_DISCO_ITEMS); + items.setAttribute('node', NS_COMMANDS); + } + + if(action && node) { + iq.setType('set'); + items.setAttribute('action', action); + } + + con.send(iq, handleDataFormCommand); + } + + // Search query + else if(type == 'search') { + iq.setQuery(NS_SEARCH); + con.send(iq, handleDataFormSearch); + } + + // Subscribe query + else if(type == 'subscribe') { + iq.setQuery(NS_REGISTER); + con.send(iq, handleDataFormSubscribe); + } + + // Join + else if(type == 'join') { + if(target == 'discovery') + closeDiscovery(); + + checkChatCreate(host, 'groupchat'); + } + } + + return false; +} + +// Sends a given dataform +function sendDataForm(type, action, x_type, id, xid, node, sessionid, target) { + // Path + var pathID = '#' + target + ' .results[data-session=' + id + ']'; + + // New IQ + var iq = new JSJaCIQ(); + iq.setTo(xid); + iq.setType('set'); + + // Set the correct query + var query; + + if(type == 'subscribe') + iqQuery = iq.setQuery(NS_REGISTER); + else if(type == 'search') + iqQuery = iq.setQuery(NS_SEARCH); + else if(type == 'command') + iqQuery = iq.appendNode('command', {'xmlns': NS_COMMANDS, 'node': node, 'sessionid': sessionid, 'action': action}); + else if(type == 'x') + iqQuery = iq.setQuery(NS_MUC_OWNER); + + // Build the XML document + if(action != 'cancel') { + // No X node + if(exists('input.register-special') && (type == 'subscribe')) { + $('input.register-special').each(function() { + var iName = $(this).attr('name'); + var iValue = $(this).val(); + + iqQuery.appendChild(iq.buildNode(iName, {'xmlns': NS_REGISTER}, iValue)); + }); + } + + // Can create the X node + else { + var iqX = iqQuery.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': x_type})); + + // Each input + $(pathID + ' .oneresult input, ' + pathID + ' .oneresult textarea, ' + pathID + ' .oneresult select').each(function() { + // Get the current input value + var iVar = $(this).attr('name'); + var iType = $(this).attr('data-type'); + var iValue = $(this).val(); + + // Build a new field node + var field = iqX.appendChild(iq.buildNode('field', {'var': iVar, 'type': iType, 'xmlns': NS_XDATA})); + + // Boolean input? + if(iType == 'boolean') { + if($(this).filter(':checked').size()) + iValue = '1'; + else + iValue = '0'; + } + + // JID-multi input? + if(iType == 'jid-multi') { + // Values array + var xid_arr = [iValue]; + var xid_check = []; + + // Try to split it + if(iValue.indexOf(',') != -1) + xid_arr = iValue.split(','); + + // Append each value to the XML document + for(i in xid_arr) { + // Get the current value + xid_current = trim(xid_arr[i]); + + // No current value? + if(!xid_current) + continue; + + // Add the current value + if(!existArrayValue(xid_check, xid_current)) { + xid_check.push(xid_current); + field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, xid_current)); + } + } + } + + // List-multi selector? + else if(iType == 'list-multi') { + // Any value? + if(iValue && iValue.length) { + for(i in iValue) + field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue[i])); + } + } + + // Other inputs? + else + field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue)); + }); + } + } + + // Clean the current session + cleanDataForm(target); + + // Show the waiting item + $('#' + target + ' .wait').show(); + + // Change the ID of the current discovered item + var iqID = target + '-' + genID(); + $('#' + target + ' .' + target + '-results').attr('data-session', iqID); + iq.setID(iqID); + + // Send the IQ + if(type == 'subscribe') + con.send(iq, handleDataFormSubscribe); + else if(type == 'search') + con.send(iq, handleDataFormSearch); + else if(type == 'command') + con.send(iq, handleDataFormCommand); + else + con.send(iq); + + return false; +} + +// Displays the good dataform buttons +function buttonsDataForm(type, action, id, xid, node, sessionid, target, pathID) { + // No need to use buttons? + if(type == 'muc') + return; + + // Override the "undefined" output + if(!id) + id = ''; + if(!xid) + xid = ''; + if(!node) + node = ''; + if(!sessionid) + sessionid = ''; + + // We generate the buttons code + var buttonsCode = '
'; + + if(action == 'submit') { + if((target == 'adhoc') && (type == 'command')) { + buttonsCode += '' + _e("Submit") + ''; + + // When keyup on one text input + $(pathID + ' input').keyup(function(e) { + if(e.keyCode == 13) { + sendDataForm(type, 'execute', 'submit', id, xid, node, sessionid, target); + + return false; + } + }); + } + + else { + buttonsCode += '' + _e("Submit") + ''; + + // When keyup on one text input + $(pathID + ' input').keyup(function(e) { + if(e.keyCode == 13) { + sendDataForm(type, 'submit', 'submit', id, xid, node, sessionid, target); + + return false; + } + }); + } + } + + if((action == 'submit') && (type != 'subscribe') && (type != 'search')) + buttonsCode += '' + _e("Cancel") + ''; + + if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery')) + buttonsCode += '' + _e("Close") + ''; + + if((action == 'back') && ((target == 'welcome') || (target == 'directory'))) + buttonsCode += '' + _e("Previous") + ''; + + if((action == 'back') && (target == 'adhoc')) + buttonsCode += '' + _e("Previous") + ''; + + buttonsCode += '
'; + + // We display the buttons code + $(pathID).append(buttonsCode); + + // If no submit link, lock the form + if(!exists(pathID + ' a.submit')) + $(pathID + ' input, ' + pathID + ' textarea').attr('readonly', true); +} + +// Handles the MUC dataform +function handleDataFormMuc(iq) { + handleErrorReply(iq); + handleDataFormContent(iq, 'muc'); +} + +// Handles the browse dataform +function handleDataFormBrowse(iq) { + handleErrorReply(iq); + handleDataFormContent(iq, 'browse'); +} + +// Handles the command dataform +function handleDataFormCommand(iq) { + handleErrorReply(iq); + handleDataFormContent(iq, 'command'); +} + +// Handles the subscribe dataform +function handleDataFormSubscribe(iq) { + handleErrorReply(iq); + handleDataFormContent(iq, 'subscribe'); +} + +// Handles the search dataform +function handleDataFormSearch(iq) { + handleErrorReply(iq); + handleDataFormContent(iq, 'search'); +} + +// Handles the dataform content +function handleDataFormContent(iq, type) { + // Get the ID + var sID = iq.getID(); + + // Get the target + var splitted = sID.split('-'); + var target = splitted[0]; + var sessionID = target + '-' + splitted[1]; + var from = fullXID(getStanzaFrom(iq)); + var pathID = '#' + target + ' .results[data-session=' + sessionID + ']'; + + // If an error occured + if(!iq || (iq.getType() != 'result')) + noResultDataForm(pathID); + + // If we got something okay + else { + var handleXML = iq.getNode(); + + if(type == 'browse') { + if($(handleXML).find('item').attr('jid')) { + // Get the query node + var queryNode = $(handleXML).find('query').attr('node'); + + $(handleXML).find('item').each(function() { + // We parse the received xml + var itemHost = $(this).attr('jid'); + var itemNode = $(this).attr('node'); + var itemName = $(this).attr('name'); + var itemHash = hex_md5(itemHost); + + // Node + if(itemNode) + $(pathID).append( + '
' + + '
' + itemNode.htmlEnc() + '
' + + '
' + ); + + // Item + else if(queryNode && itemName) + $(pathID).append( + '
' + + '
' + itemName.htmlEnc() + '
' + + '
' + ); + + // Item with children + else { + // We display the waiting element + $(pathID + ' .disco-wait .disco-category-title').after( + '
' + + '
' + + '
' + itemHost + '
' + + '
' + _e("Requesting this service...") + '
' + + '
' + ); + + // We display the category + $('#' + target + ' .disco-wait').show(); + + // We ask the server what's the service type + getDataFormType(itemHost, itemNode, sessionID); + } + }); + } + + // Else, there are no items for this query + else + noResultDataForm(pathID); + } + + else if((type == 'muc') || (type == 'search') || (type == 'subscribe') || ((type == 'command') && $(handleXML).find('command').attr('xmlns'))) { + // Get some values + var xCommand = $(handleXML).find('command'); + var bNode = xCommand.attr('node'); + var bSession = xCommand.attr('sessionid'); + var bStatus = xCommand.attr('status'); + var xRegister = $(handleXML).find('query[xmlns=' + NS_REGISTER + ']').text(); + var xElement = $(handleXML).find('x'); + + // Search done + if((xElement.attr('type') == 'result') && (type == 'search')) { + var bPath = pathID; + + // Display the result + $(handleXML).find('item').each(function() { + var bXID = $(this).find('field[var=jid] value:first').text(); + var bName = $(this).find('field[var=fn] value:first').text(); + var bCountry = $(this).find('field[var=ctry] value:first').text(); + var dName = bName; + + // Override "undefined" value + if(!bXID) + bXID = ''; + if(!bName) + bName = _e("Unknown name"); + if(!bCountry) + bCountry = _e("Unknown country"); + + // User hash + var bHash = hex_md5(bXID); + + // HTML code + var bHTML = '
' + + '
' + + '' + + '
' + + '
' + bName + '
' + + '
' + bCountry + '
' + + '
' + bXID + '
' + + '
'; + + // The buddy is not in our buddy list? + if(!exists('#buddy-list .buddy[data-xid=' + escape(bXID) + ']')) + bHTML += '' + _e("Add") + ''; + + // Chat button, if not in welcome/directory mode + if(target == 'discovery') + bHTML += '' + _e("Chat") + ''; + + // Close the HTML element + bHTML += '
'; + + $(bPath).append(bHTML); + + // Click events + $(bPath + ' .' + bHash + ' a').click(function() { + // Buddy add + if($(this).is('.one-add')) { + $(this).hide(); + + addThisContact(bXID, dName); + } + + // Buddy chat + if($(this).is('.one-chat')) { + if(target == 'discovery') + closeDiscovery(); + + checkChatCreate(bXID , 'chat', '', '', dName); + } + + return false; + }); + + // Get the user's avatar + if(bXID) + getAvatar(bXID, 'cache', 'true', 'forget'); + }); + + // No result? + if(!$(handleXML).find('item').size()) + noResultDataForm(pathID); + + // Previous button + buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID); + } + + // Command to complete + else if(xElement.attr('xmlns') || ((type == 'subscribe') && xRegister)) { + // We display the elements + fillDataForm(handleXML, sessionID); + + // We display the buttons + if(bStatus != 'completed') + buttonsDataForm(type, 'submit', sessionID, from, bNode, bSession, target, pathID); + else + buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID); + } + + // Command completed or subscription done + else if(((bStatus == 'completed') && (type == 'command')) || (!xRegister && (type == 'subscribe'))) { + // Display the good text + var cNote = $(xCommand).find('note'); + + // Any note? + if(cNote.size()) { + cNote.each(function() { + $(pathID).append( + '
' + $(this).text().htmlEnc() + '
' + ); + }); + } + + // Default text + else + $(pathID).append('
' + _e("Your form has been sent.") + '
'); + + // Display the back button + buttonsDataForm(type, 'back', sessionID, from, '', '', target, pathID); + + // Add the gateway to our roster if subscribed + if(type == 'subscribe') + addThisContact(from); + } + + // Command canceled + else if((bStatus == 'canceled') && (type == 'command')) { + if(target == 'discovery') + startDiscovery(); + else if(target == 'adhoc') + dataForm(from, 'command', '', '', 'adhoc'); + } + + // No items for this query + else + noResultDataForm(pathID); + } + + else if(type == 'command') { + if($(handleXML).find('item').attr('jid')) { + // We display the elements + $(handleXML).find('item').each(function() { + // We parse the received xml + var itemHost = $(this).attr('jid'); + var itemNode = $(this).attr('node'); + var itemName = $(this).attr('name'); + var itemHash = hex_md5(itemHost); + + // We display the waiting element + $(pathID).prepend( + '
' + + '
' + itemName + '
' + + '
»
' + + '
' + ); + }); + } + + // Else, there are no items for this query + else + noResultDataForm(pathID); + } + } + + // Focus on the first input + $(document).oneTime(10, function() { + $(pathID + ' input:visible:first').focus(); + }); + + // Hide the wait icon + $('#' + target + ' .wait').hide(); +} + +// Fills the dataform elements +function fillDataForm(xml, id) { + /* REF: http://xmpp.org/extensions/xep-0004.html */ + + // Initialize new vars + var target = id.split('-')[0]; + var pathID = '#' + target + ' .results[data-session=' + id + ']'; + var selector, is_dataform; + + // Is it a dataform? + if($(xml).find('x[xmlns=' + NS_XDATA + ']').size()) + is_dataform = true; + else + is_dataform = false; + + // Determines the good selector to use + if(is_dataform) + selector = $(xml).find('x[xmlns=' + NS_XDATA + ']'); + else + selector = $(xml); + + // Form title + selector.find('title').each(function() { + $(pathID).append( + '
' + $(this).text().htmlEnc() + '
' + ); + }); + + // Form instructions + selector.find('instructions').each(function() { + $(pathID).append( + '
' + $(this).text().htmlEnc() + '
' + ); + }); + + // Register? + if(!is_dataform) { + // Items to detect + var reg_names = [_e("Nickname"), _e("Name"), _e("Password"), _e("E-mail")]; + var reg_ids = ['username', 'name', 'password', 'email']; + + // Append these inputs + for(a in reg_names) { + selector.find(reg_ids[a]).each(function() { + $(pathID).append( + '
' + + '' + + '' + + '
' + ); + }); + } + + return false; + } + + // Dataform? + selector.find('field').each(function() { + // We parse the received xml + var type = $(this).attr('type'); + var label = $(this).attr('label'); + var field = $(this).attr('var'); + var value = $(this).find('value:first').text(); + var required = ''; + + // No value? + if(!field) + return; + + // Required input? + if($(this).find('required').size()) + required = ' required=""'; + + // Compatibility fix + if(!label) + label = field; + + if(!type) + type = ''; + + // Generate some values + var input; + var hideThis = ''; + + // Fixed field + if(type == 'fixed') + $(pathID).append('
' + value.htmlEnc() + '
'); + + else { + // Hidden field + if(type == 'hidden') { + hideThis = ' style="display: none;"'; + input = ''; + } + + // Boolean field + else if(type == 'boolean') { + var checked; + + if(value == '1') + checked = 'checked'; + else + checked = ''; + + input = ''; + } + + // List-single/list-multi field + else if((type == 'list-single') || (type == 'list-multi')) { + var multiple = ''; + + // Multiple options? + if(type == 'list-multi') + multiple = ' multiple=""'; + + // Append the select field + input = ''; + } + + // Text-multi field + else if(type == 'text-multi') + input = ''; + + // JID-multi field + else if(type == 'jid-multi') { + // Put the XID into an array + var xid_arr = []; + + $(this).find('value').each(function() { + var cValue = $(this).text(); + + if(!existArrayValue(xid_arr, cValue)) + xid_arr.push(cValue); + }); + + // Sort the array + xid_arr.sort(); + + // Create the input + var xid_value = ''; + + if(xid_arr.length) { + for(i in xid_arr) { + // Any pre-value + if(xid_value) + xid_value += ', '; + + // Add the current XID + xid_value += xid_arr[i]; + } + } + + input = ''; + } + + // Other stuffs that are similar + else { + // Text-single field + var iType = 'text'; + + // Text-private field + if(type == 'text-private') + iType = 'password'; + + // JID-single field + else if(type == 'jid-single') + iType = 'email'; + + input = ''; + } + + // Append the HTML markup for this field + $(pathID).append( + '
' + + '' + + input + + '
' + ); + } + }); + + return false; +} + +// Gets the dataform type +function getDataFormType(host, node, id) { + var iq = new JSJaCIQ(); + iq.setID(id + '-' + genID()); + iq.setTo(host); + iq.setType('get'); + + var iqQuery = iq.setQuery(NS_DISCO_INFO); + + if(node) + iqQuery.setAttribute('node', node); + + con.send(iq, handleThisBrowse); +} + +// Handles the browse stanza +function handleThisBrowse(iq) { + /* REF: http://xmpp.org/registrar/disco-categories.html */ + + var id = iq.getID(); + var splitted = id.split('-'); + var target = splitted[0]; + var sessionID = target + '-' + splitted[1]; + var from = fullXID(getStanzaFrom(iq)); + var hash = hex_md5(from); + var handleXML = iq.getQuery(); + var pathID = '#' + target + ' .results[data-session=' + sessionID + ']'; + + // We first remove the waiting element + $(pathID + ' .disco-wait .' + hash).remove(); + + if($(handleXML).find('identity').attr('type')) { + var category = $(handleXML).find('identity').attr('category'); + var type = $(handleXML).find('identity').attr('type'); + var named = $(handleXML).find('identity').attr('name'); + + if(named) + gName = named; + else + gName = ''; + + var one, two, three, four, five; + + // Get the features that this entity supports + var findFeature = $(handleXML).find('feature'); + + for(i in findFeature) { + var current = findFeature.eq(i).attr('var'); + + switch(current) { + case NS_SEARCH: + one = 1; + break; + + case NS_MUC: + two = 1; + break; + + case NS_REGISTER: + three = 1; + break; + + case NS_COMMANDS: + four = 1; + break; + + case NS_DISCO_ITEMS: + five = 1; + break; + + default: + break; + } + } + + var buttons = Array(one, two, three, four, five); + + // We define the toolbox links depending on the supported features + var tools = ''; + var aTools = Array('search', 'join', 'subscribe', 'command', 'browse'); + var bTools = Array(_e("Search"), _e("Join"), _e("Subscribe"), _e("Command"), _e("Browse")); + + for(i in buttons) { + if(buttons[i]) + tools += ''; + } + + // As defined in the ref, we detect the type of each category to put an icon + switch(category) { + case 'account': + case 'auth': + case 'automation': + case 'client': + case 'collaboration': + case 'component': + case 'conference': + case 'directory': + case 'gateway': + case 'headline': + case 'hierarchy': + case 'proxy': + case 'pubsub': + case 'server': + case 'store': + break; + + default: + category = 'others'; + } + + // We display the item we found + $(pathID + ' .disco-' + category + ' .disco-category-title').after( + '
' + + '
' + + '
' + from + '
' + + '
' + gName + '
' + + '
' + tools + '
' + + '
' + ); + + // We display the category + $(pathID + ' .disco-' + category).show(); + } + + else { + $(pathID + ' .disco-others .disco-category-title').after( + '
' + + '
' + + '
' + from + '
' + + '
' + _e("Service offline or broken") + '
' + + '
' + ); + + // We display the category + $(pathID + ' .disco-others').show(); + } + + // We hide the waiting stuffs if there's no remaining loading items + if(!$(pathID + ' .disco-wait .' + target + '-oneresult').size()) + $(pathID + ' .disco-wait, #' + target + ' .wait').hide(); +} + +// Cleans the current data-form popup +function cleanDataForm(target) { + if(target == 'discovery') + cleanDiscovery(); + else + $('#' + target + ' div.results').empty(); +} + +// Displays the no result indicator +function noResultDataForm(path) { + $(path).prepend('

' + _e("Sorry, but the entity didn't return any result!") + '

'); +} diff --git a/sources/addons/jappixmini/jappix/js/datastore.js b/sources/addons/jappixmini/jappix/js/datastore.js new file mode 100644 index 00000000..b818b301 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/datastore.js @@ -0,0 +1,209 @@ +/* + +Jappix - An open social platform +These are the temporary/persistent data store functions + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 23/06/11 + +*/ + +// Temporary: returns whether it is available or not +function hasDB() { + if(window.sessionStorage) + return true; + + return false; +} + +// Temporary: used to read a database entry +function getDB(type, id) { + try { + return sessionStorage.getItem(type + '_' + id); + } + + catch(e) { + logThis('Error while getting a temporary database entry (' + type + ' -> ' + id + '): ' + e, 1); + + return null; + } +} + +// Temporary: used to update a database entry +function setDB(type, id, value) { + try { + sessionStorage.setItem(type + '_' + id, value); + + return true; + } + + catch(e) { + logThis('Error while writing a temporary database entry (' + type + ' -> ' + id + '): ' + e, 1); + + return false; + } +} + +// Temporary: used to remove a database entry +function removeDB(type, id) { + try { + sessionStorage.removeItem(type + '_' + id); + + return true; + } + + catch(e) { + logThis('Error while removing a temporary database entry (' + type + ' -> ' + id + '): ' + e, 1); + + return false; + } +} + +// Temporary: used to check a database entry exists +function existDB(type, id) { + var read = getDB(type, id); + + if(read != null) + return true; + + return false; +} + +// Temporary: used to clear all the database +function resetDB() { + try { + sessionStorage.clear(); + + logThis('Temporary database cleared.', 3); + + return true; + } + + catch(e) { + logThis('Error while clearing temporary database: ' + e, 1); + + return false; + } +} + +// Persistent: returns whether it is available or not +function hasPersistent() { + if(window.localStorage) + return true; + + return false; +} + +// Persistent: used to read a database entry +function getPersistent(type, id) { + try { + return localStorage.getItem(type + '_' + id); + } + + catch(e) { + logThis('Error while getting a persistent database entry (' + type + ' -> ' + id + '): ' + e, 1); + + return null; + } +} + +// Persistent: used to update a database entry +function setPersistent(type, id, value) { + try { + localStorage.setItem(type + '_' + id, value); + + return true; + } + + // Database might be full + catch(e) { + logThis('Retrying: could not write a persistent database entry (' + type + ' -> ' + id + '): ' + e, 2); + + // Flush it! + flushPersistent(); + + // Set the item again + try { + localStorage.setItem(type + '_' + id, value); + + return true; + } + + // New error! + catch(e) { + logThis('Aborted: error while writing a persistent database entry (' + type + ' -> ' + id + '): ' + e, 1); + + return false; + } + } +} + +// Persistent: used to remove a database entry +function removePersistent(type, id) { + try { + localStorage.removeItem(type + '_' + id); + + return true; + } + + catch(e) { + logThis('Error while removing a persistent database entry (' + type + ' -> ' + id + '): ' + e, 1); + + return false; + } +} + +// Persistent: used to check a database entry exists +function existPersistent(type, id) { + var read = getPersistent(type, id); + + if(read != null) + return true; + + return false; +} + +// Persistent: used to clear all the database +function resetPersistent() { + try { + localStorage.clear(); + + logThis('Persistent database cleared.', 3); + + return true; + } + + catch(e) { + logThis('Error while clearing persistent database: ' + e, 1); + + return false; + } +} + +// Persistent: used to flush the database +function flushPersistent() { + try { + // Get the stored session entry + var session = getPersistent('session', 1); + + // Clear the persistent database + localStorage.clear(); + + // Restaure the stored session entry + if(session) + setPersistent('session', 1, session); + + logThis('Persistent database flushed.', 3); + + return true; + } + + catch(e) { + logThis('Error while flushing persistent database: ' + e, 1); + + return false; + } +} diff --git a/sources/addons/jappixmini/jappix/js/date.js b/sources/addons/jappixmini/jappix/js/date.js new file mode 100644 index 00000000..adbe01c8 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/date.js @@ -0,0 +1,214 @@ +/* + +Jappix - An open social platform +These are the date related JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 17/08/11 + +*/ + +// Gets a stamp from a date +function extractStamp(date) { + return Math.round(date.getTime() / 1000); +} + +// Gets the time from a date +function extractTime(date) { + return date.toLocaleTimeString(); +} + +// Gets the actual date stamp +function getTimeStamp() { + return extractStamp(new Date()); +} + +// Gets the last user activity in seconds +var LAST_ACTIVITY = 0; + +function getLastActivity() { + // Last activity not yet initialized? + if(LAST_ACTIVITY == 0) + return 0; + + return getTimeStamp() - LAST_ACTIVITY; +} + +// Gets the last user available presence in seconds +var PRESENCE_LAST_ACTIVITY = 0; + +function getPresenceLast() { + // Last presence stamp not yet initialized? + if(PRESENCE_LAST_ACTIVITY == 0) + return 0; + + return getTimeStamp() - PRESENCE_LAST_ACTIVITY; +} + +// Generates the time for XMPP +function getXMPPTime(location) { + /* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */ + + // Initialize + var jInit = new Date(); + var year, month, day, hours, minutes, seconds; + + // Gets the UTC date + if(location == 'utc') { + year = jInit.getUTCFullYear(); + month = jInit.getUTCMonth(); + day = jInit.getUTCDate(); + hours = jInit.getUTCHours(); + minutes = jInit.getUTCMinutes(); + seconds = jInit.getUTCSeconds(); + } + + // Gets the local date + else { + year = jInit.getFullYear(); + month = jInit.getMonth(); + day = jInit.getDate(); + hours = jInit.getHours(); + minutes = jInit.getMinutes(); + seconds = jInit.getSeconds(); + } + + // Generates the date string + var jDate = year + '-'; + jDate += padZero(month + 1) + '-'; + jDate += padZero(day) + 'T'; + jDate += padZero(hours) + ':'; + jDate += padZero(minutes) + ':'; + jDate += padZero(seconds) + 'Z'; + + // Returns the date string + return jDate; +} + +// Generates then human time +function getCompleteTime() { + var init = new Date(); + var time = padZero(init.getHours()) + ':'; + time += padZero(init.getMinutes()) + ':'; + time += padZero(init.getSeconds()); + + return time; +} + +// Gets the TZO of a date +function getDateTZO() { + // Get the date + var date = new Date(); + var offset = date.getTimezoneOffset(); + + // Default vars + var sign = ''; + var hours = 0; + var minutes = 0; + + // Process a neutral offset + if(offset < 0) { + offset = offset * -1; + sign = '+'; + } + + // Get the values + var n_date = new Date(offset * 60 * 1000); + hours = n_date.getHours() - 1; + minutes = n_date.getMinutes(); + + // Process the TZO + tzo = sign + padZero(hours) + ':' + padZero(minutes); + + // Return the processed value + return tzo; +} + +// Parses a XMPP date (yyyy-mm-dd, hh-mm-ss) into an human-readable one +function parseDate(to_parse) { + var date = Date.jab2date(to_parse); + var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')'; + + return parsed; +} + +// Parses a XMPP date (yyyy-mm-dd) into an human-readable one +function parseDay(to_parse) { + var date = Date.jab2date(to_parse); + var parsed = date.toLocaleDateString(); + + return parsed; +} + +// Parses a XMPP date (hh-mm-ss) into an human-readable one +function parseTime(to_parse) { + var date = Date.jab2date(to_parse); + var parsed = date.toLocaleTimeString(); + + return parsed; +} + +// Parses a XMPP date stamp into a relative one +function relativeDate(to_parse) { + // Get the current date + var current_date = Date.jab2date(getXMPPTime('utc')); + var current_day = current_date.getDate(); + var current_stamp = current_date.getTime(); + + // Parse the given date + var old_date = Date.jab2date(to_parse); + var old_day = old_date.getDate(); + var old_stamp = old_date.getTime(); + var old_time = old_date.toLocaleTimeString(); + + // Get the day number between the two dates + var days = Math.round((current_stamp - old_stamp) / 86400000); + + // Invalid date? + if(isNaN(old_stamp) || isNaN(days)) + return getCompleteTime(); + + // Is it today? + if(current_day == old_day) + return old_time; + + // It is yesterday? + if(days <= 1) + return _e("Yesterday") + ' - ' + old_time; + + // Is it less than a week ago? + if(days <= 7) + return printf(_e("%s days ago"), days) + ' - ' + old_time; + + // Another longer period + return old_date.toLocaleDateString() + ' - ' + old_time; +} + +// Reads a message delay +function readMessageDelay(node) { + try { + // Initialize + var delay, d_delay; + + // Read the delay + d_delay = jQuery(node).find('delay[xmlns=' + NS_URN_DELAY + ']:first').attr('stamp'); + + // New delay (valid XEP) + if(d_delay) + delay = d_delay; + + // Old delay (obsolete XEP!) + else { + // Try to read the old-school delay + var x_delay = jQuery(node).find('x[xmlns=' + NS_DELAY + ']:first').attr('stamp'); + + if(x_delay) + delay = x_delay.replace(/^(\w{4})(\w{2})(\w{2})T(\w{2}):(\w{2}):(\w{2})Z?(\S+)?/, '$1-$2-$3T$4:$5:$6Z$7'); + } + + return delay; + } catch(e) {} +} diff --git a/sources/addons/jappixmini/jappix/js/directory.js b/sources/addons/jappixmini/jappix/js/directory.js new file mode 100644 index 00000000..ebe1a570 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/directory.js @@ -0,0 +1,87 @@ +/* + +Jappix - An open social platform +These are the directory JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 03/03/11 + +*/ + +// Opens the directory popup +function openDirectory() { + // Popup HTML content + var html = + '
' + _e("User directory") + '
' + + + '
' + + '
' + + '
' + _e("Server to query") + '
' + + + '' + + '
' + + + '
' + + '
' + + + '
' + + '
' + + + '' + _e("Close") + '' + + '
'; + + // Create the popup + createPopup('directory', html); + + // Associate the events + launchDirectory(); + + // Start a search! + startDirectory(); + + return false; +} + +// Quits the directory popup +function closeDirectory() { + // Destroy the popup + destroyPopup('directory'); + + return false; +} + +// Launches a directory search +function startDirectory() { + // Get the server to query + var server = $('#directory .directory-server-input').val(); + + // Launch the search! + dataForm($('#directory .directory-server-input').val(), 'search', '', '', 'directory'); + + logThis('Directory search launched: ' + server); + + return false; +} + +// Plugin launcher +function launchDirectory() { + // Click event + $('#directory .bottom .finish').click(closeDirectory); + + // Keyboard event + $('#directory .directory-server-input').keyup(function(e) { + if(e.keyCode == 13) { + // No value? + if(!$(this).val()) + $(this).val(HOST_VJUD); + + // Start the directory search + startDirectory(); + + return false; + } + }); +} diff --git a/sources/addons/jappixmini/jappix/js/discovery.js b/sources/addons/jappixmini/jappix/js/discovery.js new file mode 100644 index 00000000..867037b2 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/discovery.js @@ -0,0 +1,169 @@ +/* + +Jappix - An open social platform +These are the discovery JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 03/03/11 + +*/ + +// Opens the discovery popup +function openDiscovery() { + // Popup HTML content + var html = + '
' + _e("Service discovery") + '
' + + + '
' + + '
' + + '
' + _e("Server to query") + '
' + + + '' + + '
' + + + '
' + + '' + + + '
' + + '

' + _e("Authentications") + '

' + + '
' + + + '
' + + '

' + _e("Automation") + '

' + + '
' + + + '
' + + '

' + _e("Clients") + '

' + + '
' + + + '
' + + '

' + _e("Collaboration") + '

' + + '
' + + + '
' + + '

' + _e("Components") + '

' + + '
' + + + '
' + + '

' + _e("Rooms") + '

' + + '
' + + + '
' + + '

' + _e("Directories") + '

' + + '
' + + + '
' + + '

' + _e("Gateways") + '

' + + '
' + + + '
' + + '

' + _e("News") + '

' + + '
' + + + '
' + + '

' + _e("Hierarchy") + '

' + + '
' + + + '
' + + '

' + _e("Proxies") + '

' + + '
' + + + '
' + + '

' + _e("Publication/Subscription") + '

' + + '
' + + + '
' + + '

' + _e("Server") + '

' + + '
' + + + '
' + + '

' + _e("Storage") + '

' + + '
' + + + '
' + + '

' + _e("Others") + '

' + + '
' + + + '
' + + '

' + _e("Loading") + '

' + + '
' + + '
' + + '
' + + + '
' + + '
' + + + '' + _e("Close") + '' + + '
'; + + // Create the popup + createPopup('discovery', html); + + // Associate the events + launchDiscovery(); + + // We request a disco to the default server + startDiscovery(); + + return false; +} + +// Quits the discovery popup +function closeDiscovery() { + // Destroy the popup + destroyPopup('discovery'); + + return false; +} + +// Launches a discovery +function startDiscovery() { + /* REF: http://xmpp.org/extensions/xep-0030.html */ + + // We get the server to query + var discoServer = $('#discovery .disco-server-input').val(); + + // We launch the items query + dataForm(discoServer, 'browse', '', '', 'discovery'); + + logThis('Service discovery launched: ' + discoServer); + + return false; +} + +// Cleans the discovery results +function cleanDiscovery() { + // We remove the results + $('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove(); + + // We clean the user info + $('#discovery .disco-server-info').text(''); + + // We hide the wait icon, the no result alert and the results + $('#discovery .wait, #discovery .disco-category').hide(); +} + +// Plugin launcher +function launchDiscovery() { + // Click event + $('#discovery .bottom .finish').click(closeDiscovery); + + // Keyboard event + $('#discovery .disco-server-input').keyup(function(e) { + if(e.keyCode == 13) { + // No value? + if(!$(this).val()) + $(this).val(HOST_MAIN); + + // Start the discovery + startDiscovery(); + + return false; + } + }); +} diff --git a/sources/addons/jappixmini/jappix/js/error.js b/sources/addons/jappixmini/jappix/js/error.js new file mode 100644 index 00000000..c16ca2a5 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/error.js @@ -0,0 +1,139 @@ +/* + +Jappix - An open social platform +These are the error functions for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 02/04/11 + +*/ + +// Shows the given error output +function showError(condition, reason, type) { + // Enough data to output the error + if(condition || reason) { + // Initialize the error text + var eText = ''; + + // Any error condition + if(condition) + eText += condition; + + // Any error type + if(type && eText) + eText += ' (' + type + ')'; + + // Any error reason + if(reason) { + if(eText) + eText += ' - '; + + eText += reason; + } + + // We reveal the error + openThisError(1); + + // Create the error text + $('#board .one-board.error[data-id=1] span').text(eText); + } + + // Not enough data to output the error: output a generic board + else + openThisError(2); +} + +// Handles the error from a packet and return true if any error +function handleError(packet) { + /* REF: http://xmpp.org/extensions/xep-0086.html */ + + // Initialize + var type, code, reason, condition; + var node = $(packet); + + // First level error (connection error) + if(node.is('error')) { + // Get the value + code = node.attr('code'); + + // Specific error reason + switch(code) { + case '401': + reason = _e("Authorization failed"); + break; + + case '409': + reason = _e("Registration failed, please choose a different username"); + break; + + case '503': + reason = _e("Service unavailable"); + break; + + case '500': + reason = _e("Internal server error, try later"); + break; + + default: + reason = node.find('text').text(); + break; + } + + // Remove the general wait item (security) + removeGeneralWait(); + + // Show reconnect pane + if(CURRENT_SESSION && CONNECTED) { + // Anonymous? + if(isAnonymous()) + createReconnect('anonymous'); + else + createReconnect('normal'); + } + + // Show the homepage (security) + else if(!CURRENT_SESSION || !CONNECTED) { + $('#home').show(); + pageTitle('home'); + } + + // Still connected? (security) + if(isConnected()) + con.disconnect(); + + logThis('First level error received.', 1); + } + + // Second level error (another error) + else if(node.find('error').size()) { + type = node.find('error').attr('type'); + reason = node.find('error text').text(); + condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' '); + + logThis('Second level error received.', 1); + } + + // No error + else + return false; + + // Show the error board + showError(condition, reason, type); + + // Return there's an error + return true; +} + +// Handles the error reply of a packet +function handleErrorReply(packet) { + return handleError(packet.getNode()); +} + +// Handles the error reply for a message +function handleMessageError(packet) { + if(!handleErrorReply(packet)) + handleMessage(packet); +} diff --git a/sources/addons/jappixmini/jappix/js/favorites.js b/sources/addons/jappixmini/jappix/js/favorites.js new file mode 100644 index 00000000..69a042e8 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/favorites.js @@ -0,0 +1,537 @@ +/* + +Jappix - An open social platform +These are the favorites JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 23/06/11 + +*/ + +// Opens the favorites popup +function openFavorites() { + // Popup HTML content + var html = + '
' + _e("Manage favorite rooms") + '
' + + + '
' + + '
' + + '
' + + '
' + + + _e("Change favorites") + + '
' + + + '' + + '
' + + + '
' + + '
' + + '
' + + '
' + _e("Select a favorite") + '
' + + + '' + + '
' + + + '
' + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '
' + + '' + + + '' + + '
' + + + '' + + '
' + + '
' + + + '' + + '
' + + '
' + + + '
' + + '
' + + + '' + _e("Close") + '' + + '
'; + + // Create the popup + createPopup('favorites', html); + + // Load the favorites + loadFavorites(); + + // Associate the events + launchFavorites(); +} + +// Resets the favorites elements +function resetFavorites() { + var path = '#favorites '; + + $(path + '.wait, ' + path + '.fedit-terminate').hide(); + $(path + '.fedit-add').show(); + $(path + '.fsearch-oneresult').remove(); + $(path + 'input').val(''); + $(path + '.please-complete').removeClass('please-complete'); + $(path + '.fedit-nick').val(getNick()); + $(path + '.fsearch-head-server, ' + path + '.fedit-server').val(HOST_MUC); + $(path + '.fedit-autojoin').attr('checked', false); +} + +// Quits the favorites popup +function quitFavorites() { + // Destroy the popup + destroyPopup('favorites'); + + return false; +} + +// Adds a room to the favorites +function addThisFavorite(roomXID, roomName) { + // Button path + var button = '#favorites .fsearch-results div[data-xid=' + escape(roomXID) + '] a.one-button'; + + // Add a remove button instead of the add one + $(button + '.add').replaceWith('' + _e("Remove") + ''); + + // Click event + $(button + '.remove').click(function() { + return removeThisFavorite(roomXID, roomName); + }); + + // Hide the add button in the (opened?) groupchat + $('#' + hex_md5(roomXID) + ' .tools-add').hide(); + + // Add the database entry + displayFavorites(roomXID, explodeThis(' (', roomName, 0), getNick(), '0', ''); + + // Publish the favorites + favoritePublish(); + + return false; +} + +// Removes a room from the favorites +function removeThisFavorite(roomXID, roomName) { + // Button path + var button = '#favorites .fsearch-results div[data-xid=' + escape(roomXID) + '] a.one-button'; + + // Add a remove button instead of the add one + $(button + '.remove').replaceWith('' + _e("Add") + ''); + + // Click event + $(button + '.add').click(function() { + return addThisFavorite(roomXID, roomName); + }); + + // Show the add button in the (opened?) groupchat + $('#' + hex_md5(roomXID) + ' .tools-add').show(); + + // Remove the favorite + removeFavorite(roomXID, true); + + // Publish the favorites + favoritePublish(); + + return false; +} + +// Edits a favorite +function editFavorite() { + // Path to favorites + var favorites = '#favorites .'; + + // Reset the favorites + resetFavorites(); + + // Show the edit/remove button, hide the others + $(favorites + 'fedit-terminate').hide(); + $(favorites + 'fedit-edit').show(); + $(favorites + 'fedit-remove').show(); + + // We retrieve the values + var xid = $(favorites + 'fedit-head-select').val(); + var data = XMLFromString(getDB('favorites', xid)); + + // If this is not the default room + if(xid != 'none') { + // We apply the values + $(favorites + 'fedit-title').val($(data).find('name').text()); + $(favorites + 'fedit-nick').val($(data).find('nick').text()); + $(favorites + 'fedit-chan').val(getXIDNick(xid)); + $(favorites + 'fedit-server').val(getXIDHost(xid)); + $(favorites + 'fedit-password').val($(data).find('password').text()); + + if($(data).find('autojoin').text() == '1') + $(favorites + 'fedit-autojoin').attr('checked', true); + } + + else + resetFavorites(); +} + +// Adds a favorite +function addFavorite() { + // Path to favorites + var favorites = '#favorites .'; + + // We reset the inputs + $(favorites + 'fedit-title, ' + favorites + 'fedit-nick, ' + favorites + 'fedit-chan, ' + favorites + 'fedit-server, ' + favorites + 'fedit-password').val(''); + + // Show the add button, hide the others + $(favorites + 'fedit-terminate').hide(); + $(favorites + 'fedit-add').show(); +} + +// Terminate a favorite editing +function terminateThisFavorite(type) { + // Path to favorites + var favorites = '#favorites '; + + // We get the values of the current edited groupchat + var old_xid = $(favorites + '.fedit-head-select').val(); + + var title = $(favorites + '.fedit-title').val(); + var nick = $(favorites + '.fedit-nick').val(); + var room = $(favorites + '.fedit-chan').val(); + var server = $(favorites + '.fedit-server').val(); + var xid = room + '@' + server; + var password = $(favorites + '.fedit-password').val(); + var autojoin = '0'; + + if($(favorites + '.fedit-autojoin').filter(':checked').size()) + autojoin = '1'; + + // We check the missing values and send this if okay + if((type == 'add') || (type == 'edit')) { + if(title && nick && room && server) { + // Remove the edited room + if(type == 'edit') + removeFavorite(old_xid, true); + + // Display the favorites + displayFavorites(xid, title, nick, autojoin, password); + + // Reset the inputs + resetFavorites(); + } + + else { + $(favorites + 'input[required]').each(function() { + var select = $(this); + + if(!select.val()) + $(document).oneTime(10, function() { + select.addClass('please-complete').focus(); + }); + else + select.removeClass('please-complete'); + }); + } + } + + // Must remove a favorite? + else if(type == 'remove') { + removeFavorite(old_xid, true); + + // Reset the inputs + resetFavorites(); + } + + // Publish the new favorites + favoritePublish(); + + logThis('Action on this bookmark: ' + room + '@' + server + ' / ' + type, 3); + + return false; +} + +// Removes a favorite +function removeFavorite(xid, database) { + // We remove the target favorite everywhere needed + $('.buddy-conf-groupchat-select option[value=' + xid + ']').remove(); + $('.fedit-head-select option[value=' + xid + ']').remove(); + + // Must remove it from database? + if(database) + removeDB('favorites', xid); +} + +// Sends a favorite to the XMPP server +function favoritePublish() { + var iq = new JSJaCIQ(); + iq.setType('set'); + + var query = iq.setQuery(NS_PRIVATE); + var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_BOOKMARKS})); + + // We generate the XML + for(var i = 0; i < sessionStorage.length; i++) { + // Get the pointer values + var current = sessionStorage.key(i); + + // If the pointer is on a stored favorite + if(explodeThis('_', current, 0) == 'favorites') { + var data = XMLFromString(sessionStorage.getItem(current)); + var xid = $(data).find('xid').text(); + var rName = $(data).find('name').text(); + var nick = $(data).find('nick').text(); + var password = $(data).find('password').text(); + var autojoin = $(data).find('autojoin').text(); + + // We create the node for this groupchat + var item = storage.appendChild(iq.buildNode('conference', {'name': rName, 'jid': xid, 'autojoin': autojoin, xmlns: NS_BOOKMARKS})); + item.appendChild(iq.buildNode('nick', {xmlns: NS_BOOKMARKS}, nick)); + + if(password) + item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password)); + + logThis('Bookmark sent: ' + xid, 3); + } + } + + con.send(iq); +} + +// Gets a list of the MUC items on a given server +function getGCList() { + var path = '#favorites .'; + var gcServer = $('.fsearch-head-server').val(); + + // We reset some things + $(path + 'fsearch-oneresult').remove(); + $(path + 'fsearch-noresults').hide(); + $(path + 'wait').show(); + + var iq = new JSJaCIQ(); + iq.setType('get'); + iq.setTo(gcServer); + + iq.setQuery(NS_DISCO_ITEMS); + + con.send(iq, handleGCList); +} + +// Handles the MUC items list +function handleGCList(iq) { + var path = '#favorites .'; + var from = fullXID(getStanzaFrom(iq)); + + if (!iq || (iq.getType() != 'result')) { + openThisError(3); + + $(path + 'wait').hide(); + + logThis('Error while retrieving the rooms: ' + from, 1); + } + + else { + var handleXML = iq.getQuery(); + + if($(handleXML).find('item').size()) { + // Initialize the HTML code + var html = ''; + + $(handleXML).find('item').each(function() { + var roomXID = $(this).attr('jid'); + var roomName = $(this).attr('name'); + + if(roomXID && roomName) { + // Escaped values + var escaped_xid = encodeOnclick(roomXID); + var escaped_name = encodeOnclick(roomName); + + // Initialize the room HTML + html += '
' + + '
' + roomName.htmlEnc() + '
' + + '' + _e("Join") + ''; + + // This room is yet a favorite + if(existDB('favorites', roomXID)) + html += '' + _e("Remove") + ''; + else + html += '' + _e("Add") + ''; + + // Close the room HTML + html += '
'; + } + }); + + // Append this code to the popup + $(path + 'fsearch-results').append(html); + } + + else + $(path + 'fsearch-noresults').show(); + + logThis('Rooms retrieved: ' + from, 3); + } + + $(path + 'wait').hide(); +} + +// Joins a groupchat from favorites +function joinFavorite(room) { + quitFavorites(); + checkChatCreate(room, 'groupchat', '', '', getXIDNick(room)); + + return false; +} + +// Displays a given favorite +function displayFavorites(xid, name, nick, autojoin, password) { + // Generate the HTML code + var html = ''; + + // Remove the existing favorite + removeFavorite(xid, false); + + // We complete the select forms + $('#buddy-list .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html); + + // We store the informations + var value = '' + xid.htmlEnc() + '' + name.htmlEnc() + '' + nick.htmlEnc() + '' + autojoin.htmlEnc() + '' + password.htmlEnc() + ''; + setDB('favorites', xid, value); +} + +// Loads the favorites for the popup +function loadFavorites() { + // Initialize the HTML code + var html = ''; + + // Read the database + for(var i = 0; i < sessionStorage.length; i++) { + // Get the pointer values + var current = sessionStorage.key(i); + + // If the pointer is on a stored favorite + if(explodeThis('_', current, 0) == 'favorites') { + var data = XMLFromString(sessionStorage.getItem(current)); + + // Add the current favorite to the HTML code + html += ''; + } + } + + // Generate specific HTML code + var favorites_bubble = '' + html; + var favorites_popup = '' + html; + + // Append the HTML code + $('#buddy-list .buddy-conf-groupchat-select').html(favorites_bubble); + $('#favorites .fedit-head-select').html(favorites_popup); +} + +// Plugin launcher +function launchFavorites() { + var path = '#favorites .'; + + // Keyboard events + $(path + 'fsearch-head-server').keyup(function(e) { + if(e.keyCode == 13) { + // No value? + if(!$(this).val()) + $(this).val(HOST_MUC); + + // Get the list + getGCList(); + } + }); + + $(path + 'fedit-line input').keyup(function(e) { + if(e.keyCode == 13) { + // Edit a favorite + if($(path + 'fedit-edit').is(':visible')) + terminateThisFavorite('edit'); + + // Add a favorite + else + terminateThisFavorite('add'); + } + }); + + // Change events + $('.fedit-head-select').change(editFavorite); + + // Click events + $(path + 'room-switcher').click(function() { + $(path + 'favorites-content').hide(); + resetFavorites(); + }); + + $(path + 'room-list').click(function() { + $(path + 'favorites-edit').show(); + }); + + $(path + 'room-search').click(function() { + $(path + 'favorites-search').show(); + getGCList(); + }); + + $(path + 'fedit-add').click(function() { + return terminateThisFavorite('add'); + }); + + $(path + 'fedit-edit').click(function() { + return terminateThisFavorite('edit'); + }); + + $(path + 'fedit-remove').click(function() { + return terminateThisFavorite('remove'); + }); + + $(path + 'bottom .finish').click(function() { + return quitFavorites(); + }); +} diff --git a/sources/addons/jappixmini/jappix/js/features.js b/sources/addons/jappixmini/jappix/js/features.js new file mode 100644 index 00000000..4944be0a --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/features.js @@ -0,0 +1,213 @@ +/* + +Jappix - An open social platform +This is the server features JS script for Jappix + +------------------------------------------------- + +License: AGPL +Author: Vanaryon +Last revision: 01/06/11 + +*/ + +// Gets the features of a server +function getFeatures() { + /* REF: http://xmpp.org/extensions/xep-0030.html */ + + // Get the main values + var to = getServer(); + var caps = con.server_caps; + var xml = null; + + // Try to get the stored data + if(caps) + xml = XMLFromString(getPersistent('caps', caps)); + + // Any stored data? + if(xml) { + handleFeatures(xml); + + logThis('Read server CAPS from cache.'); + } + + // Not stored (or no CAPS)! + else { + var iq = new JSJaCIQ(); + + iq.setTo(to); + iq.setType('get'); + iq.setQuery(NS_DISCO_INFO); + + con.send(iq, handleDiscoInfos); + + logThis('Read server CAPS from network.'); + } +} + +// Handles the features of a server +function handleFeatures(xml) { + // Selector + var selector = $(xml); + + // Markers + var pep = false; + var pubsub = false; + var archive = false; + var archive_auto = false; + var archive_manual = false; + var archive_manage = false; + var archive_pref = false; + var commands = false; + + // Scan the features + if(selector.find('identity[category=pubsub][type=pep]').size()) + pep = true; + if(selector.find('feature[var=' + NS_PUBSUB + ']').size()) + pubsub = true; + if(selector.find('feature[var=' + NS_URN_ARCHIVE + ']').size()) + archive = true; + if(selector.find('feature[var=' + NS_URN_AR_AUTO + ']').size()) + archive_auto = true; + if(selector.find('feature[var=' + NS_URN_AR_MANUAL + ']').size()) + archive_manual = true; + if(selector.find('feature[var=' + NS_URN_AR_MANAGE + ']').size()) + archive_manage = true; + if(selector.find('feature[var=' + NS_URN_AR_PREF + ']').size()) + archive_pref = true; + if(selector.find('feature[var=' + NS_COMMANDS + ']').size()) + commands = true; + + // Enable the pep elements if available + if(pep) { + // Update our database + enableFeature('pep'); + + // Get the microblog + getInitMicroblog(); + + // Get the notifications + getNotifications(); + + // Geolocate the user + geolocate(); + + // Enable microblogging send tools + waitMicroblog('sync'); + $('.postit.attach').css('display', 'block'); + + logThis('XMPP server supports PEP.', 3); + } + + // Disable microblogging send tools (no PEP!) + else { + waitMicroblog('unsync'); + + logThis('XMPP server does not support PEP.', 2); + } + + // Enable the pubsub features if available + if(pubsub) + enableFeature(NS_PUBSUB); + + // Enable the archiving features if available + if(archive) + enableFeature(NS_URN_ARCHIVE); + + // Enable the archiving sub-features if available + if(archive_pref) + enableFeature(NS_URN_AR_PREF); + if(archive_auto) + enableFeature(NS_URN_AR_AUTO); + if(archive_manual) + enableFeature(NS_URN_AR_MANUAL); + if(archive_manage) + enableFeature(NS_URN_AR_MANAGE); + + // Enable the commands features if available + if(commands) + enableFeature(NS_COMMANDS); + + // Hide the private life fieldset if nothing to show + if(!pep && !archive_pref) + $('#options fieldset.privacy').hide(); + + // Apply the features + applyFeatures('talk'); + + // Process the buddy-list height + if(pep) + adaptRoster(); + + return false; +} + +// The function to apply the features to an element +function applyFeatures(id) { + // Path to the elements + var path = '#' + id + ' .'; + + // PEP features + if(enabledPEP()) + $(path + 'pep-hidable').show(); + + // PubSub features + if(enabledPubSub()) + $(path + 'pubsub-hidable').show(); + + // Archives features + if(enabledArchives() || enabledArchives('auto') || enabledArchives('manual') || enabledArchives('manage')) { + $(path + 'archives-hidable:not(.pref)').show(); + + // Sub-feature: archives preferences + if(enabledArchives('pref')) + $(path + 'archives-hidable.pref').show(); + } + + // Commands features + if(enabledCommands()) + $(path + 'commands-hidable').show(); + + // XMPP links (browser feature) + if(navigator.registerProtocolHandler) + $(path + 'xmpplinks-hidable').show(); +} + +// Enables a feature +function enableFeature(feature) { + setDB('feature', feature, 'true'); +} + +// Checks if a feature is enabled +function enabledFeature(feature) { + if(getDB('feature', feature) == 'true') + return true; + else + return false; +} + +// Returns the XMPP server PEP support +function enabledPEP() { + return enabledFeature('pep'); +} + +// Returns the XMPP server PubSub support +function enabledPubSub() { + return enabledFeature(NS_PUBSUB); +} + +// Returns the XMPP server archives support +function enabledArchives(sub) { + var xmlns = NS_URN_ARCHIVE; + + // Any sub element sent? + if(sub) + xmlns += ':' + sub; + + return enabledFeature(xmlns); +} + +// Returns the XMPP server commands support +function enabledCommands() { + return enabledFeature(NS_COMMANDS); +} diff --git a/sources/addons/jappixmini/jappix/js/filter.js b/sources/addons/jappixmini/jappix/js/filter.js new file mode 100644 index 00000000..48e5238f --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/filter.js @@ -0,0 +1,189 @@ +/* + +Jappix - An open social platform +These are the filtering JS script for Jappix + +------------------------------------------------- + +License: AGPL +Authors: Vanaryon, Maranda +Last revision: 04/08/11 + +*/ + +// Generates a given emoticon HTML code +function emoteImage(image, text, after) { + return ' ' + encodeQuotes(text) + ' ' + after; +} + +// Filters a given message +function filterThisMessage(neutralMessage, nick, html_encode) { + var filteredMessage = neutralMessage; + + // We encode the HTML special chars + if(html_encode) + filteredMessage = filteredMessage.htmlEnc(); + + // /me command + filteredMessage = filteredMessage.replace(/((^)|((.+)(>)))(\/me )([^<]+)/, nick + ' $7') + + // We replace the smilies text into images + .replace(/(:-?@)($|\s|<)/gi, emoteImage('angry', '$1', '$2')) + .replace(/(:-?\[)($|\s|<)/gi, emoteImage('bat', '$1', '$2')) + .replace(/(\(B\))($|\s|<)/g, emoteImage('beer', '$1', '$2')) + .replace(/((:-?D)|(XD))($|\s|<)/gi, emoteImage('biggrin', '$1', '$4')) + .replace(/(:-?\$)($|\s|<)/gi, emoteImage('blush', '$1', '$2')) + .replace(/(\(Z\))($|\s|<)/g, emoteImage('boy', '$1', '$2')) + .replace(/(\(W\))($|\s|<)/g, emoteImage('brflower', '$1', '$2')) + .replace(/((<\/3)|(\(U\)))($|\s|<)/g, emoteImage('brheart', '$1', '$4')) + .replace(/(\(C\))($|\s|<)/g, emoteImage('coffee', '$1', '$2')) + .replace(/((8-\))|(\(H\)))($|\s|<)/g, emoteImage('coolglasses', '$1', '$4')) + .replace(/(:'-?\()($|\s|<)/gi, emoteImage('cry', '$1', '$2')) + .replace(/(\(%\))($|\s|<)/g, emoteImage('cuffs', '$1', '$2')) + .replace(/(\]:-?>)($|\s|<)/gi, emoteImage('devil', '$1', '$2')) + .replace(/(\(D\))($|\s|<)/g, emoteImage('drink', '$1', '$2')) + .replace(/(@}->--)($|\s|<)/gi, emoteImage('flower', '$1', '$2')) + .replace(/((:-?\/)|(:-?S))($|\s|<)/gi, emoteImage('frowning', '$1', '$4')) + .replace(/(\(X\))($|\s|<)/g, emoteImage('girl', '$1', '$2')) + .replace(/((<3)|(\(L\)))($|\s|<)/g, emoteImage('heart', '$1', '$4')) + .replace(/(\(}\))($|\s|<)/g, emoteImage('hugleft', '$1', '$2')) + .replace(/(\({\))($|\s|<)/g, emoteImage('hugright', '$1', '$2')) + .replace(/(:-?{})($|\s|<)/gi, emoteImage('kiss', '$1', '$2')) + .replace(/(\(I\))($|\s|<)/g, emoteImage('lamp', '$1', '$2')) + .replace(/(:-?3)($|\s|<)/gi, emoteImage('lion', '$1', '$2')) + .replace(/(\(E\))($|\s|<)/g, emoteImage('mail', '$1', '$2')) + .replace(/(\(S\))($|\s|<)/g, emoteImage('moon', '$1', '$2')) + .replace(/(\(8\))($|\s|<)/g, emoteImage('music', '$1', '$2')) + .replace(/((=-?O)|(:-?O))($|\s|<)/gi, emoteImage('oh', '$1', '$4')) + .replace(/(\(T\))($|\s|<)/g, emoteImage('phone', '$1', '$2')) + .replace(/(\(P\))($|\s|<)/g, emoteImage('photo', '$1', '$2')) + .replace(/(:-?!)($|\s|<)/gi, emoteImage('puke', '$1', '$2')) + .replace(/(\(@\))($|\s|<)/g, emoteImage('pussy', '$1', '$2')) + .replace(/(\(R\))($|\s|<)/g, emoteImage('rainbow', '$1', '$2')) + .replace(/(:-?\))($|\s|<)/gi, emoteImage('smile', '$1', '$2')) + .replace(/(\(\*\))($|\s|<)/g, emoteImage('star', '$1', '$2')) + .replace(/(:-?\|)($|\s|<)/gi, emoteImage('stare', '$1', '$2')) + .replace(/(\(N\))($|\s|<)/g, emoteImage('thumbdown', '$1', '$2')) + .replace(/(\(Y\))($|\s|<)/g, emoteImage('thumbup', '$1', '$2')) + .replace(/(:-?P)($|\s|<)/gi, emoteImage('tongue', '$1', '$2')) + .replace(/(:-?\()($|\s|<)/gi, emoteImage('unhappy', '$1', '$2')) + .replace(/(;-?\))($|\s|<)/gi, emoteImage('wink', '$1', '$2')) + + // Text in bold + .replace(/(^|\s|>)((\*)([^<>'"]+)(\*))($|\s|<)/gi, '$1$2$6') + + // Italic text + .replace(/(^|\s|>)((\/)([^<>'"]+)(\/))($|\s|<)/gi, '$1$2$6') + + // Underlined text + .replace(/(^|\s|>)((_)([^<>'"]+)(_))($|\s|<)/gi, '$1$2$6'); + + // Add the links + if(html_encode) + filteredMessage = applyLinks(filteredMessage, 'desktop'); + + // Filter integratebox links + filteredMessage = filterIntegrateBox(filteredMessage); + + return filteredMessage; +} + +// Filters a xHTML message to be displayed in Jappix +function filterThisXHTML(code) { + // Allowed elements array + var elements = new Array( + 'a', + 'abbr', + 'acronym', + 'address', + 'blockquote', + 'body', + 'br', + 'cite', + 'code', + 'dd', + 'dfn', + 'div', + 'dt', + 'em', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'head', + 'html', + 'img', + 'kbd', + 'li', + 'ol', + 'p', + 'pre', + 'q', + 'samp', + 'span', + 'strong', + 'title', + 'ul', + 'var' + ); + + // Allowed attributes array + var attributes = new Array( + 'accesskey', + 'alt', + 'charset', + 'cite', + 'class', + 'height', + 'href', + 'hreflang', + 'id', + 'longdesc', + 'profile', + 'rel', + 'rev', + 'src', + 'style', + 'tabindex', + 'title', + 'type', + 'uri', + 'version', + 'width', + 'xml:lang', + 'xmlns' + ); + + // Remove forbidden elements + $(code).find('html body *').each(function() { + // This element is not authorized + if(!existArrayValue(elements, (this).nodeName.toLowerCase())) + $(this).remove(); + }); + + // Remove forbidden attributes + $(code).find('html body *').each(function() { + // Put a pointer on this element (jQuery way & normal way) + var cSelector = $(this); + var cElement = (this); + + // Loop the attributes of the current element + $(cElement.attributes).each(function(index) { + // Read the current attribute + var cAttr = cElement.attributes[index]; + var cName = cAttr.name; + var cVal = cAttr.value; + + // This attribute is not authorized, or contains JS code + if(!existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/))) + cSelector.removeAttr(cName); + }); + }); + + // Filter some other elements + $(code).find('a').attr('target', '_blank'); + + return $(code).find('html body').html(); +} diff --git a/sources/addons/jappixmini/jappix/js/groupchat.js b/sources/addons/jappixmini/jappix/js/groupchat.js new file mode 100644 index 00000000..c8dd13b1 --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/groupchat.js @@ -0,0 +1,283 @@ +/* + +Jappix - An open social platform +These are the groupchat JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Authors: Vanaryon, Maranda, Eric +Last revision: 28/08/11 + +*/ + +// Displays the MUC admin elements +function displayMucAdmin(affiliation, id, xid, statuscode) { + // We must be in the "login" mode + if(isAnonymous()) + return; + + // We check if the user is a room owner or administrator to give him privileges + if(affiliation == 'owner' || affiliation == 'admin') + $('#' + id + ' .tools-mucadmin').show(); + + // We check if the room hasn't been yet created + if(statuscode == 201) + openThisInfo(4); + + // We add the click event + $('#' + id + ' .tools-mucadmin').click(function() { + openMucAdmin(xid, affiliation); + }); +} + +// Initializes a connection with a MUC groupchat +function getMUC(room, nickname, password) { + // Room hash + var hash = hex_md5(room); + + // Reset the elements + $('#' + hash + ' .muc-ask').remove(); + $('#' + hash + ' .compose').show(); + + // No nickname? + if(!nickname) { + // Get some values + if(!isAnonymous()) + nickname = getNick(); + else + nickname = ANONYMOUS_NICK; + + // If the nickname could not be retrieved, ask it + if(!nickname) + generateMUCAsk('nickname', room, hash, nickname, password); + } + + // Got our nickname? + if(nickname) { + // Get our general presence + var show = getDB('presence-show', 1); + var status = getDB('options', 'presence-status'); + + // Set my nick + $('#' + hash).attr('data-nick', escape(nickname)); + + // Send the appropriate presence + sendPresence(room + '/' + nickname, '', show, status, '', true, password, handleMUC); + } + + return false; +} + +// Handles the MUC main elements +function handleMUC(presence) { + // We get the xml content + var xml = presence.getNode(); + var from = fullXID(getStanzaFrom(presence)); + var room = bareXID(from); + var nickname = thisResource(from); + var hash = hex_md5(room); + + // No ID: must fix M-Link bug + if(presence.getID() == null) + presence.setID(1); + + logThis('First MUC presence: ' + from, 3); + + // Catch the errors + if(!handleError(xml)) { + // Define some stuffs + var muc_user = $(xml).find('x[xmlns=' + NS_MUC_USER + ']'); + var affiliation = muc_user.find('item').attr('affiliation'); + var statuscode = parseInt(muc_user.find('status').attr('code')); + + // Handle my presence + handlePresence(presence); + + // Check if I am a room owner + displayMucAdmin(affiliation, hash, room, statuscode); + + // Tell the MUC we can notify the incoming presences + $(document).oneTime('15s', function() { + $('#' + hash).attr('data-initial', 'true'); + }); + + // Enable the chatting input + $(document).oneTime(10, function() { + $('#' + hash + ' .message-area').removeAttr('disabled').focus(); + }); + } + + // A password is required + else if($(xml).find('error[type=auth] not-authorized').size()) + generateMUCAsk('password', room, hash, nickname); + + // There's a nickname conflict + else if($(xml).find('error[type=cancel] conflict').size()) + generateMUCAsk('nickname', room, hash); +} + +// Generates a correct MUC asker +function generateMUCAsk(type, room, hash, nickname, password) { + // Generate the path to the elements + var path_to = '#' + hash + ' .muc-ask'; + + // Define the label text + var label_text; + + switch(type) { + case 'nickname': + label_text = _e("Nickname"); + break; + + case 'password': + label_text = _e("Password"); + break; + } + + // Create the HTML markup + $('#' + hash + ' .compose').hide(); + + $('#' + hash).append( + '
' + + '' + + '' + + '
' + ); + + // When a key is pressed in the input + $(path_to + ' input').keyup(function(e) { + var value_input = $(this).val(); + + // Enter key pressed + if((e.keyCode == 13) && value_input) { + if(type == 'nickname') + nickname = value_input; + else if(type == 'password') + password = value_input; + + return getMUC(room, nickname, password); + } + }); + + // Focus on the input + $(document).oneTime(10, function() { + $(path_to + ' input').focus(); + }); +} + +// Creates a new groupchat +function groupchatCreate(hash, room, chan, nickname, password) { + /* REF: http://xmpp.org/extensions/xep-0045.html */ + + logThis('New groupchat: ' + room, 3); + + // Create the chat content + generateChat('groupchat', hash, room, chan); + + // Create the chat switcher + generateSwitch('groupchat', hash, room, chan); + + // The icons-hover functions + tooltipIcons(room, hash); + + // Click event on the add tool + $('#' + hash + ' .tools-add').click(function() { + // Hide the icon (to tell the user all is okay) + $(this).hide(); + + // Add the groupchat to the user favorites + addThisFavorite(room, chan); + }); + + // Must show the add button? + if(!existDB('favorites', room)) + $('#' + hash + ' .tools-add').show(); + + // The event handlers + var inputDetect = $('#' + hash + ' .message-area'); + + // Focus event + inputDetect.focus(function() { + chanCleanNotify(hash); + }) + + // Blur event + inputDetect.blur(function() { + resetAutocompletion(hash); + }) + + // Lock to the input + inputDetect.keypress(function(e) { + // Enter key + if(e.keyCode == 13) { + // Add a new line + if(e.shiftKey) + inputDetect.val(inputDetect.val() + '\n'); + + // Send the message + else { + sendMessage(hash, 'groupchat'); + + // Reset the composing database entry + setDB('chatstate', room, 'off'); + } + + return false; + } + + // Tabulation key + else if(e.keyCode == 9) { + createAutocompletion(hash); + + return false; + } + + // Reset the autocompleter + else + resetAutocompletion(hash); + }); + + // Chatstate events + eventsChatState(inputDetect, room, hash); + + // Get the current muc informations and content + getMUC(room, nickname, password); +} + +// Joins the defined groupchats +function joinConfGroupchats() { + // Nothing to join? + if(!GROUPCHATS_JOIN) + return; + + // Values array + var muc_arr = [GROUPCHATS_JOIN]; + var new_arr = []; + + // Try to split it + if(GROUPCHATS_JOIN.indexOf(',') != -1) + muc_arr = GROUPCHATS_JOIN.split(','); + + for(i in muc_arr) { + // Get the current value + var muc_current = trim(muc_arr[i]); + + // No current value? + if(!muc_current) + continue; + + // Filter the current value + muc_current = generateXID(muc_current, 'groupchat'); + + // Add the current value + if(!existArrayValue(new_arr, muc_current)) + new_arr.push(muc_current); + } + + // Join the chats + if(new_arr.length) { + for(g in new_arr) + checkChatCreate(new_arr[g], 'groupchat'); + } +} diff --git a/sources/addons/jappixmini/jappix/js/home.js b/sources/addons/jappixmini/jappix/js/home.js new file mode 100644 index 00000000..5322501d --- /dev/null +++ b/sources/addons/jappixmini/jappix/js/home.js @@ -0,0 +1,371 @@ +/* + +Jappix - An open social platform +These are the homepage JS scripts for Jappix + +------------------------------------------------- + +License: AGPL +Authors: Vanaryon, LinkMauve +Last revision: 15/01/12 + +*/ + +// Allows the user to switch the difference home page elements +function switchHome(div) { + // Path to + var home = '#home .'; + var right = home + 'right '; + var current = right + '.homediv.' + div; + + // We switch the div + $(right + '.homediv, ' + right + '.top').hide(); + $(right + '.' + div).show(); + + // We reset the homedivs + $(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove(); + + // Get the HTML code to display + var disable_form = ''; + var lock_host = ''; + var code = ''; + + // Apply the previous link + switch(div) { + case 'loginer': + case 'anonymouser': + case 'registerer': + if(!exists(right + '.top.sub')) { + // Append the HTML code for previous link + $(right + '.top.default').after('

«

'); + + // Click event on previous link + $(home + 'top.sub a.previous').click(function() { + return switchHome('default'); + }); + } + + break; + } + + // Apply the form + switch(div) { + // Login tool + case 'loginer': + lock_host = disableInput(LOCK_HOST, 'on'); + code = '

' + printf(_e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '' + _e("anonymous mode") + '') + '

' + + + '
' + + '
' + + '' + _e("Required") + '' + + + '' + + '@' + + '' + + '' + + '' + + '' + + '
' + + + '' + _e("Advanced") + '' + + + '
' + + '' + _e("Advanced") + '' + + + '' + + '' + + '' + + '' + + '
' + + + '' + + '
'; + + break; + + // Anonymous login tool + case 'anonymouser': + disable_form = disableInput(ANONYMOUS, 'off'); + code = '

' + printf(_e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '' + _e("login page") + '') + '

' + + + '
' + + '
' + + '' + _e("Required") + '' + + + '' + + '' + + + '' + + '' + + '
' + + + '' + + '
' + + + '
' + + _e("Share this link with your friends:") + ' ' + + '
'; + + break; + + // Register tool + case 'registerer': + disable_form = disableInput(REGISTRATION, 'off'); + + if(!disable_form) + lock_host = disableInput(LOCK_HOST, 'on'); + + code = '

' + _e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '

' + + + '
' + + '
' + + '' + _e("Required") + '' + + + '' + + '@' + + '' + + '' + + '' + + '
' + + + '' + + '
'; + + break; + } + + // Form disabled? + if(disable_form) + code += '
' + + _e("This tool has been disabled, you cannot use it!") + + '
'; + + // Create this HTML code + if(code && !exists(current)) { + // Append it! + $(right + '.homediv.default').after('
' + code + '
'); + + // Create the attached events + switch(div) { + // Login tool + case 'loginer': + $(current + ' a.to-anonymous').click(function() { + return switchHome('anonymouser'); + }); + + $(current + ' a.advanced').click(showAdvanced); + + $(current + ' form').submit(loginForm); + + break; + + // Anonymous login tool + case 'anonymouser': + $(current + ' a.to-home').click(function() { + return switchHome('loginer'); + }); + + $(current + ' form').submit(doAnonymous); + + // Keyup event on anonymous join's room input + $(current + ' input.room').keyup(function() { + var value = $(this).val(); + var report = current + ' .report'; + var span = report + ' span'; + + if(!value) { + $(report).hide(); + $(span).text(''); + } + + else { + $(report).show(); + $(span).text(JAPPIX_LOCATION + '?r=' + value); + } + }); + + break; + + // Register tool + case 'registerer': + $(current + ' form').submit(registerForm); + + break; + } + } + + // We focus on the first input + $(document).oneTime(10, function() { + $(right + 'input:visible:first').focus(); + }); + + return false; +} + +// Allows the user to display the advanced login options +function showAdvanced() { + // Hide the link + $('#home a.advanced').hide(); + + // Show the fieldset + $('#home fieldset.advanced').show(); + + return false; +} + +// Reads the login form values +function loginForm() { + // We get the values + var lPath = '#home .loginer '; + var lServer = $(lPath + '.server').val(); + var lNick = $(lPath + '.nick').val(); + var lPass = $(lPath + '.password').val(); + var lResource = $(lPath + '.resource').val(); + var lPriority = $(lPath + '.priority').val(); + var lRemember = $(lPath + '.remember').filter(':checked').size(); + + // Enough values? + if(lServer && lNick && lPass && lResource && lPriority) + doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember); + + // Something is missing? + else { + $(lPath + 'input[type=text], ' + lPath + 'input[type=password]').each(function() { + var select = $(this); + + if(!select.val()) + $(document).oneTime(10, function() { + select.addClass('please-complete').focus(); + }); + else + select.removeClass('please-complete'); + }); + } + + return false; +} + +// Reads the register form values +function registerForm() { + var rPath = '#home .registerer '; + + // Remove the success info + $(rPath + '.success').remove(); + + // Get the values + var username = $(rPath + '.nick').val(); + var domain = $(rPath + '.server').val(); + var pass = $(rPath + '.password').val(); + var spass = $(rPath + '.spassword').val(); + + // Enough values? + if(domain && username && pass && spass && (pass == spass)) { + // We remove the not completed class to avoid problems + $('#home .registerer input').removeClass('please-complete'); + + // Fire the register event! + doRegister(username, domain, pass); + } + + // Something is missing? + else { + $(rPath + 'input[type=text], ' + rPath + 'input[type=password]').each(function() { + var select = $(this); + + if(!select.val() || (select.is('#spassword') && pass && (pass != spass))) + $(document).oneTime(10, function() { + select.addClass('please-complete').focus(); + }); + else + select.removeClass('please-complete'); + }); + } + + return false; +} + +// Plugin launcher +function launchHome() { + // Define the vars + var home = '#home '; + var button = home + 'button'; + var corp = home + '.corporation'; + var locale = home + '.locale'; + + // Removes the