summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bruederli <thomas@roundcube.net>2013-11-07 11:39:23 +0100
committerThomas Bruederli <thomas@roundcube.net>2013-11-07 11:39:23 +0100
commit884e1ecce94a41e705856b0cae6540a171f53461 (patch)
tree8fe459e326459c4a3077af2f53d0fc21b9573ad7
parent1e7d1240ed09c4abf411e9ad76eaccf93d4512c0 (diff)
parent00de8ddf8d899a8c9a9ca89009f845f88eb7a6cc (diff)
Merge branch 'master' of github.com:roundcube/roundcubemail
-rw-r--r--.htaccess21
-rw-r--r--config/.htaccess2
-rw-r--r--logs/.htaccess2
-rw-r--r--program/.htaccess4
-rw-r--r--program/js/app.js141
-rw-r--r--program/js/list.js16
-rw-r--r--program/lib/Roundcube/rcube_db.php29
-rw-r--r--temp/.htaccess2
8 files changed, 99 insertions, 118 deletions
diff --git a/.htaccess b/.htaccess
index dc6e62f38..43ab5b04f 100644
--- a/.htaccess
+++ b/.htaccess
@@ -26,12 +26,27 @@ php_value session.gc_probability 1
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^favicon\.ico$ skins/larry/images/favicon.ico
+
# security rules
-RewriteRule \.git - [F]
-RewriteRule ^/?(README(.md)?|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ - [F]
-RewriteRule ^/?(SQL|bin) - [F]
+RewriteRule ^/?(\.git|SQL|bin|config|logs|temp|tests|program\/(include|lib|localization|steps)) - [F]
+RewriteRule /?(README(.md)?|composer\.json-dist|composer\.json|package\.xml)$ - [F]
</IfModule>
+# deny access to all files not containing a "." (dot)
+# to block access to different README, Changelog, INSTALL, etc.
+# files of various skins and plugins.
+<FilesMatch "^[^\.]+$">
+ # Apache 2.4
+ <IfModule mod_authz_core.c>
+ Require all denied
+ </IfModule>
+ # Apache 2.2
+ <IfModule !mod_authz_core.c>
+ Order Allow,Deny
+ Deny from all
+ </IfModule>
+</FilesMatch>
+
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
</IfModule>
diff --git a/config/.htaccess b/config/.htaccess
deleted file mode 100644
index 8e6a345dc..000000000
--- a/config/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-Order allow,deny
-Deny from all \ No newline at end of file
diff --git a/logs/.htaccess b/logs/.htaccess
deleted file mode 100644
index 8e6a345dc..000000000
--- a/logs/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-Order allow,deny
-Deny from all \ No newline at end of file
diff --git a/program/.htaccess b/program/.htaccess
deleted file mode 100644
index be9e7e25a..000000000
--- a/program/.htaccess
+++ /dev/null
@@ -1,4 +0,0 @@
-<IfModule mod_rewrite.c>
-RewriteEngine On
-RewriteRule !^(js|resources) - [F]
-</IfModule>
diff --git a/program/js/app.js b/program/js/app.js
index 1f75e219c..f7fd7cea0 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -218,12 +218,8 @@ function rcube_webmail()
// load messages
this.command('list');
- }
- if (this.gui_objects.qsearchbox) {
- if (this.env.search_text != null)
- this.gui_objects.qsearchbox.value = this.env.search_text;
- $(this.gui_objects.qsearchbox).focusin(function() { rcmail.message_list && rcmail.message_list.blur(); });
+ $(this.gui_objects.qsearchbox).val(this.env.search_text).focusin(function() { rcmail.message_list.blur(); });
}
this.set_button_titles();
@@ -285,10 +281,10 @@ function rcube_webmail()
return rcube_event.cancel(e);
});
- // avoid textarea loosing focus when hitting the save-response button/link
- for (var i=0; this.buttons['save-response'] && i < this.buttons['save-response'].length; i++) {
- $('#'+this.buttons['save-response'][i].id).mousedown(function(e){ return rcube_event.cancel(e); })
- }
+ // avoid textarea loosing focus when hitting the save-response button/link
+ for (var i=0; this.buttons['save-response'] && i < this.buttons['save-response'].length; i++) {
+ $('#'+this.buttons['save-response'][i].id).mousedown(function(e){ return rcube_event.cancel(e); })
+ }
}
document.onmouseup = function(e){ return p.doc_mouse_up(e); };
@@ -351,7 +347,7 @@ function rcube_webmail()
this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups);
this.enable_command('add', 'import', this.env.writable_source);
- this.enable_command('list', 'listgroup', 'pushgroup', 'popgroup', 'listsearch', 'advanced-search', true);
+ this.enable_command('list', 'listgroup', 'pushgroup', 'popgroup', 'listsearch', 'search', 'reset-search', 'advanced-search', true);
if (this.gui_objects.contactslist) {
this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
@@ -369,8 +365,8 @@ function rcube_webmail()
this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return p.click_on_list(e); };
document.onmouseup = function(e){ return p.doc_mouse_up(e); };
- if (this.gui_objects.qsearchbox)
- $(this.gui_objects.qsearchbox).focusin(function() { rcmail.contact_list.blur(); });
+
+ $(this.gui_objects.qsearchbox).focusin(function() { rcmail.contact_list.blur(); });
this.update_group_commands();
this.command('list');
@@ -394,9 +390,6 @@ function rcube_webmail()
this.init_contact_form();
}
- if (this.gui_objects.qsearchbox)
- this.enable_command('search', 'reset-search', true);
-
break;
case 'settings':
@@ -408,9 +401,6 @@ function rcube_webmail()
else if (this.env.action == 'edit-identity' || this.env.action == 'add-identity') {
this.enable_command('save', 'edit', 'toggle-editor', true);
this.enable_command('delete', this.env.identities_level < 2);
-
- if (this.env.action == 'add-identity')
- $("input[type='text']").first().select();
}
else if (this.env.action == 'folders') {
this.enable_command('subscribe', 'unsubscribe', 'create-folder', 'rename-folder', true);
@@ -419,7 +409,6 @@ function rcube_webmail()
this.enable_command('save', 'folder-size', true);
parent.rcmail.env.exists = this.env.messagecount;
parent.rcmail.enable_command('purge', this.env.messagecount);
- $("input[type='text']").first().select();
}
else if (this.env.action == 'responses') {
this.enable_command('add', true);
@@ -445,7 +434,7 @@ function rcube_webmail()
}
else if (this.gui_objects.responseslist) {
this.responses_list = new rcube_list_widget(this.gui_objects.responseslist, {multiselect:false, draggable:false, keyboard:false});
- this.responses_list.addEventListener('select', function(list){
+ this.responses_list.addEventListener('select', function(list) {
var win, id = list.get_single_selection();
p.enable_command('delete', !!id && $.inArray(id, p.env.readonly_responses) < 0);
if (id && (win = p.get_frame_window(p.env.contentframe))) {
@@ -489,6 +478,11 @@ function rcube_webmail()
break;
}
+ // select first input field in an edit form
+ if (this.gui_objects.editform)
+ $("input,select,textarea", this.gui_objects.editform)
+ .not(':hidden').not(':disabled').first().select();
+
// unset contentframe variable if preview_pane is enabled
if (this.env.contentframe && !$('#' + this.env.contentframe).is(':visible'))
this.env.contentframe = null;
@@ -4820,8 +4814,6 @@ function rcube_webmail()
$('input.datepicker').datepicker();
}
- $("input[type='text']:visible").first().focus();
-
// Submit search form on Enter
if (this.env.action == 'search')
$(this.gui_objects.editform).append($('<input type="submit">').hide())
@@ -5438,7 +5430,10 @@ function rcube_webmail()
this.init_subscription_list = function()
{
- var p = this;
+ var p = this, delim = RegExp.escape(this.env.delimiter);
+
+ this.last_sub_rx = RegExp('['+delim+']?[^'+delim+']+$');
+
this.subscription_list = new rcube_list_widget(this.gui_objects.subscriptionlist,
{multiselect:false, draggable:true, keyboard:false, toggleselect:true});
this.subscription_list.addEventListener('select', function(o){ p.subscription_select(o); });
@@ -5449,6 +5444,7 @@ function rcube_webmail()
row.obj.onmouseout = function() { p.unfocus_subscription(row.id); };
};
this.subscription_list.init();
+
$('#mailboxroot')
.mouseover(function(){ p.focus_subscription(this.id); })
.mouseout(function(){ p.unfocus_subscription(this.id); })
@@ -5456,9 +5452,7 @@ function rcube_webmail()
this.focus_subscription = function(id)
{
- var row, folder,
- delim = RegExp.escape(this.env.delimiter),
- reg = RegExp('['+delim+']?[^'+delim+']+$');
+ var row, folder;
if (this.drag_active && this.env.mailbox && (row = document.getElementById(id)))
if (this.env.subscriptionrows[id] &&
@@ -5466,8 +5460,8 @@ function rcube_webmail()
) {
if (this.check_droptarget(folder) &&
!this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2] &&
- (folder != this.env.mailbox.replace(reg, '')) &&
- (!folder.startsWith(this.env.mailbox + this.env.delimiter))
+ folder != this.env.mailbox.replace(this.last_sub_rx, '') &&
+ !folder.startsWith(this.env.mailbox + this.env.delimiter)
) {
this.env.dstfolder = folder;
$(row).addClass('droptarget');
@@ -5480,7 +5474,8 @@ function rcube_webmail()
var row = $('#'+id);
this.env.dstfolder = null;
- if (this.env.subscriptionrows[id] && row[0])
+
+ if (this.env.subscriptionrows[id] && row.length)
row.removeClass('droptarget');
else
$(this.subscription_list.frame).removeClass('droptarget');
@@ -5506,21 +5501,20 @@ function rcube_webmail()
this.subscription_move_folder = function(list)
{
- var delim = RegExp.escape(this.env.delimiter),
- reg = RegExp('['+delim+']?[^'+delim+']+$');
-
- if (this.env.mailbox && this.env.dstfolder !== null && (this.env.dstfolder != this.env.mailbox) &&
- (this.env.dstfolder != this.env.mailbox.replace(reg, ''))
+ if (this.env.mailbox && this.env.dstfolder !== null &&
+ this.env.dstfolder != this.env.mailbox &&
+ this.env.dstfolder != this.env.mailbox.replace(this.last_sub_rx, '')
) {
- reg = new RegExp('[^'+delim+']*['+delim+']', 'g');
- var basename = this.env.mailbox.replace(reg, ''),
- newname = this.env.dstfolder === '' ? basename : this.env.dstfolder+this.env.delimiter+basename;
+ var path = this.env.mailbox.split(this.env.delimiter),
+ basename = path.pop(),
+ newname = this.env.dstfolder === '' ? basename : this.env.dstfolder + this.env.delimiter + basename;
if (newname != this.env.mailbox) {
this.http_post('rename-folder', {_folder_oldname: this.env.mailbox, _folder_newname: newname}, this.set_busy(true, 'foldermoving'));
this.subscription_list.draglayer.hide();
}
}
+
this.drag_active = false;
this.unfocus_subscription(this.get_folder_row_id(this.env.dstfolder));
};
@@ -5642,7 +5636,7 @@ function rcube_webmail()
tbody = this.gui_objects.subscriptionlist.tBodies[0],
folders = this.env.subscriptionrows,
id = this.get_folder_row_id(oldfolder),
- regex = new RegExp('^'+RegExp.escape(oldfolder)),
+ prefix_len = oldfolder.length,
subscribed = $('input[name="_subscribed[]"]', $('#'+id)).prop('checked'),
// find subfolders of renamed folder
list = this.get_subfolders(oldfolder);
@@ -5667,7 +5661,7 @@ function rcube_webmail()
row.after(tmprow);
row = tmprow;
// update folder index
- name = name.replace(regex, newfolder);
+ name = newfolder + name.slice(prefix_len);
$('input[name="_subscribed[]"]', row).val(name);
this.env.subscriptionrows[id][0] = name;
// update the name if level is changed
@@ -5912,59 +5906,36 @@ function rcube_webmail()
// mouse over button
this.button_over = function(command, id)
{
- var n, button, obj, a_buttons = this.buttons[command],
- len = a_buttons ? a_buttons.length : 0;
-
- for (n=0; n<len; n++) {
- button = a_buttons[n];
- if (button.id == id && button.status == 'act') {
- obj = document.getElementById(button.id);
- if (obj && button.over) {
- if (button.type == 'image')
- obj.src = button.over;
- else
- obj.className = button.over;
- }
- }
- }
+ this.button_event(command, id, 'over');
};
// mouse down on button
this.button_sel = function(command, id)
{
- var n, button, obj, a_buttons = this.buttons[command],
- len = a_buttons ? a_buttons.length : 0;
-
- for (n=0; n<len; n++) {
- button = a_buttons[n];
- if (button.id == id && button.status == 'act') {
- obj = document.getElementById(button.id);
- if (obj && button.sel) {
- if (button.type == 'image')
- obj.src = button.sel;
- else
- obj.className = button.sel;
- }
- this.buttons_sel[id] = command;
- }
- }
+ this.button_event(command, id, 'sel');
};
// mouse out of button
this.button_out = function(command, id)
{
+ this.button_event(command, id, 'act');
+ };
+
+ // event of button
+ this.button_event = function(command, id, event)
+ {
var n, button, obj, a_buttons = this.buttons[command],
len = a_buttons ? a_buttons.length : 0;
for (n=0; n<len; n++) {
button = a_buttons[n];
if (button.id == id && button.status == 'act') {
- obj = document.getElementById(button.id);
- if (obj && button.act) {
- if (button.type == 'image')
- obj.src = button.act;
- else
- obj.className = button.act;
+ if (button[event] && (obj = document.getElementById(button.id))) {
+ obj[button.type == 'image' ? 'src' : 'className'] = button[event];
+ }
+
+ if (event == 'sel') {
+ this.buttons_sel[id] = command;
}
}
}
@@ -6152,8 +6123,8 @@ function rcube_webmail()
// enable/disable buttons for page shifting
this.set_page_buttons = function()
{
- this.enable_command('nextpage', 'lastpage', (this.env.pagecount > this.env.current_page));
- this.enable_command('previouspage', 'firstpage', (this.env.current_page > 1));
+ this.enable_command('nextpage', 'lastpage', this.env.pagecount > this.env.current_page);
+ this.enable_command('previouspage', 'firstpage', this.env.current_page > 1);
};
// mark a mailbox as selected and set environment variable
@@ -6163,14 +6134,10 @@ function rcube_webmail()
this.treelist.select(name);
}
else if (this.gui_objects.folderlist) {
- var current_li, target_li;
-
- if ((current_li = $('li.selected', this.gui_objects.folderlist))) {
- current_li.removeClass('selected').addClass('unfocused');
- }
- if ((target_li = this.get_folder_li(name, prefix, encode))) {
- $(target_li).removeClass('unfocused').addClass('selected');
- }
+ $('li.selected', this.gui_objects.folderlist)
+ .removeClass('selected').addClass('unfocused');
+ $(this.get_folder_li(name, prefix, encode))
+ .removeClass('unfocused').addClass('selected');
// trigger event hook
this.triggerEvent('selectfolder', { folder:name, prefix:prefix });
@@ -6199,8 +6166,6 @@ function rcube_webmail()
name = this.html_identifier(name, encode);
return document.getElementById(prefix+name);
}
-
- return null;
};
// for reordering column array (Konqueror workaround)
diff --git a/program/js/list.js b/program/js/list.js
index e1d57745c..4ae6c0c66 100644
--- a/program/js/list.js
+++ b/program/js/list.js
@@ -795,8 +795,10 @@ select_row: function(id, mod_key, with_mouse)
break;
case CONTROL_KEY:
- if (with_mouse)
+ if (with_mouse) {
+ this.shift_start = id;
this.highlight_row(id, true);
+ }
break;
case CONTROL_SHIFT_KEY:
@@ -893,7 +895,7 @@ select_children: function(uid)
for (i=0; i<len; i++)
if (!this.in_selection(children[i]))
- this.select_row(children[i], CONTROL_KEY);
+ this.select_row(children[i], CONTROL_KEY, true);
},
@@ -1133,13 +1135,15 @@ key_press: function(e)
// Stop propagation so that the browser doesn't scroll
rcube_event.cancel(e);
return this.use_arrow_key(keyCode, mod_key);
+
case 32:
rcube_event.cancel(e);
return this.select_row(this.last_selected, mod_key, true);
+
case 37: // Left arrow key
case 39: // Right arrow key
case 107: // Plus sign on a numeric keypad
- case 109: // Minus sign on a numeric keypad
+ case 109: // Minus sign on a numeric keypad
// Stop propagation
rcube_event.cancel(e);
var ret = this.use_plusminus_key(keyCode, mod_key);
@@ -1148,20 +1152,26 @@ key_press: function(e)
this.triggerEvent('keypress');
this.modkey = 0;
return ret;
+
case 36: // Home
this.select_first(mod_key);
return rcube_event.cancel(e);
+
case 35: // End
this.select_last(mod_key);
return rcube_event.cancel(e);
+
case 27:
if (this.drag_active)
return this.drag_mouse_up(e);
+
if (this.col_drag_active) {
this.selected_column = null;
return this.column_drag_mouse_up(e);
}
+
return rcube_event.cancel(e);
+
default:
this.key_pressed = keyCode;
this.modkey = mod_key;
diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php
index aaba28172..2828f26ee 100644
--- a/program/lib/Roundcube/rcube_db.php
+++ b/program/lib/Roundcube/rcube_db.php
@@ -392,7 +392,7 @@ class rcube_db
*/
protected function _query($query, $offset, $numrows, $params)
{
- $query = trim($query);
+ $query = ltrim($query);
$this->db_connect($this->dsn_select($query), true);
@@ -405,27 +405,28 @@ class rcube_db
$query = $this->set_limit($query, $numrows, $offset);
}
- $params = (array) $params;
-
// Because in Roundcube we mostly use queries that are
// executed only once, we will not use prepared queries
$pos = 0;
$idx = 0;
- while ($pos = strpos($query, '?', $pos)) {
- if ($query[$pos+1] == '?') { // skip escaped ?
- $pos += 2;
- }
- else {
- $val = $this->quote($params[$idx++]);
- unset($params[$idx-1]);
- $query = substr_replace($query, $val, $pos, 1);
- $pos += strlen($val);
+ if (count($params)) {
+ while ($pos = strpos($query, '?', $pos)) {
+ if ($query[$pos+1] == '?') { // skip escaped '?'
+ $pos += 2;
+ }
+ else {
+ $val = $this->quote($params[$idx++]);
+ unset($params[$idx-1]);
+ $query = substr_replace($query, $val, $pos, 1);
+ $pos += strlen($val);
+ }
}
}
- // replace escaped ? back to normal
- $query = rtrim(strtr($query, array('??' => '?')), ';');
+ // replace escaped '?' back to normal, see self::quote()
+ $query = str_replace('??', '?', $query);
+ $query = rtrim($query, " \t\n\r\0\x0B;");
$this->debug($query);
diff --git a/temp/.htaccess b/temp/.htaccess
deleted file mode 100644
index 8e6a345dc..000000000
--- a/temp/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-Order allow,deny
-Deny from all \ No newline at end of file