From 309e3b09942389bd92205fc04d5e73088a30df60 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 31 Mar 2012 18:15:08 +0100 Subject: [PATCH 01/22] fix pitas fix --- node/db/PadManager.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/node/db/PadManager.js b/node/db/PadManager.js index 4e3a31999..5f08b1b1b 100644 --- a/node/db/PadManager.js +++ b/node/db/PadManager.js @@ -115,7 +115,13 @@ exports.doesPadExists = function(padId, callback) db.get("pad:"+padId, function(err, value) { if(ERR(err, callback)) return; - callback(null, value != null && value.atext); + if(value != null && value.atext){ + callback(null, true); + } + else + { + callback(null, false); + } }); } From 9e063341ce25bde326485e2bceef00341fa55907 Mon Sep 17 00:00:00 2001 From: levu Date: Sun, 8 Apr 2012 16:22:00 +0200 Subject: [PATCH 02/22] fix for bug 'userlist not scrolling' --- src/static/css/pad.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 21f365e24..5dd29412b 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -18,6 +18,12 @@ iframe {position:absolute;} border-radius: 6px; } +#otherusers +{ + max-height: 400px; + overflow: auto; +} + a img { border: 0; From c3095bbd1b2e87ef975d88d73889a391a6b78260 Mon Sep 17 00:00:00 2001 From: 0ip Date: Mon, 9 Apr 2012 15:16:40 +0200 Subject: [PATCH 03/22] improved userlist ux (prevent overlapping of objects) --- src/static/css/pad.css | 1 - src/static/js/pad_userlist.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 21f365e24..324303698 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -427,7 +427,6 @@ table#otheruserstable { display: none; } #nootherusers a { color: #3C88FF; } #otheruserstable td { - border-top: 1px solid #555; height: 26px; vertical-align: middle; padding: 0 2px; diff --git a/src/static/js/pad_userlist.js b/src/static/js/pad_userlist.js index 5a3f9b355..47ee63a7c 100644 --- a/src/static/js/pad_userlist.js +++ b/src/static/js/pad_userlist.js @@ -1,4 +1,4 @@ -/** ++/** * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED @@ -120,7 +120,7 @@ var paduserlist = (function() nameHtml = ''; } - return ['
 
', '', nameHtml, '', '', padutils.escapeHtml(data.status), '', '', padutils.escapeHtml(data.activity), ''].join(''); + return ['
 
', '', nameHtml, '', '', padutils.escapeHtml(data.activity), ''].join(''); } function getRowHtml(id, innerHtml) From 77936c6c12820cf230e4939ea34bbc35c7628172 Mon Sep 17 00:00:00 2001 From: 0ip Date: Mon, 9 Apr 2012 18:42:09 +0300 Subject: [PATCH 04/22] removed a weird plus --- src/static/js/pad_userlist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/js/pad_userlist.js b/src/static/js/pad_userlist.js index 47ee63a7c..f7ee81434 100644 --- a/src/static/js/pad_userlist.js +++ b/src/static/js/pad_userlist.js @@ -1,4 +1,4 @@ -+/** +/** * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED From 50c79df2721d69bd558a3b1c077c09877f5c1262 Mon Sep 17 00:00:00 2001 From: 0ip Date: Mon, 9 Apr 2012 17:52:43 +0200 Subject: [PATCH 05/22] prefixed css files containing css3 attributes due to recently removed prefixfree.js --- src/static/css/pad.css | 1876 +++++++++++++++++++-------------- src/static/css/timeslider.css | 362 +++++-- 2 files changed, 1326 insertions(+), 912 deletions(-) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 6227bee43..2ce8dbb66 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -1,13 +1,27 @@ -*,html,body,p{ margin: 0; padding: 0; } -.clear { clear: both; } -html { font-size: 62.5%; width: 100%; } -body, textarea { font-family: Helvetica, Arial, sans-serif; } -iframe {position:absolute;} - -#users -{ +*, +html, +body, +p { + margin: 0; + padding: 0; +} +.clear { + clear: both +} +html { + font-size: 62.5%; + width: 100%; +} +body, +textarea { + font-family: Helvetica, Arial, sans-serif +} +iframe { + position: absolute +} +#users { position: absolute; - z-index:500; + z-index: 500; background-color: #000; background-color: rgba(0,0,0,0.7); width: 160px; @@ -15,35 +29,32 @@ iframe {position:absolute;} top: 40px; color: #fff; padding: 5px; - border-radius: 6px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; } - -#otherusers -{ +#otherusers { max-height: 400px; overflow: auto; } - -a img -{ - border: 0; +a img { + border: 0 } - /* menu */ -.toolbar ul -{ +.toolbar ul { position: relative; list-style: none; padding-right: 3px; padding-left: 1px; z-index: 2; overflow: hidden; - } - -.toolbar -{ +.toolbar { background: #f7f7f7; + background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); background: linear-gradient(#f7f7f7, #f1f1f1 80%); border-bottom: 1px solid #ccc; overflow: hidden; @@ -52,12 +63,16 @@ a img white-space: nowrap; height: 32px; } - -.toolbar ul li -{ +.toolbar ul li { background: #fff; + background: -webkit-linear-gradient(#fff, #f0f0f0); + background: -moz-linear-gradient(#fff, #f0f0f0); + background: -o-linear-gradient(#fff, #f0f0f0); + background: -ms-linear-gradient(#fff, #f0f0f0); background: linear-gradient(#fff, #f0f0f0); border: 1px solid #ccc; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; border-radius: 4px; cursor: pointer; float: left; @@ -67,150 +82,195 @@ a img padding: 4px 5px; width: 18px; } - -.toolbar ul li a -{ +.toolbar ul li a { text-decoration: none; color: #ccc; position: absolute; } - -.toolbar ul li a span -{ +.toolbar ul li a span { position: relative; - top:-2px + top: -2px; } - .toolbar ul li:hover { background: #fff; + background: -webkit-linear-gradient(#f4f4f4, #e4e4e4); + background: -moz-linear-gradient(#f4f4f4, #e4e4e4); + background: -o-linear-gradient(#f4f4f4, #e4e4e4); + background: -ms-linear-gradient(#f4f4f4, #e4e4e4); background: linear-gradient(#f4f4f4, #e4e4e4); } - .toolbar ul li:active { background: #eee; + background: -webkit-linear-gradient(#ddd, #fff); + background: -moz-linear-gradient(#ddd, #fff); + background: -o-linear-gradient(#ddd, #fff); + background: -ms-linear-gradient(#ddd, #fff); background: linear-gradient(#ddd, #fff); + -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; + -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; box-shadow: 0 0 8px rgba(0,0,0,.1) inset; } - -.toolbar ul li.separator -{ +.toolbar ul li.separator { border: inherit; background: inherit; - visibility:hidden; + visibility: hidden; width: 0px; } -.toolbar ul li a -{ - display: block; +.toolbar ul li a { + display: block } -.toolbar ul li a img -{ - padding: 1px; +.toolbar ul li a img { + padding: 1px } - - -.toolbar ul -{ - float: left; +.toolbar ul { + float: left } -.toolbar ul.menu_right -{ - float: right; +.toolbar ul.menu_right { + float: right } - -#users -{ - display: none; +#users { + display: none } - -#editorcontainer -{ +#editorcontainer { position: absolute; - width: 100%; - top: 36px; - left: 0px; + left: 0px; bottom: 0px; - z-index: 1; } - #editorcontainer iframe { height: 100%; - width: 100%; - padding: 0; - margin: 0; + width: 100%; + padding: 0; + margin: 0; } - -#editorloadingbox { padding-top: 100px; padding-bottom: 100px; font-size: 2.5em; color: #aaa; - text-align: center; position: absolute; width: 100%; height: 30px; z-index: 100; } - -#editorcontainerbox{ - position:absolute; - bottom:0; - top:0; - width:100%; +#editorloadingbox { + padding-top: 100px; + padding-bottom: 100px; + font-size: 2.5em; + color: #aaa; + text-align: center; + position: absolute; + width: 100%; + height: 30px; + z-index: 100; +} +#editorcontainerbox { + position: absolute; + bottom: 0; + top: 0; + width: 100%; } - - #padpage { - position: absolute; - top: 0px; - bottom: 0px; - width: 100%; + position: absolute; + top: 0px; + bottom: 0px; + width: 100%; } - .maximized #padpage { - left: 8px; - right: 8px; - width: auto; - margin-left: 0; + left: 8px; + right: 8px; + width: auto; + margin-left: 0; } - -body.fullwidth #padpage { width: auto; margin-left: 6px; margin-right: 6px; } -body.squish1width #padpage { width: 800px; } -body.squish2width #padpage { width: 700px; } - -a#backtoprosite, #accountnav { - display: block; position: absolute; height: 15px; line-height: 15px; - width: auto; top: 5px; font-size: 1.2em; display:none; +body.fullwidth #padpage { + width: auto; + margin-left: 6px; + margin-right: 6px; +} +body.squish1width #padpage { + width: 800px +} +body.squish2width #padpage { + width: 700px +} +a#backtoprosite, +#accountnav { + display: block; + position: absolute; + height: 15px; + line-height: 15px; + width: auto; + top: 5px; + font-size: 1.2em; + display: none; +} +a#backtoprosite, +#accountnav a { + color: #cde7ff; + text-decoration: underline; +} +a#backtoprosite { + padding-left: 20px; + left: 6px; + background: url(static/img/protop.gif) no-repeat -5px -6px; +} +#accountnav { + right: 30px; + color: #fff; +} +#specialkeyarea { + top: 5px; + left: 250px; + color: yellow; + font-weight: bold; + font-size: 1.5em; + position: absolute; } -a#backtoprosite, #accountnav a { color: #cde7ff; text-decoration: underline; } - -a#backtoprosite { padding-left: 20px; left: 6px; - background: url(static/img/protop.gif) no-repeat -5px -6px; } -#accountnav { right: 30px; color: #fff; } - - -#specialkeyarea { top: 5px; left: 250px; color: yellow; font-weight: bold; - font-size: 1.5em; position: absolute; } - #alertbar { margin-top: 6px; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); opacity: 0; display: none; - position:absolute; - left:0; - right:0; - z-index:53; + position: absolute; + left: 0; + right: 0; + z-index: 53; } - -#servermsg { position: relative; zoom: 1; border: 1px solid #992; - background: #ffc; padding: 0.8em; font-size: 1.2em; } -#servermsg h3 { font-weight: bold; margin-right: 10px; - margin-bottom: 1em; float: left; width: auto; } -#servermsg #servermsgdate { font-style: italic; font-weight: normal; color: #666; } -a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; } - -#shuttingdown { position: relative; zoom: 1; border: 1px solid #992; - background: #ffc; padding: 0.6em; font-size: 1.2em; margin-top: 6px; } - -#docbar { margin-top: 6px; height: 25px; position: relative; zoom: 1; - background: #fbfbfb url(static/img/padtopback2.gif) repeat-x 0 -31px; } - -.docbarbutton -{ +#servermsg { + position: relative; + zoom: 1; + border: 1px solid #992; + background: #ffc; + padding: 0.8em; + font-size: 1.2em; +} +#servermsg h3 { + font-weight: bold; + margin-right: 10px; + margin-bottom: 1em; + float: left; + width: auto; +} +#servermsg #servermsgdate { + font-style: italic; + font-weight: normal; + color: #666; +} +a#hidetopmsg { + position: absolute; + right: 5px; + bottom: 5px; +} +#shuttingdown { + position: relative; + zoom: 1; + border: 1px solid #992; + background: #ffc; + padding: 0.6em; + font-size: 1.2em; + margin-top: 6px; +} +#docbar { + margin-top: 6px; + height: 25px; + position: relative; + zoom: 1; + background: #fbfbfb url(static/img/padtopback2.gif) repeat-x 0 -31px; +} +.docbarbutton { padding-top: 2px; padding-bottom: 2px; padding-left: 4px; @@ -218,9 +278,7 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; } border-left: 1px solid #CCC; white-space: nowrap; } - -.docbarbutton img -{ +.docbarbutton img { border: 0px; width: 13px; margin-right: 2px; @@ -228,17 +286,14 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; } margin-top: 3px; margin-bottom: 2px; } - .menu, .menu ul { font-size: 10pt; list-style-type: none; } - .menu ul { - padding-left: 20px; + padding-left: 20px } - .menu a { font-size: 10px; line-height: 18px; @@ -246,49 +301,99 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; } color: #444; font-weight: bold; } - -.docbarbutton.highlight -{ +.docbarbutton.highlight { background-color: #fef2bd; border: 1px solid #CCC; border-right: 0px; } - -#docbarleft { position: absolute; left: 0; top: 0; height: 100%; +#docbarleft { + position: absolute; + left: 0; + top: 0; + height: 100%; overflow: hidden; - background: url(static/img/padtop5.gif) no-repeat left -31px; width: 7px; } - - - -#docbarpadtitle { position: absolute; height: auto; left: 9px; - width: 280px; font-size: 1.6em; color: #444; font-weight: normal; - line-height: 22px; margin-left: 2px; height: 22px; top: 2px; - overflow: hidden; text-overflow: ellipsis /*not supported in FF*/; - white-space:nowrap; } -.docbar-public #docbarpadtitle { padding-left: 22px; - background: url(static/img/public.gif) no-repeat left center; } - -#docbarrenamelink { position: absolute; top: 6px; - font-size: 1.1em; display: none; } -#docbarrenamelink a { color: #999; } -#docbarrenamelink a:hover { color: #48d; } -#padtitlebuttons { position: absolute; width: 74px; zoom: 1; - height: 17px; top: 4px; left: 170px; display: none; - background: url(static/img/ok_or_cancel.gif) 0px 0px; } -#padtitlesave { position: absolute; display: block; - height: 0; padding-top: 17px; overflow: hidden; - width: 23px; left: 0; top: 0; } -#padtitlecancel { position: absolute; display: block; - height: 0; padding-top: 17px; overflow: hidden; - width: 35px; right: 0; top: 0; } -#padtitleedit { position: absolute; top: 2px; left: 5px; - height: 15px; padding: 2px; font-size: 1.4em; - background: white; border-left: 1px solid #c3c3c3; - border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; border-bottom: 1px solid #e6e6e6; - width: 150px; display: none; + background: url(static/img/padtop5.gif) no-repeat left -31px; + width: 7px; +} +#docbarpadtitle { + position: absolute; + height: auto; + left: 9px; + width: 280px; + font-size: 1.6em; + color: #444; + font-weight: normal; + line-height: 22px; + margin-left: 2px; + height: 22px; + top: 2px; + overflow: hidden; /*not supported in FF*/ + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + text-overflow: ellipsis; + white-space: nowrap; +} +.docbar-public #docbarpadtitle { + padding-left: 22px; + background: url(static/img/public.gif) no-repeat left center; +} +#docbarrenamelink { + position: absolute; + top: 6px; + font-size: 1.1em; + display: none; +} +#docbarrenamelink a { + color: #999 +} +#docbarrenamelink a:hover { + color: #48d +} +#padtitlebuttons { + position: absolute; + width: 74px; + zoom: 1; + height: 17px; + top: 4px; + left: 170px; + display: none; + background: url(static/img/ok_or_cancel.gif) 0px 0px; +} +#padtitlesave { + position: absolute; + display: block; + height: 0; + padding-top: 17px; + overflow: hidden; + width: 23px; + left: 0; + top: 0; +} +#padtitlecancel { + position: absolute; + display: block; + height: 0; + padding-top: 17px; + overflow: hidden; + width: 35px; + right: 0; + top: 0; +} +#padtitleedit { + position: absolute; + top: 2px; + left: 5px; + height: 15px; + padding: 2px; + font-size: 1.4em; + background: white; + border-left: 1px solid #c3c3c3; + border-top: 1px solid #c3c3c3; + border-right: 1px solid #e6e6e6; + border-bottom: 1px solid #e6e6e6; + width: 150px; + display: none; } - #padmain { margin-top: 0px; position: absolute; @@ -298,211 +403,324 @@ a#hidetopmsg { position: absolute; right: 5px; bottom: 5px; } bottom: 0px; zoom: 1; } - #padeditor { - bottom:0px; - left:0; - position:absolute; - right:0px; - top:0; + bottom: 0px; + left: 0; + position: absolute; + right: 0px; + top: 0; zoom: 1; } -.hidesidebar #padeditor { right: 0; } - +.hidesidebar #padeditor { + right: 0 +} #vdraggie { -/* background: url(static/img/vdraggie.gif) no-repeat top center;*/ - width:16px; - height:16px; - background-image:url('../../static/img/etherpad_lite_icons.png'); + /* background: url(static/img/vdraggie.gif) no-repeat top center;;*/ + width: 16px; + height: 16px; + background-image: url('../../static/img/etherpad_lite_icons.png'); background-repeat: no-repeat; background-position: 0px -300px; - cursor: W-resize; - bottom:0; - position:absolute; - right:268px; - top:0; - width:56px; + bottom: 0; + position: absolute; + right: 268px; + top: 0; + width: 56px; z-index: 10; } - -.toolbarsavetable -{ - position:absolute; +.toolbarsavetable { + position: absolute; top: 6px; right: 8px; height: 24px; } - -.toolbarsavetable td, .toolbartable td -{ - white-space: nowrap; +.toolbarsavetable td, +.toolbartable td { + white-space: nowrap } - -#myswatchbox { - position: absolute; - left: 5px; - top: 5px; +#myswatchbox { + position: absolute; + left: 5px; + top: 5px; width: 24px; height: 24px; border: 1px solid #000; - background: transparent; - cursor: pointer; + background: transparent; + cursor: pointer; +} +#myswatch { + width: 100%; + height: 100%; + background: transparent; /*...initially*/ } - -#myswatch { width: 100%; height: 100%; background: transparent;/*...initially*/ } - #mycolorpicker { - width: 232px; height: 265px; + width: 232px; + height: 265px; position: absolute; - left: -250px; top: 0px; z-index: 101; + left: -250px; + top: 0px; + z-index: 101; display: none; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; border-radius: 5px; - background: rgba(0, 0, 0, 0.7); - padding-left:10px; - padding-top:10px; + background: rgba(0, 0, 0, 0.7); + padding-left: 10px; + padding-top: 10px; } /* #mycolorpicker ul li -{ - float: left; + { + +float: left; + } -#mycolorpicker .picked { border: 1px solid #000 !important; } -#mycolorpicker .picked .pickerswatch { border: 1px solid #fff; } -*/ -#mycolorpickersave { - left: 10px; +#mycolorpicker .picked { + border: 1px solid #000 !important; + } + + +#mycolorpicker .picked .pickerswatch { + border: 1px solid #fff; + } + + */ +#mycolorpickersave { + left: 10px; font-weight: bold; } - -#mycolorpickercancel { - left: 85px; +#mycolorpickercancel { + left: 85px } - -#mycolorpickersave, #mycolorpickercancel { +#mycolorpickersave, +#mycolorpickercancel { background: #fff; + background: -webkit-linear-gradient(#fff, #ccc); + background: -moz-linear-gradient(#fff, #ccc); + background: -o-linear-gradient(#fff, #ccc); + background: -ms-linear-gradient(#fff, #ccc); background: linear-gradient(#fff, #ccc); border: 1px solid #ccc; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; border-radius: 4px; - font-size:12px; - cursor: pointer; - color:#000; - overflow: hidden; - padding: 4px; + font-size: 12px; + cursor: pointer; + color: #000; + overflow: hidden; + padding: 4px; top: 240px; - text-align:center; - position: absolute; - width: 60px; + text-align: center; + position: absolute; + width: 60px; } - -#mycolorpickerpreview { - position: absolute; - left: 207px; - top: 240px; - width:16px; - height:16px; - padding:4px; - overflow: hidden; - color: #fff; - border-radius:5px; +#mycolorpickerpreview { + position: absolute; + left: 207px; + top: 240px; + width: 16px; + height: 16px; + padding: 4px; + overflow: hidden; + color: #fff; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; } - - -#myusernameform { margin-left: 35px; } -#myusernameedit { font-size: 1.3em; color: #fff; - padding: 3px; height: 18px; margin: 0; border: 0; - width: 117px; background: transparent; } -#myusernameform input.editable { border: 1px solid #444; } -#myuser .myusernameedithoverable:hover { background: white; color: black} -#mystatusform { margin-left: 35px; margin-top: 5px; } -#mystatusedit { font-size: 1.2em; color: #777; - font-style: italic; display: none; - padding: 2px; height: 14px; margin: 0; border: 1px solid #bbb; - width: 199px; background: transparent; } -#myusernameform .editactive, #myusernameform .editempty { - background: white; border-left: 1px solid #c3c3c3; +#myusernameform { + margin-left: 35px +} +#myusernameedit { + font-size: 1.3em; + color: #fff; + padding: 3px; + height: 18px; + margin: 0; + border: 0; + width: 117px; + background: transparent; +} +#myusernameform input.editable { + border: 1px solid #444 +} +#myuser .myusernameedithoverable:hover { + background: white; + color: black; +} +#mystatusform { + margin-left: 35px; + margin-top: 5px; +} +#mystatusedit { + font-size: 1.2em; + color: #777; + font-style: italic; + display: none; + padding: 2px; + height: 14px; + margin: 0; + border: 1px solid #bbb; + width: 199px; + background: transparent; +} +#myusernameform .editactive, +#myusernameform .editempty { + background: white; + border-left: 1px solid #c3c3c3; border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; border-bottom: 1px solid #e6e6e6; - color: #000 + border-right: 1px solid #e6e6e6; + border-bottom: 1px solid #e6e6e6; + color: #000; +} +#myusernameform .editempty { + color: #333 +} +table#otheruserstable { + display: none +} +#nootherusers { + padding: 10px; + font-size: 1.2em; + color: #eee; + font-weight: bold; +} +#nootherusers a { + color: #3C88FF } -#myusernameform .editempty { color: #333; } - -table#otheruserstable { display: none; } -#nootherusers { padding: 10px; font-size: 1.2em; color: #eee; font-weight: bold;} -#nootherusers a { color: #3C88FF; } - #otheruserstable td { height: 26px; vertical-align: middle; padding: 0 2px; color: #fff; } - #otheruserstable .swatch { - border: 1px solid #000; width: 13px; height: 13px; overflow: hidden; + border: 1px solid #000; + width: 13px; + height: 13px; + overflow: hidden; margin: 0 4px; } - -.usertdswatch { width: 1%; } -.usertdname { font-size: 1.3em; color: #444; } -.usertdstatus { font-size: 1.1em; font-style: italic; color: #999; } -.usertdactivity { font-size: 1.1em; color: #777; } - -.usertdname input { border: 1px solid #bbb; width: 80px; padding: 2px; } -.usertdname input.editactive, .usertdname input.editempty { - background: white; border-left: 1px solid #c3c3c3; - border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; border-bottom: 1px solid #e6e6e6; +.usertdswatch { + width: 1% +} +.usertdname { + font-size: 1.3em; + color: #444; +} +.usertdstatus { + font-size: 1.1em; + font-style: italic; + color: #999; +} +.usertdactivity { + font-size: 1.1em; + color: #777; +} +.usertdname input { + border: 1px solid #bbb; + width: 80px; + padding: 2px; +} +.usertdname input.editactive, +.usertdname input.editempty { + background: white; + border-left: 1px solid #c3c3c3; + border-top: 1px solid #c3c3c3; + border-right: 1px solid #e6e6e6; + border-bottom: 1px solid #e6e6e6; +} +.usertdname input.editempty { + color: #888; + font-style: italic; } -.usertdname input.editempty { color: #888; font-style: italic;} - .modaldialog.cboxreconnecting .modaldialog-inner, .modaldialog.cboxconnecting .modaldialog-inner { background: url(../../static/img/connectingbar.gif) no-repeat center 60px; height: 100px; } -.modaldialog.cboxreconnecting, +.modaldialog.cboxreconnecting, .modaldialog.cboxconnecting, .modaldialog.cboxdisconnected { - background: #8FCDE0; + background: #8FCDE0 +} +.cboxdisconnected #connectionboxinner div { + display: none +} +.cboxdisconnected_userdup #connectionboxinner #disconnected_userdup { + display: block +} +.cboxdisconnected_deleted #connectionboxinner #disconnected_deleted { + display: block +} +.cboxdisconnected_initsocketfail #connectionboxinner #disconnected_initsocketfail { + display: block +} +.cboxdisconnected_looping #connectionboxinner #disconnected_looping { + display: block +} +.cboxdisconnected_slowcommit #connectionboxinner #disconnected_slowcommit { + display: block +} +.cboxdisconnected_unauth #connectionboxinner #disconnected_unauth { + display: block +} +.cboxdisconnected_unknown #connectionboxinner #disconnected_unknown { + display: block } -.cboxdisconnected #connectionboxinner div { display: none; } -.cboxdisconnected_userdup #connectionboxinner #disconnected_userdup { display: block; } -.cboxdisconnected_deleted #connectionboxinner #disconnected_deleted { display: block; } -.cboxdisconnected_initsocketfail #connectionboxinner #disconnected_initsocketfail { display: block; } -.cboxdisconnected_looping #connectionboxinner #disconnected_looping { display: block; } -.cboxdisconnected_slowcommit #connectionboxinner #disconnected_slowcommit { display: block; } -.cboxdisconnected_unauth #connectionboxinner #disconnected_unauth { display: block; } -.cboxdisconnected_unknown #connectionboxinner #disconnected_unknown { display: block; } .cboxdisconnected_initsocketfail #connectionboxinner #reconnect_advise, .cboxdisconnected_looping #connectionboxinner #reconnect_advise, .cboxdisconnected_slowcommit #connectionboxinner #reconnect_advise, -.cboxdisconnected_unknown #connectionboxinner #reconnect_advise { display: block; } -.cboxdisconnected div#reconnect_form { display: block; } -.cboxdisconnected .disconnected h2 { display: none; } -.cboxdisconnected .disconnected .h2_disconnect { display: block; } -.cboxdisconnected_userdup .disconnected h2.h2_disconnect { display: none; } -.cboxdisconnected_userdup .disconnected h2.h2_userdup { display: block; } -.cboxdisconnected_unauth .disconnected h2.h2_disconnect { display: none; } -.cboxdisconnected_unauth .disconnected h2.h2_unauth { display: block; } - +.cboxdisconnected_unknown #connectionboxinner #reconnect_advise { + display: block +} +.cboxdisconnected div#reconnect_form { + display: block +} +.cboxdisconnected .disconnected h2 { + display: none +} +.cboxdisconnected .disconnected .h2_disconnect { + display: block +} +.cboxdisconnected_userdup .disconnected h2.h2_disconnect { + display: none +} +.cboxdisconnected_userdup .disconnected h2.h2_userdup { + display: block +} +.cboxdisconnected_unauth .disconnected h2.h2_disconnect { + display: none +} +.cboxdisconnected_unauth .disconnected h2.h2_unauth { + display: block +} #connectionstatus { - position: absolute; width: 37px; height: 41px; overflow: hidden; + position: absolute; + width: 37px; + height: 41px; + overflow: hidden; right: 0; z-index: 11; } #connectionboxinner .connecting { margin-top: 20px; - font-size: 2.0em; color: #555; - text-align: center; display: none; + font-size: 2.0em; + color: #555; + text-align: center; + display: none; +} +.cboxconnecting #connectionboxinner .connecting { + display: block } -.cboxconnecting #connectionboxinner .connecting { display: block; } - #connectionboxinner .disconnected h2 { - font-size: 1.8em; color: #333; + font-size: 1.8em; + color: #333; text-align: left; - margin-top: 10px; margin-left: 10px; margin-right: 10px; + margin-top: 10px; + margin-left: 10px; + margin-right: 10px; margin-bottom: 10px; } #connectionboxinner .disconnected p { @@ -511,54 +729,104 @@ table#otheruserstable { display: none; } line-height: 1.1; color: #333; } -#connectionboxinner .disconnected { display: none; } -.cboxdisconnected #connectionboxinner .disconnected { display: block; } - +#connectionboxinner .disconnected { + display: none +} +.cboxdisconnected #connectionboxinner .disconnected { + display: block +} #connectionboxinner .reconnecting { margin-top: 20px; - font-size: 1.6em; color: #555; - text-align: center; display: none; + font-size: 1.6em; + color: #555; + text-align: center; + display: none; +} +.cboxreconnecting #connectionboxinner .reconnecting { + display: block } -.cboxreconnecting #connectionboxinner .reconnecting { display: block; } - #reconnect_form button { font-size: 12pt; padding: 5px; } - /* We give docbar a higher z-index than its descendant impexp-wrapper in - order to allow the Import/Export panel to be on top of stuff lower - down on the page in IE. Strange but it works! */ -#docbar { z-index: 52; } - -#impexp-wrapper { width: 650px; right: 10px; } -#impexp-panel { height: 160px; } -.docbarimpexp-closing #impexp-wrapper { z-index: 50; } - -#savedrevs-wrapper { width: 100%; left: 0; } -#savedrevs-panel { height: 79px; } -.docbarsavedrevs-closing #savedrevs-wrapper { z-index: 50; } -#savedrevs-wrapper .dbpanel-rightedge { background-position: 0 -10px; } - -#options-wrapper { width: 340px; right: 200px; } -#options-panel { height: 114px; } -.docbaroptions-closing #options-wrapper { z-index: 50; } - -#security-wrapper { width: 320px; right: 300px; } -#security-panel { height: 130px; } -.docbarsecurity-closing #security-wrapper { z-index: 50; } - -#revision-notifier { position: absolute; right: 8px; top: 25px; - width: auto; height: auto; font-size: 1.2em; background: #ffc; - border: 1px solid #aaa; color: #444; padding: 3px 5px; - display: none; z-index: 55; } -#revision-notifier .label { color: #777; font-weight: bold; } - -#mainmodals { z-index: 600; /* higher than the modals themselves - so that modals are on top in IE */ } -.modalfield { font-size: 1.2em; padding: 1px; border: 1px solid #bbb;} -#mainmodals .editempty { color: #aaa; } - +order to allow the Import/Export panel to be on top of stuff lower +down on the page in IE. Strange but it works! */ +#docbar { + z-index: 52 +} +#impexp-wrapper { + width: 650px; + right: 10px; +} +#impexp-panel { + height: 160px +} +.docbarimpexp-closing #impexp-wrapper { + z-index: 50 +} +#savedrevs-wrapper { + width: 100%; + left: 0; +} +#savedrevs-panel { + height: 79px +} +.docbarsavedrevs-closing #savedrevs-wrapper { + z-index: 50 +} +#savedrevs-wrapper .dbpanel-rightedge { + background-position: 0 -10px +} +#options-wrapper { + width: 340px; + right: 200px; +} +#options-panel { + height: 114px +} +.docbaroptions-closing #options-wrapper { + z-index: 50 +} +#security-wrapper { + width: 320px; + right: 300px; +} +#security-panel { + height: 130px +} +.docbarsecurity-closing #security-wrapper { + z-index: 50 +} +#revision-notifier { + position: absolute; + right: 8px; + top: 25px; + width: auto; + height: auto; + font-size: 1.2em; + background: #ffc; + border: 1px solid #aaa; + color: #444; + padding: 3px 5px; + display: none; + z-index: 55; +} +#revision-notifier .label { + color: #777; + font-weight: bold; +} +#mainmodals { + z-index: 600; /* higher than the modals themselves: */ +} +.modalfield { + font-size: 1.2em; + padding: 1px; + border: 1px solid #bbb; +} +#mainmodals .editempty { + color: #aaa +} .expand-collapse { height: 22px; background-image: url(static/img/sharedistri.gif); @@ -568,72 +836,75 @@ table#otheruserstable { display: none; } text-decoration: none; } .expand-collapse.expanded { - background-position: 0 -31px; + background-position: 0 -31px } - - .modaldialog { position: absolute; top: 100px; - left:50%; - margin-left:-243px; + left: 50%; + margin-left: -243px; width: 485px; display: none; z-index: 501; zoom: 1; overflow: hidden; background: white; - border: 1px solid #999; + border: 1px solid #999; +} +.modaldialog .modaldialog-inner { + padding: 10pt } -.modaldialog .modaldialog-inner { padding: 10pt; } .modaldialog .modaldialog-hide { float: right; background-repeat: no-repeat; background-image: url(static/img/sharebox4.gif); display: block; - width: 22px; height: 22px; + width: 22px; + height: 22px; background-position: -454px -6px; - margin-right:-5px; - margin-top:-5px; + margin-right: -5px; + margin-top: -5px; } - .modaldialog label, .modaldialog h1 { - color:#222222; - font-size:125%; - font-weight:bold; + color: #222222; + font-size: 125%; + font-weight: bold; } - .modaldialog th { vertical-align: top; text-align: left; } - .sharebox-url { - width: 440px; height: 18px; + width: 440px; + height: 18px; text-align: left; font-size: 1.3em; line-height: 18px; padding: 2px; } - #sharebox-send { float: right; background-repeat: no-repeat; background-image: url(static/img/sharebox4.gif); display: block; - width: 87px; height: 22px; + width: 87px; + height: 22px; background-position: -383px -289px; } - - -#viewbarcontents { display: none; } +#viewbarcontents { + display: none +} #viewzoomtitle { - position: absolute; left: 10px; top: 4px; height: 20px; line-height: 20px; + position: absolute; + left: 10px; + top: 4px; + height: 20px; + line-height: 20px; width: auto; } #viewzoommenu { - width: 65px; + width: 65px } #bottomarea { height: 28px; @@ -646,123 +917,136 @@ table#otheruserstable { display: none; } font-size: 1.2em; color: #444; } -#widthprefcheck { position: absolute; +#widthprefcheck { + position: absolute; background-image: url(static/img/layoutbuttons.gif); - background-repeat: no-repeat; cursor: pointer; - width: 86px; height: 20px; top: 4px; right: 2px; } -.widthprefunchecked { background-position: -1px -1px; } -.widthprefchecked { background-position: -1px -23px; } -#sidebarcheck { position: absolute; + background-repeat: no-repeat; + cursor: pointer; + width: 86px; + height: 20px; + top: 4px; + right: 2px; +} +.widthprefunchecked { + background-position: -1px -1px +} +.widthprefchecked { + background-position: -1px -23px +} +#sidebarcheck { + position: absolute; background-image: url(static/img/layoutbuttons.gif); - background-repeat: no-repeat; cursor: pointer; - width: 86px; height: 20px; top: 4px; right: 90px; } -.sidebarunchecked { background-position: -1px -45px; } -.sidebarchecked { background-position: -1px -67px; } -#feedbackbutton { display: block; position: absolute; width: 68px; - height: 0; padding-top: 17px; overflow: hidden; + background-repeat: no-repeat; + cursor: pointer; + width: 86px; + height: 20px; + top: 4px; + right: 90px; +} +.sidebarunchecked { + background-position: -1px -45px +} +.sidebarchecked { + background-position: -1px -67px +} +#feedbackbutton { + display: block; + position: absolute; + width: 68px; + height: 0; + padding-top: 17px; + overflow: hidden; background: url(static/img/bottomareagfx.gif); - top: 5px; right: 220px; + top: 5px; + right: 220px; } - #modaloverlay { - z-index: 500; display: none; + z-index: 500; + display: none; background-repeat: repeat-both; - width: 100%; position: absolute; - height: 100%; left: 0; top: 0; + width: 100%; + position: absolute; + height: 100%; + left: 0; + top: 0; } - -* html #modaloverlay { /* for IE 6+ */ +* html #modaloverlay { + /* for IE 6+ */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); opacity: 1; /* in case this is looked at */ background-image: none; - background-repeat: no-repeat; - /* scale the image */ + background-repeat: no-repeat; /* scale the image */ } - a#topbarmaximize { - float: right; - width: 16px; - height: 16px; - margin-right:-143px; - margin-top:4px; - background: url(static/img/maximize_normal.png); + float: right; + width: 16px; + height: 16px; + margin-right: -143px; + margin-top: 4px; + background: url(static/img/maximize_normal.png); } - .maximized a#topbarmaximize { - background: url(static/img/maximize_maximized.png); + background: url(static/img/maximize_maximized.png) } - .toolbarinner h1 { - line-height: 29px; - font-size: 16px; - padding-left: 6pt; - margin-top: 0; - white-space: nowrap; + line-height: 29px; + font-size: 16px; + padding-left: 6pt; + margin-top: 0; + white-space: nowrap; } - .toolbarinner h1 a { - font-size: 12px; + font-size: 12px } - .bigbutton { - display: block; - background-color: #a3bde0; - color: #555555; - border-style: solid; - border-width: 2px; - border-left-color: #d6e2f1; - border-right-color: #86aee1; - border-top-color: #d6e2f1; - border-bottom-color: #86aee1; - margin: 10pt; - text-align: center; - text-decoration: none; - padding: 50pt; - font-size: 20pt; - border-radius: 3pt; + display: block; + background-color: #a3bde0; + color: #555555; + border-style: solid; + border-width: 2px; + border-left-color: #d6e2f1; + border-right-color: #86aee1; + border-top-color: #d6e2f1; + border-bottom-color: #86aee1; + margin: 10pt; + text-align: center; + text-decoration: none; + padding: 50pt; + font-size: 20pt; + -webkit-border-radius: 3pt; + -moz-border-radius: 3pt; + border-radius: 3pt; } - .modaldialog .bigbutton { - padding-left: 0; - padding-right: 0; - width: 100%; + padding-left: 0; + padding-right: 0; + width: 100%; } - -} - - -ul#colorpickerswatches -{ +ul#colorpickerswatches { padding-left: 3px; padding-top: 5px; } - -ul#colorpickerswatches li -{ - border: 1px solid #ccc; - width: 14px; - height: 14px; +ul#colorpickerswatches li { + border: 1px solid #ccc; + width: 14px; + height: 14px; overflow: hidden; margin: 3px 6px; padding: 0px; } - -ul#colorpickerswatches li:hover -{ - border: 1px solid #000; +ul#colorpickerswatches li:hover { + border: 1px solid #000; cursor: pointer; } - - - -#chatbox -{ - position:absolute; - bottom:0px; +#chatbox { + position: absolute; + bottom: 0px; right: 20px; width: 180px; height: 200px; z-index: 400; - background-color:#f7f7f7; + background-color: #f7f7f7; border-left: 1px solid #999; border-right: 1px solid #999; border-top: 1px solid #999; @@ -770,57 +1054,47 @@ ul#colorpickerswatches li:hover padding-bottom: 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; - display:none; + display: none; } - -#chattext -{ +#chattext { background-color: white; border: 1px solid white; - overflow-y:scroll; + -ms-overflow-y: scroll; + overflow-y: scroll; font-size: 12px; - position:absolute; - right:0px; - left:0px; - top:25px; - bottom:25px; - z-index:1002; + position: absolute; + right: 0px; + left: 0px; + top: 25px; + bottom: 25px; + z-index: 1002; } - -#chattext p -{ +#chattext p { padding: 3px; + -ms-overflow-x: hidden; overflow-x: hidden; } - -#chatinputbox -{ +#chatinputbox { padding: 3px 2px; position: absolute; - bottom:0px; - right:0px; - left:3px; + bottom: 0px; + right: 0px; + left: 3px; } - -#chatlabel -{ - font-size:13px; - font-weight:bold; - color:#555; +#chatlabel { + font-size: 13px; + font-weight: bold; + color: #555; text-decoration: none; margin-right: 3px; vertical-align: middle; } - -#chatinput -{ +#chatinput { border: 1px solid #BBBBBB; width: 100%; - float:right; + float: right; } - -#chaticon -{ +#chaticon { z-index: 400; position: fixed; bottom: 0px; @@ -831,202 +1105,183 @@ ul#colorpickerswatches li:hover border-top: 1px solid #999; border-top-left-radius: 5px; border-top-right-radius: 5px; - background-color:#fff; + background-color: #fff; cursor: pointer; } - -#chaticon a -{ - text-decoration: none; +#chaticon a { + text-decoration: none } - -#chatcounter -{ - color:#555; - font-size:9px; +#chatcounter { + color: #555; + font-size: 9px; vertical-align: middle; } - -#titlebar -{ - line-height:16px; - font-weight:bold; - color:#555; +#titlebar { + line-height: 16px; + font-weight: bold; + color: #555; position: relative; bottom: 2px; -} - -#titlelabel -{ - font-size:13px; - margin:4px 0 0 4px; - position:absolute; -} - -#titlecross -{ - font-size:25px; - float:right; +} +#titlelabel { + font-size: 13px; + margin: 4px 0 0 4px; + position: absolute; +} +#titlecross { + font-size: 25px; + float: right; text-align: right; text-decoration: none; cursor: pointer; - color:#555; + color: #555; } - -.time -{ - float:right; - color:#333; - font-style:italic; +.time { + float: right; + color: #333; + font-style: italic; font-size: 10px; margin-left: 3px; margin-right: 3px; - margin-top:2px; -} - -.exporttype{ margin-top: 2px; - background-repeat:no-repeat; - padding-left:25px; - background-image: url("../../static/img/etherpad_lite_icons.png"); - color:#fff; - text-decoration:none; } - -#importexportline{ +.exporttype { + margin-top: 2px; + background-repeat: no-repeat; + padding-left: 25px; + background-image: url("../../static/img/etherpad_lite_icons.png"); + color: #fff; + text-decoration: none; +} +#importexportline { border-left: 1px solid #fff; height: 190px; - position:absolute; - width:0px; - left:260px; - opacity:.8; + position: absolute; + width: 0px; + left: 260px; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; + filter: alpha(opacity=80); + opacity: .8; } - -.impexpbutton{ +.impexpbutton { + background-image: -webkit-linear-gradient(center top , #EEEEEE, white 20%, white 20%); + background-image: -moz-linear-gradient(center top , #EEEEEE, white 20%, white 20%); + background-image: -o-linear-gradient(center top , #EEEEEE, white 20%, white 20%); + background-image: -ms-linear-gradient(center top , #EEEEEE, white 20%, white 20%); background-image: linear-gradient(center top , #EEEEEE, white 20%, white 20%); - padding:3px; + padding: 3px; } - -#exporthtml{ - background-position: 0px -299px; +#exporthtml { + background-position: 0px -299px } - -#exportplain{ - background-position: 0px -395px; +#exportplain { + background-position: 0px -395px } - -#exportword{ - background-position: 0px -275px; +#exportword { + background-position: 0px -275px } - -#exportpdf{ - background-position: 0px -371px; +#exportpdf { + background-position: 0px -371px } - -#exportopen{ - background-position: 0px -347px; +#exportopen { + background-position: 0px -347px } - -#exportwordle{ - background-position: 0px -323px; +#exportwordle { + background-position: 0px -323px } - -#exportdokuwiki{ - background-position: 0px -459px; +#exportdokuwiki { + background-position: 0px -459px } - -#importstatusball{ - display:none; +#importstatusball { + display: none } - -#importarrow{ - display:none; +#importarrow { + display: none } - -#importmessagesuccess{ - display:none; +#importmessagesuccess { + display: none } - -#importsubmitinput{ - height:25px; - width:85px; - margin-top:12px; +#importsubmitinput { + height: 25px; + width: 85px; + margin-top: 12px; } - -#importstatusball{ - height:50px; +#importstatusball { + height: 50px } - -#chatthrob{ -display:none; -position:absolute; -bottom:40px; -font-size:14px; -width:150px; -height:40px; -right: 20px; -z-index: 200; -background-color: #000; -color: white; -background-color: rgb(0,0,0); -background-color: rgba(0,0,0,0.7); -padding: 10px; -border-radius: 6px; -opacity:.8; +#chatthrob { + display: none; + position: absolute; + bottom: 40px; + font-size: 14px; + width: 150px; + height: 40px; + right: 20px; + z-index: 200; + background-color: #000; + color: white; + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.7); + padding: 10px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; + filter: alpha(opacity=80); + opacity: .8; } - -.buttonicon{ -width:16px; -height:16px; -background-image:url('../../static/img/etherpad_lite_icons.png'); -background-repeat: no-repeat; -margin-left: 1px; -margin-top: 1px; +.buttonicon { + width: 16px; + height: 16px; + background-image: url('../../static/img/etherpad_lite_icons.png'); + background-repeat: no-repeat; + margin-left: 1px; + margin-top: 1px; } .buttonicon-bold { - background-position: 0px -116px; + background-position: 0px -116px } .buttonicon-italic { - background-position: 0px 0px; + background-position: 0px 0px } .buttonicon-underline { - background-position: 0px -236px; + background-position: 0px -236px } .buttonicon-strikethrough { - background-position: 0px -200px; + background-position: 0px -200px } .buttonicon-insertorderedlist { background-position: 0px -477px } .buttonicon-insertunorderedlist { - background-position: 0px -34px; + background-position: 0px -34px } .buttonicon-indent { - background-position: 0px -52px; + background-position: 0px -52px } .buttonicon-outdent { - background-position: 0px -134px; + background-position: 0px -134px } .buttonicon-undo { - background-position: 0px -255px; + background-position: 0px -255px } .buttonicon-redo { - background-position :0px -166px; + background-position: 0px -166px } .buttonicon-clearauthorship { - background-position: 0px -86px; + background-position: 0px -86px } .buttonicon-settings { - background-position: 0px -436px; + background-position: 0px -436px } .buttonicon-import_export { - background-position: 0px -68px; + background-position: 0px -68px } .buttonicon-embed { - background-position: 0px -18px; + background-position: 0px -18px } .buttonicon-history { - background-position: 0px -218px; + background-position: 0px -218px } .buttonicon-chat { background-position: 0px -102px; @@ -1041,14 +1296,10 @@ margin-top: 1px; .buttonicon-savedRevision { background-position: 0px -493px } - -#usericon -{ -width:33px !important; +#usericon { + width: 33px !important } - -#focusprotector -{ +#focusprotector { z-index: 100; position: absolute; bottom: 0px; @@ -1056,222 +1307,257 @@ width:33px !important; left: 0px; right: 0px; background-color: white; - opacity:0.01; - display:none; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=1)"; + filter: alpha(opacity=1); + opacity: 0.01; + display: none; } - -#online_count{ +#online_count { color: #888; font-size: 11px; line-height: 18px; position: fixed; } - #qr_center { margin: 10px 10px auto 0; text-align: center; } - #embedreadonlyqr { + -webkit-box-shadow: 0 0 10px #000; + -moz-box-shadow: 0 0 10px #000; box-shadow: 0 0 10px #000; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; border-radius: 3px; + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + -ms-transition: all .2s ease-in-out; transition: all .2s ease-in-out; } - #embedreadonlyqr:hover { cursor: none; + -webkit-transform: scale(1.5); + -moz-transform: scale(1.5); + -o-transform: scale(1.5); + -ms-transform: scale(1.5); transform: scale(1.5); } - -.rtl{ - direction:RTL; -} - -#chattext p { - word-wrap: break-word; +.rtl { + direction: RTL +} +#chattext p { + word-wrap: break-word } - /* fix for misaligned checkboxes */ input[type=checkbox] { - vertical-align: -1px; + vertical-align: -1px } - .right { - float:right; + float: right } - .popup { - font-size: 14px; - width: 450px; - z-index: 500; - padding: 10px; - border-radius: 6px; - background: #222; - background: rgba(0,0,0,.7); - background: linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6)); - box-shadow: 0 0 8px #888; - color: #fff; + font-size: 14px; + width: 450px; + z-index: 500; + padding: 10px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + background: #222; + background: rgba(0,0,0,.7); + background: -webkit-linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6)); + background: -moz-linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6)); + background: -o-linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6)); + background: -ms-linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6)); + background: linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6)); + -webkit-box-shadow: 0 0 8px #888; + -moz-box-shadow: 0 0 8px #888; + box-shadow: 0 0 8px #888; + color: #fff; } - .popup input[type=text] { - width: 100%; - padding: 5px; - box-sizing: border-box; - display:block; - margin-top: 10px; + width: 100%; + padding: 5px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + display: block; + margin-top: 10px; } - .popup a { - text-decoration: none; + text-decoration: none } - .popup h1 { - font-size: 18px; + font-size: 18px } .popup h2 { - font-size: 15px; + font-size: 15px } .popup p { - margin: 5px 0; + margin: 5px 0 } - .column { - float: left; - width: 50%; + float: left; + width: 50%; } - -#settingsmenu, #importexport, #embed { - position: absolute; - top: 55px; - right: 20px; - display: none; +#settingsmenu, +#importexport, +#embed { + position: absolute; + top: 55px; + right: 20px; + display: none; } - .note { - color: #ddd; - font-size: 11px; - font-weight: bold; + color: #ddd; + font-size: 11px; + font-weight: bold; } - .selected { - background: #eee !important; - background: linear-gradient(#EEE, #F0F0F0) !important; + background: #eee !important; + background: -webkit-linear-gradient(#EEE, #F0F0F0) !important; + background: -moz-linear-gradient(#EEE, #F0F0F0) !important; + background: -o-linear-gradient(#EEE, #F0F0F0) !important; + background: -ms-linear-gradient(#EEE, #F0F0F0) !important; + background: linear-gradient(#EEE, #F0F0F0) !important; } - .stickyChat { - background-color: #f1f1f1 !important; - right: 0px !important; - top: 36px; - border-radius: 0px !important; - height: auto !important; - border: none !important; - border-left: 1px solid #ccc !important; - width: 185px !important; + background-color: #f1f1f1 !important; + right: 0px !important; + top: 36px; + -webkit-border-radius: 0px !important; + -moz-border-radius: 0px !important; + border-radius: 0px !important; + height: auto !important; + border: none !important; + border-left: 1px solid #ccc !important; + width: 185px !important; } - -@media screen and (max-width: 960px) { - .modaldialog { - position: relative; - margin: 0 auto; - width: 80%; - top: 40px; - left: 0; - } +@media screen and (max-width: 960px) { + .modaldialog { + position: relative; + margin: 0 auto; + width: 80%; + top: 40px; + left: 0; + } } - -@media screen and (max-width: 600px) { - .toolbar ul li { - padding: 4px 1px; - } -} - -@media only screen and (min-device-width: 320px) and (max-device-width: 720px) { - .toolbar ul li { - padding: 4px 3px; - } - #users { - right: 0; - top: 36px; - bottom: 33px; - border-radius: none; - } - #mycolorpicker { - left: -72px; /* #mycolorpicker:width - #users:width */ - } - #editorcontainer { - margin-bottom: 33px; - } - .toolbar ul.menu_right { - background: #f7f7f7; - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - width: 100%; - overflow: hidden; - height: 32px; - position: fixed; - bottom: 0; - border-top: 1px solid #ccc; - } - .toolbar ul.menu_right li:last-child { - height: 24px; - border-radius: 0; - margin-top: 0; - border: 0; - float: right; - } - #chaticon { - bottom: 3px; - right: 55px; - border-right: none; - border-radius: 0; - background: #f7f7f7; - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - border: 0; - } - #chatbox { - bottom: 32px; - right: 0; - border-top-right-radius: 0; - border-right: none; - } - .toolbar ul li a span { - top: -3px; - } - #usericonback { - margin-top: 4px; - } - #qrcode { - display: none; - } - .toolbar ul.menu_right li:not(:last-child) { - display: block; - } - .toolbar ul.menu_right > li { - background: none; - border: none; - margin-top: 4px; - padding: 4px 8px; - } - .selected { - background: none !important; - } - #timesliderlink { - display: none !important; - } - .popup { - border-radius: 0; - box-sizing: border-box; - width: 100%; - } - #settingsmenu, #importexport, #embed { - left: 0; - top: 0; - bottom: 33px; - right: 0; - } - .separator { - display: none; - } - #online_count { - line-height: 24px; - } +@media screen and (max-width: 600px) { + .toolbar ul li { + padding: 4px 1px + } } +@media only screen and (min-device-width: 320px) and (max-device-width: 720px) { + .toolbar ul li { + padding: 4px 3px + } + #users { + right: 0; + top: 36px; + bottom: 33px; + -webkit-border-radius: none; + -moz-border-radius: none; + border-radius: none; + } + #mycolorpicker { + left: -72px; + /* #mycolorpicker: width -#users: width */; + } + #editorcontainer { + margin-bottom: 33px + } + .toolbar ul.menu_right { + background: #f7f7f7; + background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: linear-gradient(#f7f7f7, #f1f1f1 80%); + width: 100%; + overflow: hidden; + height: 32px; + position: fixed; + bottom: 0; + border-top: 1px solid #ccc; + } + .toolbar ul.menu_right li:last-child { + height: 24px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + margin-top: 0; + border: 0; + float: right; + } + #chaticon { + bottom: 3px; + right: 55px; + border-right: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + background: #f7f7f7; + background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: linear-gradient(#f7f7f7, #f1f1f1 80%); + border: 0; + } + #chatbox { + bottom: 32px; + right: 0; + border-top-right-radius: 0; + border-right: none; + } + .toolbar ul li a span { + top: -3px + } + #usericonback { + margin-top: 4px + } + #qrcode { + display: none + } + .toolbar ul.menu_right li:not(:last-child) { + display: block + } + .toolbar ul.menu_right > li { + background: none; + border: none; + margin-top: 4px; + padding: 4px 8px; + } + .selected { + background: none !important + } + #timesliderlink { + display: none !important + } + .popup { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + } + #settingsmenu, + #importexport, + #embed { + left: 0; + top: 0; + bottom: 33px; + right: 0; + } + .separator { + display: none + } + #online_count { + line-height: 24px + } +} \ No newline at end of file diff --git a/src/static/css/timeslider.css b/src/static/css/timeslider.css index 03e970481..4c8913d38 100644 --- a/src/static/css/timeslider.css +++ b/src/static/css/timeslider.css @@ -1,160 +1,288 @@ #editorcontainerbox { - overflow:auto; top:40px; + overflow: auto; + top: 40px; position: static; } - -#padcontent {font-size:12px; padding:10px;} - -#timeslider-wrapper {left:0; position:relative; right:0; top:0;} -#timeslider-left {background-image:url(../../static/img/timeslider_left.png); height:63px; left:0; position:absolute; width:134px;} -#timeslider-right {background-image:url(../../static/img/timeslider_right.png); height:63px; position:absolute; right:0; top:0; width:155px;} -#timeslider {background-image:url(../../static/img/timeslider_background.png); height:63px; margin:0 9px;} -#timeslider #timeslider-slider {height:61px; left:0; position:absolute; top:1px; width:100%;} +#padcontent { + font-size: 12px; + padding: 10px; +} +#timeslider-wrapper { + left: 0; + position: relative; + right: 0; + top: 0; +} +#timeslider-left { + background-image: url(../../static/img/timeslider_left.png); + height: 63px; + left: 0; + position: absolute; + width: 134px; +} +#timeslider-right { + background-image: url(../../static/img/timeslider_right.png); + height: 63px; + position: absolute; + right: 0; + top: 0; + width: 155px; +} +#timeslider { + background-image: url(../../static/img/timeslider_background.png); + height: 63px; + margin: 0 9px; +} +#timeslider #timeslider-slider { + height: 61px; + left: 0; + position: absolute; + top: 1px; + width: 100%; +} #ui-slider-handle { - -khtml-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - -webkit-user-select:none; - background-image:url(../../static/img/crushed_current_location.png); - cursor:pointer; - height:61px; - left:0; - position:absolute; - top:0; - user-select:none; - width:13px; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + background-image: url(../../static/img/crushed_current_location.png); + cursor: pointer; + height: 61px; + left: 0; + position: absolute; + top: 0; + width: 13px; } #ui-slider-bar { - -khtml-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - -webkit-user-select:none; - cursor:pointer; - height:35px; - margin-left:5px; - margin-right:148px; - position:relative; - top:20px; - user-select:none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + cursor: pointer; + height: 35px; + margin-left: 5px; + margin-right: 148px; + position: relative; + top: 20px; +} +#playpause_button, +#playpause_button_icon { + height: 47px; + position: absolute; + width: 47px; +} +#playpause_button { + background-image: url(../../static/img/crushed_button_undepressed.png); + right: 77px; + top: 9px; +} +#playpause_button_icon { + background-image: url(../../static/img/play.png); + left: 0; + top: 0; +} +.pause#playpause_button_icon { + background-image: url(../../static/img/pause.png) +} +#leftstar, +#rightstar, +#leftstep, +#rightstep { + background: url(../../static/img/stepper_buttons.png) 0 0 no-repeat; + height: 21px; + overflow: hidden; + position: absolute; +} +#leftstar { + background-position: 0 -44px; + right: 34px; + top: 8px; + width: 30px; +} +#rightstar { + background-position: -29px -44px; + right: 5px; + top: 8px; + width: 29px; +} +#leftstep { + background-position: 0 -22px; + right: 34px; + top: 20px; + width: 30px; +} +#rightstep { + background-position: -29px -22px; + right: 5px; + top: 20px; + width: 29px; } - -#playpause_button, #playpause_button_icon {height:47px; position:absolute; width:47px;} -#playpause_button {background-image:url(../../static/img/crushed_button_undepressed.png); right:77px; top:9px;} -#playpause_button_icon {background-image:url(../../static/img/play.png); left:0; top:0;} -.pause#playpause_button_icon {background-image:url(../../static/img/pause.png);} - -#leftstar, #rightstar, #leftstep, #rightstep - {background:url(../../static/img/stepper_buttons.png) 0 0 no-repeat; height:21px; overflow:hidden; position:absolute;} -#leftstar {background-position:0 -44px; right:34px; top:8px; width:30px;} -#rightstar {background-position:-29px -44px; right:5px; top:8px; width:29px;} -#leftstep {background-position:0 -22px; right:34px; top:20px; width:30px;} -#rightstep {background-position:-29px -22px; right:5px; top:20px; width:29px;} - #timeslider .star { - background-image:url(../../static/img/star.png); - cursor:pointer; - height:16px; - position:absolute; - top:40px; - width:15px; + background-image: url(../../static/img/star.png); + cursor: pointer; + height: 16px; + position: absolute; + top: 40px; + width: 15px; } - #timeslider #timer { - color:#fff; - font-family:Arial, sans-serif; - font-size:11px; - left:7px; - position:absolute; - text-align:center; - top:9px; - width:122px; + color: #fff; + font-family: Arial, sans-serif; + font-size: 11px; + left: 7px; + position: absolute; + text-align: center; + top: 9px; + width: 122px; } - - -.topbarcenter, #docbar {display:none;} -#padmain {top:0px !important;} -#editbarright {float:right;} -#returnbutton {color:#222; font-size:16px; line-height:29px; margin-top:0; padding-right:6px;} -#importexport .popup {width:185px;} -#importexport{ - top:118px; - width:185px; +.topbarcenter, +#docbar { + display: none } - - -.timeslider-bar -{ +#padmain { + top: 0px !important +} +#editbarright { + float: right +} +#returnbutton { + color: #222; + font-size: 16px; + line-height: 29px; + margin-top: 0; + padding-right: 6px; +} +#importexport .popup { + width: 185px +} +#importexport { + top: 118px; + width: 185px; +} +.timeslider-bar { background: #f7f7f7; + background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); + background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); background: linear-gradient(#f7f7f7, #f1f1f1 80%); - border-bottom: 1px solid #ccc; overflow: hidden; padding-top: 3px; width: 100%; } - -.timeslider-bar #editbar -{ +.timeslider-bar #editbar { border-bottom: none; float: right; width: 170px; width: initial; } - -.timeslider-bar h1 -{ - margin: 5px; +.timeslider-bar h1 { + margin: 5px } -.timeslider-bar p -{ - margin: 5px; +.timeslider-bar p { + margin: 5px } #timeslider-top { width: 100%; position: fixed; z-index: 1; } - #authorsList .author { padding-left: 0.4em; padding-right: 0.4em; } - #authorsList .author-anonymous { padding-left: 0.6em; padding-right: 0.6em; } - #padeditor { - position: static; + position: static } - /* lists */ -.list-bullet2, .list-indent2, .list-number2 {margin-left:3em;} -.list-bullet3, .list-indent3, .list-number3 {margin-left:4.5em;} -.list-bullet4, .list-indent4, .list-number4 {margin-left:6em;} -.list-bullet5, .list-indent5, .list-number5 {margin-left:7.5em;} -.list-bullet6, .list-indent6, .list-number6 {margin-left:9em;} -.list-bullet7, .list-indent7, .list-number7 {margin-left:10.5em;} -.list-bullet8, .list-indent8, .list-number8 {margin-left:12em;} - +.list-bullet2, +.list-indent2, +.list-number2 { + margin-left: 3em +} +.list-bullet3, +.list-indent3, +.list-number3 { + margin-left: 4.5em +} +.list-bullet4, +.list-indent4, +.list-number4 { + margin-left: 6em +} +.list-bullet5, +.list-indent5, +.list-number5 { + margin-left: 7.5em +} +.list-bullet6, +.list-indent6, +.list-number6 { + margin-left: 9em +} +.list-bullet7, +.list-indent7, +.list-number7 { + margin-left: 10.5em +} +.list-bullet8, +.list-indent8, +.list-number8 { + margin-left: 12em +} /* unordered lists */ -UL {list-style-type:disc; margin-left:1.5em;} -UL UL {margin-left:0 !important;} - -.list-bullet2, .list-bullet5, .list-bullet8 {list-style-type:circle;} -.list-bullet3, .list-bullet6 {list-style-type:square;} - -.list-indent1, .list-indent2, .list-indent3, .list-indent5, .list-indent5, .list-indent6, .list-indent7, .list-indent8 {list-style-type:none;} - +UL { + list-style-type: disc; + margin-left: 1.5em; +} +UL UL { + margin-left: 0 !important +} +.list-bullet2, +.list-bullet5, +.list-bullet8 { + list-style-type: circle +} +.list-bullet3, +.list-bullet6 { + list-style-type: square +} +.list-indent1, +.list-indent2, +.list-indent3, +.list-indent5, +.list-indent5, +.list-indent6, +.list-indent7, +.list-indent8 { + list-style-type: none +} /* ordered lists */ -OL {list-style-type:decimal; margin-left:1.5em;} -.list-number2, .list-number5, .list-number8 {list-style-type:lower-latin;} -.list-number3, .list-number6 {list-style-type:lower-roman;} - - - -/* IE 6/7 fixes ################################################################ */ -* HTML #ui-slider-handle {background-image:url(../../static/img/current_location.gif);} -* HTML #timeslider .star {background-image:url(../../static/img/star.gif);} -* HTML #playpause_button_icon {background-image:url(../../static/img/play.gif);} -* HTML .pause#playpause_button_icon {background-image:url(../../static/img/pause.gif);} \ No newline at end of file +OL { + list-style-type: decimal; + margin-left: 1.5em; +} +.list-number2, +.list-number5, +.list-number8 { + list-style-type: lower-latin +} +.list-number3, +.list-number6 { + list-style-type: lower-roman +} +/* IE 6/7 fixes */ +* HTML #ui-slider-handle { + background-image: url(../../static/img/current_location.gif) +} +* HTML #timeslider .star { + background-image: url(../../static/img/star.gif) +} +* HTML #playpause_button_icon { + background-image: url(../../static/img/play.gif) +} +* HTML .pause#playpause_button_icon { + background-image: url(../../static/img/pause.gif) +} \ No newline at end of file From b767192c583c7ab41452eca4b4b593e20785bef1 Mon Sep 17 00:00:00 2001 From: Chad Weider Date: Wed, 11 Apr 2012 01:54:16 -0700 Subject: [PATCH 06/22] Revert "Made it possible to disable minification again" This reverts commit 22eaa6ffc012e83438d54e6fb5b023a7952246a7. --- src/templates/pad.html | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/templates/pad.html b/src/templates/pad.html index 533bb2ba7..91583b360 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -276,21 +276,14 @@ - <% if (settings.minify) { %> - - <% } %> + - - - - - <% if (errors.length) { %> -
- <% errors.forEach(function (item) { %> -
<%= item.toString() %>
- <% }) %> -
- <% } %> - - -

Installed plugins

- - - - - - - - - - - - - - - - - -
NameDescription
- -
- - - -

Search for plugins to install

-
- - -
- - - - - - - - - - - - - - - - - -
NameDescription
- -
- - -
-

- Please wait: - -

- -
-
- - - + + + Plugin manager + + + + + + +
+ +

Etherpad Lite

+ +
+ + <% if (errors.length) { %> +
+ <% errors.forEach(function (item) { %> +
<%= item.toString() %>
+ <% }) %> +
+ <% } %> + + +

Installed plugins

+ + + + + + + + + + + + + + + + + +
NameDescription
+ +
+
+

Search for plugins to install

+
+ + +
+ + + + + + + + + + + + + + + + + +
NameDescription
+ +
+ +
+

+ Please wait: + +

+
+
+
+ + \ No newline at end of file From 05fcf4ba4a9a63c2007eef31405c2a3712776241 Mon Sep 17 00:00:00 2001 From: 0ip Date: Wed, 11 Apr 2012 22:22:28 +0300 Subject: [PATCH 09/22] Having "maxAge" twice doesn't double the fun --- settings.json.template | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/settings.json.template b/settings.json.template index 7aaa5d7ed..d75d53a8d 100644 --- a/settings.json.template +++ b/settings.json.template @@ -40,8 +40,8 @@ "minify" : true, /* How long may clients use served javascript code (in seconds)? Without versioning this - is may cause problems during deployment. Set to 0 to disable caching */ - "maxAge" : 21600, // 6 hours + may cause problems during deployment. Set to 0 to disable caching */ + "maxAge" : 21600, // 60 * 60 * 6 = 6 hours /* This is the path to the Abiword executable. Setting it to null, disables abiword. Abiword is needed to enable the import/export of pads*/ @@ -55,7 +55,4 @@ /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ "loglevel": "INFO", - - /* cache 6 hours = 1000*60*60*6 */ - "maxAge": 21600000 } From 3dd24bdf6f8ef330928c66bde9ed4ddd4dc58f6d Mon Sep 17 00:00:00 2001 From: 0ip Date: Wed, 11 Apr 2012 22:25:04 +0300 Subject: [PATCH 10/22] forgot to remove a ',' ^.^ --- settings.json.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.json.template b/settings.json.template index d75d53a8d..a664ea8ed 100644 --- a/settings.json.template +++ b/settings.json.template @@ -54,5 +54,5 @@ // "adminHttpAuth" : "user:pass", /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ - "loglevel": "INFO", + "loglevel": "INFO" } From 362ef454b811802a5e170835756ba158a393aa06 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Fri, 13 Apr 2012 05:17:48 -0400 Subject: [PATCH 11/22] Don't block static paths with http auth --- src/node/hooks/express/webaccess.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index d0e287373..48b5edae7 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -28,6 +28,11 @@ exports.basicAuth = function (req, res, next) { return next(); } } + // Do not require auth for static paths...this could be a bit brittle + else if (req.path.match(/^\/(static|javascripts|pluginfw)/)) { + return next(); + } + // Otherwise return Auth required Headers, delayed for 1 second, if auth failed. res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); From 06f36664b85340ec87aab09a5bfbeab0f65f489f Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Fri, 13 Apr 2012 17:21:07 -0400 Subject: [PATCH 12/22] Fix re-enabling line numbers. issue #618 --- src/static/js/ace2_inner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index d2d145035..b61c50e38 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -4635,7 +4635,7 @@ function Ace2Inner(){ function setClassPresence(elem, className, present) { if (present) $(elem).addClass(className); - else $(elem).removeClass(elem, className); + else $(elem).removeClass(className); } function setup() From d834c42ffc728ee7f21a27e4a975b99395276026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bartelme=C3=9F?= Date: Sun, 15 Apr 2012 19:18:29 +0200 Subject: [PATCH 13/22] avoid missing anon. timeslider authors --- src/static/js/broadcast_slider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/js/broadcast_slider.js b/src/static/js/broadcast_slider.js index a2a157733..6dffc0ef1 100644 --- a/src/static/js/broadcast_slider.js +++ b/src/static/js/broadcast_slider.js @@ -216,7 +216,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) authorsList.append(' ('); _.each(colorsAnonymous, function(color, i){ if( i > 0 ) authorsList.append(' '); - $(' ') + $(' ') .css('background-color', color) .addClass('author author-anonymous') .appendTo(authorsList); From e664320b8ceb734a333c1877a3f358975e55cf33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bartelme=C3=9F?= Date: Sun, 15 Apr 2012 19:25:23 +0200 Subject: [PATCH 14/22] removed sliderEnabled, supportsSlider clientVars, as they were not used anywhere --- src/node/handler/TimesliderMessageHandler.js | 2 - src/static/js/broadcast_slider.js | 131 ++++++++----------- 2 files changed, 52 insertions(+), 81 deletions(-) diff --git a/src/node/handler/TimesliderMessageHandler.js b/src/node/handler/TimesliderMessageHandler.js index a6cf8f4d8..5556efa1e 100644 --- a/src/node/handler/TimesliderMessageHandler.js +++ b/src/node/handler/TimesliderMessageHandler.js @@ -155,8 +155,6 @@ function createTimesliderClientVars (padId, callback) var clientVars = { viewId: padId, colorPalette: ["#ffc7c7", "#fff1c7", "#e3ffc7", "#c7ffd5", "#c7ffff", "#c7d5ff", "#e3c7ff", "#ffc7f1", "#ff8f8f", "#ffe38f", "#c7ff8f", "#8fffab", "#8fffff", "#8fabff", "#c78fff", "#ff8fe3", "#d97979", "#d9c179", "#a9d979", "#79d991", "#79d9d9", "#7991d9", "#a979d9", "#d979c1", "#d9a9a9", "#d9cda9", "#c1d9a9", "#a9d9b5", "#a9d9d9", "#a9b5d9", "#c1a9d9", "#d9a9cd"], - sliderEnabled : true, - supportsSlider: true, savedRevisions: [], padIdForUrl: padId, fullWidth: false, diff --git a/src/static/js/broadcast_slider.js b/src/static/js/broadcast_slider.js index a2a157733..1d1f279cf 100644 --- a/src/static/js/broadcast_slider.js +++ b/src/static/js/broadcast_slider.js @@ -162,11 +162,8 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) function showReconnectUI() { - if (!clientVars.sliderEnabled || !clientVars.supportsSlider) - { - $("#padmain, #rightbars").css('top', "130px"); - $("#timeslider").show(); - } + $("#padmain, #rightbars").css('top', "130px"); + $("#timeslider").show(); $('#error').show(); } @@ -287,55 +284,52 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) { disableSelection($("#playpause_button")[0]); disableSelection($("#timeslider")[0]); - - if (clientVars.sliderEnabled && clientVars.supportsSlider) + + $(document).keyup(function(e) { - $(document).keyup(function(e) - { - var code = -1; - if (!e) var e = window.event; - if (e.keyCode) code = e.keyCode; - else if (e.which) code = e.which; + var code = -1; + if (!e) var e = window.event; + if (e.keyCode) code = e.keyCode; + else if (e.which) code = e.which; - if (code == 37) - { // left - if (!e.shiftKey) - { - setSliderPosition(getSliderPosition() - 1); - } - else - { - var nextStar = 0; // default to first revision in document - for (var i = 0; i < savedRevisions.length; i++) - { - var pos = parseInt(savedRevisions[i].attr('pos')); - if (pos < getSliderPosition() && nextStar < pos) nextStar = pos; - } - setSliderPosition(nextStar); - } - } - else if (code == 39) + if (code == 37) + { // left + if (!e.shiftKey) { - if (!e.shiftKey) - { - setSliderPosition(getSliderPosition() + 1); - } - else - { - var nextStar = sliderLength; // default to last revision in document - for (var i = 0; i < savedRevisions.length; i++) - { - var pos = parseInt(savedRevisions[i].attr('pos')); - if (pos > getSliderPosition() && nextStar > pos) nextStar = pos; - } - setSliderPosition(nextStar); - } + setSliderPosition(getSliderPosition() - 1); } - else if (code == 32) playpause(); - - }); - } + else + { + var nextStar = 0; // default to first revision in document + for (var i = 0; i < savedRevisions.length; i++) + { + var pos = parseInt(savedRevisions[i].attr('pos')); + if (pos < getSliderPosition() && nextStar < pos) nextStar = pos; + } + setSliderPosition(nextStar); + } + } + else if (code == 39) + { + if (!e.shiftKey) + { + setSliderPosition(getSliderPosition() + 1); + } + else + { + var nextStar = sliderLength; // default to last revision in document + for (var i = 0; i < savedRevisions.length; i++) + { + var pos = parseInt(savedRevisions[i].attr('pos')); + if (pos > getSliderPosition() && nextStar > pos) nextStar = pos; + } + setSliderPosition(nextStar); + } + } + else if (code == 32) playpause(); + }); + $(window).resize(function() { updateSliderElements(); @@ -485,37 +479,16 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) $("#revision").css('right', "20px"); $("#revision").css('top', "20px"); } - - - if (clientVars.sliderEnabled) + + $("#timeslider").show(); + setSliderLength(clientVars.totalRevs); + setSliderPosition(clientVars.revNum); + + _.each(clientVars.savedRevisions, function(revision) { - if (clientVars.supportsSlider) - { - $("#timeslider").show(); - setSliderLength(clientVars.totalRevs); - setSliderPosition(clientVars.revNum); - _.each(clientVars.savedRevisions, function(revision) - { - addSavedRevision(revision.revNum, revision); - }) - } - else - { - // slider is not supported - $("#padmain, #rightbars").css('top', "130px"); - $("#timeslider").show(); - $("#error").html("The timeslider feature is not supported on this pad. Why not?"); - $("#error").show(); - } - } - else - { - if (clientVars.supportsSlider) - { - setSliderLength(clientVars.totalRevs); - setSliderPosition(clientVars.revNum); - } - } + addSavedRevision(revision.revNum, revision); + }) + } }); })(); From 3a62c6d2aba101563adb048746b339057f1eb459 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Mon, 9 Apr 2012 16:22:09 +0200 Subject: [PATCH 15/22] Bugfix for this being wrong in editorInfo.ace_performDocumentApplyAttributesToRange --- src/static/js/ace2_inner.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index b61c50e38..6e5f07bcb 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -5401,7 +5401,9 @@ function Ace2Inner(){ // Init documentAttributeManager documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset); - editorInfo.ace_performDocumentApplyAttributesToRange = documentAttributeManager.setAttributesOnRange; + editorInfo.ace_performDocumentApplyAttributesToRange = function () { + return documentAttributeManager.setAttributesOnRange.apply(documentAttributeManager, arguments); + }; $(document).ready(function(){ doc = document; // defined as a var in scope outside From 6f774bc6a567211a8a7157458c249d89a145c3ab Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Wed, 11 Apr 2012 18:07:19 +0200 Subject: [PATCH 16/22] Separated out the code for the plugin manager --- src/static/js/admin/plugins.js | 87 ++++++++++++++++++++++++++++++ src/templates/admin/plugins.html | 90 +------------------------------- 2 files changed, 88 insertions(+), 89 deletions(-) create mode 100644 src/static/js/admin/plugins.js diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js new file mode 100644 index 000000000..4ed8a6c64 --- /dev/null +++ b/src/static/js/admin/plugins.js @@ -0,0 +1,87 @@ +$(document).ready(function () { + var socket = io.connect().of("/pluginfw/installer"); + + var doUpdate = false; + + function updateHandlers() { + $("#progress.dialog .close").unbind('click').click(function () { + $("#progress.dialog").hide(); + }); + + $("#do-search").unbind('click').click(function () { + if ($("#search-query")[0].value != "") + socket.emit("search", $("#search-query")[0].value); + }); + + $(".do-install").unbind('click').click(function (e) { + var row = $(e.target).closest("tr"); + doUpdate = true; + socket.emit("install", row.find(".name").html()); + }); + + $(".do-uninstall").unbind('click').click(function (e) { + var row = $(e.target).closest("tr"); + doUpdate = true; + socket.emit("uninstall", row.find(".name").html()); + }); + } + + updateHandlers(); + + socket.on('progress', function (data) { + $("#progress.dialog .close").hide(); + $("#progress.dialog").show(); + var message = "Unknown status"; + if (data.message) { + message = "" + data.message.toString() + ""; + } + if (data.error) { + message = "" + data.error.toString() + ""; + } + $("#progress.dialog .message").html(message); + $("#progress.dialog .history").append("
" + message + "
"); + + if (data.progress >= 1) { + if (data.error) { + $("#progress.dialog .close").show(); + } else { + if (doUpdate) { + doUpdate = false; + socket.emit("load"); + } + $("#progress.dialog").hide(); + } + } + }); + + socket.on('search-result', function (data) { + $("#search-results *").remove(); + for (plugin_name in data.results) { + var plugin = data.results[plugin_name]; + var row = $("#search-result-template").clone(); + + for (attr in plugin) { + row.find("." + attr).html(plugin[attr]); + } + $("#search-results").append(row); + } + updateHandlers(); + }); + + socket.on('installed-results', function (data) { + $("#installed-plugins *").remove(); + for (plugin_name in data.results) { + var plugin = data.results[plugin_name]; + var row = $("#installed-plugin-template").clone(); + + for (attr in plugin.package) { + row.find("." + attr).html(plugin.package[attr]); + } + $("#installed-plugins").append(row); + } + updateHandlers(); + }); + + socket.emit("load"); + +}); diff --git a/src/templates/admin/plugins.html b/src/templates/admin/plugins.html index 6f38d0480..82bad5552 100644 --- a/src/templates/admin/plugins.html +++ b/src/templates/admin/plugins.html @@ -4,95 +4,7 @@ - +
From 7ab7ee9f5ee1caedbf1ca5ac10934a269ecde8f6 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Tue, 17 Apr 2012 22:18:43 +0200 Subject: [PATCH 17/22] Plugin admin fixes --- src/static/js/admin/plugins.js | 27 +++++++++++--- src/static/js/pluginfw/installer.js | 15 +++++--- src/templates/admin/plugins.html | 56 ++++++++++++++++------------- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index 4ed8a6c64..7f6c17b08 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -9,8 +9,10 @@ $(document).ready(function () { }); $("#do-search").unbind('click').click(function () { - if ($("#search-query")[0].value != "") - socket.emit("search", $("#search-query")[0].value); + socket.emit("search", { + pattern: $("#search-query")[0].value, + offset: $('#search-results').data('offset') || 0, + limit: 4}); }); $(".do-install").unbind('click').click(function (e) { @@ -29,8 +31,13 @@ $(document).ready(function () { updateHandlers(); socket.on('progress', function (data) { + if ($('#progress.dialog').data('progress') > data.progress) return; + $("#progress.dialog .close").hide(); $("#progress.dialog").show(); + + $('#progress.dialog').data('progress', data.progress); + var message = "Unknown status"; if (data.message) { message = "" + data.message.toString() + ""; @@ -55,16 +62,26 @@ $(document).ready(function () { }); socket.on('search-result', function (data) { - $("#search-results *").remove(); + var widget=$(".search-results"); + + widget.data('query', data.query); + widget.data('total', data.total); + + widget.find('.offset').html(data.qyery.offset); + widget.find('.limit').html(data.qyery.offset + data.qyery.offset.limit); + widget.find('.total').html(data.total); + + widget.find(".results *").remove(); for (plugin_name in data.results) { var plugin = data.results[plugin_name]; - var row = $("#search-result-template").clone(); + var row = widget.find(".template tr").clone(); for (attr in plugin) { row.find("." + attr).html(plugin[attr]); } - $("#search-results").append(row); + widget.find(".results").append(row); } + updateHandlers(); }); diff --git a/src/static/js/pluginfw/installer.js b/src/static/js/pluginfw/installer.js index 127a95aa7..09bde9203 100644 --- a/src/static/js/pluginfw/installer.js +++ b/src/static/js/pluginfw/installer.js @@ -55,7 +55,7 @@ exports.install = function(plugin_name, cb) { ); }; -exports.search = function(pattern, cb) { +exports.search = function(query, cb) { withNpm( function (cb) { registry.get( @@ -63,11 +63,18 @@ exports.search = function(pattern, cb) { function (er, data) { if (er) return cb(er); var res = {}; + var i = 0; for (key in data) { - if (key.indexOf(plugins.prefix) == 0 && key.indexOf(pattern) != -1) - res[key] = data[key]; + if (/* && key.indexOf(plugins.prefix) == 0 */ + key.indexOf(query.pattern) != -1) { + i++; + if (i > query.offset + && i <= query.offset + query.limit) { + res[key] = data[key]; + } + } } - cb(null, {results:res}); + cb(null, {results:res, query: query, total:i}); } ); }, diff --git a/src/templates/admin/plugins.html b/src/templates/admin/plugins.html index 82bad5552..c1cc645a0 100644 --- a/src/templates/admin/plugins.html +++ b/src/templates/admin/plugins.html @@ -40,31 +40,37 @@ -

Search for plugins to install

-
- - -
- - - - - - - - - - - - - - - - - -
NameDescription
- -
+
+

Search for plugins to install

+
+ + +
+ + + + + + + + + + + + + + + + + +
NameDescription
+ +
+ + .. of . + +
+

From d6f476312d7380e29d9995756c32a2b33134ab46 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Wed, 18 Apr 2012 10:16:41 +0200 Subject: [PATCH 18/22] Spelling bugfixes --- src/static/js/admin/plugins.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index 7f6c17b08..54454c2bc 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -67,8 +67,8 @@ $(document).ready(function () { widget.data('query', data.query); widget.data('total', data.total); - widget.find('.offset').html(data.qyery.offset); - widget.find('.limit').html(data.qyery.offset + data.qyery.offset.limit); + widget.find('.offset').html(data.query.offset); + widget.find('.limit').html(data.query.offset + data.query.limit); widget.find('.total').html(data.total); widget.find(".results *").remove(); From 4c1d94343fe1b1a8ff02d7cfaef9f9506676d072 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Wed, 18 Apr 2012 13:43:34 +0200 Subject: [PATCH 19/22] Better plugin admin interface --- src/node/hooks/express/adminplugins.js | 2 +- src/static/js/admin/plugins.js | 38 ++++++++++++++++++++++---- src/static/js/pluginfw/installer.js | 25 +++++++++++++---- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index fa7e70771..1d1320ab3 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -27,7 +27,7 @@ exports.socketio = function (hook_name, args, cb) { socket.on("search", function (query) { socket.emit("progress", {progress:0, message:'Fetching results...'}); - installer.search(query, function (progress) { + installer.search(query, true, function (progress) { if (progress.results) socket.emit("search-result", progress); socket.emit("progress", progress); diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index 54454c2bc..6ae085c2a 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -1,18 +1,28 @@ $(document).ready(function () { var socket = io.connect().of("/pluginfw/installer"); + $('.search-results').data('query', { + pattern: '', + offset: 0, + limit: 4, + }); + var doUpdate = false; + var search = function () { + socket.emit("search", $('.search-results').data('query')); + } + function updateHandlers() { $("#progress.dialog .close").unbind('click').click(function () { $("#progress.dialog").hide(); }); $("#do-search").unbind('click').click(function () { - socket.emit("search", { - pattern: $("#search-query")[0].value, - offset: $('#search-results').data('offset') || 0, - limit: 4}); + var query = $('.search-results').data('query'); + query.pattern = $("#search-query")[0].value; + query.offset = 0; + search(); }); $(".do-install").unbind('click').click(function (e) { @@ -26,12 +36,29 @@ $(document).ready(function () { doUpdate = true; socket.emit("uninstall", row.find(".name").html()); }); + + $(".do-prev-page").unbind('click').click(function (e) { + var query = $('.search-results').data('query'); + query.offset -= query.limit; + if (query.offset < 0) { + query.offset = 0; + } + search(); + }); + $(".do-next-page").unbind('click').click(function (e) { + var query = $('.search-results').data('query'); + var total = $('.search-results').data('total'); + if (query.offset + query.limit < total) { + query.offset += query.limit; + } + search(); + }); } updateHandlers(); socket.on('progress', function (data) { - if ($('#progress.dialog').data('progress') > data.progress) return; + if (data.progress > 0 && $('#progress.dialog').data('progress') > data.progress) return; $("#progress.dialog .close").hide(); $("#progress.dialog").show(); @@ -100,5 +127,6 @@ $(document).ready(function () { }); socket.emit("load"); + search(); }); diff --git a/src/static/js/pluginfw/installer.js b/src/static/js/pluginfw/installer.js index 09bde9203..1bb8db9e0 100644 --- a/src/static/js/pluginfw/installer.js +++ b/src/static/js/pluginfw/installer.js @@ -55,18 +55,33 @@ exports.install = function(plugin_name, cb) { ); }; -exports.search = function(query, cb) { +exports.searchCache = null; + +exports.search = function(query, cache, cb) { withNpm( function (cb) { - registry.get( - "/-/all", null, 600, false, true, + var getData = function (cb) { + if (cache && exports.searchCache) { + cb(null, exports.searchCache); + } else { + registry.get( + "/-/all", null, 600, false, true, + function (er, data) { + if (er) return cb(er); + exports.searchCache = data; + cb(er, data); + } + ); + } + } + getData( function (er, data) { if (er) return cb(er); var res = {}; var i = 0; for (key in data) { - if (/* && key.indexOf(plugins.prefix) == 0 */ - key.indexOf(query.pattern) != -1) { + if ( key.indexOf(plugins.prefix) == 0 + && key.indexOf(query.pattern) != -1) { i++; if (i > query.offset && i <= query.offset + query.limit) { From ac36a99a7226e1092c2e7e28c9b6e32d8f82e6fb Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Thu, 19 Apr 2012 14:25:12 +0200 Subject: [PATCH 20/22] More general basic auth --- settings.json.template | 25 ++++-- src/node/hooks/express/adminplugins.js | 2 + src/node/hooks/express/socketio.js | 18 +++- src/node/hooks/express/webaccess.js | 110 +++++++++++++++++-------- src/node/utils/Settings.js | 15 ++-- src/package.json | 1 + 6 files changed, 123 insertions(+), 48 deletions(-) diff --git a/settings.json.template b/settings.json.template index a664ea8ed..d8f67e765 100644 --- a/settings.json.template +++ b/settings.json.template @@ -46,12 +46,27 @@ /* This is the path to the Abiword executable. Setting it to null, disables abiword. Abiword is needed to enable the import/export of pads*/ "abiword" : null, - - /* This setting is used if you need http basic auth */ - // "httpAuth" : "user:pass", + + /* This setting is used if you require authentication of all users. + Note: /admin always requires authentication. */ + "requireAuthentication": false, - /* This setting is used for http basic auth for admin pages. If not set, the admin page won't be accessible from web*/ - // "adminHttpAuth" : "user:pass", + /* Require authorization by a module, or a user with is_admin set, + see below. Access to /admin allways requires either, regardless + of this setting. */ + "requireAuthorization": false, + + /* Users for basic authentication. is_admin = true gives access to /admin */ + "users": { + "admin": { + "password": "changeme", + "is_admin": true + }, + "user": { + "password": "changeme", + "is_admin": false + } + }, /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ "loglevel": "INFO" diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index 1d1320ab3..6cc80cf2a 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -21,6 +21,8 @@ exports.expressCreateServer = function (hook_name, args, cb) { exports.socketio = function (hook_name, args, cb) { var io = args.io.of("/pluginfw/installer"); io.on('connection', function (socket) { + if (!socket.handshake.session.user.is_admin) return; + socket.on("load", function (query) { socket.emit("installed-results", {results: plugins.plugins}); }); diff --git a/src/node/hooks/express/socketio.js b/src/node/hooks/express/socketio.js index e040f7aca..6774b653a 100644 --- a/src/node/hooks/express/socketio.js +++ b/src/node/hooks/express/socketio.js @@ -7,11 +7,27 @@ var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); var padMessageHandler = require("../../handler/PadMessageHandler"); var timesliderMessageHandler = require("../../handler/TimesliderMessageHandler"); - +var connect = require('connect'); + exports.expressCreateServer = function (hook_name, args, cb) { //init socket.io and redirect all requests to the MessageHandler var io = socketio.listen(args.app); + /* Require an express session cookie to be present, and load the + * session. See http://www.danielbaulig.de/socket-ioexpress for more + * info */ + io.set('authorization', function (data, accept) { + if (!data.headers.cookie) return accept('No session cookie transmitted.', false); + data.cookie = connect.utils.parseCookie(data.headers.cookie); + data.sessionID = data.cookie.express_sid; + args.app.sessionStore.get(data.sessionID, function (err, session) { + if (err || !session) return accept('Bad session / session has expired', false); + data.session = new connect.middleware.session.Session(data, session); + accept(null, true); + }); + }); + + //this is only a workaround to ensure it works with all browers behind a proxy //we should remove this when the new socket.io version is more stable io.set('transports', ['xhr-polling']); diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 48b5edae7..499451d89 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -2,55 +2,99 @@ var express = require('express'); var log4js = require('log4js'); var httpLogger = log4js.getLogger("http"); var settings = require('../../utils/Settings'); +var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; +var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); //checks for basic http auth exports.basicAuth = function (req, res, next) { - - // When handling HTTP-Auth, an undefined password will lead to no authorization at all - var pass = settings.httpAuth || ''; - - if (req.path.indexOf('/admin') == 0) { - var pass = settings.adminHttpAuth; - + var authorize = function (cb) { + // Do not require auth for static paths...this could be a bit brittle + if (req.path.match(/^\/(static|javascripts|pluginfw)/)) return cb(true); + + if (req.path.indexOf('/admin') != 0) { + if (!settings.requireAuthentication) return cb(true); + if (!settings.requireAuthorization && req.session && req.session.user) return cb(true); + } + + if (req.session && req.session.user && req.session.user.is_admin) return cb(true); + + // hooks.aCallFirst("authorize", {resource: req.path, req: req}, cb); + cb(false); } - - // Just pass if password is an empty string - if (pass === '') { - return next(); + + var authenticate = function (cb) { + // If auth headers are present use them to authenticate... + if (req.headers.authorization && req.headers.authorization.search('Basic ') === 0) { + var userpass = new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString().split(":") + var username = userpass[0]; + var password = userpass[1]; + + if (settings.users[username] != undefined && settings.users[username].password == password) { + settings.users[username].username = username; + req.session.user = settings.users[username]; + return cb(true); + } + // return hooks.aCallFirst("authenticate", {req: req, username: username, password: password}, cb); + } + // hooks.aCallFirst("authenticate", {req: req}, cb); + cb(false); } - - - // If a password has been set and auth headers are present... - if (pass && req.headers.authorization && req.headers.authorization.search('Basic ') === 0) { - // ...check login and password - if (new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString() === pass) { - return next(); + + + var failure = function () { + /* Authentication OR authorization failed. Return Auth required + * Headers, delayed for 1 second, if authentication failed. */ + res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); + if (req.headers.authorization) { + setTimeout(function () { + res.send('Authentication required', 401); + }, 1000); + } else { + res.send('Authentication required', 401); } } - // Do not require auth for static paths...this could be a bit brittle - else if (req.path.match(/^\/(static|javascripts|pluginfw)/)) { - return next(); - } - // Otherwise return Auth required Headers, delayed for 1 second, if auth failed. - res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); - if (req.headers.authorization) { - setTimeout(function () { - res.send('Authentication required', 401); - }, 1000); - } else { - res.send('Authentication required', 401); - } + /* This is the actual authentication/authorization hoop. It is done in four steps: + + 1) Try to just access the thing + 2) If not allowed using whatever creds are in the current session already, try to authenticate + 3) If authentication using already supplied credentials succeeds, try to access the thing again + 4) If all els fails, give the user a 401 to request new credentials + + Note that the process could stop already in step 3 with a redirect to login page. + + */ + + authorize(function (ok) { + if (ok) return next(); + authenticate(function (ok) { + if (!ok) return failure(); + authorize(function (ok) { + if (ok) return next(); + failure(); + }); + }); + }); } exports.expressConfigure = function (hook_name, args, cb) { - args.app.use(exports.basicAuth); - // If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158. // Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway. if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR")) args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'})); args.app.use(express.cookieParser()); + + /* Do not let express create the session, so that we can retain a + * reference to it for socket.io to use. Also, set the key (cookie + * name) to a javascript identifier compatible string. Makes code + * handling it cleaner :) */ + + args.app.sessionStore = new express.session.MemoryStore(); + args.app.use(express.session({store: args.app.sessionStore, + key: 'express_sid', + secret: apikey = randomString(32)})); + + args.app.use(exports.basicAuth); } diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 12fcc55c5..cb6a64033 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -80,15 +80,12 @@ exports.abiword = null; */ exports.loglevel = "INFO"; -/** - * Http basic auth, with "user:password" format - */ -exports.httpAuth = null; - -/** - * Http basic auth, with "user:password" format - */ -exports.adminHttpAuth = null; +/* This setting is used if you need authentication and/or + * authorization. Note: /admin always requires authentication, and + * either authorization by a module, or a user with is_admin set */ +exports.requireAuthentication = false; +exports.requireAuthorization = false; +exports.users = {}; //checks if abiword is avaiable exports.abiwordAvailable = function() diff --git a/src/package.json b/src/package.json index 83441da08..eda385b22 100644 --- a/src/package.json +++ b/src/package.json @@ -17,6 +17,7 @@ "ueberDB" : "0.1.7", "async" : "0.1.18", "express" : "2.5.8", + "connect" : "1.8.7", "clean-css" : "0.3.2", "uglify-js" : "1.2.5", "formidable" : "1.0.9", From 7b39da2d69e759e0f75cc19adb92e130583c68d0 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Thu, 19 Apr 2012 16:03:42 +0200 Subject: [PATCH 21/22] Bugfix for callFirst to actually call call hooks until it finds one that returns non-empty, which is actually usefull, as opposed to just calling one hook. --- src/static/js/pluginfw/hooks.js | 64 +++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/src/static/js/pluginfw/hooks.js b/src/static/js/pluginfw/hooks.js index c4cd5aebf..49e46c608 100644 --- a/src/static/js/pluginfw/hooks.js +++ b/src/static/js/pluginfw/hooks.js @@ -4,27 +4,63 @@ var _; /* FIXME: Ugly hack, in the future, use same code for server & client */ if (plugins.isClient) { var async = require("ep_etherpad-lite/static/js/pluginfw/async"); - _ = require("ep_etherpad-lite/static/js/underscore"); + var _ = require("ep_etherpad-lite/static/js/underscore"); } else { var async = require("async"); - _ = require("underscore"); + var _ = require("underscore"); } exports.bubbleExceptions = true var hookCallWrapper = function (hook, hook_name, args, cb) { if (cb === undefined) cb = function (x) { return x; }; + + // Normalize output to list for both sync and async cases + var normalize = function(x) { + if (x == undefined) return []; + return x; + } + var normalizedhook = function () { + return normalize(hook.hook_fn(hook_name, args, function (x) { + return cb(normalize(x)); + })); + } + if (exports.bubbleExceptions) { - return hook.hook_fn(hook_name, args, cb); + return normalizedhook(); } else { try { - return hook.hook_fn(hook_name, args, cb); + return normalizedhook(); } catch (ex) { console.error([hook_name, hook.part.full_name, ex.stack || ex]); } } } +exports.syncMapFirst = function (lst, fn) { + var i; + var result; + for (i = 0; i < lst.length; i++) { + result = fn(lst[i]) + if (result.length) return result; + } + return undefined; +} + +exports.mapFirst = function (lst, fn, cb) { + var i = 0; + + next = function () { + if (i >= lst.length) return cb(undefined); + fn(lst[i++], function (err, result) { + if (err) return cb(err); + if (result.length) return cb(null, result); + next(); + }); + } + next(); +} + /* Don't use Array.concat as it flatterns arrays within the array */ exports.flatten = function (lst) { @@ -44,9 +80,9 @@ exports.flatten = function (lst) { exports.callAll = function (hook_name, args) { if (!args) args = {}; if (plugins.hooks[hook_name] === undefined) return []; - return exports.flatten(_.map(plugins.hooks[hook_name], function (hook) { + return _.flatten(_.map(plugins.hooks[hook_name], function (hook) { return hookCallWrapper(hook, hook_name, args); - })); + }), true); } exports.aCallAll = function (hook_name, args, cb) { @@ -59,7 +95,7 @@ exports.aCallAll = function (hook_name, args, cb) { hookCallWrapper(hook, hook_name, args, function (res) { cb(null, res); }); }, function (err, res) { - cb(null, exports.flatten(res)); + cb(null, _.flatten(res, true)); } ); } @@ -67,14 +103,22 @@ exports.aCallAll = function (hook_name, args, cb) { exports.callFirst = function (hook_name, args) { if (!args) args = {}; if (plugins.hooks[hook_name][0] === undefined) return []; - return exports.flatten(hookCallWrapper(plugins.hooks[hook_name][0], hook_name, args)); + return exports.syncMapFirst(plugins.hooks[hook_name], function (hook) { + return hookCallWrapper(hook, hook_name, args); + }); } exports.aCallFirst = function (hook_name, args, cb) { if (!args) args = {}; if (!cb) cb = function () {}; - if (plugins.hooks[hook_name][0] === undefined) return cb(null, []); - hookCallWrapper(plugins.hooks[hook_name][0], hook_name, args, function (res) { cb(null, exports.flatten(res)); }); + if (plugins.hooks[hook_name] === undefined) return cb(null, []); + exports.mapFirst( + plugins.hooks[hook_name], + function (hook, cb) { + hookCallWrapper(hook, hook_name, args, function (res) { cb(null, res); }); + }, + cb + ); } exports.callAllStr = function(hook_name, args, sep, pre, post) { From ecac40d062747e4668dd942443b361077fd55f74 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Thu, 19 Apr 2012 16:04:03 +0200 Subject: [PATCH 22/22] Changed the authentication mechanism to support hooks --- settings.json.template | 13 +++++---- src/node/hooks/express/adminplugins.js | 2 +- src/node/hooks/express/webaccess.js | 39 ++++++++++++++++---------- src/node/server.js | 5 ++-- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/settings.json.template b/settings.json.template index d8f67e765..f89fcd8ed 100644 --- a/settings.json.template +++ b/settings.json.template @@ -51,22 +51,23 @@ Note: /admin always requires authentication. */ "requireAuthentication": false, - /* Require authorization by a module, or a user with is_admin set, - see below. Access to /admin allways requires either, regardless - of this setting. */ + /* Require authorization by a module, or a user with is_admin set, see below. */ "requireAuthorization": false, - /* Users for basic authentication. is_admin = true gives access to /admin */ + /* Users for basic authentication. is_admin = true gives access to /admin. + If you do not uncomment this, /admin will not be available! */ + /* "users": { "admin": { - "password": "changeme", + "password": "changeme1", "is_admin": true }, "user": { - "password": "changeme", + "password": "changeme1", "is_admin": false } }, + */ /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ "loglevel": "INFO" diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index 6cc80cf2a..7b21206c9 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -21,7 +21,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { exports.socketio = function (hook_name, args, cb) { var io = args.io.of("/pluginfw/installer"); io.on('connection', function (socket) { - if (!socket.handshake.session.user.is_admin) return; + if (!socket.handshake.session.user || !socket.handshake.session.user.is_admin) return; socket.on("load", function (query) { socket.emit("installed-results", {results: plugins.plugins}); diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 499451d89..028d8ab1b 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -8,7 +8,13 @@ var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); //checks for basic http auth exports.basicAuth = function (req, res, next) { - var authorize = function (cb) { + var hookResultMangle = function (cb) { + return function (err, data) { + return cb(!err && data.length && data[0]); + } + } + + var authorize = function (cb) { // Do not require auth for static paths...this could be a bit brittle if (req.path.match(/^\/(static|javascripts|pluginfw)/)) return cb(true); @@ -19,8 +25,7 @@ exports.basicAuth = function (req, res, next) { if (req.session && req.session.user && req.session.user.is_admin) return cb(true); - // hooks.aCallFirst("authorize", {resource: req.path, req: req}, cb); - cb(false); + hooks.aCallFirst("authorize", {req: req, res:res, next:next, resource: req.path}, hookResultMangle(cb)); } var authenticate = function (cb) { @@ -35,24 +40,28 @@ exports.basicAuth = function (req, res, next) { req.session.user = settings.users[username]; return cb(true); } - // return hooks.aCallFirst("authenticate", {req: req, username: username, password: password}, cb); + return hooks.aCallFirst("authenticate", {req: req, res:res, next:next, username: username, password: password}, hookResultMangle(cb)); } - // hooks.aCallFirst("authenticate", {req: req}, cb); - cb(false); + hooks.aCallFirst("authenticate", {req: req, res:res, next:next}, hookResultMangle(cb)); } + /* Authentication OR authorization failed. */ var failure = function () { - /* Authentication OR authorization failed. Return Auth required - * Headers, delayed for 1 second, if authentication failed. */ - res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); - if (req.headers.authorization) { - setTimeout(function () { + return hooks.aCallFirst("authFailure", {req: req, res:res, next:next}, hookResultMangle(function (ok) { + if (ok) return; + /* No plugin handler for invalid auth. Return Auth required + * Headers, delayed for 1 second, if authentication failed + * before. */ + res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); + if (req.headers.authorization) { + setTimeout(function () { + res.send('Authentication required', 401); + }, 1000); + } else { res.send('Authentication required', 401); - }, 1000); - } else { - res.send('Authentication required', 401); - } + } + })); } diff --git a/src/node/server.js b/src/node/server.js index 6b443edb7..9d2c52e44 100644 --- a/src/node/server.js +++ b/src/node/server.js @@ -30,6 +30,7 @@ var path = require('path'); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); var npm = require("npm/lib/npm.js"); +var _ = require("underscore"); //try to get the git version var version = ""; @@ -88,11 +89,11 @@ async.waterfall([ //let the server listen app.listen(settings.port, settings.ip); console.log("Server is listening at " + settings.ip + ":" + settings.port); - if(settings.adminHttpAuth){ + if(!_.isEmpty(settings.users)){ console.log("Plugin admin page listening at " + settings.ip + ":" + settings.port + "/admin/plugins"); } else{ - console.log("Admin username and password not set in settings.json. To access admin please uncomment and edit adminHttpAuth in settings.json"); + console.log("Admin username and password not set in settings.json. To access admin please uncomment and edit 'users' in settings.json"); } callback(null); }