[Svn] r4424 - in trunk/roundcubemail: . config program/include program/js program/localization/en_US program/steps/addressbook program/steps/mail skins/default skins/default/images skins/default/templates

trac at roundcube.net trac at roundcube.net
Tue Jan 18 19:00:57 CET 2011


Author: thomasb
Date: 2011-01-18 12:00:57 -0600 (Tue, 18 Jan 2011)
New Revision: 4424

Added:
   trunk/roundcubemail/skins/default/images/contactpic.png
Modified:
   trunk/roundcubemail/
   trunk/roundcubemail/config/main.inc.php.dist
   trunk/roundcubemail/program/include/html.php
   trunk/roundcubemail/program/include/main.inc
   trunk/roundcubemail/program/include/rcmail.php
   trunk/roundcubemail/program/include/rcube_addressbook.php
   trunk/roundcubemail/program/include/rcube_browser.php
   trunk/roundcubemail/program/include/rcube_contacts.php
   trunk/roundcubemail/program/include/rcube_ldap.php
   trunk/roundcubemail/program/include/rcube_plugin.php
   trunk/roundcubemail/program/include/rcube_plugin_api.php
   trunk/roundcubemail/program/include/rcube_shared.inc
   trunk/roundcubemail/program/include/rcube_template.php
   trunk/roundcubemail/program/include/rcube_vcard.php
   trunk/roundcubemail/program/js/app.js
   trunk/roundcubemail/program/localization/en_US/labels.inc
   trunk/roundcubemail/program/localization/en_US/messages.inc
   trunk/roundcubemail/program/steps/addressbook/copy.inc
   trunk/roundcubemail/program/steps/addressbook/delete.inc
   trunk/roundcubemail/program/steps/addressbook/edit.inc
   trunk/roundcubemail/program/steps/addressbook/export.inc
   trunk/roundcubemail/program/steps/addressbook/func.inc
   trunk/roundcubemail/program/steps/addressbook/groups.inc
   trunk/roundcubemail/program/steps/addressbook/import.inc
   trunk/roundcubemail/program/steps/addressbook/list.inc
   trunk/roundcubemail/program/steps/addressbook/mailto.inc
   trunk/roundcubemail/program/steps/addressbook/save.inc
   trunk/roundcubemail/program/steps/addressbook/search.inc
   trunk/roundcubemail/program/steps/addressbook/show.inc
   trunk/roundcubemail/program/steps/mail/autocomplete.inc
   trunk/roundcubemail/program/steps/mail/compose.inc
   trunk/roundcubemail/skins/default/addressbook.css
   trunk/roundcubemail/skins/default/common.css
   trunk/roundcubemail/skins/default/functions.js
   trunk/roundcubemail/skins/default/iehacks.css
   trunk/roundcubemail/skins/default/mail.css
   trunk/roundcubemail/skins/default/templates/contact.html
   trunk/roundcubemail/skins/default/templates/contactadd.html
   trunk/roundcubemail/skins/default/templates/contactedit.html
Log:
Merge branch devel-addressbook (r4193:4382) back into trunk


Property changes on: trunk/roundcubemail
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/devel-threads:3067-3364
   + /branches/devel-addressbook:4193-4422
/branches/devel-threads:3067-3364

Modified: trunk/roundcubemail/config/main.inc.php.dist
===================================================================
--- trunk/roundcubemail/config/main.inc.php.dist	2011-01-18 11:50:46 UTC (rev 4423)
+++ trunk/roundcubemail/config/main.inc.php.dist	2011-01-18 18:00:57 UTC (rev 4424)
@@ -308,6 +308,15 @@
 // mime magic database
 $rcmail_config['mime_magic'] = '/usr/share/misc/magic';
 
+// path to imagemagick identify binary
+$rcmail_config['im_identify_path'] = null;
+
+// path to imagemagick convert binary
+$rcmail_config['im_convert_path'] = null;
+
+// maximum size of uploaded contact photos in pixel
+$rcmail_config['contact_photo_size'] = 160;
+
 // Enable DNS checking for e-mail address validation
 $rcmail_config['email_dns_check'] = false;
 
@@ -346,6 +355,9 @@
 // use this format for today's date display (date or strftime format)
 $rcmail_config['date_today'] = 'H:i';
 
+// use this format for date display without time (date or strftime format)
+$rcmail_config['date_format'] = 'Y-m-d';
+
 // store draft message is this mailbox
 // leave blank if draft messages should not be stored
 $rcmail_config['drafts_mbox'] = 'Drafts';
@@ -458,7 +470,6 @@
   // The login name is used to search for the DN to bind with
   'search_base_dn' => '',
   'search_filter'  => '',   // e.g. '(&(objectClass=posixAccount)(uid=%u))'
-
   'writable'      => false,   // Indicates if we can write to the LDAP directory or not.
   // If writable is true then these fields need to be populated:
   // LDAP_Object_Classes, required_fields, LDAP_rdn
@@ -467,10 +478,21 @@
   'LDAP_rdn'      => 'mail', // The RDN field that is used for new entries, this field needs to be one of the search_fields, the base of base_dn is appended to the RDN to insert into the LDAP directory.
   'ldap_version'  => 3,       // using LDAPv3
   'search_fields' => array('mail', 'cn'),  // fields to search in
-  'name_field'    => 'cn',    // this field represents the contact's name
-  'email_field'   => 'mail',  // this field represents the contact's e-mail
-  'surname_field' => 'sn',    // this field represents the contact's last name
-  'firstname_field' => 'gn',  // this field represents the contact's first name
+  'fieldmap' => array(      // mapping of contact fields to directory attributes
+    // Roundcube  => LDAP
+    'name'        => 'cn',
+    'surname'     => 'sn',
+    'firstname'   => 'givenName',
+    'email'       => 'mail',
+    'phone:home'  => 'homePhone',
+    'phone:work'  => 'telephoneNumber',
+    'phone:mobile' => 'mobile',
+    'street'      => 'street',
+    'zipcode'     => 'postalCode',
+    'locality'    => 'l',
+    'country'     => 'c',
+    'organization' => 'o',
+  ),
   'sort'          => 'cn',    // The field to sort the listing by.
   'scope'         => 'sub',   // search mode: sub|base|list
   'filter'        => '',      // used for basic listing (if not empty) and will be &'d with search queries. example: status=act
@@ -489,6 +511,10 @@
 // may need to do lengthy results building given overly-broad searches
 $rcmail_config['autocomplete_min_length'] = 1;
 
+// show address fields in this order
+// available placeholders: {street}, {locality}, {zipcode}, {country}, {region}
+$rcmail_config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}';
+
 // ----------------------------------
 // USER PREFERENCES
 // ----------------------------------

Modified: trunk/roundcubemail/program/include/html.php
===================================================================
--- trunk/roundcubemail/program/include/html.php	2011-01-18 11:50:46 UTC (rev 4423)
+++ trunk/roundcubemail/program/include/html.php	2011-01-18 18:00:57 UTC (rev 4424)
@@ -71,6 +71,9 @@
      */
     public static function tag($tagname, $attrib = array(), $content = null, $allowed_attrib = null)
     {
+        if (is_string($attrib))
+            $attrib = array('class' => $attrib);
+
         $inline_tags = array('a','span','img');
         $suffix = $attrib['nl'] || ($content && $attrib['nl'] !== false && !in_array($tagname, $inline_tags)) ? "\n" : '';
 
@@ -147,7 +150,7 @@
             $attr = array('href' => $attr);
         }
         return self::tag('a', $attr, $cont, array_merge(self::$common_attrib,
-	    array('href','target','name','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
+	    array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
     }
 
     /**
@@ -501,7 +504,7 @@
     protected $tagname = 'select';
     protected $options = array();
     protected $allowed = array('name','size','tabindex','autocomplete',
-	'multiple','onchange','disabled');
+	'multiple','onchange','disabled','rel');
     
     /**
      * Add a new option to this drop-down

Modified: trunk/roundcubemail/program/include/main.inc
===================================================================
--- trunk/roundcubemail/program/include/main.inc	2011-01-18 11:50:46 UTC (rev 4423)
+++ trunk/roundcubemail/program/include/main.inc	2011-01-18 18:00:57 UTC (rev 4424)
@@ -799,7 +799,7 @@
 
       // format each col
       foreach ($a_show_cols as $col)
-        $table->add($col, Q($row_data[$col]));
+        $table->add($col, Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]));
         
       $c++;
     }
@@ -819,32 +819,43 @@
  * @return string HTML field definition
  */
 function rcmail_get_edit_field($col, $value, $attrib, $type='text')
-  {
+{
+  static $colcounts = array();
+  
   $fname = '_'.$col;
-  $attrib['name'] = $fname;
+  $attrib['name'] = $fname . ($attrib['array'] ? '[]' : '');
+  $attrib['class'] = trim($attrib['class'] . ' ff_' . $col);
   
-  if ($type=='checkbox')
-    {
+  if ($type == 'checkbox') {
     $attrib['value'] = '1';
     $input = new html_checkbox($attrib);
-    }
-  else if ($type=='textarea')
-    {
+  }
+  else if ($type == 'textarea') {
     $attrib['cols'] = $attrib['size'];
     $input = new html_textarea($attrib);
-    }
-  else
+  }
+  else if ($type == 'select') {
+    $input = new html_select($attrib);
+    $input->add('---', '');
+    $input->add(array_values($attrib['options']), array_keys($attrib['options']));
+  }
+  else {
+    if ($attrib['type'] != 'text' && $attrib['type'] != 'hidden')
+        $attrib['type'] = 'text';
     $input = new html_inputfield($attrib);
+  }
 
   // use value from post
-  if (!empty($_POST[$fname]))
-    $value = get_input_value($fname, RCUBE_INPUT_POST,
-	    $type == 'textarea' && strpos($attrib['class'], 'mce_editor')!==false ? true : false);
+  if (isset($_POST[$fname])) {
+    $postvalue = get_input_value($fname, RCUBE_INPUT_POST,
+      $type == 'textarea' && strpos($attrib['class'], 'mce_editor')!==false ? true : false);
+    $value = $attrib['array'] ? $postvalue[intval($colcounts[$col]++)] : $postvalue;
+  }
 
   $out = $input->show($value);
-         
+
   return $out;
-  }
+}
 
 
 /**

Modified: trunk/roundcubemail/program/include/rcmail.php
===================================================================
--- trunk/roundcubemail/program/include/rcmail.php	2011-01-18 11:50:46 UTC (rev 4423)
+++ trunk/roundcubemail/program/include/rcmail.php	2011-01-18 18:00:57 UTC (rev 4424)
@@ -114,7 +114,7 @@
   public $comm_path = './';
 
   private $texts;
-  private $books = array();
+  private $address_books = array();
   private $action_map = array();
 
 
@@ -331,6 +331,10 @@
     if ($plugin['instance'] instanceof rcube_addressbook) {
       $contacts = $plugin['instance'];
     }
+    // use existing instance
+    else if (isset($this->address_books[$id]) && is_a($this->address_books[$id], 'rcube_addressbook') && (!$writeable || !$this->address_books[$id]->readonly)) {
+      $contacts = $this->address_books[$id];
+    }
     else if ($id && $ldap_config[$id]) {
       $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['imap_host']));
     }
@@ -351,8 +355,8 @@
     }
 
     // add to the 'books' array for shutdown function
-    if (!in_array($contacts, $this->books))
-      $this->books[] = $contacts;
+    if (!isset($this->address_books[$id]))
+      $this->address_books[$id] = $contacts;
 
     return $contacts;
   }
@@ -373,11 +377,12 @@
 
     // We are using the DB address book
     if ($abook_type != 'ldap') {
-      $contacts = new rcube_contacts($this->db, null);
+      if (!isset($this->address_books['0']))
+        $this->address_books['0'] = new rcube_contacts($this->db, $this->user->ID);
       $list['0'] = array(
-        'id' => 0,
+        'id' => '0',
         'name' => rcube_label('personaladrbook'),
-        'groups' => $contacts->groups,
+        'groups' => $this->address_books['0']->groups,
         'readonly' => false,
         'autocomplete' => in_array('sql', $autocomplete)
       );
@@ -398,14 +403,15 @@
     $plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list));
     $list = $plugin['sources'];
 
-    if ($writeable && !empty($list)) {
-      foreach ($list as $idx => $item) {
-        if ($item['readonly']) {
+    foreach ($list as $idx => $item) {
+      // register source for shutdown function
+      if (!is_object($this->address_books[$item['id']]))
+        $this->address_books[$item['id']] = $item;
+      // remove from list if not writeable as requested
+      if ($writeable && $item['readonly'])
           unset($list[$idx]);
-        }
-      }
     }
-
+    
     return $list;
   }
 
@@ -1078,9 +1084,12 @@
     if (is_object($this->smtp))
       $this->smtp->disconnect();
 
-    foreach ($this->books as $book)
-      if (is_object($book))
+    foreach ($this->address_books as $book) {
+      if (!is_object($book))  // maybe an address book instance wasn't fetched using get_address_book() yet
+        $book = $this->get_address_book($book['id']);
+      if (is_a($book, 'rcube_addressbook'))
         $book->close();
+    }
 
     // before closing the database connection, write session data
     if ($_SERVER['REMOTE_ADDR'])
@@ -1307,6 +1316,112 @@
 
 
   /**
+   * Use imagemagick or GD lib to read image properties
+   *
+   * @param string Absolute file path
+   * @return mixed Hash array with image props like type, width, height or False on error
+   */
+  public static function imageprops($filepath)
+  {
+    $rcmail = rcmail::get_instance();
+    if ($cmd = $rcmail->config->get('im_identify_path', false)) {
+      list(, $type, $size) = explode(' ', strtolower(rcmail::exec($cmd. ' 2>/dev/null {in}', array('in' => $filepath))));
+      if ($size)
+        list($width, $height) = explode('x', $size);
+    }
+    else if (function_exists('getimagesize')) {
+      $imsize = @getimagesize($filepath);
+      $width = $imsize[0];
+      $height = $imsize[1];
+      $type = preg_replace('!image/!', '', $imsize['mime']);
+    }
+
+    return $type ? array('type' => $type, 'width' => $width, 'height' => $height) : false;
+  }
+
+
+  /**
+   * Convert an image to a given size and type using imagemagick (ensures input is an image)
+   *
+   * @param $p['in']  Input filename (mandatory)
+   * @param $p['out'] Output filename (mandatory)
+   * @param $p['size']  Width x height of resulting image, e.g. "160x60"
+   * @param $p['type']  Output file type, e.g. "jpg"
+   * @param $p['-opts'] Custom command line options to ImageMagick convert