+ * Create and initialize an addressbook object.
+ * @param boolean $showerr display any address book init errors. html page header
+ * must be created before calling addressbook_init() with $showerr enabled.
+ * @param boolean $onlylocal enable only local address book backends. Should
+ * be used when code does not need access to remote backends. Backends
+ * that provide read only address books with limited listing options can be
+ * tagged as remote.
+ * @return object address book object.
+ */
+function addressbook_init($showerr = true, $onlylocal = false) {
+ global $data_dir, $username, $ldap_server, $address_book_global_filename;
+ global $addrbook_dsn, $addrbook_table;
+ global $abook_global_file, $abook_global_file_writeable, $abook_global_file_listing;
+ global $addrbook_global_dsn, $addrbook_global_table, $addrbook_global_writeable, $addrbook_global_listing;
+ global $abook_file_line_length;
+
+ /* Create a new addressbook object */
+ $abook = new AddressBook;
+
+ /* Create empty error message */
+ $abook_init_error='';
+
+ /*
+ Always add a local backend. We use *either* file-based *or* a
+ database addressbook. If $addrbook_dsn is set, the database
+ backend is used. If not, addressbooks are stores in files.
+ */
+ if (isset($addrbook_dsn) && !empty($addrbook_dsn)) {
+ /* Database */
+ if (!isset($addrbook_table) || empty($addrbook_table)) {
+ $addrbook_table = 'address';
+ }
+ $r = $abook->add_backend('database', Array('dsn' => $addrbook_dsn,
+ 'owner' => $username,
+ 'table' => $addrbook_table));
+ if (!$r && $showerr) {
+ $abook_init_error.=_("Error initializing address book database.") . "\n" . $abook->error;
+ }
+ } else {
+ /* File */
+ $filename = getHashedFile($username, $data_dir, "$username.abook");
+ $r = $abook->add_backend('local_file', Array('filename' => $filename,
+ 'umask' => 0077,
+ 'line_length' => $abook_file_line_length,
+ 'create' => true));
+ if(!$r && $showerr) {
+ // no need to use $abook->error, because message explains error.
+ $abook_init_error.=sprintf( _("Error opening file %s"), $filename );
+ }
+ }
+
+ /* Global file based addressbook */
+ if (isset($abook_global_file) &&
+ isset($abook_global_file_writeable) &&
+ isset($abook_global_file_listing) &&
+ trim($abook_global_file)!=''){
+
+ // Detect place of address book
+ if (! preg_match("/[\/\\\]/",$abook_global_file)) {
+ /* no path chars, address book stored in data directory
+ * make sure that there is a slash between data directory
+ * and address book file name
+ */
+ $abook_global_filename=$data_dir
+ . ((substr($data_dir, -1) != '/') ? '/' : '')
+ . $abook_global_file;
+ } elseif (preg_match("/^\/|\w:/",$abook_global_file)) {
+ // full path is set in options (starts with slash or x:)
+ $abook_global_filename=$abook_global_file;
+ } else {
+ $abook_global_filename=SM_PATH . $abook_global_file;
+ }
+
+ $r = $abook->add_backend('local_file',array('filename'=>$abook_global_filename,
+ 'name' => _("Global Address Book"),
+ 'detect_writeable' => false,
+ 'line_length' => $abook_file_line_length,
+ 'writeable'=> $abook_global_file_writeable,
+ 'listing' => $abook_global_file_listing));
+
+ /* global abook init error is not fatal. add error message and continue */
+ if (!$r && $showerr) {
+ if ($abook_init_error!='') $abook_init_error.="\n";
+ $abook_init_error.=_("Error initializing global address book.") . "\n" . $abook->error;
+ }
+ }
+
+ /* Load global addressbook from SQL if configured */
+ if (isset($addrbook_global_dsn) && !empty($addrbook_global_dsn)) {
+ /* Database configured */
+ if (!isset($addrbook_global_table) || empty($addrbook_global_table)) {
+ $addrbook_global_table = 'global_abook';
+ }
+ $r = $abook->add_backend('database',
+ Array('dsn' => $addrbook_global_dsn,
+ 'owner' => 'global',
+ 'name' => _("Global Address Book"),
+ 'writeable' => $addrbook_global_writeable,
+ 'listing' => $addrbook_global_listing,
+ 'table' => $addrbook_global_table));
+ /* global abook init error is not fatal. add error message and continue */
+ if (!$r && $showerr) {
+ if ($abook_init_error!='') $abook_init_error.="\n";
+ $abook_init_error.=_("Error initializing global address book.") . "\n" . $abook->error;
+ }
+ }
+
+ /*
+ * hook allows to include different address book backends.
+ * plugins should extract $abook and $r from arguments
+ * and use same add_backend commands as above functions.
+ * Since 1.5.2 hook sends third ($onlylocal) argument to address book
+ * plugins in order to allow detection of local address book init.
+ * @since 1.5.1 and 1.4.5
+ * Since 1.5.2, the plugin arguments are passed inside an array
+ * and by reference, so plugins hooking in here need to accept arguments
+ * in an array and change those values as needed instead of returning
+ * the changed values.
+ */
+ $temp = array(&$abook, &$r, &$onlylocal);
+ do_hook('abook_init', $temp);
+ if (!$r && $showerr) {
+ if ($abook_init_error!='') $abook_init_error.="\n";
+ $abook_init_error.=_("Error initializing other address books.") . "\n" . $abook->error;
+ }
+
+ /* Load configured LDAP servers (if PHP has LDAP support) */
+ if (isset($ldap_server) && is_array($ldap_server)) {
+ reset($ldap_server);
+ while (list($undef,$param) = each($ldap_server)) {
+ if (!is_array($param))
+ continue;
+
+ /* if onlylocal is true, we only add writeable ldap servers */
+ if ($onlylocal && (!isset($param['writeable']) || $param['writeable'] != true))
+ continue;
+
+ $r = $abook->add_backend('ldap_server', $param);
+ if (!$r && $showerr) {
+ if ($abook_init_error!='') $abook_init_error.="\n";
+ $abook_init_error.=sprintf(_("Error initializing LDAP server %s:"), $param['host'])."\n";
+ $abook_init_error.= $abook->error;
+ }
+ }
+ } // end of ldap server init
+
+ /**
+ * display address book init errors.
+ */
+ if ($abook_init_error!='' && $showerr) {
+ error_box(nl2br(sm_encode_html_special_chars($abook_init_error)));
+ }
+
+ /* Return the initialized object */
+ return $abook;
+}
+
+/**
+ * Constructs the "new address" form