summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthomascube <thomas@roundcube.net>2008-09-04 18:20:27 +0000
committerthomascube <thomas@roundcube.net>2008-09-04 18:20:27 +0000
commit0dbac3218130dfe418d6c7dc162f819c746bec2d (patch)
tree12fe7f8ac96d3fcbff68d32f6e048374b474d9a2
parentd41f9762a7fa9e206a499bfa197435a578e36360 (diff)
Enable export of contacts as vCard + DRY
-rw-r--r--CHANGELOG4
-rw-r--r--program/include/rcube_shared.inc8
-rw-r--r--program/include/rcube_vcard.php11
-rw-r--r--program/js/app.js101
-rw-r--r--program/js/list.js6
-rw-r--r--program/steps/addressbook/export.inc43
-rw-r--r--program/steps/mail/get.inc18
-rw-r--r--skins/default/templates/addcontact.html2
8 files changed, 131 insertions, 62 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 3bba337f5..92a08c6a9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
CHANGELOG RoundCube Webmail
---------------------------
+2008/09/04 (thomasb)
+----------
+- Enable export of address book contacts as vCard
+
2008/09/04 (alec)
----------
- Truncate very long (above 50 characters) attachment filenames when displaying
diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc
index 0dd661ec5..5008251ad 100644
--- a/program/include/rcube_shared.inc
+++ b/program/include/rcube_shared.inc
@@ -37,8 +37,14 @@ function send_nocacheing_headers()
header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
- header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
+ header("Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");
+
+ // We need to set the following headers to make downloads work using IE in HTTPS mode.
+ if (isset($_SERVER['HTTPS'])) {
+ header('Pragma: ');
+ header('Cache-Control: ');
+ }
}
diff --git a/program/include/rcube_vcard.php b/program/include/rcube_vcard.php
index 560d37d17..3ad47a5cb 100644
--- a/program/include/rcube_vcard.php
+++ b/program/include/rcube_vcard.php
@@ -28,7 +28,10 @@
*/
class rcube_vcard
{
- private $raw = array();
+ private $raw = array(
+ 'FN' => array(),
+ 'N' => array(array('','','','','')),
+ );
public $business = false;
public $displayname;
@@ -98,7 +101,7 @@ class rcube_vcard
* @param string Field value
* @param string Section name
*/
- public function set($field, $value, $section = 'home')
+ public function set($field, $value, $section = 'HOME')
{
switch ($field) {
case 'name':
@@ -222,7 +225,7 @@ class rcube_vcard
private static function rfc2425_fold($val)
{
- return preg_replace('/:([^\n]{72,})/e', '":\n ".rtrim(chunk_split("\\1", 72, "\n "))', $val) . "\n\n";
+ return preg_replace('/:([^\n]{72,})/e', '":\n ".rtrim(chunk_split("\\1", 72, "\n "))', $val) . "\n";
}
@@ -325,7 +328,7 @@ class rcube_vcard
}
}
- return "BEGIN:VCARD\nVERSION:3.0\n{$vcard}END:VCARD\n";
+ return "BEGIN:VCARD\nVERSION:3.0\n{$vcard}END:VCARD";
}
diff --git a/program/js/app.js b/program/js/app.js
index 7ba8572b3..3e49fc3b2 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -205,10 +205,7 @@ function rcube_webmail()
if (this.env.messagecount)
this.enable_command('select-all', 'select-none', 'expunge', true);
- if (this.env.messagecount
- && (this.env.mailbox == this.env.trash_mailbox || this.env.mailbox == this.env.junk_mailbox
- || this.env.mailbox.match('^' + RegExp.escape(this.env.trash_mailbox) + RegExp.escape(this.env.delimiter))
- || this.env.mailbox.match('^' + RegExp.escape(this.env.junk_mailbox) + RegExp.escape(this.env.delimiter))))
+ if (this.purge_mailbox_test())
this.enable_command('purge', true);
this.set_page_buttons();
@@ -282,6 +279,9 @@ function rcube_webmail()
this.enable_command('save', true);
else
this.enable_command('search', 'reset-search', 'moveto', 'import', true);
+
+ if (this.contact_list && this.contact_list.rowcount > 0)
+ this.enable_command('export', true);
this.enable_command('list', true);
break;
@@ -1002,7 +1002,17 @@ function rcube_webmail()
}
else
this.goto_url('import');
- break
+ break;
+
+ case 'export':
+ if (this.contact_list.rowcount > 0) {
+ var add_url = '';
+ if (this.env.search_request)
+ add_url = '_search='+this.env.search_request;
+
+ this.goto_url('export', add_url);
+ }
+ break;
// collapse/expand folder
case 'collapse-folder':
@@ -1490,7 +1500,15 @@ function rcube_webmail()
return true;
};
-
+ // test if purge command is allowed
+ this.purge_mailbox_test = function()
+ {
+ return (this.env.messagecount && (this.env.mailbox == this.env.trash_mailbox || this.env.mailbox == this.env.junk_mailbox
+ || this.env.mailbox.match('^' + RegExp.escape(this.env.trash_mailbox) + RegExp.escape(this.env.delimiter))
+ || this.env.mailbox.match('^' + RegExp.escape(this.env.junk_mailbox) + RegExp.escape(this.env.delimiter))));
+ };
+
+
// move selected messages to the specified mailbox
this.move_messages = function(mbox)
{
@@ -1900,7 +1918,8 @@ function rcube_webmail()
}
}
};
-
+
+
/*********************************************************/
/********* login form methods *********/
/*********************************************************/
@@ -3599,6 +3618,7 @@ function rcube_webmail()
}
this.contact_list.insert_row(row);
+ this.enable_command('export', (this.contact_list.rowcount > 0));
};
@@ -3739,53 +3759,46 @@ function rcube_webmail()
eval(request_obj.get_text());
// process the response data according to the sent action
- switch (request_obj.__action)
- {
-
+ switch (request_obj.__action) {
case 'delete':
- if (this.task == 'addressbook')
- {
- var uid = this.contact_list.get_selection();
- this.enable_command('compose', (uid && this.contact_list.rows[uid]));
- this.enable_command('delete', 'edit', (uid && this.contact_list.rows[uid] && this.env.address_sources && !this.env.address_sources[this.env.source].readonly));
- break;
- }
+ if (this.task == 'addressbook') {
+ var uid = this.contact_list.get_selection();
+ this.enable_command('compose', (uid && this.contact_list.rows[uid]));
+ this.enable_command('delete', 'edit', (uid && this.contact_list.rows[uid] && this.env.address_sources && !this.env.address_sources[this.env.source].readonly));
+ this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
+ }
+
case 'moveto':
- if (this.env.action=='show')
+ if (this.env.action == 'show')
this.command('list');
else if (this.message_list)
this.message_list.init();
-
+ break;
+
case 'purge':
case 'expunge':
- if (!this.env.messagecount && this.task == 'mail')
- {
- // clear preview pane content
- if (this.env.contentframe)
- this.show_contentframe(false);
- // disable commands useless when mailbox is empty
- this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource',
- 'print', 'load-attachment', 'purge', 'expunge', 'select-all', 'select-none', 'sort', false);
- }
- break;
-
- case 'list':
- this.msglist_select(this.message_list);
+ if (!this.env.messagecount && this.task == 'mail') {
+ // clear preview pane content
+ if (this.env.contentframe)
+ this.show_contentframe(false);
+ // disable commands useless when mailbox is empty
+ this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource',
+ 'print', 'load-attachment', 'purge', 'expunge', 'select-all', 'select-none', 'sort', false);
+ }
+ break;
case 'check-recent':
case 'getunread':
- if (this.task == 'mail')
- {
- this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0));
- var mailboxtest = (this.env.mailbox == this.env.trash_mailbox || this.env.mailbox == this.env.junk_mailbox
- || this.env.mailbox.match('^' + RegExp.escape(this.env.trash_mailbox) + RegExp.escape(this.env.delimiter))
- || this.env.mailbox.match('^' + RegExp.escape(this.env.junk_mailbox) + RegExp.escape(this.env.delimiter))) ? true : false;
-
- this.enable_command('purge', (this.env.messagecount && mailboxtest));
- }
- break;
-
- }
+ case 'list':
+ if (this.task == 'mail') {
+ 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();
};
diff --git a/program/js/list.js b/program/js/list.js
index 1986e8b25..97549f7eb 100644
--- a/program/js/list.js
+++ b/program/js/list.js
@@ -31,6 +31,7 @@ function rcube_list_widget(list, p)
this.frame = null;
this.rows = [];
this.selection = [];
+ this.rowcount = 0;
this.subject_col = -1;
this.shiftkey = false;
@@ -69,6 +70,7 @@ init: function()
if (this.list && this.list.tBodies[0])
{
this.rows = new Array();
+ this.rowcount = 0;
var row;
for(var r=0; r<this.list.tBodies[0].childNodes.length; r++)
@@ -81,6 +83,7 @@ init: function()
}
this.init_row(row);
+ this.rowcount++;
}
this.frame = this.list.parentNode;
@@ -128,6 +131,7 @@ clear: function(sel)
this.list.insertBefore(tbody, this.list.tBodies[0]);
this.list.removeChild(this.list.tBodies[1]);
this.rows = new Array();
+ this.rowcount = 0;
if (sel) this.clear_selection();
},
@@ -145,6 +149,7 @@ remove_row: function(uid, sel_next)
this.select_next();
this.rows[uid] = null;
+ this.rowcount--;
},
@@ -161,6 +166,7 @@ insert_row: function(row, attop)
tbody.appendChild(row);
this.init_row(row);
+ this.rowcount++;
},
diff --git a/program/steps/addressbook/export.inc b/program/steps/addressbook/export.inc
new file mode 100644
index 000000000..bfffac1f8
--- /dev/null
+++ b/program/steps/addressbook/export.inc
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/addressbook/export.inc |
+ | |
+ | This file is part of the RoundCube Webmail client |
+ | Copyright (C) 2008, RoundCube Dev. - Switzerland |
+ | Licensed under the GNU GPL |
+ | |
+ | PURPOSE: |
+ | Export the selected address book as vCard file |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+
+ $Id: $
+
+*/
+
+// get contacts for this user
+$CONTACTS->set_pagesize(999);
+$result = $CONTACTS->list_records();
+
+// send downlaod headers
+send_nocacheing_headers();
+header('Content-Type: text/x-vcard; charset=UTF-8');
+header('Content-Disposition: attachment; filename="rcube_contacts.vcf"');
+
+while ($result && ($row = $result->next())) {
+ $vcard = new rcube_vcard($row['vcard']);
+ $vcard->set('displayname', $row['name']);
+ $vcard->set('firstname', $row['firstname']);
+ $vcard->set('surname', $row['surname']);
+ $vcard->set('email', $row['email']);
+
+ echo $vcard->export();
+}
+
+exit;
+
+?>
diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc
index b95784f19..fc3ee83ea 100644
--- a/program/steps/mail/get.inc
+++ b/program/steps/mail/get.inc
@@ -57,26 +57,20 @@ else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) {
$browser = new rcube_browser;
- header("Expires: 0");
- header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
- header("Cache-Control: private", false);
- header("Content-Transfer-Encoding: binary");
-
+ send_nocacheing_headers();
+
// send download headers
if ($_GET['_download']) {
header("Content-Type: application/octet-stream");
if ($browser->ie)
header("Content-Type: application/force-download");
}
- else if ($ctype_primary == 'text')
+ else if ($ctype_primary == 'text') {
header("Content-Type: text/$ctype_secondary; charset=" . ($part->charset ? $part->charset : RCMAIL_CHARSET));
- else
+ }
+ else {
header("Content-Type: $mimetype");
-
- // We need to set the following headers to make downloads work using IE in HTTPS mode.
- if (isset($_SERVER['HTTPS'])) {
- header('Pragma: ');
- header('Cache-Control: ');
+ header("Content-Transfer-Encoding: binary");
}
// deliver part content
diff --git a/skins/default/templates/addcontact.html b/skins/default/templates/addcontact.html
index 70a796aa2..10a121a2f 100644
--- a/skins/default/templates/addcontact.html
+++ b/skins/default/templates/addcontact.html
@@ -14,7 +14,7 @@
<p><br />
<input type="button" value="<roundcube:label name="cancel" />" class="button" onclick="history.back()" />&nbsp;
-<roundcube:button command="save" type="input" class="button" label="save mainaction" />
+<roundcube:button command="save" type="input" class="button mainaction" label="save" />
</p>
</form>