').attr('id', 'rcmKSearchpane').css({ position:'absolute', 'z-index':30000 }).append(ul).appendTo(document.body);
+ this.ksearch_pane.__ul = ul[0];
}
- else
- ul = this.ksearch_pane.ul;
// remove all search results
+ ul = this.ksearch_pane.__ul;
ul.innerHTML = '';
// add each result line to list
@@ -2583,14 +2611,12 @@ function rcube_webmail()
}
// select the first
- ul.firstChild.setAttribute('id', 'rcmksearchSelected');
- this.set_classname(ul.firstChild, 'selected', true);
+ $(ul.firstChild).attr('id', 'rcmksearchSelected').addClass('selected');
this.ksearch_selected = 0;
// move the results pane right under the input box and make it visible
- var pos = rcube_get_object_pos(this.ksearch_input);
- this.ksearch_pane.move(pos.x, pos.y+this.ksearch_input.offsetHeight);
- this.ksearch_pane.show(1);
+ var pos = $(this.ksearch_input).offset();
+ this.ksearch_pane.css({ left:pos.left+'px', top:(pos.top + this.ksearch_input.offsetHeight)+'px' }).show();
}
// hide results pane
else
@@ -2623,7 +2649,7 @@ function rcube_webmail()
this.ksearch_selected = null;
if (this.ksearch_pane)
- this.ksearch_pane.show(0);
+ this.ksearch_pane.hide();
};
@@ -2788,19 +2814,18 @@ function rcube_webmail()
// update a contact record in the list
this.update_contact_row = function(cid, cols_arr)
- {
+ {
var row;
- if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj))
- {
+ if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj)) {
for (var c=0; c'+cont+'
';
- var _rcube = this;
- this.gui_objects.message.innerHTML = cont;
- this.gui_objects.message.style.display = 'block';
+ var obj = $(this.gui_objects.message).html(cont).show();
if (type!='loading')
- this.gui_objects.message.onmousedown = function(){ _rcube.hide_message(); return true; };
+ obj.bind('mousedown', function(){ ref.hide_message(); return true; });
if (!hold)
- this.message_timer = window.setTimeout(function(){ ref.hide_message(); }, this.message_time);
+ this.message_timer = window.setTimeout(function(){ ref.hide_message(true); }, this.message_time);
};
// make a message row disapear
- this.hide_message = function()
+ this.hide_message = function(fade)
{
if (this.gui_objects.message)
- {
- this.gui_objects.message.style.display = 'none';
- this.gui_objects.message.onmousedown = null;
- }
+ $(this.gui_objects.message).unbind()[(fade?'fadeOut':'hide')]();
};
// mark a mailbox as selected and set environment variable
@@ -3446,16 +3454,12 @@ function rcube_webmail()
{
var current_li, target_li;
- if ((current_li = this.get_folder_li(old)))
- {
- this.set_classname(current_li, 'selected', false);
- this.set_classname(current_li, 'unfocused', false);
+ if ((current_li = this.get_folder_li(old))) {
+ $(current_li).removeClass('selected').removeClass('unfocused');
}
- if ((target_li = this.get_folder_li(name)))
- {
- this.set_classname(target_li, 'unfocused', false);
- this.set_classname(target_li, 'selected', true);
+ if ((target_li = this.get_folder_li(name))) {
+ $(target_li).removeClass('unfocused').addClass('selected');
}
}
};
@@ -3512,22 +3516,24 @@ function rcube_webmail()
var rowcount = tbody.rows.length;
var even = rowcount%2;
- this.env.messages[uid] = {deleted:flags.deleted?1:0,
- replied:flags.replied?1:0,
- unread:flags.unread?1:0,
- forwarded:flags.forwarded?1:0,
- flagged:flags.flagged?1:0};
-
- var row = document.createElement('TR');
- row.id = 'rcmrow'+uid;
- row.className = 'message'
- + (even ? ' even' : ' odd')
+ this.env.messages[uid] = {
+ deleted: flags.deleted?1:0,
+ replied: flags.replied?1:0,
+ unread: flags.unread?1:0,
+ forwarded: flags.forwarded?1:0,
+ flagged:flags.flagged?1:0
+ };
+
+ var css_class = 'message'
+ + (even ? ' even' : ' odd')
+ (flags.unread ? ' unread' : '')
- + (flags.deleted ? ' deleted' : '')
- + (flags.flagged ? ' flagged' : '');
+ + (flags.deleted ? ' deleted' : '')
+ + (flags.flagged ? ' flagged' : '');
+
+ var row = $('').attr('id', 'rcmrow'+cid).addClass('class').addClass(even ? 'even' : 'odd');
if (this.contact_list.in_selection(cid))
- row.className += ' selected';
+ row.addClass('selected');
// add each submitted col
- for (var c in cols)
- {
- col = document.createElement('TD');
- col.className = String(c).toLowerCase();
- col.innerHTML = cols[c];
- row.appendChild(col);
- }
+ for (var c in cols) {
+ col = $('').addClass(String(c).toLowerCase()).html(cols[c]).appendTo(row);
+ }
this.contact_list.insert_row(row);
this.enable_command('export', (this.contact_list.rowcount > 0));
@@ -3720,19 +3715,16 @@ function rcube_webmail()
// display fetched raw headers
this.set_headers = function(content)
- {
- if (this.gui_objects.all_headers_row && this.gui_objects.all_headers_box && content)
- {
- var box = this.gui_objects.all_headers_box;
- box.innerHTML = content;
- box.style.display = 'block';
+ {
+ if (this.gui_objects.all_headers_row && this.gui_objects.all_headers_box && content) {
+ $(this.gui_objects.all_headers_box).html(content).show();
if (this.env.framed && parent.rcmail)
- parent.rcmail.set_busy(false);
+ parent.rcmail.set_busy(false);
else
this.set_busy(false);
- }
- };
+ }
+ };
// display all-headers row and fetch raw message headers
this.load_headers = function(elem)
@@ -3740,15 +3732,14 @@ function rcube_webmail()
if (!this.gui_objects.all_headers_row || !this.gui_objects.all_headers_box || !this.env.uid)
return;
- this.set_classname(elem, 'show-headers', false);
- this.set_classname(elem, 'hide-headers', true);
- this.gui_objects.all_headers_row.style.display = bw.ie ? 'block' : 'table-row';
+ $(elem).removeClass('show-headers').addClass('hide-headers');
+ $(this.gui_objects.all_headers_row).show();
elem.onclick = function() { rcmail.hide_headers(elem); }
// fetch headers only once
if (!this.gui_objects.all_headers_box.innerHTML)
{
- this.display_message(this.get_label('loading'), 'loading', true);
+ this.display_message(this.get_label('loading'), 'loading', true);
this.http_post('headers', '_uid='+this.env.uid);
}
}
@@ -3759,9 +3750,8 @@ function rcube_webmail()
if (!this.gui_objects.all_headers_row || !this.gui_objects.all_headers_box)
return;
- this.set_classname(elem, 'hide-headers', false);
- this.set_classname(elem, 'show-headers', true);
- this.gui_objects.all_headers_row.style.display = 'none';
+ $(elem).removeClass('hide-headers').addClass('show-headers');
+ $(this.gui_objects.all_headers_row).hide();
elem.onclick = function() { rcmail.load_headers(elem); }
}
@@ -3772,23 +3762,16 @@ function rcube_webmail()
this.html2plain = function(htmlText, id)
{
- var http_request = new rcube_http_request();
var url = this.env.bin_path+'html2text.php';
var rcmail = this;
this.set_busy(true, 'converting');
console.log('HTTP POST: '+url);
- http_request.onerror = function(o) { rcmail.http_error(o); };
- http_request.oncomplete = function(o) { rcmail.set_text_value(o, id); };
- http_request.POST(url, htmlText, 'application/octet-stream');
- }
-
- this.set_text_value = function(httpRequest, id)
- {
- this.set_busy(false);
- document.getElementById(id).value = httpRequest.get_text();
- console.log(httpRequest.get_text());
+ $.ajax({ type: 'POST', url: url, data: htmlText, contentType: 'application/octet-stream',
+ error: function(o) { rcmail.http_error(o); },
+ success: function(data) { rcmail.set_busy(false); $(document.getElementById(id)).val(data); console.log(data); }
+ });
}
@@ -3813,99 +3796,61 @@ function rcube_webmail()
this.redirect(this.env.comm_path+'&_action='+action+querystring, lock);
};
- this.http_sockets = new Array();
-
- // find a non-busy socket or create a new one
- this.get_request_obj = function()
- {
- for (var n=0; n execute it
- if (request_obj.get_text() && (ctype=='text/javascript' || ctype=='application/x-javascript'))
- eval(request_obj.get_text());
+ // we have labels to add
+ if (typeof response.texts == 'object') {
+ for (var name in response.texts)
+ if (typeof response.texts[name] == 'string')
+ this.add_label(name, response.texts[name]);
+ }
+ // if we get javascript code from server -> execute it
+ if (response.exec) {
+ console.log(response.exec);
+ eval(response.exec);
+ }
+
// process the response data according to the sent action
- switch (request_obj.__action) {
+ switch (response.action) {
case 'delete':
if (this.task == 'addressbook') {
var uid = this.contact_list.get_selection();
@@ -3922,7 +3867,7 @@ function rcube_webmail()
break;
case 'purge':
- case 'expunge':
+ case 'expunge':
if (!this.env.messagecount && this.task == 'mail') {
// clear preview pane content
if (this.env.contentframe)
@@ -3937,23 +3882,22 @@ function rcube_webmail()
case 'getunread':
case 'list':
if (this.task == 'mail') {
- if (this.message_list && request_obj.__action == 'list')
+ if (this.message_list && response.action == 'list')
this.msglist_select(this.message_list);
this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0));
this.enable_command('purge', this.purge_mailbox_test());
}
else if (this.task == 'addressbook')
this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
-
break;
- }
-
- request_obj.reset();
- };
+ }
+ };
// handle HTTP request errors
- this.http_error = function(request_obj)
+ this.http_error = function(request, status, err)
{
+ alert(status+":"+err);
+/*
//alert('Error sending request: '+request_obj.url+' => HTTP '+request_obj.xmlhttp.status);
if (request_obj.__lock)
this.set_busy(false);
@@ -3961,6 +3905,7 @@ function rcube_webmail()
request_obj.reset();
request_obj.__lock = false;
this.display_message('Unknown Server Error!', 'error');
+*/
};
// use an image to send a keep-alive siganl to the server
@@ -4066,161 +4011,11 @@ function rcube_webmail()
}
};
- } // end object rcube_webmail
+} // end object rcube_webmail
-/**
- * Class for sending HTTP requests
- * @constructor
- */
-function rcube_http_request()
- {
- this.url = '';
- this.busy = false;
- this.xmlhttp = null;
-
- // reset object properties
- this.reset = function()
- {
- // set unassigned event handlers
- this.onloading = function(){ };
- this.onloaded = function(){ };
- this.oninteractive = function(){ };
- this.oncomplete = function(){ };
- this.onabort = function(){ };
- this.onerror = function(){ };
-
- this.url = '';
- this.busy = false;
- this.xmlhttp = null;
- }
-
- // create HTMLHTTP object
- this.build = function()
- {
- if (window.XMLHttpRequest)
- this.xmlhttp = new XMLHttpRequest();
- else if (window.ActiveXObject)
- {
- try { this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
- catch(e) { this.xmlhttp = null; }
- }
- else
- {
-
- }
- }
-
- // send GET request
- this.GET = function(url)
- {
- this.build();
-
- if (!this.xmlhttp)
- {
- this.onerror(this);
- return false;
- }
-
- var _ref = this;
- this.url = url;
- this.busy = true;
-
- this.xmlhttp.onreadystatechange = function(){ _ref.xmlhttp_onreadystatechange(); };
- this.xmlhttp.open('GET', url, true);
- this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid'));
- this.xmlhttp.send(null);
- };
-
- this.POST = function(url, body, contentType)
- {
- // default value for contentType if not provided
- if (typeof(contentType) == 'undefined')
- contentType = 'application/x-www-form-urlencoded';
-
- this.build();
-
- if (!this.xmlhttp)
- {
- this.onerror(this);
- return false;
- }
-
- var req_body = body;
- if (typeof(body) == 'object')
- {
- req_body = '';
- for (var p in body)
- req_body += (req_body ? '&' : '') + p+'='+urlencode(body[p]);
- }
-
- var ref = this;
- this.url = url;
- this.busy = true;
-
- this.xmlhttp.onreadystatechange = function() { ref.xmlhttp_onreadystatechange(); };
- this.xmlhttp.open('POST', url, true);
- this.xmlhttp.setRequestHeader('Content-Type', contentType);
- this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid'));
- this.xmlhttp.send(req_body);
- };
-
- // handle onreadystatechange event
- this.xmlhttp_onreadystatechange = function()
- {
- if(this.xmlhttp.readyState == 1)
- this.onloading(this);
-
- else if(this.xmlhttp.readyState == 2)
- this.onloaded(this);
-
- else if(this.xmlhttp.readyState == 3)
- this.oninteractive(this);
-
- else if(this.xmlhttp.readyState == 4)
- {
- try {
- if (this.xmlhttp.status == 0)
- this.onabort(this);
- else if(this.xmlhttp.status == 200)
- this.oncomplete(this);
- else
- this.onerror(this);
-
- this.busy = false;
- }
- catch(err)
- {
- this.onerror(this);
- this.busy = false;
- }
- }
- }
-
- // getter method for HTTP headers
- this.get_header = function(name)
- {
- return this.xmlhttp.getResponseHeader(name);
- };
-
- this.get_text = function()
- {
- return this.xmlhttp.responseText;
- };
-
- this.get_xml = function()
- {
- return this.xmlhttp.responseXML;
- };
-
- this.reset();
-
- } // end class rcube_http_request
-
-// helper function to call the init method with a delay
-function call_init(o)
- {
- window.setTimeout('if (window[\''+o+'\'] && window[\''+o+'\'].init) { '+o+'.init(); }',
- bw.win ? 500 : 200);
- }
+// copy event engine prototype
+rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener;
+rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener;
+rcube_webmail.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent;
diff --git a/program/js/common.js b/program/js/common.js
index bd699d924..407da4170 100644
--- a/program/js/common.js
+++ b/program/js/common.js
@@ -93,7 +93,7 @@ function roundcube_browser()
}
-// static functions for event handling
+// static functions for DOM event handling
var rcube_event = {
/**
@@ -159,8 +159,8 @@ get_mouse_pos: function(e)
}
if (e._offset) {
- mX += e._offset.x;
- mY += e._offset.y;
+ mX += e._offset.left;
+ mY += e._offset.top;
}
return { x:mX, y:mY };
@@ -234,7 +234,86 @@ cancel: function(evt)
};
-var rcube_layer_objects = new Array();
+/**
+ * rcmail objects event interface
+ */
+function rcube_event_engine()
+{
+ this._events = {};
+}
+
+rcube_event_engine.prototype = {
+
+/**
+ * Setter for object event handlers
+ *
+ * @param {String} Event name
+ * @param {Function} Handler function
+ * @return Listener ID (used to remove this handler later on)
+ */
+addEventListener: function(evt, func, obj)
+{
+ if (!this._events)
+ this._events = {};
+ if (!this._events[evt])
+ this._events[evt] = [];
+
+ var e = {func:func, obj:obj ? obj : window};
+ this._events[evt][this._events[evt].length] = e;
+},
+
+/**
+ * Removes a specific event listener
+ *
+ * @param {String} Event name
+ * @param {Int} Listener ID to remove
+ */
+removeEventListener: function(evt, func, obj)
+{
+ if (typeof obj == 'undefined')
+ obj = window;
+
+ for (var h,i=0; this._events && this._events[evt] && i < this._events[evt].length; i++)
+ if ((h = this._events[evt][i]) && h.func == func && h.obj == obj)
+ this._events[evt][i] = null;
+},
+
+/**
+ * This will execute all registered event handlers
+ *
+ * @param {String} Event to trigger
+ * @param {Object} Event object/arguments
+ */
+triggerEvent: function(evt, e)
+{
+ var ret, h;
+ if (typeof e == 'undefined')
+ e = {};
+ if (typeof e == 'object')
+ e.event = evt;
+
+ if (this._events && this._events[evt] && !this._event_exec) {
+ this._event_exec = true;
+ for (var i=0; i < this._events[evt].length; i++) {
+ if ((h = this._events[evt][i])) {
+ if (typeof h.func == 'function')
+ ret = h.func.call ? h.func.call(h.obj, this, e) : h.func(this, e);
+ else if (typeof h.obj[h.func] == 'function')
+ ret = h.obj[h.func](this, e);
+
+ // cancel event execution
+ if (typeof ret != 'undefined' && !ret)
+ break;
+ }
+ }
+ }
+
+ this._event_exec = false;
+ return ret;
+}
+
+} // end rcube_event_engine.prototype
+
/**
@@ -243,7 +322,7 @@ var rcube_layer_objects = new Array();
* @constructor
*/
function rcube_layer(id, attributes)
- {
+{
this.name = id;
// create a new layer in the current document
@@ -310,10 +389,6 @@ function rcube_layer(id, attributes)
this.y = parseInt(this.elm.offsetTop);
this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false;
- this.id = rcube_layer_objects.length;
- this.obj = 'rcube_layer_objects['+this.id+']';
- rcube_layer_objects[this.id] = this;
-
// ********* layer object methods *********
@@ -327,16 +402,6 @@ function rcube_layer(id, attributes)
this.css.top = Math.round(this.y)+'px';
}
-
- // move the layer for a specific step
- this.shift = function(x,y)
- {
- x = Math.round(x*100)/100;
- y = Math.round(y*100)/100;
- this.move(this.x+x, this.y+y);
- }
-
-
// change the layers width and height
this.resize = function(w,h)
{
@@ -347,15 +412,6 @@ function rcube_layer(id, attributes)
}
- // cut the layer (top,width,height,left)
- this.clip = function(t,w,h,l)
- {
- this.css.clip='rect('+t+' '+w+' '+h+' '+l+')';
- this.clip_height = h;
- this.clip_width = w;
- }
-
-
// show or hide the layer
this.show = function(a)
{
@@ -383,36 +439,7 @@ function rcube_layer(id, attributes)
this.elm.innerHTML = cont;
}
-
- // set the given color to the layer background
- this.set_bgcolor = function(c)
- {
- if(!c || c=='#')
- c = 'transparent';
-
- this.css.backgroundColor = c;
- }
-
-
- // set the opacity of a layer to the given ammount (in %)
- this.set_opacity = function(v)
- {
- if(!bw.opacity)
- return;
-
- var op = v<=1 ? Math.round(v*100) : parseInt(v);
-
- if(bw.ie)
- this.css.filter = 'alpha(opacity:'+op+')';
- else if(bw.safari)
- {
- this.css.opacity = op/100;
- this.css.KhtmlOpacity = op/100;
- }
- else if(bw.mz)
- this.css.MozOpacity = op/100;
- }
- }
+}
// check if input is a valid email address
@@ -472,7 +499,7 @@ function urlencode(str)
// get any type of html objects by id/name
function rcube_find_object(id, d)
- {
+{
var n, f, obj, e;
if(!d) d = document;
@@ -486,88 +513,34 @@ function rcube_find_object(id, d)
if(!obj && d.images.length)
obj = d.images[id];
- if(!obj && d.forms.length)
- for(f=0; f= pos.x) && (mouse.x < (pos.x + obj.offsetWidth)) &&
- (mouse.y >= pos.y) && (mouse.y < (pos.y + obj.offsetHeight)));
-}
+ var pos = $(obj).offset();
+ return ((mouse.x >= pos.left) && (mouse.x < (pos.left + obj.offsetWidth)) &&
+ (mouse.y >= pos.top) && (mouse.y < (pos.top + obj.offsetHeight)));
+}
-/**
- * Return the currently applied value of a css property
- *
- * @param {Object} html_element Node reference
- * @param {String} css_property Property name to read in Javascript notation (eg. 'textAlign')
- * @param {String} mozilla_equivalent Equivalent property name in CSS notation (eg. 'text-align')
- * @return CSS property value
- * @type String
- */
-function get_elements_computed_style(html_element, css_property, mozilla_equivalent)
- {
- if (arguments.length==2)
- mozilla_equivalent = css_property;
-
- var el = html_element;
- if (typeof(html_element)=='string')
- el = rcube_find_object(html_element);
-
- if (el && el.currentStyle)
- return el.currentStyle[css_property];
- else if (el && document.defaultView && document.defaultView.getComputedStyle)
- return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozilla_equivalent);
- else
- return false;
- }
-
// cookie functions by GoogieSpell
function setCookie(name, value, expires, path, domain, secure)
@@ -611,7 +584,7 @@ function rcube_console()
if (box) {
if (msg.charAt(msg.length-1)=='\n')
- msg += '--------------------------------------\n';
+ msg += '--------------------------------------\n';
else
msg += '\n--------------------------------------\n';
@@ -633,7 +606,8 @@ function rcube_console()
}
var bw = new roundcube_browser();
-var console = new rcube_console();
+if (!window.console)
+ console = new rcube_console();
// Add escape() method to RegExp object
diff --git a/program/js/editor.js b/program/js/editor.js
index 6b847ba00..7f937b2b8 100644
--- a/program/js/editor.js
+++ b/program/js/editor.js
@@ -52,8 +52,8 @@ function rcmail_editor_init(skin_path, editor_lang, spellcheck, mode)
spellchecker_languages : (rcmail.env.spellcheck_langs ? rcmail.env.spellcheck_langs : 'Dansk=da,Deutsch=de,+English=en,Espanol=es,Francais=fr,Italiano=it,Nederlands=nl,Polski=pl,Portugues=pt,Suomi=fi,Svenska=sv'),
gecko_spellcheck : true,
relative_urls : false,
- remove_script_host : false ,
- rc_client: rcube_webmail_client,
+ remove_script_host : false,
+ rc_client: rcmail,
oninit : 'rcmail_editor_callback'
});
}
diff --git a/program/js/list.js b/program/js/list.js
index 522af59ab..dabcecb92 100644
--- a/program/js/list.js
+++ b/program/js/list.js
@@ -51,7 +51,6 @@ function rcube_list_widget(list, p)
this.drag_mouse_start = null;
this.dblclick_time = 600;
this.row_init = function(){};
- this.events = { click:[], dblclick:[], select:[], keypress:[], dragstart:[], dragmove:[], dragend:[] };
// overwrite default paramaters
if (p && typeof(p)=='object')
@@ -160,13 +159,15 @@ remove_row: function(uid, sel_next)
insert_row: function(row, attop)
{
var tbody = this.list.tBodies[0];
+ if (!row.jquery)
+ row = $(row);
if (attop && tbody.rows.length)
- tbody.insertBefore(row, tbody.firstChild);
+ row.prependTo(tbody)
else
- tbody.appendChild(row);
+ row.appendTo(tbody);
- this.init_row(row);
+ this.init_row(row[0]);
this.rowcount++;
},
@@ -181,10 +182,8 @@ focus: function(e)
for (var n=0; n').attr('id', 'rcmdraglayer').css({ position:'absolute', display:'none', 'z-index':2000 }).appendTo(document.body);
// get subjects of selectedd messages
var names = '';
@@ -754,6 +747,9 @@ drag_mouse_move: function(e)
if (((node = obj.childNodes[i].firstChild) && (node.nodeType==3 || node.nodeName=='A')) &&
(this.subject_col < 0 || (this.subject_col >= 0 && this.subject_col == c)))
{
+ if (n == 0)
+ this.drag_start_pos = $(node).offset();
+
subject = node.nodeType==3 ? node.data : node.innerHTML;
// remove leading spaces
subject = subject.replace(/^\s+/i, '');
@@ -767,18 +763,18 @@ drag_mouse_move: function(e)
}
}
- this.draglayer.write(names);
- this.draglayer.show(1);
+ this.draglayer.html(names);
+ this.draglayer.show();
this.drag_active = true;
- this.trigger_event('dragstart');
+ this.triggerEvent('dragstart');
}
if (this.drag_active && this.draglayer)
{
var pos = rcube_event.get_mouse_pos(e);
- this.draglayer.move(pos.x+20, bw.ie ? pos.y-5+document.documentElement.scrollTop : pos.y-5);
- this.trigger_event('dragmove', e);
+ this.draglayer.css({ left:(pos.x+20)+'px', top:(pos.y-5 + (bw.ie ? document.documentElement.scrollTop : 0))+'px' });
+ this.triggerEvent('dragmove', e);
}
this.drag_start = false;
@@ -794,11 +790,15 @@ drag_mouse_up: function(e)
{
document.onmousemove = null;
- if (this.draglayer && this.draglayer.visible)
- this.draglayer.show(0);
+ if (this.draglayer && this.draglayer.is(':visible')) {
+ if (this.drag_start_pos)
+ this.draglayer.animate(this.drag_start_pos, 300, 'swing').hide(20);
+ else
+ this.draglayer.hide();
+ }
this.drag_active = false;
- this.trigger_event('dragend');
+ this.triggerEvent('dragend');
rcube_event.remove_listener({element:document, event:'mousemove', object:this, method:'drag_mouse_move'});
rcube_event.remove_listener({element:document, event:'mouseup', object:this, method:'drag_mouse_up'});
@@ -828,68 +828,10 @@ drag_mouse_up: function(e)
}
return rcube_event.cancel(e);
-},
-
-
-
-/**
- * set/unset a specific class name
- */
-set_classname: function(obj, classname, set)
-{
- var reg = new RegExp('\s*'+classname, 'i');
- if (!set && obj.className.match(reg))
- obj.className = obj.className.replace(reg, '');
- else if (set && !obj.className.match(reg))
- obj.className += ' '+classname;
-},
-
-
-/**
- * Setter for object event handlers
- *
- * @param {String} Event name
- * @param {Function} Handler function
- * @return Listener ID (used to remove this handler later on)
- */
-addEventListener: function(evt, handler)
-{
- if (this.events[evt]) {
- var handle = this.events[evt].length;
- this.events[evt][handle] = handler;
- return handle;
- }
- else
- return false;
-},
-
-
-/**
- * Removes a specific event listener
- *
- * @param {String} Event name
- * @param {Int} Listener ID to remove
- */
-removeEventListener: function(evt, handle)
-{
- if (this.events[evt] && this.events[evt][handle])
- this.events[evt][handle] = null;
-},
-
-
-/**
- * This will execute all registered event handlers
- * @private
- */
-trigger_event: function(evt, p)
-{
- if (this.events[evt] && this.events[evt].length) {
- for (var i=0; ipriority = intval($matches[1]);
break;
+ default:
+ if (strlen($field) > 2)
+ $result[$id]->others[$field] = $string;
+ break;
} // end switch ()
} // end while ()
@@ -1964,9 +1972,9 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
return $result;
}
-function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false) {
+function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false, $add='') {
- $a = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr);
+ $a = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr, $add);
if (is_array($a)) {
return array_shift($a);
}
diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc
index 33dfad646..e3d7606cb 100644
--- a/program/steps/addressbook/func.inc
+++ b/program/steps/addressbook/func.inc
@@ -42,18 +42,20 @@ $OUTPUT->set_env('readonly', $CONTACTS->readonly, false);
$js_list = array();
if (strtolower($CONFIG['address_book_type']) != 'ldap') {
// We are using the DB address book, add it.
- $js_list = array("0" => array('id' => 0, 'readonly' => false));
+ $js_list['0'] = array('id' => 0, 'name' => rcube_label('personaladrbook'), 'readonly' => false);
}
if (is_array($CONFIG['ldap_public'])) {
foreach ($CONFIG['ldap_public'] as $id => $prop)
- $js_list[$id] = array('id' => $id, 'readonly' => !$prop['writable']);
+ $js_list[$id] = array('id' => $id, 'name' => $prop['name'], 'readonly' => !$prop['writable']);
}
-$OUTPUT->set_env('address_sources', $js_list);
+
+$plugin = $RCMAIL->plugins->exec_hook('address_sources', array('sources' => $js_list));
+$OUTPUT->set_env('address_sources', $plugin['sources']);
function rcmail_directory_list($attrib)
{
- global $CONFIG, $OUTPUT;
+ global $RCMAIL, $OUTPUT;
if (!$attrib['id'])
$attrib['id'] = 'rcmdirectorylist';
@@ -63,26 +65,24 @@ function rcmail_directory_list($attrib)
$current = get_input_value('_source', RCUBE_INPUT_GPC);
$line_templ = html::tag('li', array('id' => 'rcmli%s', 'class' => '%s'),
html::a(array('href' => '%s', 'onclick' => "return ".JS_OBJECT_NAME.".command('list','%s',this)"), '%s'));
-
- if (strtolower($CONFIG['address_book_type']) != 'ldap') {
- $out .= sprintf($line_templ, $local_id, (!$current ? 'selected' : ''),
- Q(rcmail_url(null, array('_source' => $local_id))), $local_id, rcube_label('personaladrbook'));
- } // end if
- else {
+
+ if (!$current && strtolower($RCMAIL->config->get('address_book_type', 'sql')) != 'ldap') {
+ $current = '0';
+ }
+ else if (!$current) {
// DB address book not used, see if a source is set, if not use the
// first LDAP directory.
- if (!$current) {
- $current = key((array)$CONFIG['ldap_public']);
- } // end if
- } // end else
-
- foreach ((array)$CONFIG['ldap_public'] as $id => $prop) {
+ $current = key((array)$RCMAIL->config->get('ldap_public', array()));
+ }
+
+ foreach ((array)$OUTPUT->env['address_sources'] as $j => $source) {
+ $id = $source['id'] ? $source['id'] : $j;
$js_id = JQ($id);
$dom_id = preg_replace('/[^a-z0-9\-_]/i', '', $id);
$out .= sprintf($line_templ, $dom_id, ($current == $id ? 'selected' : ''),
- Q(rcmail_url(null, array('_source' => $id))), $js_id, (!empty($prop['name']) ? Q($prop['name']) : Q($id)));
+ Q(rcmail_url(null, array('_source' => $id))), $js_id, (!empty($source['name']) ? Q($source['name']) : Q($id)));
}
-
+
$OUTPUT->add_gui_object('folderlist', $attrib['id']);
return html::tag('ul', $attrib, $out, html::$common_attrib);
diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc
index f6e29f9d7..6d58edc8e 100644
--- a/program/steps/mail/attachments.inc
+++ b/program/steps/mail/attachments.inc
@@ -28,46 +28,45 @@ if (!$_SESSION['compose']) {
// remove an attachment
if ($RCMAIL->action=='remove-attachment')
{
- if (preg_match('/^rcmfile([0-9]+)$/', $_POST['_file'], $regs))
- {
+ $id = 'undefined';
+ if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs))
$id = $regs[1];
- if (is_array($_SESSION['compose']['attachments'][$id]))
- {
- @unlink($_SESSION['compose']['attachments'][$id]['path']);
+ if ($attachment = $_SESSION['compose']['attachments'][$id])
+ $attachment = $RCMAIL->plugins->exec_hook('remove_attachment', $attachment);
+ if ($attachment['status']) {
+ if (is_array($_SESSION['compose']['attachments'][$id])) {
unset($_SESSION['compose']['attachments'][$id]);
$OUTPUT->command('remove_from_attachment_list', "rcmfile$id");
- $OUTPUT->send();
}
}
+
+ $OUTPUT->send();
exit;
}
if ($RCMAIL->action=='display-attachment')
{
- if (preg_match('/^rcmfile([0-9]+)$/', $_GET['_file'], $regs))
- {
+ $id = 'undefined';
+ if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs))
$id = $regs[1];
- if (is_array($_SESSION['compose']['attachments'][$id]))
- {
- $apath = $_SESSION['compose']['attachments'][$id]['path'];
- header('Content-Type: ' . $_SESSION['compose']['attachments'][$id]['mimetype']);
- header('Content-Length: ' . filesize($apath));
- readfile($apath);
- }
+ if ($attachment = $_SESSION['compose']['attachments'][$id])
+ $attachment = $RCMAIL->plugins->exec_hook('display_attachment', $attachment);
+
+ if ($attachment['status']) {
+ $size = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']);
+ header('Content-Type: ' . $attachment['mimetype']);
+ header('Content-Length: ' . $size);
+
+ if ($attachment['data'])
+ echo $attachment['data'];
+ else if ($attachment['path'])
+ readfile($attachment['path']);
}
exit;
}
// attachment upload action
-// use common temp dir for file uploads
-$temp_dir = unslashify($CONFIG['temp_dir']);
-
-// #1484529: we need absolute path on Windows for move_uploaded_file()
-if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- $temp_dir = realpath($temp_dir);
-}
-
if (!is_array($_SESSION['compose']['attachments'])) {
$_SESSION['compose']['attachments'] = array();
}
@@ -77,15 +76,20 @@ $OUTPUT->reset();
if (is_array($_FILES['_attachments']['tmp_name'])) {
foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) {
- $tmpfname = tempnam($temp_dir, 'rcmAttmnt');
- if (move_uploaded_file($filepath, $tmpfname) && file_exists($tmpfname)) {
- $id = count($_SESSION['compose']['attachments']);
- $_SESSION['compose']['attachments'][] = array(
- 'name' => $_FILES['_attachments']['name'][$i],
- 'mimetype' => rc_mime_content_type($tmpfname, $_FILES['_attachments']['name'][$i], $_FILES['_attachments']['type'][$i]),
- 'path' => $tmpfname,
- );
-
+ $attachment = array(
+ 'path' => $filepath,
+ 'name' => $_FILES['_attachments']['name'][$i],
+ 'mimetype' => rc_mime_content_type($tmpfname, $_FILES['_attachments']['type'][$i])
+ );
+
+ $attachment = $RCMAIL->plugins->exec_hook('upload_attachment', $attachment);
+ if ($attachment['status']) {
+ $id = $attachment['id'];
+
+ // store new attachment in session
+ unset($attachment['status']);
+ $_SESSION['compose']['attachments'][$id] = $attachment;
+
if (is_file($icon = $CONFIG['skin_path'] . '/images/icons/remove-attachment.png')) {
$button = html::img(array(
'src' => $icon,
@@ -99,11 +103,11 @@ if (is_array($_FILES['_attachments']['tmp_name'])) {
$content = html::a(array(
'href' => "#delete",
- 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%d', this)", JS_OBJECT_NAME, $id),
+ 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", JS_OBJECT_NAME, $id),
'title' => rcube_label('delete'),
), $button);
-
- $content .= Q($_FILES['_attachments']['name'][$i]);
+
+ $content .= Q($attachment['name']);
$OUTPUT->command('add2attachment_list', "rcmfile$id", $content);
}
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 49c4c3011..c93fa9be2 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -594,8 +594,6 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
global $OUTPUT;
$cid_map = array();
- $id = 0;
-
foreach ((array)$message->mime_parts as $pid => $part)
{
if (($part->ctype_primary != 'message' || !$bodyIsHtml) &&
@@ -603,16 +601,14 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
|| (empty($part->disposition) && $part->filename)))
{
if ($attachment = rcmail_save_attachment($message, $pid)) {
- $_SESSION['compose']['attachments'][$id] = $attachment;
- if ($bodyIsHtml && $part->filename && $part->content_id) {
- $cid_map['cid:'.$part->content_id] =
- $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$id;
+ $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+ if ($bodyIsHtml && $part->filename && $part->content_id) {
+ $cid_map['cid:'.$part->content_id] = $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'];
}
- $id++;
}
}
}
-
+
$_SESSION['compose']['forward_attachments'] = true;
return $cid_map;
@@ -624,15 +620,11 @@ function rcmail_write_inline_attachments(&$message)
global $OUTPUT;
$cid_map = array();
- $id = 0;
-
foreach ((array)$message->mime_parts as $pid => $part) {
if ($part->content_id && $part->filename) {
if ($attachment = rcmail_save_attachment($message, $pid)) {
- $_SESSION['compose']['attachments'][$id] = $attachment;
- $cid_map['cid:'.$part->content_id] =
- $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$id;
- $id++;
+ $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+ $cid_map['cid:'.$part->content_id] = $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'];
}
}
}
@@ -642,24 +634,22 @@ function rcmail_write_inline_attachments(&$message)
function rcmail_save_attachment(&$message, $pid)
{
- global $RCMAIL;
-
- $temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
- $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
$part = $message->mime_parts[$pid];
- if ($fp = fopen($tmp_path, 'w'))
- {
- $message->get_part_content($pid, $fp);
- fclose($fp);
-
- return array(
- 'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
- 'name' => $part->filename,
- 'path' => $tmp_path,
- 'content_id' => $part->content_id
- );
+ $attachment = array(
+ 'name' => $part->filename,
+ 'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
+ 'content_id' => $part->content_id,
+ 'data' => $message->get_part_content($pid),
+ );
+
+ $attachment = rcmail::get_instance()->plugins->exec_hook('save_attachment', $attachment);
+ if ($attachment['status']) {
+ unset($attachment['data'], $attachment['status']);
+ return $attachment;
}
+
+ return false;
}
@@ -739,7 +729,7 @@ function rcmail_compose_attachment_list($attrib)
html::a(array(
'href' => "#delete",
'title' => rcube_label('delete'),
- 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%d', this)", JS_OBJECT_NAME, $id)),
+ 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", JS_OBJECT_NAME, $id)),
$button) . Q($a_prop['name']));
}
}
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 8931cfa4e..28ae70ca3 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -730,71 +730,86 @@ function rcmail_wash_html($html, $p = array(), $cid_replaces)
*/
function rcmail_print_body($part, $p = array())
{
- $p += array('safe' => false, 'plain' => false, 'inline_html' => true);
+ global $RCMAIL;
+
+ // trigger plugin hook
+ $data = $RCMAIL->plugins->exec_hook('message_part_before',
+ array('type' => $part->ctype_secondary, 'body' => $part->body) + $p + array('safe' => false, 'plain' => false, 'inline_html' => true));
// convert html to text/plain
- if ($part->ctype_secondary == 'html' && $p['plain']) {
- $txt = new html2text($part->body, false, true);
+ if ($data['type'] == 'html' && $data['plain']) {
+ $txt = new html2text($data['body'], false, true);
$body = $txt->get_text();
$part->ctype_secondary = 'plain';
}
// text/html
- else if ($part->ctype_secondary == 'html') {
- return rcmail_wash_html($part->body, $p, $part->replaces);
+ else if ($data['type'] == 'html') {
+ $body = rcmail_wash_html($data['body'], $data, $part->replaces);
+ $part->ctype_secondary = $data['type'];
}
// text/enriched
- else if ($part->ctype_secondary=='enriched') {
+ else if ($data['type'] == 'enriched') {
$part->ctype_secondary = 'html';
require_once('lib/enriched.inc');
- return Q(enriched_to_html($part->body), 'show');
+ $body = Q(enriched_to_html($data['body']), 'show');
}
- else
+ else {
+ // assert plaintext
$body = $part->body;
+ $part->ctype_secondary = $data['type'] = 'plain';
+ }
+
+ // free some memory (hopefully)
+ unset($data['body']);
- /**** assert plaintext ****/
-
- // make links and email-addresses clickable
- $replacements = new rcube_string_replacer;
-
- $url_chars = 'a-z0-9_\-\+\*\$\/&%=@#:;';
- $url_chars_within = '\?\.~,!';
-
- // search for patterns like links and e-mail addresses
- $body = preg_replace_callback("/([\w]+):\/\/([a-z0-9\-\.]+[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body);
- $body = preg_replace_callback("/([^\/:]|\s)(www\.)([a-z0-9\-]{2,}[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body);
- $body = preg_replace_callback('/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i', array($replacements, 'mailto_callback'), $body);
-
- // split body into single lines
- $a_lines = preg_split('/\r?\n/', $body);
- $quote_level = 0;
-
- // colorize quoted parts
- for ($n=0; $n < sizeof($a_lines); $n++) {
- $line = $a_lines[$n];
- $quotation = '';
- $q = 0;
+ // plaintext postprocessing
+ if ($part->ctype_secondary == 'plain') {
+ // make links and email-addresses clickable
+ $replacements = new rcube_string_replacer;
+
+ $url_chars = 'a-z0-9_\-\+\*\$\/&%=@#:;';
+ $url_chars_within = '\?\.~,!';
+
+ // search for patterns like links and e-mail addresses
+ $body = preg_replace_callback("/([\w]+):\/\/([a-z0-9\-\.]+[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body);
+ $body = preg_replace_callback("/([^\/:]|\s)(www\.)([a-z0-9\-]{2,}[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body);
+ $body = preg_replace_callback('/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i', array($replacements, 'mailto_callback'), $body);
+
+ // split body into single lines
+ $a_lines = preg_split('/\r?\n/', $body);
+ $quote_level = 0;
+
+ // colorize quoted parts
+ for ($n=0; $n < count($a_lines); $n++) {
+ $line = $a_lines[$n];
+ $quotation = '';
+ $q = 0;
- if (preg_match('/^(>+\s*)+/', $line, $regs)) {
- $q = strlen(preg_replace('/\s/', '', $regs[0]));
- $line = substr($line, strlen($regs[0]));
-
- if ($q > $quote_level)
- $quotation = str_repeat('', $q - $quote_level);
- else if ($q < $quote_level)
- $quotation = str_repeat(" ", $quote_level - $q);
+ if (preg_match('/^(>+\s*)+/', $line, $regs)) {
+ $q = strlen(preg_replace('/\s/', '', $regs[0]));
+ $line = substr($line, strlen($regs[0]));
+
+ if ($q > $quote_level)
+ $quotation = str_repeat('', $q - $quote_level);
+ else if ($q < $quote_level)
+ $quotation = str_repeat(" ", $quote_level - $q);
+ }
+ else if ($quote_level > 0)
+ $quotation = str_repeat("", $quote_level);
+
+ $quote_level = $q;
+ $a_lines[$n] = $quotation . Q($line, 'replace', false); // htmlquote plaintext
}
- else if ($quote_level > 0)
- $quotation = str_repeat("", $quote_level);
- $quote_level = $q;
- $a_lines[$n] = $quotation . Q($line, 'replace', false); // htmlquote plaintext
+ // insert the links for urls and mailtos
+ $body = $replacements->resolve(join("\n", $a_lines));
}
+
+ // allow post-processing of the message body
+ $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body) + $data);
- // insert the links for urls and mailtos
- $body = $replacements->resolve(join("\n", $a_lines));
-
- return html::tag('pre', array(), $body);
+ return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']);
}
@@ -842,7 +857,7 @@ function rcmail_washtml_callback($tagname, $attrib, $content)
*/
function rcmail_message_headers($attrib, $headers=NULL)
{
- global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $CONFIG;
+ global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL;
static $sa_attrib;
// keep header table attrib
@@ -851,7 +866,6 @@ function rcmail_message_headers($attrib, $headers=NULL)
else if (!is_array($attrib) && is_array($sa_attrib))
$attrib = $sa_attrib;
-
if (!isset($MESSAGE))
return FALSE;
@@ -859,58 +873,55 @@ function rcmail_message_headers($attrib, $headers=NULL)
if (!$headers)
$headers = is_object($MESSAGE->headers) ? get_object_vars($MESSAGE->headers) : $MESSAGE->headers;
- $header_count = 0;
-
- // allow the following attributes to be added to the tag
- $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
- $out = '\n";
-
// show these headers
$standard_headers = array('subject', 'from', 'to', 'cc', 'bcc', 'replyto', 'date');
+ $output_headers = array();
- foreach ($standard_headers as $hkey)
- {
+ foreach ($standard_headers as $hkey) {
if (!$headers[$hkey])
continue;
- if ($hkey == 'date')
- {
+ if ($hkey == 'date') {
if ($PRINT_MODE)
- $header_value = format_date($headers[$hkey], $CONFIG['date_long'] ? $CONFIG['date_long'] : 'x');
+ $header_value = format_date($headers[$hkey], $RCMAIL->config->get('date_long', 'x'));
else
$header_value = format_date($headers[$hkey]);
- }
- else if ($hkey == 'replyto')
- {
+ }
+ else if ($hkey == 'replyto') {
if ($headers['replyto'] != $headers['from'])
- $header_value = Q(rcmail_address_string($headers['replyto'], null, true, $attrib['addicon']), 'show');
+ $header_value = rcmail_address_string($headers['replyto'], null, true, $attrib['addicon']);
else
continue;
- }
+ }
else if (in_array($hkey, array('from', 'to', 'cc', 'bcc')))
- $header_value = Q(rcmail_address_string($headers[$hkey], null, true, $attrib['addicon']), 'show');
+ $header_value = rcmail_address_string($headers[$hkey], null, true, $attrib['addicon']);
else if ($hkey == 'subject' && empty($headers[$hkey]))
- $header_value = Q(rcube_label('nosubject'));
+ $header_value = rcube_label('nosubject');
else
- $header_value = Q(trim($IMAP->decode_header($headers[$hkey])));
-
- $out .= "\n\n";
- $out .= '\n";
- $out .= '| '.$header_value." | \n ";
- $header_count++;
- }
+ $header_value = trim($IMAP->decode_header($headers[$hkey]));
+
+ $output_headers[$hkey] = array('title' => rcube_label($hkey), 'value' => $header_value, 'raw' => $headers[$hkey]);
+ }
+
+ $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array('output' => $output_headers, 'headers' => $MESSAGE->headers));
+
+ // compose html table
+ $table = new html_table(array('cols' => 2));
+
+ foreach ($plugin['output'] as $hkey => $row) {
+ $table->add(array('class' => 'header-title'), Q($row['title']));
+ $table->add(array('class' => $hkey, 'width' => "90%"), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
+ }
// all headers division
- $out .= "\n".' ';
- $out .= "\n".'';
-
+ $table->add(array('colspan' => 2, 'class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('load-headers','',this)"), '');
+ $table->add_row(array('id' => "all-headers"));
+ $table->add(array('colspan' => 2, 'class' => "all"), html::div(array('id' => 'headers-source'), ''));
+
$OUTPUT->add_gui_object('all_headers_row', 'all-headers');
$OUTPUT->add_gui_object('all_headers_box', 'headers-source');
- $out .= "\n \n\n";
-
- return $header_count ? $out : '';
+ return $table->show($attrib);
}
@@ -1251,10 +1262,7 @@ function rcmail_compose_cleanup()
if (!isset($_SESSION['compose']))
return;
- // remove attachment files from temp dir
- if (is_array($_SESSION['compose']['attachments']))
- foreach ($_SESSION['compose']['attachments'] as $attachment)
- @unlink($attachment['path']);
+ rcmail::get_instance()->plugins->exec_hook('cleanup_attachments',array());
unset($_SESSION['compose']);
}
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 9607619e9..34e2c0904 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -297,86 +297,92 @@ $MAIL_MIME = new rcube_mail_mime($RCMAIL->config->header_delimiter());
// For HTML-formatted messages, construct the MIME message with both
// the HTML part and the plain-text part
-if ($isHtml)
- {
- $MAIL_MIME->setHTMLBody($message_body . ($footer ? "\r\n".$footer.' ' : ''));
+if ($isHtml) {
+ $plugin = $RCMAIL->plugins->exec_hook('outgoing_message_body', array('body' => $message_body, 'type' => 'html', 'message' => $MAIL_MIME));
+ $MAIL_MIME->setHTMLBody($plugin['body'] . ($footer ? "\r\n".$footer.' ' : ''));
// add a plain text version of the e-mail as an alternative part.
- $h2t = new html2text($message_body, false, true, 0);
- $plainTextPart = rc_wordwrap($h2t->get_text(), 75, "\r\n"). ($footer ? "\r\n".$footer : '');
+ $h2t = new html2text($plugin['body'], false, true, 0);
+ $plainTextPart = rc_wordwrap($h2t->get_text(), 75, "\r\n") . ($footer ? "\r\n".$footer : '');
$plainTextPart = wordwrap($plainTextPart, 998, "\r\n", true);
- if (!strlen($plainTextPart))
- {
+ if (!strlen($plainTextPart)) {
// empty message body breaks attachment handling in drafts
$plainTextPart = "\r\n";
- }
- $MAIL_MIME->setTXTBody($plainTextPart);
+ }
+ $plugin = $RCMAIL->plugins->exec_hook('outgoing_message_body', array('body' => $plainTextPart, 'type' => 'alternative', 'message' => $MAIL_MIME));
+ $MAIL_MIME->setTXTBody($plugin['body']);
// look for "emoticon" images from TinyMCE and copy into message as attachments
$message_body = rcmail_attach_emoticons($MAIL_MIME);
- }
+}
else
{
$message_body = rc_wordwrap($message_body, 75, "\r\n");
if ($footer)
$message_body .= "\r\n" . $footer;
$message_body = wordwrap($message_body, 998, "\r\n", true);
- if (!strlen($message_body))
- {
+ if (!strlen($message_body)) {
// empty message body breaks attachment handling in drafts
$message_body = "\r\n";
- }
- $MAIL_MIME->setTXTBody($message_body, FALSE, TRUE);
}
+ $plugin = $RCMAIL->plugins->exec_hook('outgoing_message_body', array('body' => $message_body, 'type' => 'plain', 'message' => $MAIL_MIME));
+ $MAIL_MIME->setTXTBody($plugin['body'], false, true);
+}
// chose transfer encoding
$charset_7bit = array('ASCII', 'ISO-2022-JP', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-15');
$transfer_encoding = in_array(strtoupper($message_charset), $charset_7bit) ? '7bit' : '8bit';
// add stored attachments, if any
-if (is_array($_SESSION['compose']['attachments']))
- foreach ($_SESSION['compose']['attachments'] as $id => $attachment)
- {
- $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . $id . '[\s\'"]\s*/';
- $match = preg_match($dispurl, $message_body, $matches);
- if ($isHtml && ($match > 0))
- {
+if (is_array($_SESSION['compose']['attachments'])) {
+ foreach ($_SESSION['compose']['attachments'] as $id => $attachment) {
+ // This hook retrieves the attachment contents from the file storage backend
+ $attachment = $RCMAIL->plugins->exec_hook('get_attachment', $attachment);
+
+ $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]\s*/';
+ $message_body = $MAIL_MIME->getHTMLBody();
+ if ($isHtml && (preg_match($dispurl, $message_body) > 0)) {
$message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body);
$MAIL_MIME->setHTMLBody($message_body);
- $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name']);
+
+ if ($attachment['data'])
+ $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false);
+ else
+ $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true);
}
- else
- {
+ else {
$ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914
+ $file = $attachment['data'] ? $attachment['data'] : $attachment['path'];
// .eml attachments send inline
- $MAIL_MIME->addAttachment($attachment['path'],
+ $MAIL_MIME->addAttachment($file,
$ctype,
- $attachment['name'], true,
+ $attachment['name'],
+ ($attachment['data'] ? false : true),
($ctype == 'message/rfc822' ? $transfer_encoding : 'base64'),
($ctype == 'message/rfc822' ? 'inline' : 'attachment'),
$message_charset, '', '',
- $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,
- $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL
- );
+ $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,
+ $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL
+ );
}
}
+}
// add submitted attachments
-if (is_array($_FILES['_attachments']['tmp_name']))
- foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath)
- {
+if (is_array($_FILES['_attachments']['tmp_name'])) {
+ foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) {
$ctype = $files['type'][$i];
$ctype = str_replace('image/pjpeg', 'image/jpeg', $ctype); // #1484914
$MAIL_MIME->addAttachment($filepath, $ctype, $files['name'][$i], true,
- $ctype == 'message/rfc822' ? $transfer_encoding : 'base64',
- 'attachment', $message_charset, '', '',
- $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,
- $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL
- );
- }
-
+ $ctype == 'message/rfc822' ? $transfer_encoding : 'base64',
+ 'attachment', $message_charset, '', '',
+ $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,
+ $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL
+ );
+ }
+}
// encoding settings for mail composing
$MAIL_MIME->setParam(array(
@@ -388,6 +394,9 @@ $MAIL_MIME->setParam(array(
'text_charset' => $message_charset,
));
+$data = $RCMAIL->plugins->exec_hook('outgoing_message_headers', array('headers' => $headers));
+$headers = $data['headers'];
+
// encoding subject header with mb_encode provides better results with asian characters
if (function_exists("mb_encode_mimeheader"))
{
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index fd31fa91c..9beb42521 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -135,9 +135,11 @@ if ($_GET['_uid']) {
}
// mark message as read
- if (!$MESSAGE->headers->seen)
+ if (!$MESSAGE->headers->seen) {
$IMAP->set_flag($MESSAGE->uid, 'SEEN');
+ $RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid, 'mailbox' => $IMAP->mailbox, 'message' => $MESSAGE));
}
+}
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 3f0357717..6eda4dba3 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -159,6 +159,8 @@ function rcmail_user_prefs_block($part, $no_override, $attrib)
}
}
+ $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table));
+
if ($table->size())
$out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('uisettings'))) . $table->show($attrib));
break;
@@ -216,6 +218,8 @@ function rcmail_user_prefs_block($part, $no_override, $attrib)
$table->add(null, $input_check_all->show($config['check_all_folders']?1:0));
}
+ $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table));
+
if ($table->size())
$out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('mailboxview'))) . $table->show($attrib));
break;
@@ -254,6 +258,8 @@ function rcmail_user_prefs_block($part, $no_override, $attrib)
$table->add(null, $input_inline_images->show($config['inline_images']?1:0));
}
+ $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table));
+
if ($table->size())
$out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('messagesdisplaying'))) . $table->show($attrib));
break;
@@ -295,6 +301,8 @@ function rcmail_user_prefs_block($part, $no_override, $attrib)
$table->add(null, $select_param_folding->show($config['mime_param_folding']));
}
+ $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table));
+
if ($table->size())
$out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('messagescomposition'))) . $table->show($attrib));
break;
@@ -329,6 +337,8 @@ function rcmail_user_prefs_block($part, $no_override, $attrib)
$table->add(null, $select->show($config['trash_mbox'], array('name' => "_trash_mbox")));
}
+ $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table));
+
$out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('specialfolders'))) . $table->show($attrib));
}
break;
@@ -381,6 +391,8 @@ function rcmail_user_prefs_block($part, $no_override, $attrib)
$table->add(null, $input_expunge->show($config['logout_expunge']?1:0));
}
+ $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table));
+
if ($table->size())
$out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('serversettings'))) . $table->show($attrib));
break;
diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc
index 9affded98..79d313c37 100644
--- a/program/steps/settings/manage_folders.inc
+++ b/program/steps/settings/manage_folders.inc
@@ -256,6 +256,7 @@ function rcube_subscription_form($attrib)
$a_js_folders['rcmrow'.$idx] = array($folder_utf8, $display_folder, $protected || $folder['virtual']);
}
+ rcmail::get_instance()->plugins->exec_hook('manage_folders', array('table'=>$table));
$OUTPUT->add_gui_object('subscriptionlist', $attrib['id']);
$OUTPUT->set_env('subscriptionrows', $a_js_folders);
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index 09cf63d6f..c5afd5b0c 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -48,6 +48,9 @@ $a_user_prefs = array(
'trash_mbox' => get_input_value('_trash_mbox', RCUBE_INPUT_POST),
);
+$data = rcmail::get_instance()->plugins->exec_hook('save_preferences', array('prefs' => $a_user_prefs));
+$a_user_prefs = $data['prefs'];
+
// don't override these parameters
foreach ((array)$CONFIG['dont_override'] as $p)
$a_user_prefs[$p] = $CONFIG[$p];
diff --git a/skins/default/common.css b/skins/default/common.css
index 34ea1d2b8..631321c72 100644
--- a/skins/default/common.css
+++ b/skins/default/common.css
@@ -246,6 +246,13 @@ a.button-logout
border: 1px solid #CCCCCC;
}
+#pagecontent
+{
+ position: absolute;
+ top: 95px;
+ left: 20px;
+}
+
.splitter
{
user-select: none;
diff --git a/skins/default/functions.js b/skins/default/functions.js
index 9e71f6f9a..fd6e612ee 100644
--- a/skins/default/functions.js
+++ b/skins/default/functions.js
@@ -8,24 +8,16 @@
function rcube_init_settings_tabs()
{
+ var tab = '#settingstabdefault';
if (window.rcmail && rcmail.env.action)
- {
- var action = rcmail.env.action=='preferences' ? 'default' : (rcmail.env.action.indexOf('identity')>0 ? 'identities' : rcmail.env.action);
- var tab = document.getElementById('settingstab'+action);
- }
- else
- var tab = document.getElementById('settingstabdefault');
-
- if (tab)
- tab.className = 'tablink-selected';
+ tab = '#settingstab' + (rcmail.env.action=='preferences' ? 'default' : (rcmail.env.action.indexOf('identity')>0 ? 'identities' : rcmail.env.action.replace(/\./g, '')));
+
+ $(tab).addClass('tablink-selected');
}
function rcube_show_advanced(visible)
{
- var rows = document.getElementsByTagName('TR');
- for(var i=0; i
+
+
diff --git a/skins/default/includes/taskbar.html b/skins/default/includes/taskbar.html
index ef1aa8268..c2841a606 100644
--- a/skins/default/includes/taskbar.html
+++ b/skins/default/includes/taskbar.html
@@ -1,4 +1,5 @@
+
diff --git a/skins/default/mail.css b/skins/default/mail.css
index 5a4e57bfe..ab4579eb9 100644
--- a/skins/default/mail.css
+++ b/skins/default/mail.css
@@ -49,7 +49,7 @@
top: 32px;
left: 90px;
width: auto;
- visibility: hidden;
+ display: none;
background-color: #F9F9F9;
border: 1px solid #CCC;
padding: 1px;
diff --git a/skins/default/splitter.js b/skins/default/splitter.js
index 3ed0eb62a..fae3ca5cb 100644
--- a/skins/default/splitter.js
+++ b/skins/default/splitter.js
@@ -22,18 +22,18 @@ function rcube_splitter(attrib)
this.p2 = document.getElementById(this.p2id);
// create and position the handle for this splitter
- this.p1pos = rcube_get_object_pos(this.p1, this.relative);
- this.p2pos = rcube_get_object_pos(this.p2, this.relative);
+ this.p1pos = this.relative ? $(this.p1).position() : $(this.p1).offset();
+ this.p2pos = this.relative ? $(this.p2).position() : $(this.p2).offset();
if (this.horizontal)
{
- var top = this.p1pos.y + this.p1.offsetHeight;
+ var top = this.p1pos.top + this.p1.offsetHeight;
this.layer = new rcube_layer(this.id, {x: 0, y: top, height: 10,
width: '100%', vis: 1, parent: this.p1.parentNode});
}
else
{
- var left = this.p1pos.x + this.p1.offsetWidth;
+ var left = this.p1pos.left + this.p1.offsetWidth;
this.layer = new rcube_layer(this.id, {x: left, y: 0, width: 10,
height: '100%', vis: 1, parent: this.p1.parentNode});
}
@@ -70,18 +70,18 @@ function rcube_splitter(attrib)
if (this.horizontal)
{
var lh = this.layer.height - this.offset * 2;
- this.p1.style.height = Math.floor(this.pos - this.p1pos.y - lh / 2) + 'px';
+ this.p1.style.height = Math.floor(this.pos - this.p1pos.top - lh / 2) + 'px';
this.p2.style.top = Math.ceil(this.pos + lh / 2) + 'px';
- this.layer.move(this.layer.x, Math.round(this.pos - lh / 2 + 1));
+ this.layer.move(this.layer.x, Math.round(this.pos - lh / 2 + 1));
if (bw.ie)
- {
+ {
var new_height = (parseInt(this.p2.parentNode.offsetHeight) - parseInt(this.p2.style.top));
this.p2.style.height = (new_height > 0 ? new_height : 0) +'px';
}
}
else
{
- this.p1.style.width = Math.floor(this.pos - this.p1pos.x - this.layer.width / 2) + 'px';
+ this.p1.style.width = Math.floor(this.pos - this.p1pos.left - this.layer.width / 2) + 'px';
this.p2.style.left = Math.ceil(this.pos + this.layer.width / 2) + 'px';
this.layer.move(Math.round(this.pos - this.layer.width / 2 + 1), this.layer.y);
if (bw.ie)
@@ -94,8 +94,8 @@ function rcube_splitter(attrib)
*/
this.onDragStart = function(e)
{
- this.p1pos = rcube_get_object_pos(this.p1, this.relative);
- this.p2pos = rcube_get_object_pos(this.p2, this.relative);
+ this.p1pos = this.relative ? $(this.p1).position() : $(this.p1).offset();
+ this.p2pos = this.relative ? $(this.p2).position() : $(this.p2).offset();
this.drag_active = true;
// start listening to mousemove events
@@ -119,8 +119,8 @@ function rcube_splitter(attrib)
// I don't use the add_listener function for this one because I need to create closures to fetch
// the position of each iframe when the event is received
var s = this;
- var id = iframes[n].id;
- this.iframe_events[n] = function(e){ e._offset = rcube_get_object_pos(document.getElementById(id)); return s.onDrag(e); }
+ var id = '#'+iframes[n].id;
+ this.iframe_events[n] = function(e){ e._offset = $(id).offset(); return s.onDrag(e); }
if (iframedoc.addEventListener)
iframedoc.addEventListener('mousemove', this.iframe_events[n], false);
@@ -145,14 +145,14 @@ function rcube_splitter(attrib)
if (this.relative)
{
- var parent = rcube_get_object_pos(this.p1.parentNode);
- pos.x -= parent.x;
- pos.y -= parent.y;
+ var parent = $(this.p1.parentNode).offset();
+ pos.x -= parent.left;
+ pos.y -= parent.top;
}
if (this.horizontal)
{
- if (((pos.y - this.layer.height * 1.5) > this.p1pos.y) && ((pos.y + this.layer.height * 1.5) < (this.p2pos.y + this.p2.offsetHeight)))
+ if (((pos.y - this.layer.height * 1.5) > this.p1pos.top) && ((pos.y + this.layer.height * 1.5) < (this.p2pos.top + this.p2.offsetHeight)))
{
this.pos = pos.y;
this.resize();
@@ -160,15 +160,15 @@ function rcube_splitter(attrib)
}
else
{
- if (((pos.x - this.layer.width * 1.5) > this.p1pos.x) && ((pos.x + this.layer.width * 1.5) < (this.p2pos.x + this.p2.offsetWidth)))
+ if (((pos.x - this.layer.width * 1.5) > this.p1pos.left) && ((pos.x + this.layer.width * 1.5) < (this.p2pos.left + this.p2.offsetWidth)))
{
this.pos = pos.x;
this.resize();
}
}
- this.p1pos = rcube_get_object_pos(this.p1, this.relative);
- this.p2pos = rcube_get_object_pos(this.p2, this.relative);
+ this.p1pos = this.relative ? $(this.p1).position() : $(this.p1).offset();
+ this.p2pos = this.relative ? $(this.p2).position() : $(this.p2).offset();
return false;
};
@@ -198,7 +198,7 @@ function rcube_splitter(attrib)
if (this.iframe_events[n]) {
if (iframedoc.removeEventListener)
iframedoc.removeEventListener('mousemove', this.iframe_events[n], false);
- else if (iframedoc.detachEvent)
+ else if (iframedoc.detachEvent)
iframedoc.detachEvent('onmousemove', this.iframe_events[n]);
else
iframedoc['onmousemove'] = null;
diff --git a/skins/default/templates/addressbook.html b/skins/default/templates/addressbook.html
index ce295567b..431c0589e 100644
--- a/skins/default/templates/addressbook.html
+++ b/skins/default/templates/addressbook.html
@@ -7,7 +7,7 @@
|