Changeset 4850 in subversion


Ignore:
Timestamp:
Jun 14, 2011 9:45:26 AM (2 years ago)
Author:
alec
Message:
  • Added searching in all addressbook sources (global-search)
  • Added addressbook source selection in contacts import
Location:
trunk/roundcubemail
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/roundcubemail/CHANGELOG

    r4844 r4850  
    22=========================== 
    33 
     4- Added searching in all addressbook sources 
     5- Added addressbook source selection in contacts import 
    46- Implement LDAPv3 Virtual List View (VLV) for paged results listing 
    57- Use 'address_template' config option when adding a new address block (#1487944) 
  • trunk/roundcubemail/config/main.inc.php.dist

    r4844 r4850  
    451451// In order to enable public ldap search, configure an array like the Verisign 
    452452// example further below. if you would like to test, simply uncomment the example. 
     453// Array key must contain only safe characters, ie. a-zA-Z0-9_ 
    453454$rcmail_config['ldap_public'] = array(); 
    454455 
  • trunk/roundcubemail/program/js/app.js

    r4841 r4850  
    337337          this.enable_command('export', true); 
    338338 
    339         this.enable_command('add', 'import', !this.env.readonly); 
     339        this.enable_command('add', 'import', this.env.writable_source); 
    340340        this.enable_command('list', 'listgroup', 'advanced-search', true); 
    341341        break; 
     
    530530            this.set_alttext('delete', this.env.mailbox != this.env.trash_mailbox ? 'movemessagetotrash' : 'deletemessage'); 
    531531        } 
    532         else if (this.task=='addressbook') { 
     532        else if (this.task == 'addressbook') { 
    533533          if (!this.env.search_request || (props != this.env.source)) 
    534534            this.reset_qsearch(); 
    535535 
    536536          this.list_contacts(props); 
    537           this.enable_command('add', 'import', (this.env.address_sources && !this.env.address_sources[this.env.source].readonly)); 
     537          this.enable_command('add', 'import', this.env.writable_source); 
    538538        } 
    539539        break; 
     
    989989        if (s && this.env.mailbox) 
    990990          this.list_mailbox(this.env.mailbox); 
    991         else if (s && this.task == 'addressbook') 
     991        else if (s && this.task == 'addressbook') { 
     992          if (this.env.source == '') { 
     993            for (var n in this.env.address_sources) break; 
     994            this.env.source = n; 
     995            this.env.group = ''; 
     996          } 
    992997          this.list_contacts(this.env.source, this.env.group); 
     998        } 
    993999        break; 
    9941000 
     
    36523658      clearTimeout(this.preview_timer); 
    36533659 
    3654     var id, frame, ref = this; 
     3660    var n, id, sid, ref = this, writable = false, 
     3661      source = this.env.source ? this.env.address_sources[this.env.source] : null; 
     3662 
    36553663    if (id = list.get_single_selection()) 
    36563664      this.preview_timer = window.setTimeout(function(){ ref.load_contact(id, 'show'); }, 200); 
     
    36583666      this.show_contentframe(false); 
    36593667 
     3668    // no source = search result, we'll need to detect if any of 
     3669    // selected contacts are in writable addressbook to enable edit/delete 
     3670    if (list.selection.length) { 
     3671      if (!source) { 
     3672        for (n in list.selection) { 
     3673          sid = String(list.selection[n]).replace(/^[^-]+-/, ''); 
     3674          if (sid && this.env.address_sources[sid] && !this.env.address_sources[sid].readonly) { 
     3675            writable = true; 
     3676            break; 
     3677          } 
     3678        } 
     3679      } 
     3680      else { 
     3681        writable = !source.readonly; 
     3682      } 
     3683    } 
     3684 
    36603685    this.enable_command('compose', list.selection.length > 0); 
    3661     this.enable_command('edit', (id && this.env.address_sources && !this.env.address_sources[this.env.source].readonly) ? true : false); 
    3662     this.enable_command('delete', list.selection.length && this.env.address_sources && !this.env.address_sources[this.env.source].readonly); 
     3686    this.enable_command('edit', id && writable); 
     3687    this.enable_command('delete', list.selection.length && writable); 
    36633688 
    36643689    return false; 
     
    37983823      return; 
    37993824 
    3800     var id, a_cids = [], qs = ''; 
     3825    var id, n, a_cids = [], qs = ''; 
    38013826 
    38023827    if (this.env.cid) 
    38033828      a_cids.push(this.env.cid); 
    38043829    else { 
    3805       for (var n=0; n<selection.length; n++) { 
     3830      for (n=0; n<selection.length; n++) { 
    38063831        id = selection[n]; 
    38073832        a_cids.push(id); 
     
    38183843 
    38193844    // also send search request to get the right records from the next page 
    3820     if (this.env.search_request)  
     3845    if (this.env.search_request) 
    38213846      qs += '&_search='+this.env.search_request; 
    38223847 
     
    41204145              cols.push(childcol); 
    41214146          } 
    4122            
     4147 
    41234148          for (var i=0; i < cols.length; i++) { 
    41244149            childcol = cols[i]; 
     
    42424267      this.contact_list.clear_selection(); 
    42434268    } 
    4244     else if (framed) 
    4245       return false; 
    4246  
    4247     this.location_href(this.env.comm_path+'&_action=search'+add_url 
    4248       +'&_source='+urlencode(this.env.source) 
    4249       +(this.env.group ? '&_gid='+urlencode(this.env.group) : ''), target); 
     4269 
     4270    this.location_href(this.env.comm_path+'&_action=search'+add_url, target); 
    42504271 
    42514272    return true; 
     4273  }; 
     4274 
     4275  // unselect directory/group 
     4276  this.unselect_directory = function() 
     4277  { 
     4278    if (this.env.address_sources.length > 1 || this.env.group != '') { 
     4279      this.select_folder('', (this.env.group ? 'G'+this.env.source+this.env.group : this.env.source)); 
     4280      this.env.group = ''; 
     4281      this.env.source = ''; 
     4282    } 
    42524283  }; 
    42534284 
     
    54695500      case 'delete': 
    54705501        if (this.task == 'addressbook') { 
    5471           var uid = this.contact_list.get_selection(); 
     5502          var sid, uid = this.contact_list.get_selection(), writable = false; 
     5503 
     5504          if (uid && this.contact_list.rows[uid]) { 
     5505            // search results, get source ID from record ID 
     5506            if (this.env.source == '') { 
     5507              sid = String(uid).replace(/^[^-]+-/, ''); 
     5508              writable = sid && this.env.address_sources[sid] && !this.env.address_sources[sid].readonly; 
     5509            } 
     5510            else { 
     5511              writable = !this.env.address_sources[this.env.source].readonly; 
     5512            } 
     5513          } 
    54725514          this.enable_command('compose', (uid && this.contact_list.rows[uid])); 
    5473           this.enable_command('delete', 'edit', (uid && this.contact_list.rows[uid] && this.env.address_sources && !this.env.address_sources[this.env.source].readonly)); 
     5515          this.enable_command('delete', 'edit', writable); 
    54745516          this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0)); 
    54755517        } 
     
    55205562 
    55215563          if (response.action == 'list' || response.action == 'search') { 
    5522             this.enable_command('group-create', 
    5523               (this.env.address_sources[this.env.source].groups && !this.env.address_sources[this.env.source].readonly)); 
    5524             this.enable_command('group-rename', 'group-delete', 
    5525               (this.env.address_sources[this.env.source].groups && this.env.group && !this.env.address_sources[this.env.source].readonly)); 
     5564            var source = this.env.source != '' ? this.env.address_sources[this.env.source] : null; 
     5565            this.enable_command('group-create', (source && source.groups && !source.readonly)); 
     5566            this.enable_command('group-rename', 'group-delete', (source && source.groups && this.env.group && !source.readonly)); 
    55265567            this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount }); 
    55275568          } 
     
    55815622    return frame_name; 
    55825623  }; 
    5583    
     5624 
    55845625  // starts interval for keep-alive/check-recent signal 
    55855626  this.start_keepalive = function() 
  • trunk/roundcubemail/program/localization/en_US/labels.inc

    r4834 r4850  
    327327$labels['importcontacts'] = 'Import contacts'; 
    328328$labels['importfromfile'] = 'Import from file:'; 
     329$labels['importtarget'] = 'Add new contacts to address book:'; 
    329330$labels['importreplace'] = 'Replace the entire address book'; 
    330331$labels['importtext'] = 'You can upload contacts from an existing address book.<br/>We currently support importing addresses from the <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> data format.'; 
  • trunk/roundcubemail/program/localization/pl_PL/labels.inc

    r4843 r4850  
    464464$labels['advsearch'] = 'Wyszukiwanie zaawansowane'; 
    465465$labels['other'] = 'Inne'; 
     466$labels['importtarget'] = 'Dodaj nowe kontakty do ksiÄ 
     467ÅŒki adresowej:'; 
    466468 
    467469?> 
  • trunk/roundcubemail/program/steps/addressbook/copy.inc

    r4424 r4850  
    2424  return; 
    2525 
    26 $cid = get_input_value('_cid', RCUBE_INPUT_POST); 
    27 $target = get_input_value('_to', RCUBE_INPUT_POST); 
     26 
     27$cids         = rcmail_get_cids(); 
     28$target       = get_input_value('_to', RCUBE_INPUT_POST); 
    2829$target_group = get_input_value('_togid', RCUBE_INPUT_POST); 
    2930 
    30 if ($cid && preg_match('/^[a-zA-Z0-9\+\/=_-]+(,[a-zA-Z0-9\+\/=_-]+)*$/', $cid) && strlen($target) && $target !== $source) 
     31$success = 0; 
     32$maxnum  = $RCMAIL->config->get('max_group_members', 0); 
     33 
     34foreach ($cids as $source => $cid) 
    3135{ 
    32   $success = 0; 
    33   $TARGET = $RCMAIL->get_address_book($target); 
     36    // Something wrong, target not specified 
     37    if (!strlen($target)) { 
     38        break; 
     39    } 
    3440 
    35   if ($TARGET && $TARGET->ready && !$TARGET->readonly) { 
    36     $arr_cids = explode(',', $cid); 
     41    // It maight happen when copying records from search result 
     42    // Do nothing, go to next source 
     43    if ($target == $source) { 
     44        continue; 
     45    } 
     46 
     47    $CONTACTS = $RCMAIL->get_address_book($source); 
     48    $TARGET   = $RCMAIL->get_address_book($target); 
     49 
     50    if (!$TARGET || !$TARGET->ready || $TARGET->readonly) { 
     51        break; 
     52    } 
     53 
    3754    $ids = array(); 
    3855 
    39     foreach ($arr_cids as $cid) { 
    40       $a_record = $CONTACTS->get_record($cid, true); 
     56    foreach ($cid as $cid) { 
     57        $a_record = $CONTACTS->get_record($cid, true); 
    4158 
    42       // check if contact exists, if so, we'll need it's ID 
    43       $result = $TARGET->search('email', $a_record['email'], true, true); 
     59        // check if contact exists, if so, we'll need it's ID 
     60        $result = $TARGET->search('email', $a_record['email'], true, true); 
    4461 
    45       // insert contact record 
    46       if (!$result->count) { 
    47         $plugin = $RCMAIL->plugins->exec_hook('contact_create', array( 
    48           'record' => $a_record, 'source' => $target, 'group' => $target_group)); 
     62        // insert contact record 
     63        if (!$result->count) { 
     64            $plugin = $RCMAIL->plugins->exec_hook('contact_create', array( 
     65                'record' => $a_record, 'source' => $target, 'group' => $target_group)); 
    4966 
    50         if (!$plugin['abort']) { 
    51           if ($insert_id = $TARGET->insert($plugin['record'], false)) { 
    52             $ids[] = $insert_id; 
    53             $success++; 
    54           } 
     67            if (!$plugin['abort']) { 
     68                if ($insert_id = $TARGET->insert($plugin['record'], false)) { 
     69                    $ids[] = $insert_id; 
     70                    $success++; 
     71                } 
     72            } 
     73            else if ($plugin['result']) { 
     74                $ids = array_merge($ids, $plugin['result']); 
     75                $success++; 
     76            } 
    5577        } 
    56         else if ($plugin['result']) { 
    57           $ids = array_merge($ids, $plugin['result']); 
    58           $success++; 
     78        else { 
     79            $record = $result->first(); 
     80            $ids[] = $record['ID']; 
    5981        } 
    60       } 
    61       else { 
    62         $record = $result->first(); 
    63         $ids[] = $record['ID']; 
    64       } 
    6582    } 
    6683 
    6784    // assign to group 
    6885    if ($target_group && $TARGET->groups && !empty($ids)) { 
    69       $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array( 
    70         'group_id' => $target_group, 'ids' => $ids, 'source' => $target)); 
     86        $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array( 
     87            'group_id' => $target_group, 'ids' => $ids, 'source' => $target)); 
    7188 
    72       if (!$plugin['abort']) { 
    73         $TARGET->reset(); 
    74         $TARGET->set_group($target_group); 
     89        if (!$plugin['abort']) { 
     90            $TARGET->reset(); 
     91            $TARGET->set_group($target_group); 
    7592 
    76         if (($maxnum = $RCMAIL->config->get('max_group_members', 0)) && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) { 
    77           $OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum)); 
    78           $OUTPUT->send(); 
     93            if ($maxnum && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) { 
     94                $OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum)); 
     95                $OUTPUT->send(); 
     96            } 
     97 
     98            if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success) 
     99                $success = $cnt; 
    79100        } 
     101        else if ($plugin['result']) { 
     102            $success = $plugin['result']; 
     103        } 
     104    } 
     105} 
    80106 
    81         if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success) 
    82           $success = $cnt; 
    83       } 
    84       else if ($plugin['result']) 
    85         $success = $plugin['result']; 
    86     } 
    87   } 
    88  
    89   if ($success == 0) 
     107if ($success == 0) 
    90108    $OUTPUT->show_message('copyerror', 'error'); 
    91   else 
     109else 
    92110    $OUTPUT->show_message('copysuccess', 'notice', array('nr' => $success)); 
    93 } 
    94111 
    95112// send response 
    96113$OUTPUT->send(); 
    97  
  • trunk/roundcubemail/program/steps/addressbook/delete.inc

    r4424 r4850  
    2020*/ 
    2121 
    22 if ($OUTPUT->ajax_call && 
    23     ($cid = get_input_value('_cid', RCUBE_INPUT_POST)) && 
    24     preg_match('/^[a-zA-Z0-9\+\/=_-]+(,[a-zA-Z0-9\+\/=_-]+)*$/', $cid) 
    25 ) { 
     22// process ajax requests only 
     23if (!$OUTPUT->ajax_call) 
     24    return; 
     25 
     26$cids   = rcmail_get_cids(); 
     27$delcnt = 0; 
     28 
     29foreach ($cids as $source => $cid) 
     30{ 
     31    $CONTACTS = rcmail_contact_source($source); 
     32 
     33    if ($CONTACTS->readonly) { 
     34        // more sources? do nothing, probably we have search results from 
     35        // more than one source, some of these sources can be readonly 
     36        if (count($cids) == 1) { 
     37            $OUTPUT->show_message('contactdelerror', 'error'); 
     38            $OUTPUT->command('list_contacts'); 
     39        } 
     40        continue; 
     41    } 
     42 
    2643    $plugin = $RCMAIL->plugins->exec_hook('contact_delete', array( 
    27         'id' => $cid, 'source' => get_input_value('_source', RCUBE_INPUT_GPC))); 
     44        'id' => $cid, 'source' => $source)); 
    2845 
    2946    $deleted = !$plugin['abort'] ? $CONTACTS->delete($cid) : $plugin['result']; 
     
    3249        $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'contactdelerror', 'error'); 
    3350        $OUTPUT->command('list_contacts'); 
     51        $OUTPUT->send(); 
    3452    } 
    3553    else { 
    36         $OUTPUT->show_message('contactdeleted', 'confirmation'); 
     54        $delcnt += $deleted; 
     55    } 
     56} 
    3757 
    38         // count contacts for this user 
    39         $result = $CONTACTS->count(); 
     58$OUTPUT->show_message('contactdeleted', 'confirmation'); 
    4059 
    41         // update saved search after data changed 
    42         if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) 
    43             $_SESSION['search'][$search_request] = $CONTACTS->refresh_search(); 
     60$page = isset($_SESSION['page']) ? $_SESSION['page'] : 1; 
    4461 
    45         // update message count display 
    46         $OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size)); 
    47         $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result->count)); 
     62// update saved search after data changed 
     63if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { 
     64    $search  = (array)$_SESSION['search'][$search_request]; 
     65    $records = array(); 
    4866 
    49         // add new rows from next page (if any) 
    50         $pages = ceil(($result->count + $deleted) / $CONTACTS->page_size); 
    51         if ($_GET['_from'] != 'show' && $pages > 1 && $CONTACTS->list_page < $pages) 
    52             rcmail_js_contacts_list($CONTACTS->list_records(null, -$deleted)); 
     67    // Get records from all sources (refresh search) 
     68    foreach ($search as $s => $set) { 
     69        $source = $RCMAIL->get_address_book($s); 
     70 
     71        // reset page 
     72        $source->set_page(1); 
     73        $source->set_pagesize(9999); 
     74        $source->set_search_set($set); 
     75 
     76        // get records 
     77        $result = $source->list_records(array('name', 'email')); 
     78 
     79        if (!$result->count) { 
     80            unset($search[$s]); 
     81            continue; 
     82        } 
     83 
     84        while ($row = $result->next()) { 
     85            $row['sourceid'] = $s; 
     86            $key = $row['name'] . ':' . $row['sourceid']; 
     87            $records[$key] = $row; 
     88        } 
     89        unset($result); 
     90 
     91        $search[$s] = $source->get_search_set(); 
    5392    } 
    5493 
    55     // send response 
    56     $OUTPUT->send(); 
     94    $_SESSION['search'][$search_request] = $search; 
     95 
     96    // create resultset object 
     97    $count  = count($records); 
     98    $first  = ($page-1) * $CONFIG['pagesize']; 
     99    $result = new rcube_result_set($count, $first); 
     100 
     101    // get records from the next page to add to the list 
     102    $pages = ceil((count($records) + $delcnt) / $CONFIG['pagesize']); 
     103    if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { 
     104        // sort the records 
     105        ksort($records, SORT_LOCALE_STRING); 
     106 
     107        $first += $CONFIG['pagesize']; 
     108        // create resultset object 
     109        $res = new rcube_result_set($count, $first - $delcnt); 
     110 
     111        if ($CONFIG['pagesize'] < $count) { 
     112            $records = array_slice($records, $first - $delcnt, $delcnt); 
     113        } 
     114 
     115        $res->records = array_values($records); 
     116        $records = $res; 
     117    } 
     118    else { 
     119        unset($records); 
     120    } 
     121} 
     122else { 
     123    // count contacts for this user 
     124    $result = $CONTACTS->count(); 
     125 
     126    // get records from the next page to add to the list 
     127    $pages = ceil(($result->count + $delcnt) / $CONFIG['pagesize']); 
     128    if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { 
     129        $CONTACTS->set_page($page); 
     130        $records = $CONTACTS->list_records(null, -$delcnt); 
     131    } 
    57132} 
    58133 
    59 exit; 
     134// update message count display 
     135$OUTPUT->set_env('pagecount', ceil($result->count / $CONFIG['pagesize'])); 
     136$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result)); 
    60137 
     138// add new rows from next page (if any) 
     139if (!empty($records)) { 
     140    rcmail_js_contacts_list($records); 
     141} 
     142 
     143// send response 
     144$OUTPUT->send(); 
  • trunk/roundcubemail/program/steps/addressbook/edit.inc

    r4840 r4850  
    2020*/ 
    2121 
    22  
    23 if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && ($record = $CONTACTS->get_record($cid, true))) 
    24     $OUTPUT->set_env('cid', $record['ID']); 
    25  
    26 // adding not allowed here 
    27 if ($CONTACTS->readonly) { 
    28     $OUTPUT->show_message('sourceisreadonly'); 
    29     rcmail_overwrite_action('show'); 
    30     return; 
     22if ($RCMAIL->action == 'edit') { 
     23    // Get contact ID and source ID from request 
     24    $cids   = rcmail_get_cids(); 
     25    $source = key($cids); 
     26    $cid    = array_shift($cids[$source]); 
     27 
     28    // Initialize addressbook 
     29    $CONTACTS = rcmail_contact_source($source, true); 
     30 
     31    // Contact edit 
     32    if ($cid && ($record = $CONTACTS->get_record($cid, true))) { 
     33        $OUTPUT->set_env('cid', $record['ID']); 
     34    } 
     35 
     36    // adding not allowed here 
     37    if ($CONTACTS->readonly) { 
     38        $OUTPUT->show_message('sourceisreadonly'); 
     39        rcmail_overwrite_action('show'); 
     40        return; 
     41    } 
     42} 
     43else { 
     44    $source = get_input_value('_source', RCUBE_INPUT_GPC); 
     45 
     46    $CONTACTS = $RCMAIL->get_address_book($source); 
     47 
     48    // find writable addressbook 
     49    if (!$CONTACTS || $CONTACTS->readonly) 
     50        $source = rcmail_default_source(true); 
     51 
     52    // Initialize addressbook 
     53    $CONTACTS = rcmail_contact_source($source, true); 
    3154} 
    3255 
     
    4669         return false; 
    4770     } 
    48       
     71 
    4972     return $record; 
    5073} 
     
    91114    // add some labels to client 
    92115    $RCMAIL->output->add_label('noemailwarning', 'nonamewarning'); 
    93      
     116 
    94117    // copy (parsed) address template to client 
    95118    if (preg_match_all('/\{([a-z0-9]+)\}([^{]*)/i', $RCMAIL->config->get('address_template', ''), $templ, PREG_SET_ORDER)) 
     
    124147        ), 
    125148    ); 
    126      
     149 
    127150    if (isset($CONTACT_COLTYPES['notes'])) { 
    128151        $form['notes'] = array( 
     
    159182    $max_filesize = $max_postsize; 
    160183  $max_filesize = show_bytes($max_filesize); 
    161    
     184 
    162185  $hidden = new html_hiddenfield(array('name' => '_cid', 'value' => $GLOBALS['cid'])); 
    163186  $input = new html_inputfield(array('type' => 'file', 'name' => '_photo', 'size' => $attrib['size'])); 
    164187  $button = new html_inputfield(array('type' => 'button')); 
    165    
     188 
    166189  $out = html::div($attrib, 
    167190    $OUTPUT->form_tag(array('name' => 'uploadform', 'method' => 'post', 'enctype' => 'multipart/form-data'), 
     
    175198    ) 
    176199  ); 
    177    
     200 
    178201  $OUTPUT->add_label('addphoto','replacephoto'); 
    179202  $OUTPUT->add_gui_object('uploadbox', $attrib['id']); 
     
    212235 
    213236 
    214 $OUTPUT->add_handler('contactedithead', 'rcmail_contact_edithead'); 
    215 $OUTPUT->add_handler('contacteditform', 'rcmail_contact_editform'); 
    216 $OUTPUT->add_handler('contactphoto',    'rcmail_contact_photo'); 
    217 $OUTPUT->add_handler('photouploadform', 'rcmail_upload_photo_form'); 
    218  
    219 if (!$CONTACTS->get_result() && $OUTPUT->template_exists('contactadd')) 
     237$OUTPUT->add_handlers(array( 
     238    'contactedithead' => 'rcmail_contact_edithead', 
     239    'contacteditform' => 'rcmail_contact_editform', 
     240    'contactphoto'    => 'rcmail_contact_photo', 
     241    'photouploadform' => 'rcmail_upload_photo_form', 
     242)); 
     243 
     244if ($RCMAIL->action == 'add' && $OUTPUT->template_exists('contactadd')) 
    220245    $OUTPUT->send('contactadd'); 
    221246 
  • trunk/roundcubemail/program/steps/addressbook/export.inc

    r4752 r4850  
    77 | This file is part of the Roundcube Webmail client                     | 
    88 | Copyright (C) 2008-2011, The Roundcube Dev Team                       | 
     9 | Copyright (C) 2011, Kolab Systems AG                                  | 
    910 | Licensed under the GNU GPL                                            | 
    1011 |                                                                       | 
     
    1415 +-----------------------------------------------------------------------+ 
    1516 | Author: Thomas Bruederli <roundcube@gmail.com>                        | 
     17 | Author: Aleksander Machniak <machniak@kolabsys.com>                   | 
    1618 +-----------------------------------------------------------------------+ 
    1719 
    18  $Id$ 
     20 $Id$ 
    1921 
    2022*/ 
    2123 
    22 // get contacts for this user 
    23 $CONTACTS->set_page(1); 
    24 $CONTACTS->set_pagesize(99999); 
    25 $result = $CONTACTS->list_records(null, 0, true); 
     24// Use search result 
     25if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) 
     26{ 
     27    $search  = (array)$_SESSION['search'][$_REQUEST['_search']]; 
     28    $records = array(); 
     29 
     30    // Get records from all sources 
     31    foreach ($search as $s => $set) { 
     32        $source = $RCMAIL->get_address_book($s); 
     33 
     34        // reset page 
     35        $source->set_page(1); 
     36        $source->set_pagesize(99999); 
     37        $source->set_search_set($set); 
     38 
     39        // get records 
     40        $result = $source->list_records(); 
     41 
     42        while ($row = $result->next()) { 
     43            $row['sourceid'] = $s; 
     44            $key = $row['name'] . ':' . $row['sourceid']; 
     45            $records[$key] = $row; 
     46        } 
     47        unset($result); 
     48    } 
     49 
     50    // sort the records 
     51    ksort($records, SORT_LOCALE_STRING); 
     52 
     53    // create resultset object 
     54    $count  = count($records); 
     55    $result = new rcube_result_set($count); 
     56    $result->records = array_values($records); 
     57} 
     58// selected directory/group 
     59else { 
     60    $CONTACTS = rcmail_contact_source(null, true); 
     61 
     62    // get contacts for this user 
     63    $CONTACTS->set_page(1); 
     64    $CONTACTS->set_pagesize(99999); 
     65    $result = $CONTACTS->list_records(null, 0, true); 
     66} 
    2667 
    2768// send downlaod headers 
     
    3172 
    3273while ($result && ($row = $result->next())) { 
    33   // we already have a vcard record 
    34   if ($row['vcard'] && $row['name']) { 
    35     echo rcube_vcard::rfc2425_fold($row['vcard']) . "\n"; 
    36   } 
    37   // copy values into vcard object 
    38   else { 
    39     $vcard = new rcube_vcard($row['vcard']); 
    40     $vcard->reset(); 
    41     foreach ($row as $key => $values) { 
    42       list($field, $section) = explode(':', $key); 
    43       foreach ((array)$values as $value) { 
    44         if (is_array($value) || strlen($value)) 
    45           $vcard->set($field, $value, strtoupper($section)); 
    46       } 
     74    // we already have a vcard record 
     75    if ($row['vcard'] && $row['name']) { 
     76        echo rcube_vcard::rfc2425_fold($row['vcard']) . "\n"; 
    4777    } 
     78    // copy values into vcard object 
     79    else { 
     80        $vcard = new rcube_vcard($row['vcard']); 
     81        $vcard->reset(); 
    4882 
    49     echo $vcard->export(true) . "\n"; 
    50   } 
     83        foreach ($row as $key => $values) { 
     84            list($field, $section) = explode(':', $key); 
     85            foreach ((array)$values as $value) { 
     86                if (is_array($value) || strlen($value)) 
     87                    $vcard->set($field, $value, strtoupper($section)); 
     88            } 
     89        } 
     90 
     91        echo $vcard->export(true) . "\n"; 
     92    } 
    5193} 
    5294 
    5395exit; 
    54  
  • trunk/roundcubemail/program/steps/addressbook/func.inc

    r4841 r4850  
    2121 
    2222$SEARCH_MODS_DEFAULT = array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1); 
    23  
    24 // select source 
    25 $source = get_input_value('_source', RCUBE_INPUT_GPC); 
    26  
    27 if (!$RCMAIL->action && !$OUTPUT->ajax_call) { 
    28     // add list of address sources to client env 
    29     $js_list = $RCMAIL->get_address_sources(); 
    30  
    31     // if source is not set use first directory 
    32     if (empty($source)) 
    33         $source = $js_list[key($js_list)]['id']; 
    34  
    35     $search_mods = $RCMAIL->config->get('addressbook_search_mods', $SEARCH_MODS_DEFAULT); 
    36     $OUTPUT->set_env('search_mods', $search_mods); 
    37     $OUTPUT->set_env('address_sources', $js_list); 
    38 } 
    39  
    40 // instantiate a contacts object according to the given source 
    41 $CONTACTS = $RCMAIL->get_address_book($source); 
    42  
    43 $CONTACTS->set_pagesize($CONFIG['pagesize']); 
    44  
    45 // set list properties and session vars 
    46 if (!empty($_GET['_page'])) 
    47     $CONTACTS->set_page(($_SESSION['page'] = intval($_GET['_page']))); 
    48 else 
    49     $CONTACTS->set_page(isset($_SESSION['page']) ?$_SESSION['page'] : 1); 
    50  
    51 if (!empty($_REQUEST['_gid'])) 
    52     $CONTACTS->set_group(get_input_value('_gid', RCUBE_INPUT_GPC)); 
    53  
    54 // set data source env 
    55 $OUTPUT->set_env('source', $source ? $source : '0'); 
    56 $OUTPUT->set_env('readonly', $CONTACTS->readonly); 
    57 if (!$OUTPUT->ajax_call) { 
    58     $search_mods = $RCMAIL->config->get('addressbook_search_mods', $SEARCH_MODS_DEFAULT); 
    59     $OUTPUT->set_env('search_mods', $search_mods); 
    60     $OUTPUT->set_pagetitle(rcube_label('addressbook')); 
    61 } 
    62  
    6323 
    6424// general definition of contact coltypes 
     
    9757); 
    9858 
    99 // reduce/extend $CONTACT_COLTYPES with specification from the current $CONTACT object 
    100 if (is_array($CONTACTS->coltypes)) { 
    101     // remove cols not listed by the backend class 
    102     $contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes; 
    103     $CONTACT_COLTYPES = array_intersect_key($CONTACT_COLTYPES, $contact_cols); 
    104     // add associative coltypes definition 
    105     if (!$CONTACTS->coltypes[0]) { 
    106         foreach ($CONTACTS->coltypes as $col => $colprop) 
    107             $CONTACT_COLTYPES[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], $colprop) : $colprop; 
    108     } 
    109 } 
    110  
    111 $OUTPUT->set_env('photocol', is_array($CONTACT_COLTYPES['photo'])); 
     59 
     60// Addressbook UI 
     61if (!$RCMAIL->action && !$OUTPUT->ajax_call) { 
     62    // add list of address sources to client env 
     63    $js_list = $RCMAIL->get_address_sources(); 
     64 
     65    // use first directory by default 
     66    $source = $js_list[key($js_list)]['id']; 
     67 
     68    // find writeable source 
     69    foreach ($js_list as $s) { 
     70        if (!$s['readonly']) { 
     71            $OUTPUT->set_env('writable_source', $s['id']); 
     72            break; 
     73        } 
     74    } 
     75 
     76    $search_mods = $RCMAIL->config->get('addressbook_search_mods', $SEARCH_MODS_DEFAULT); 
     77    $OUTPUT->set_env('search_mods', $search_mods); 
     78    $OUTPUT->set_env('address_sources', $js_list); 
     79 
     80    $OUTPUT->set_pagetitle(rcube_label('addressbook')); 
     81 
     82    $CONTACTS = rcmail_contact_source($source, true); 
     83} 
     84 
     85 
     86// instantiate a contacts object according to the given source 
     87function rcmail_contact_source($source=null, $init_env=false) 
     88{ 
     89    global $RCMAIL, $OUTPUT, $CONFIG, $CONTACT_COLTYPES; 
     90 
     91    if (!strlen($source)) { 
     92        $source = get_input_value('_source', RCUBE_INPUT_GPC); 
     93    } 
     94 
     95    if (!strlen($source)) { 
     96        return null; 
     97    } 
     98 
     99    // Get object 
     100    $CONTACTS = $RCMAIL->get_address_book($source); 
     101    $CONTACTS->set_pagesize($CONFIG['pagesize']); 
     102 
     103    // set list properties and session vars 
     104    if (!empty($_GET['_page'])) 
     105        $CONTACTS->set_page(($_SESSION['page'] = intval($_GET['_page']))); 
     106    else 
     107        $CONTACTS->set_page(isset($_SESSION['page']) ? $_SESSION['page'] : 1); 
     108 
     109    if (!empty($_REQUEST['_gid'])) 
     110        $CONTACTS->set_group(get_input_value('_gid', RCUBE_INPUT_GPC)); 
     111 
     112    if (!$init_env) 
     113        return $CONTACTS; 
     114 
     115    $OUTPUT->set_env('readonly', $CONTACTS->readonly); 
     116    $OUTPUT->set_env('source', $source); 
     117 
     118    // reduce/extend $CONTACT_COLTYPES with specification from the current $CONTACT object 
     119    if (is_array($CONTACTS->coltypes)) { 
     120        // remove cols not listed by the backend class 
     121        $contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes; 
     122        $CONTACT_COLTYPES = array_intersect_key($CONTACT_COLTYPES, $contact_cols); 
     123        // add associative coltypes definition 
     124        if (!$CONTACTS->coltypes[0]) { 
     125            foreach ($CONTACTS->coltypes as $col => $colprop) 
     126                $CONTACT_COLTYPES[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], $colprop) : $colprop; 
     127        } 
     128    } 
     129 
     130    $OUTPUT->set_env('photocol', is_array($CONTACT_COLTYPES['photo'])); 
     131 
     132    return $CONTACTS; 
     133} 
     134 
     135 
     136function rcmail_default_source($writable=false) 
     137{ 
     138    global $RCMAIL; 
     139 
     140    // get list of address sources 
     141    $list = $RCMAIL->get_address_sources($writable); 
     142 
     143    // use first directory by default 
     144    return $list[key($list)]['id']; 
     145} 
    112146 
    113147 
     
    231265        $a_row_cols = array(); 
    232266 
     267        // build contact ID with source ID 
     268        if (isset($row['sourceid'])) { 
     269            $row['ID'] = $row['ID'].'-'.$row['sourceid']; 
     270        } 
     271 
    233272        // format each col 
    234273        foreach ($a_show_cols as $col) 
     
    247286    if (!$attrib['id']) 
    248287        $attrib['id'] = 'rcmcontactframe'; 
    249      
     288 
    250289    $attrib['name'] = $attrib['id']; 
    251290 
     
    270309 
    271310 
    272 function rcmail_get_rowcount_text() 
    273 { 
    274     global $CONTACTS; 
    275    
     311function rcmail_get_rowcount_text($result=null) 
     312{ 
     313    global $CONTACTS, $CONFIG; 
     314 
    276315    // read nr of contacts 
    277     $result = $CONTACTS->get_result(); 
     316    if (!$result) { 
     317        $result = $CONTACTS->get_result(); 
     318    } 
    278319    if (!$result) { 
    279320        $result = $CONTACTS->count(); 
     
    287328            'vars'  => array( 
    288329            'from'  => $result->first + 1, 
    289             'to'    => min($result->count, $result->first + $CONTACTS->page_size), 
     330            'to'    => min($result->count, $result->first + $CONFIG['pagesize']), 
    290331            'count' => $result->count) 
    291332        )); 
     
    304345            && rcube_label_exists($label)) 
    305346        return rcube_label($label) . ' ' . $m[1]; 
    306      
     347 
    307348    return ucfirst($type); 
    308349} 
     
    323364    unset($attrib['deleteicon']); 
    324365    $out = ''; 
    325      
     366 
    326367    // get default coltypes 
    327368    $coltypes = $GLOBALS['CONTACT_COLTYPES']; 
    328369    $coltype_labels = array(); 
    329      
     370 
    330371    foreach ($coltypes as $col => $prop) { 
    331372        if ($prop['subtypes']) { 
     
    370411                    if (!$coltypes[$col]) 
    371412                        continue; 
    372                      
     413 
    373414                    // only string values are expected here 
    374415                    if (is_array($record[$col])) 
     
    391432                $content .= html::div($blockname, $fields); 
    392433            } 
    393              
     434 
    394435            if ($edit_mode) 
    395436                $content .= html::p('addfield', $select_add->show(null)); 
     
    523564                        $rows .= html::div('row', html::div('contactfield', $val)); 
    524565                } 
    525                  
     566 
    526567                // add option to the add-field menu 
    527568                if (!$colprop['limit'] || $coltypes[$field]['count'] < $colprop['limit']) { 
     
    529570                    $select_add->_count++; 
    530571                } 
    531                  
     572 
    532573                // wrap rows in fieldgroup container 
    533574                $content .= html::tag('fieldset', array('class' => 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col, 'style' => ($rows ? null : 'display:none')), 
     
    599640} 
    600641 
     642 
     643/** 
     644 * Returns contact ID(s) and source(s) from GET/POST data 
     645 * 
     646 * @return array List of contact IDs per-source 
     647 */ 
     648function rcmail_get_cids() 
     649{ 
     650    // contact ID (or comma-separated list of IDs) is provided in two 
     651    // forms. If _source is an empty string then the ID is a string 
     652    // containing contact ID and source name in form: <ID>-<SOURCE> 
     653 
     654    $cid    = get_input_value('_cid', RCUBE_INPUT_GPC); 
     655    $source = get_input_value('_source', RCUBE_INPUT_GPC); 
     656 
     657    if (!preg_match('/^[a-zA-Z0-9\+\/=_-]+(,[a-zA-Z0-9\+\/=_-]+)*$/', $cid)) { 
     658        return array(); 
     659    } 
     660 
     661    $cid        = explode(',', $cid); 
     662    $got_source = strlen($source); 
     663    $result     = array(); 
     664 
     665    // create per-source contact IDs array 
     666    foreach ($cid as $id) { 
     667        // if _source is not specified we'll find it from decoded ID 
     668        if (!$got_source) { 
     669            list ($c, $s) = explode('-', $id, 2); 
     670            if (strlen($s)) { 
     671                $result[$s][] = $c; 
     672            } 
     673            else if (strlen($source)) { 
     674                $result[$source][] = $c; 
     675            } 
     676        } 
     677        else { 
     678            $result[$source][] = $id; 
     679        } 
     680    } 
     681 
     682    return $result; 
     683} 
    601684 
    602685// register UI objects 
  • trunk/roundcubemail/program/steps/addressbook/groups.inc

    r4814 r4850  
    2020*/ 
    2121 
     22$source = get_input_value('_source', RCUBE_INPUT_GPC); 
     23$CONTACTS = rcmail_contact_source($source, true); 
     24 
    2225if ($CONTACTS->readonly || !$CONTACTS->groups) { 
    2326  $OUTPUT->show_message('sourceisreadonly', 'warning'); 
    2427  $OUTPUT->send(); 
    2528} 
    26  
    27 $source = get_input_value('_source', RCUBE_INPUT_GPC); 
    2829 
    2930if ($RCMAIL->action == 'group-addmembers') { 
  • trunk/roundcubemail/program/steps/addressbook/import.inc

    r4765 r4850  
    1414 +-----------------------------------------------------------------------+ 
    1515 | Author: Thomas Bruederli <roundcube@gmail.com>                        | 
     16 | Author: Aleksander Machniak <machniak@kolabsys.com>                   | 
    1617 +-----------------------------------------------------------------------+ 
    1718 
    18  $Id: $ 
     19 $Id$ 
    1920 
    2021*/ 
     
    2728  global $RCMAIL, $OUTPUT; 
    2829  $target = get_input_value('_target', RCUBE_INPUT_GPC); 
    29    
     30 
    3031  $attrib += array('id' => "rcmImportForm"); 
    31    
    32   $abook = new html_hiddenfield(array('name' => '_target', 'value' => $target)); 
    33   $form = $abook->show(); 
     32 
     33  $writable_books = $RCMAIL->get_address_sources(true); 
    3434 
    3535  $upload = new html_inputfield(array('type' => 'file', 'name' => '_file', 'id' => 'rcmimportfile', 'size' => 40)); 
    36   $form .= html::p(null, html::label('rcmimportfile', rcube_label('importfromfile')) . html::br() . $upload->show()); 
    37    
     36  $form = html::p(null, html::label('rcmimportfile', rcube_label('importfromfile')) . $upload->show()); 
     37 
     38  // addressbook selector 
     39  if (count($writable_books) > 1) { 
     40    $select = new html_select(array('name' => '_target', 'id' => 'rcmimporttarget')); 
     41 
     42    foreach ($writable_books as $book) 
     43        $select->add($book['name'], $book['id']); 
     44 
     45    $form .= html::p(null, html::label('rcmimporttarget', rcube_label('importtarget')) 
     46        . $select->show($target)); 
     47  } 
     48  else { 
     49    $abook = new html_hiddenfield(array('name' => '_target', 'value' => key($writable_books))); 
     50    $form .= $abook->show(); 
     51  } 
     52 
    3853  $check_replace = new html_checkbox(array('name' => '_replace', 'value' => 1, 'id' => 'rcmimportreplace')); 
    3954  $form .= html::p(null, $check_replace->show(get_input_value('_replace', RCUBE_INPUT_GPC)) . 
    4055    html::label('rcmimportreplace', rcube_label('importreplace'))); 
    41    
     56 
    4257  $OUTPUT->add_label('selectimportfile','importwait'); 
    4358  $OUTPUT->add_gui_object('importform', $attrib['id']); 
    44    
     59 
    4560  $out = html::p(null, Q(rcube_label('importtext'), 'show')); 
    46    
     61 
    4762  $out .= $OUTPUT->form_tag(array( 
    4863      'action' => $RCMAIL->url('import'), 
     
    5065      'enctype' => 'multipart/form-data') + $attrib, 
    5166    $form); 
    52    
     67 
    5368  return $out; 
    5469} 
     
    6176{ 
    6277  global $IMPORT_STATS; 
    63    
     78 
    6479  $vars = get_object_vars($IMPORT_STATS); 
    6580  $vars['names'] = $vars['skipped_names'] = ''; 
    66    
     81 
    6782  $content = html::p(null, rcube_label(array( 
    6883      'name' => 'importconfirm', 
     
    7085      'vars' => $vars, 
    7186    )) . ($IMPORT_STATS->names ? ':' : '.')); 
    72      
     87 
    7388  if ($IMPORT_STATS->names) 
    7489    $content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->names))); 
    75    
     90 
    7691  if ($IMPORT_STATS->skipped) { 
    7792      $content .= html::p(null, rcube_label(array( 
     
    8297      $content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->skipped_names))); 
    8398  } 
    84    
     99 
    85100  return html::div($attrib, $content); 
    86101} 
     
    94109  global $IMPORT_STATS, $OUTPUT; 
    95110  $target = get_input_value('_target', RCUBE_INPUT_GPC); 
    96    
     111 
    97112  $attrib += array('type' => 'input'); 
    98113  unset($attrib['name']); 
    99    
     114 
    100115  if (is_object($IMPORT_STATS)) { 
    101116    $attrib['class'] = trim($attrib['class'] . ' mainaction'); 
     
    108123    $out .= $OUTPUT->button(array('command' => 'import', 'label' => 'import') + $attrib); 
    109124  } 
    110    
     125 
    111126  return $out; 
    112127} 
     
    138153    $IMPORT_STATS->count = count($vcards); 
    139154    $IMPORT_STATS->inserted = $IMPORT_STATS->skipped = $IMPORT_STATS->nomail = $IMPORT_STATS->errors = 0; 
    140      
     155 
    141156    if ($replace) 
    142157      $CONTACTS->delete_all(); 
    143      
     158 
    144159    foreach ($vcards as $vcard) { 
    145160      $email = $vcard->email[0]; 
    146        
     161 
    147162      // skip entries without an e-mail address 
    148163      if (empty($email)) { 
     
    153168      // We're using UTF8 internally 
    154169      $email = rcube_idn_to_utf8($email); 
    155        
     170 
    156171      if (!$replace && $email) { 
    157172        // compare e-mail address 
     
    166181        } 
    167182      } 
    168        
     183 
    169184      $a_record = $vcard->get_assoc(); 
    170185      $a_record['vcard'] = $vcard->export(); 
    171        
     186 
    172187      $plugin = $RCMAIL->plugins->exec_hook('contact_create', array('record' => $a_record, 'source' => null)); 
    173188      $a_record = $plugin['record']; 
  • trunk/roundcubemail/program/steps/addressbook/list.inc

    r4836 r4850  
    2020*/ 
    2121 
    22 // set message set for search result 
     22// Use search result 
    2323if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) 
    24     $CONTACTS->set_search_set($_SESSION['search'][$_REQUEST['_search']]); 
     24{ 
     25    $search  = (array)$_SESSION['search'][$_REQUEST['_search']]; 
     26    $records = array(); 
    2527 
    26 // get contacts for this user 
    27 $result = $CONTACTS->list_records(array('name')); 
     28    if (!empty($_GET['_page'])) 
     29        $page = intval($_GET['_page']); 
     30    else 
     31        $page = isset($_SESSION['page']) ? $_SESSION['page'] : 1; 
     32 
     33    $_SESSION['page'] = $page; 
     34 
     35    // Get records from all sources 
     36    foreach ($search as $s => $set) { 
     37        $source = $RCMAIL->get_address_book($s); 
     38 
     39        // reset page 
     40        $source->set_page(1); 
     41        $source->set_pagesize(9999); 
     42        $source->set_search_set($set); 
     43 
     44        // get records 
     45        $result = $source->list_records(array('name', 'email')); 
     46 
     47        while ($row = $result->next()) { 
     48            $row['sourceid'] = $s; 
     49            $key = $row['name'] . ':' . $row['sourceid']; 
     50            $records[$key] = $row; 
     51        } 
     52        unset($result); 
     53    } 
     54 
     55    // sort the records 
     56    ksort($records, SORT_LOCALE_STRING); 
     57 
     58    // create resultset object 
     59    $count  = count($records); 
     60    $first  = ($page-1) * $CONFIG['pagesize']; 
     61    $result = new rcube_result_set($count, $first); 
     62 
     63    // we need only records for current page 
     64    if ($CONFIG['pagesize'] < $count) { 
     65        $records = array_slice($records, $first, $CONFIG['pagesize']); 
     66    } 
     67 
     68    $result->records = array_values($records); 
     69} 
     70// List selected directory 
     71else { 
     72    $CONTACTS = rcmail_contact_source(null, true); 
     73 
     74    // get contacts for this user 
     75    $result = $CONTACTS->list_records(array('name')); 
     76} 
    2877 
    2978// update message count display 
    30 $OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size)); 
    31 $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($rowcount)); 
     79$OUTPUT->set_env('pagecount', ceil($result->count / $CONFIG['pagesize'])); 
     80$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result)); 
    3281 
    3382// create javascript list 
     
    3685// send response 
    3786$OUTPUT->send(); 
    38  
  • trunk/roundcubemail/program/steps/addressbook/mailto.inc

    r4711 r4850  
    2020*/ 
    2121 
    22 $cid = get_input_value('_cid', RCUBE_INPUT_POST); 
    23 $recipients = null; 
     22$cids   = rcmail_get_cids(); 
    2423$mailto = array(); 
    2524 
    26 if ($cid && preg_match('/^[a-z0-9\+\/=_-]+(,[a-z0-9\+\/=_-]+)*$/i', $cid) && $CONTACTS->ready) 
     25foreach ($cids as $source => $cid) 
    2726{ 
    28   $CONTACTS->set_page(1); 
    29   $CONTACTS->set_pagesize(substr_count($cid, ',')+2); // +2 to skip counting query 
    30   $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid); 
     27    $CONTACTS = $RCMAIL->get_address_book($source); 
    3128 
    32   while (is_object($recipients) && ($rec = $recipients->iterate())) { 
    33     $emails = $CONTACTS->get_col_values('email', $rec, true); 
    34     $mailto[] = format_email_recipient($emails[0], $rec['name']); 
    35   } 
     29    if ($CONTACTS->ready) 
     30    { 
     31        $CONTACTS->set_page(1); 
     32        $CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query 
     33        $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, false, true, true, 'email'); 
     34 
     35        while (is_object($recipients) && ($rec = $recipients->iterate())) { 
     36            $emails = $CONTACTS->get_col_values('email', $rec, true); 
     37            $mailto[] = format_email_recipient($emails[0], $rec['name']); 
     38        } 
     39    } 
    3640} 
    3741 
    3842if (!empty($mailto)) 
    3943{ 
    40   $mailto_str = join(', ', $mailto); 
    41   $mailto_id = substr(md5($mailto_str), 0, 16); 
    42   $_SESSION['mailto'][$mailto_id] = urlencode($mailto_str); 
    43   $OUTPUT->redirect(array('task' => 'mail', '_action' => 'compose', '_mailto' => $mailto_id)); 
     44    $mailto_str = join(', ', $mailto); 
     45    $mailto_id = substr(md5($mailto_str), 0, 16); 
     46    $_SESSION['mailto'][$mailto_id] = urlencode($mailto_str); 
     47    $OUTPUT->redirect(array('task' => 'mail', '_action' => 'compose', '_mailto' => $mailto_id)); 
    4448} 
    45 else 
    46   $OUTPUT->show_message('nocontactsfound', 'warning'); 
    47  
     49else { 
     50    $OUTPUT->show_message('nocontactsfound', 'warning'); 
     51} 
    4852 
    4953// send response 
    5054$OUTPUT->send(); 
    51  
  • trunk/roundcubemail/program/steps/addressbook/save.inc

    r4812 r4850  
    2020*/ 
    2121 
    22 $cid = get_input_value('_cid', RCUBE_INPUT_POST); 
     22$CONTACTS = rcmail_contact_source(null, true); 
     23$cid      = get_input_value('_cid', RCUBE_INPUT_POST); 
    2324$return_action = empty($cid) ? 'add' : 'edit'; 
     25 
    2426 
    2527// cannot edit record 
     
    3941        // check file type and resize image 
    4042        $imageprop = rcmail::imageprops($_FILES['_photo']['tmp_name']); 
    41          
     43 
    4244        if ($imageprop['width'] && $imageprop['height']) { 
    4345            $maxsize = intval($RCMAIL->config->get('contact_photo_size', 160)); 
    4446            $tmpfname = tempnam($RCMAIL->config->get('temp_dir'), 'rcmImgConvert'); 
    4547            $save_hook = 'attachment_upload'; 
    46              
     48 
    4749            // scale image to a maximum size 
    4850            if (($imageprop['width'] > $maxsize || $imageprop['height'] > $maxsize) && 
     
    5153                $save_hook = 'attachment_save'; 
    5254            } 
    53              
     55 
    5456            // save uploaded file in storage backend 
    5557            $attachment = $RCMAIL->plugins->exec_hook($save_hook, array( 
     
    8890        else 
    8991            $msg = rcube_label('fileuploaderror'); 
    90              
     92 
    9193        $OUTPUT->command('display_message', $msg, 'error'); 
    9294    } 
    93      
     95 
    9496    $OUTPUT->command('photo_upload_end'); 
    9597    $OUTPUT->send('iframe'); 
     
    156158    else 
    157159        unset($a_record['photo']); 
    158      
     160 
    159161    // cleanup session data 
    160162    $RCMAIL->plugins->exec_hook('attachments_cleanup', array('group' => 'contact')); 
     
    241243      } 
    242244    } 
    243      
     245 
    244246    // add contact row or jump to the page where it should appear 
    245247    $CONTACTS->reset(); 
  • trunk/roundcubemail/program/steps/addressbook/search.inc

    r4841 r4850  
    3232function rcmail_contact_search() 
    3333{ 
    34     global $RCMAIL, $OUTPUT, $CONTACTS, $CONTACT_COLTYPES, $SEARCH_MODS_DEFAULT; 
     34    global $RCMAIL, $OUTPUT, $CONFIG, $SEARCH_MODS_DEFAULT; 
    3535 
    3636    $adv = isset($_POST['_adv']); 
     
    3838    // get fields/values from advanced search form 
    3939    if ($adv) { 
    40         foreach ($CONTACT_COLTYPES as $col => $colprop) { 
    41             $s = trim(get_input_value('_'.$col, RCUBE_INPUT_POST, true)); 
    42             if (strlen($s)) { 
     40        foreach (array_keys($_POST) as $key) { 
     41            $s = trim(get_input_value($key, RCUBE_INPUT_POST, true)); 
     42            if (strlen($s) && preg_match('/^_search_([a-zA-Z0-9_-]+)$/', $key, $m)) { 
    4343                $search[] = $s; 
    44                 $fields[] = $col; 
     44                $fields[] = $m[1]; 
    4545            } 
    4646        } 
     
    7272    } 
    7373 
     74    // get sources list 
     75    $sources    = $RCMAIL->get_address_sources(); 
     76    $search_set = array(); 
     77    $records    = array(); 
     78 
     79    foreach ($sources as $s) { 
     80        $source = $RCMAIL->get_address_book($s['id']); 
     81 
     82        // check if all search fields are supported.... 
     83        if (is_array($fields)) { 
     84            $cols = $source->coltypes[0] ? array_flip($source->coltypes) : $source->coltypes; 
     85            $supported = 0; 
     86 
     87            foreach ($fields as $f) { 
     88                if (array_key_exists($f, $cols)) { 
     89                    $supported ++; 
     90                } 
     91            } 
     92 
     93            // ...if not, we can skip this source 
     94            if ($supported < count($fields)) { 
     95                continue; 
     96            } 
     97        } 
     98 
     99        // reset page 
     100        $source->set_page(1); 
     101        $source->set_pagesize(9999); 
     102 
     103        // get contacts count 
     104        $result = $source->search($fields, $search, false, false); 
     105 
     106        if (!$result->count) { 
     107            continue; 
     108        } 
     109 
     110        // get records 
     111        $result = $source->list_records(array('name', 'email')); 
     112 
     113        while ($row = $result->next()) { 
     114            $row['sourceid'] = $s['id']; 
     115            $key = $row['name'] . ':' . $row['sourceid']; 
     116            $records[$key] = $row; 
     117        } 
     118 
     119        unset($result); 
     120        $search_set[$s['id']] = $source->get_search_set(); 
     121    } 
     122 
     123    // sort the records 
     124    ksort($records, SORT_LOCALE_STRING); 
     125 
     126    // create resultset object 
     127    $count  = count($records); 
     128    $result = new rcube_result_set($count); 
     129 
     130    // cut first-page records 
     131    if ($CONFIG['pagesize'] < $count) { 
     132        $records = array_slice($records, 0, $CONFIG['pagesize']); 
     133    } 
     134 
     135    $result->records = array_values($records); 
     136 
    74137    // search request ID 
    75138    $search_request = md5('addr' 
     
    77140        .(is_array($search) ? implode($search, ',') : $search)); 
    78141 
    79     // reset page 
    80     $CONTACTS->set_page(1); 
     142    // save search settings in session 
     143    $_SESSION['search'][$search_request] = $search_set; 
    81144    $_SESSION['page'] = 1; 
    82  
    83     // get contacts for this user 
    84     $result = $CONTACTS->search($fields, $search); 
    85  
    86     // save search settings in session 
    87     $_SESSION['search'][$search_request] = $CONTACTS->get_search_set(); 
    88145 
    89146    if ($adv) 
     
    100157    // update message count display 
    101158    $OUTPUT->command('set_env', 'search_request', $search_request); 
    102     $OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONTACTS->page_size)); 
    103     $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text()); 
     159    $OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONFIG['pagesize'])); 
     160    $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result)); 
     161 
     162    // unselect currently selected directory/group 
     163    $OUTPUT->command('unselect_directory'); 
    104164 
    105165    // send response 
     
    109169function rcmail_contact_search_form($attrib) 
    110170{ 
    111     global $RCMAIL, $CONTACTS, $CONTACT_COLTYPES; 
     171    global $RCMAIL, $CONTACT_COLTYPES; 
    112172 
    113173    $i_size = !empty($attrib['size']) ? $attrib['size'] : 30; 
     
    131191    ); 
    132192 
    133     foreach ($CONTACT_COLTYPES as $col => $colprop) 
     193    // get supported coltypes from all address sources 
     194    $sources  = $RCMAIL->get_address_sources(); 
     195    $coltypes = array(); 
     196 
     197    foreach ($sources as $s) { 
     198        $CONTACTS = $RCMAIL->get_address_book($s['id']); 
     199 
     200        if (is_array($CONTACTS->coltypes)) { 
     201            $contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes; 
     202            $coltypes = array_merge($coltypes, $contact_cols); 
     203        } 
     204    } 
     205 
     206    // merge supported coltypes with $CONTACT_COLTYPES 
     207    foreach ($coltypes as $col => $colprop) { 
     208        $coltypes[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], (array)$colprop) : (array)$colprop; 
     209    } 
     210 
     211    // build form fields list 
     212    foreach ($coltypes as $col => $colprop) 
    134213    { 
    135214        if ($colprop['type'] != 'image' && !$colprop['nosearch']) 
     
    143222 
    144223            $content  = html::div('row', html::div('contactfieldlabel label', Q($label)) 
    145                 . html::div('contactfieldcontent', rcmail_get_edit_field($col, '', $colprop, $ftype))); 
     224                . html::div('contactfieldcontent', rcmail_get_edit_field('search_'.$col, '', $colprop, $ftype))); 
    146225 
    147226            $form[$category]['content'][] = $content; 
     
    149228    } 
    150229 
    151     $hiddenfields = new html_hiddenfield(array( 
    152         'name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); 
    153     $hiddenfields->add(array('name' => '_gid', 'value' => $CONTACTS->group_id)); 
     230    $hiddenfields = new html_hiddenfield(); 
    154231    $hiddenfields->add(array('name' => '_adv', 'value' => 1)); 
    155232 
  • trunk/roundcubemail/program/steps/addressbook/show.inc

    r4499 r4850  
    2020*/ 
    2121 
     22// Get contact ID and source ID from request 
     23$cids   = rcmail_get_cids(); 
     24$source = key($cids); 
     25$cid    = array_shift($cids[$source]); 
     26 
     27// Initialize addressbook source 
     28$CONTACTS = rcmail_contact_source($source, true); 
    2229 
    2330// read contact record 
    24 if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && ($record = $CONTACTS->get_record($cid, true))) { 
     31if ($cid && ($record = $CONTACTS->get_record($cid, true))) { 
    2532    $OUTPUT->set_env('cid', $record['ID']); 
    2633} 
     
    4249            $data = base64_decode($data, true); 
    4350    } 
    44      
     51 
    4552    header('Content-Type: ' . rc_image_content_type($data)); 
    4653    echo $data ? $data : file_get_contents('program/blank.gif'); 
     
    191198 
    192199    $RCMAIL->output->add_gui_object('editform', 'form'); 
    193    
     200 
    194201    return $form_start . $table->show() . $form_end; 
    195202} 
    196203 
    197204 
    198 //$OUTPUT->framed = $_framed; 
    199 $OUTPUT->add_handler('contacthead', 'rcmail_contact_head'); 
    200 $OUTPUT->add_handler('contactdetails', 'rcmail_contact_details'); 
    201 $OUTPUT->add_handler('contactphoto', 'rcmail_contact_photo'); 
     205$OUTPUT->add_handlers(array( 
     206    'contacthead'    => 'rcmail_contact_head', 
     207    'contactdetails' => 'rcmail_contact_details', 
     208    'contactphoto'   => 'rcmail_contact_photo', 
     209)); 
    202210 
    203211$OUTPUT->send('contact'); 
Note: See TracChangeset for help on using the changeset viewer.