Patch for improved vCard support

"Vincent Touchard" <[email protected]>
Newsgroups gmane.mail.squirrelmail.devel
Message-ID <[email protected]>
Hi,

I have developed a patch for SquirrelMail 1.5.1 as available in debian.
This patch improves the support of vCard :
 - display of vcards attached to mail with more fields (including PHOTO
and LOGO), sorted by category (Personal, Work, Miscellaneous and
Security)
 - add vcards to identities in the options of the user's account
 - attach the vcard when sending a mail

The parsing of vcards is done using the pear module Contact_Vcard_Parse
which does a better job that the "parser" that is currently in
squirrelmail.

We did it as a patch and not a plugin to have it fully integrated into the
webmail and to replace the code already written to display vcards attached
to mails.

The next step would be to save the vcards received as mail attachments
into the address book.

As it is my first patch against SquirrelMail, it may be far from being
perfect. Any comments are welcome.

Best Regards,
Vincent Touchard

-- 
Vincent Touchard
First Choice Internet

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

-----
squirrelmail-devel mailing list
Posting guidelines: http://squirrelmail.org/postingguidelines
List address: [email protected]
List archives: http://news.gmane.org/gmane.mail.squirrelmail.devel
List info (subscribe/unsubscribe/change options): https://lists.sourceforge.net/lists/listinfo/squirrelmail-devel
squirrelmail-vcard.diff (text/x-patch, 34.7 KB)
diff -rbNu squirrelmail/functions/db_prefs.php /usr/share/squirrelmail/functions/db_prefs.php
--- squirrelmail/functions/db_prefs.php	2006-07-09 04:01:27.000000000 +0900
+++ /usr/share/squirrelmail/functions/db_prefs.php	2008-11-07 17:14:26.000000000 +0900
@@ -538,5 +538,45 @@
     return getPref($data_dir, $username, $key);
 }
 
+/**
+ * Writes the vCard
+ * @ignore
+ */
+function setVcard($data_dir, $username, $number, $tmp_file) {
+    if ($number == "d") {
+        $key = '___vcard___';
+    } else {
+        $key = sprintf('___vcar%s___', $number);
+	}
+
+	/* Open the file for reading, or else display an error to the user. */
+	if(!$file = @fopen($tmp_file, 'r')) {
+		logout_error( sprintf( _("vCard file, %s, could not be opened. Contact your system administrator to resolve this issue."), $tmp_file) );
+		exit;
+	}
+	if ( @fread($file, $value) == strlen($value) ) {
+		logout_error( sprintf( _("vCard file, %s, could not be written. Contact your system administrator to resolve this issue.") , $tmp_file));
+		exit;
+	}
+	fclose($file);
+
+
+	setPref($data_dir, $username, $key, $value);
+    return;
+}
+
+/**
+ * Gets the vCard
+ * @ignore
+ */
+function getVcard($data_dir, $username, $number) {
+    if ($number == "d") {
+        $key = '___vcard___';
+    } else {
+        $key = sprintf('___vcar%d___', $number);
+    }
+    return getPref($data_dir, $username, $key);
+}
+
 // vim: et ts=4
 ?>
\ No newline at end of file
diff -rbNu squirrelmail/functions/file_prefs.php /usr/share/squirrelmail/functions/file_prefs.php
--- squirrelmail/functions/file_prefs.php	2006-07-09 04:01:27.000000000 +0900
+++ /usr/share/squirrelmail/functions/file_prefs.php	2008-11-10 09:49:38.000000000 +0900
@@ -311,5 +311,52 @@
     return $sig;
 }
 
+/**
+ * Write the User vCard.
+ * @param string $data_dir data directory
+ * @param string $username user name
+ * @param integer $number identity number.
+ * @param string $tmp_file temporary file where the vcard is stored after upload
+ */
+function setVcard($data_dir, $username, $number, $tmp_file) {
+    $filename = getHashedFile($username, $data_dir, "$username.vcar$number");
+
+	if ($tmp_file == '') {
+		@unlink($filename);
+	} else {
+		if (! @copy($tmp_file, $filename) ) {
+		   logout_error( sprintf( _("vCard file, %s, could not be copied from temporary file, %s. Contact your system administrator to resolve this issue."), $filename, $tmp_file) );
+		   exit;
+		}
+		@unlink($tmp_file);
+		@chmod($filename, 0600);
+	}
+}
+
+/**
+ * Get the vCard.
+ * @param string $data_dir data directory
+ * @param string $username user name
+ * @param integer $number (since 1.2.5) identity number
+ * @return string signature
+ */
+function getVcard($data_dir, $username, $number) {
+    $filename = getHashedFile($username, $data_dir, "$username.vcar$number");
+    $vcard = '';
+    if (file_exists($filename)) {
+        /* Open the file, or else display an error to the user. */
+        if(!$file = @fopen($filename, 'r'))
+        {
+            logout_error( sprintf( _("vCard file, %s, could not be opened. Contact your system administrator to resolve this issue."), $filename) );
+            exit;
+        }
+        while (!feof($file)) {
+            $vcard .= fgets($file, 1024);
+        }
+        fclose($file);
+    }
+    return $vcard;
+}
+
 // vim: et ts=4
 ?>
\ No newline at end of file
diff -rbNu squirrelmail/functions/identity.php /usr/share/squirrelmail/functions/identity.php
--- squirrelmail/functions/identity.php	2006-07-09 04:01:27.000000000 +0900
+++ /usr/share/squirrelmail/functions/identity.php	2008-11-14 16:11:43.000000000 +0900
@@ -88,6 +88,7 @@
         removePref($data_dir, $username, 'email_address' . $i);
         removePref($data_dir, $username, 'reply_to' . $i);
         setSig($data_dir, $username, $i, '');
+        setVcard($data_dir, $username, $i, '');
     }
 
     foreach($identities as $id=>$ident) {
@@ -104,6 +105,15 @@
             setSig($data_dir, $username, $key, $ident['signature']);
         }
 
+		$vcard_file = check_vcard($id);
+		if ($vcard_file != FALSE) {
+			if ($id === 0) {
+				setVcard($data_dir, $username, 'd', $vcard_file);
+			} else {
+				setVcard($data_dir, $username, $key, $vcard_file);
+			}
+		}
+
     }
 
     setPref($data_dir, $username, 'identities', $cnt);
@@ -220,4 +230,63 @@
     }
 }
 
+/*
+ * Test if the vCard was correctly uploaded and if it is tagged as a being a vCard (text/x-vcard)
+ *
+ * mostly taken from
+ * plugins/abook_import_export/address_book_import.php
+ *
+ * @param  int    identity id
+ * @return mixte  FALSE if the file was not correctly uploaded or is not a vCard, otherwise the name of
+ *                the tempory file where the vCard related to the "identity id" is store
+ */
+function check_vcard($id) {
+    $vcards = $_FILES['newidentities'];
+
+    if ($vcards['tmp_name'][$id]['vcard'] == '' || $vcards['size'][$id]['vcard'] == 0) {
+        // Detect PHP 4.2.0+ upload error codes (http://www.php.net/features.file-upload.errors)
+        $upload_error = "";
+        if (isset($vcards['error'][$id]['vcard']) && $vcards['error'][$id]['vcard']!=0 ) {
+            switch($vcards['error'][$id]['vcard']) {
+            case 1:
+                $upload_error = _("The uploaded file exceeds PHP upload_max_filesize limits.");
+                break;
+            case 2:
+                $upload_error = _("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML.");
+                break;
+            case 3:
+                $upload_error = _("The uploaded file was only partially uploaded.");
+                break;
+            case 4:
+                break;
+            case 6:
+                $upload_error = _("Missing a temporary directory.");
+                break;
+            case 7:
+                $upload_error = _("Failed to write file to disk.");
+                break;
+            case 8:
+                // File upload stopped by extension. 'security library' is more user friendly.
+                $upload_error = _("File upload stopped by security library.");
+                break;
+            default:
+                $upload_error = _("Unknown upload error.");
+                break;
+            }
+		}
+		if (!empty($upload_error)) {
+			plain_error_message( $upload_error, $color);
+		}
+		return FALSE;
+	}
+	elseif (isset($vcards['type'][$id]['vcard']) && $vcards['type'][$id]['vcard'] != 'text/x-vcard') {
+		$upload_error = _("Please upload a vCard.");
+		plain_error_message( $upload_error, $color);
+		return FALSE;
+	}
+	else {
+		return $vcards['tmp_name'][$id]['vcard'];
+	} 
+}
+
 ?>
\ No newline at end of file
diff -rbNu squirrelmail/functions/imap_messages.php /usr/share/squirrelmail/functions/imap_messages.php
--- squirrelmail/functions/imap_messages.php	2006-07-09 04:01:27.000000000 +0900
+++ /usr/share/squirrelmail/functions/imap_messages.php	2008-11-05 19:04:53.000000000 +0900
@@ -923,7 +923,7 @@
     if ($read) {
         if (preg_match('/.+FLAGS\s\((.*)\)\s/AUi',$read[0],$regs)) {
             if (trim($regs[1])) {
-                $flags = preg_split('/ /', $regs[1],-1,'PREG_SPLIT_NI_EMPTY');
+                $flags = preg_split('/ /', $regs[1],-1,PREG_SPLIT_NO_EMPTY);
             }
         }
     } else {
diff -rbNu squirrelmail/functions/options.php /usr/share/squirrelmail/functions/options.php
--- squirrelmail/functions/options.php	2006-07-09 04:01:27.000000000 +0900
+++ /usr/share/squirrelmail/functions/options.php	2008-11-17 09:21:01.000000000 +0900
@@ -26,6 +26,7 @@
 define('SMOPT_TYPE_HIDDEN', 6);
 define('SMOPT_TYPE_COMMENT', 7);
 define('SMOPT_TYPE_FLDRLIST', 8);
+define('SMOPT_TYPE_FILE', 9);
 
 /* Define constants for the options refresh levels. */
 define('SMOPT_REFRESH_NONE', 0);
@@ -314,6 +315,9 @@
             case SMOPT_TYPE_FLDRLIST:
                 $result = $this->createWidget_FolderList();
                 break;
+            case SMOPT_TYPE_FILE:
+                $result = $this->createWidget_File();
+                break;
             default:
                $result = '<font color="' . $color[2] . '">'
                        . sprintf(_("Option Type '%s' Not Found"), $this->type)
@@ -539,6 +543,19 @@
     }
 
     /**
+     * Creates file field
+     * @return string html formated file input field
+     */
+    function createWidget_File() {
+        $result = '<input type="file" name="new_' . $this->name
+                . '" />';
+        $result .= '<input type="hidden" name="MAX_FILE_SIZE'
+                . '" value="' . '500000000'
+                . '" />';
+        return ($result);
+    }
+
+    /**
      * Creates comment
      * @return string comment
      */
diff -rbNu squirrelmail/functions/vcard.php /usr/share/squirrelmail/functions/vcard.php
--- squirrelmail/functions/vcard.php	1970-01-01 09:00:00.000000000 +0900
+++ /usr/share/squirrelmail/functions/vcard.php	2008-11-17 09:23:58.000000000 +0900
@@ -0,0 +1,323 @@
+<?php
+
+/*
+ * Vincent Touchard
+ * 2008/11/12
+ *
+ * set of a functions to render a vcard
+ *
+ * You can use it calling vcard_fromFile or vcard_fromText
+ *
+ * Needs the pear class Contact_Vcard_Parse
+ */
+
+require_once 'Contact_Vcard_Parse.php';
+
+/*
+ * display each field
+ *
+ * name     string   name of the field
+ * value    array    values to display
+ * url      boolean  is the value is an url
+ * charset  string   charset of the text to render
+ */
+function vcard_format_text($name, $value, $url = 0, $charset = '') {
+	$ret = "";
+	foreach ($value as $t) {
+		if (isset($t[0]) && $t[0]) {
+			$text = $t[0];
+
+			// convert to utf-8 if needed
+			if (!empty($charset)) {
+				$res = iconv($charset, "UTF-8", $text);
+				// check if conversion didn't fail - keep the unconverted text if it failed
+				if($res != FALSE) {
+					$text = $res;
+				}
+			}
+
+			$ret .= ', ' . ($url ? '<a href="' . $text . '" >' . $text . '</a>' : $text);
+		}
+	}
+	return '  <tr><td align="right" valign="top" style="width:15%">' . $name . ':</td>' .
+		'<td>' . nl2br(ltrim($ret, ", ")) . "</td></tr>\n";
+}
+
+/*
+ * Generate a table for each topic
+ *
+ * name        string  name of the topic
+ * fields      array   fields to display
+ * vcard_data  array   data extracted from the vcard
+ */
+function vcard_data_to_table($name, $fields, $vcard_data) {
+
+	echo '<table border="0" cellpadding="2" cellspacing="0" align="center" style="width:100%">' . "\n" .
+		'  <tr><td colspan="2"><b>' . $name . '</b></td></tr>' . "\n";
+
+	// read all attributes with the wanted keyword (TEL, PHOTO, ...)
+	foreach ($fields as $k => $v) {
+		if (isset($vcard_data[0][$k]) && $vcard_data[0][$k]) {
+
+			// read all the attributes with the same keyword
+			foreach ($vcard_data[0][$k] as $values) {
+
+				// go to all the wanted attributes with the same keyword
+				foreach ($v as $w) {
+
+					// is an url?
+					$url = isset($values['param']['VALUE']) && $values['param']['VALUE'][0] == 'URL' || $k == 'URL';
+
+					// which charset ?
+					$charset = isset($values['param']['CHARSET'][0]) ? $values['param']['CHARSET'][0] : '';
+
+					// if a parameter is given, keep only if it matches
+					if (isset($w["param"]) && $w["param"][1] != "DEFAULT" && !empty($values['param'][$w["param"][0]])) {
+						foreach ($values['param'][$w["param"][0]] as $param) {
+							if ($param == $w["param"][1]) {
+								echo vcard_format_text($w["name"], $values['value'], $url, $charset);
+							}
+						}
+					} elseif (isset($w["param"]) && $w["param"][1] == "DEFAULT" && empty($values['param'][$w["param"][0]])) {
+						echo vcard_format_text($w["name"], $values['value'], $url, $charset);
+
+						// else, print it
+					} elseif (!isset($w["param"])) {
+						echo vcard_format_text($w["name"], $values['value'], $url, $charset);
+					}
+				}
+			}
+		}
+	}
+	echo "</table>\n";
+}
+
+/*
+ * Display an image
+ *
+ * Used by PHOTO and LOGO keywords
+ *
+ * Can handle base64 images and url ones
+ *
+ *
+ */
+function vcard_display_image($image_info) {
+	$data = $image_info[0]['value'][0][0];
+
+	// default values
+	$x = 120;
+	$y = 160;
+
+	// check if it is an URL or not
+	if (!isset($image_info[0]['param']['VALUE']) || $image_info[0]['param']['VALUE'][0] != 'URL') {
+
+		// find size
+		$im = imagecreatefromstring(base64_decode($data));
+		if ($im != FALSE) {
+			$x = imagesx($im);
+			$y = imagesy($im);
+
+			$ratio_x = $x / 160.0;
+			$ratio_y = $y / 160.0;
+
+			// reduce size to stay in the limit of 160x160
+			if ($ratio_x > 1.0 || $ratio_y > 1.0) {
+				$ratio = max($ratio_x, $ratio_y);
+				$x = $x / $ratio;
+				$y = $y / $ratio;
+			}
+
+		}
+
+		$data = "data:image/jpg;base64," . $data;
+	} else {
+		// find size
+		$a = getimagesize($data);
+		$x = $a[0];
+		$y = $a[1];
+
+		$ratio_x = $x / 160.0;
+		$ratio_y = $y / 160.0;
+
+			// reduce size to stay in the limit of 160x160
+		if ($ratio_x > 1.0 || $ratio_y > 1.0) {
+			$ratio = max($ratio_x, $ratio_y);
+			$x = $x / $ratio;
+			$y = $y / $ratio;
+		}
+	}
+	return "<img src=\"" . $data . "\" height=\"$y\" width=\"$x\" \>";
+}
+
+/*
+ * Generate the vcard display
+ *
+ * cardinfo  array  nested array containing the vcard data
+ */
+function vcard_generate_vcard($cardinfo) {
+	echo '<table width="100%" border="0" cellspacing="0" cellpadding="2" align="center">' . "\n";
+
+
+	$fn = $cardinfo[0]['FN'][0]['value'][0][0];
+	if (isset($cardinfo[0]['FN'][0]['param']['CHARSET'][0])) {
+		$fn2 = iconv($cardinfo[0]['FN'][0]['param']['CHARSET'][0], "UTF-8", $fn);
+		// if iconv failed, keep the old text
+		if ($fn2 != FALSE) {
+			$fn = $fn2;
+		}
+	}
+
+	echo '<tr><td><div style="text-align: center;"><b>' . $fn . '</b></div></td></tr>';
+
+?>
+
+<!-- Personal Data -->
+<tr><td>
+
+<?php
+	$ShowValues = array(
+		'N' =>             array(array("name" => _("Name"))),
+		'NICKNAME' =>             array(array("name" => _("Nickname"))),
+		'EMAIL' =>         array(array("name" => _("E-mail"), "param" => array("TYPE", "DEFAULT")),
+		array("name" => _("E-mail"), "param" => array("TYPE", "INTERNET")),
+		array("name" => _("E-mail"), "param" => array("TYPE", "HOME"))),
+		'TEL' =>           array(array("name" => _("Phone"), "param" => array("TYPE", "DEFAULT")),
+		array("name" => _("Phone"), "param" => array("TYPE", "HOME")),
+		array("name" => _("Cell Phone"), "param" => array("TYPE", "CELL"))),
+		'LABEL' =>         array(array("name" => _("Address"), "param" => array("TYPE", "DEFAULT")),
+		array("name" => _("Address"), "param" => array("TYPE", "DOM")),
+		array("name" => _("Address"), "param" => array("TYPE", "HOME"))),
+		'ADR' =>         array(array("name" => _("Address"), "param" => array("TYPE", "DEFAULT")),
+		array("name" => _("Address"), "param" => array("TYPE", "HOME"))),
+		'BDAY' =>			array(array("name" => _("Birthday")))
+	);
+
+	vcard_data_to_table("Personal Data", $ShowValues, $cardinfo);
+
+?>
+
+</td>
+<td>
+
+<?php
+	// display only the first photo
+	if (isset($cardinfo[0]['PHOTO']) && $cardinfo[0]['PHOTO'])     {
+		echo vcard_display_image($cardinfo[0]['PHOTO']);
+	}
+?>
+
+</td></tr>
+<!-- Personal Data -->
+
+<tr><td colspan="2"><hr /></td></tr>
+
+<!-- Work -->
+<tr><td>
+
+<?php
+	$ShowValues = array(
+		'ORG' =>             array(array("name" => _("Organisation"))),
+		'TITLE' =>             array(array("name" => _("Title"))),
+		'ROLE' =>             array(array("name" => _("Role"))),
+		'EMAIL' =>         array(array("name" => _("E-mail"), "param" => array("TYPE", "WORK"))),
+		'TEL' =>           array(array("name" => _("Phone"), "param" => array("TYPE", "WORK")),
+		array("name" => _("Fax"), "param" => array("TYPE", "FAX"))),
+		'LABEL' =>         array(array("name" => _("Address"), "param" => array("TYPE", "WORK"))),
+		'ADR' =>         array(array("name" => _("Address"), "param" => array("TYPE", "WORK")))
+	);
+
+	vcard_data_to_table("Work", $ShowValues, $cardinfo);
+
+?>
+
+</td>
+<td>
+
+<?php
+	// display only the first logo
+	if (isset($cardinfo[0]['LOGO']) && $cardinfo[0]['LOGO'])     {
+		echo vcard_display_image($cardinfo[0]['LOGO']);
+	}
+?>
+
+</td></tr>
+<!-- Work -->
+
+<tr><td colspan="2"><hr /></td></tr>
+
+<!-- Miscelleaneous -->
+<tr><td>
+
+<?php
+	$ShowValues = array(
+		'NOTE' =>          array(array("name" => _("Note"))),
+		'URL' =>          array(array("name" => _("Website")))
+	);
+
+	vcard_data_to_table("Miscelleaneous", $ShowValues, $cardinfo);
+?>
+
+</td></tr>
+<!-- Miscelleaneous -->
+
+<tr><td colspan="2"><hr /></td></tr>
+
+<!-- Security -->
+<tr><td>
+
+<?php
+	$ShowValues = array(
+		'KEY' =>           array(array("name" => _("PGP Public Key"), "param" => array("TYPE", "PGP")),
+		array("name" => _("X509 Public Key"), "param" => array("TYPE", "X509"))),
+	);
+
+	vcard_data_to_table("Security", $ShowValues, $cardinfo);
+?>
+
+</td></tr>
+<!-- Security -->
+
+</table>
+<?php
+
+}
+
+/*
+ * Function to extract some basic information from the vcard
+ *
+ * returns an array with the information extracted
+ */
+function vcard_extractBasicInfo($cardinfo) {
+	// Key "N", mandatory in all current vcard version (2.1 and 3.0)
+	$info['firstname'] = $cardinfo[0]['N'][0]['value'][0][0];
+	$info['lastname'] = $cardinfo[0]['N'][0]['value'][1][0];
+
+	// Key "Nickname", optional
+	if (isset($cardinfo[0]['NICKNAME'])) {
+		$info['nickname'] = $cardinfo[0]['NICKNAME'][0]['value'][0][0];
+	}
+	return $info;
+}
+
+/*
+ * Display a vcard taking the data in a file
+ */
+function vcard_fromFile($file) {
+	$parse = new Contact_Vcard_Parse();
+	$cardinfo = $parse->fromFile($file);
+//print_r($cardinfo[0]);
+	vcard_generate_vcard($cardinfo);
+	return vcard_extractBasicInfo($cardinfo);
+}
+
+/*
+ * Display a vcard taking the data from the text given as an argument
+ */
+function vcard_fromText($text) {
+	$parse = new Contact_Vcard_Parse();
+	$cardinfo = $parse->fromText($text);
+	vcard_generate_vcard($cardinfo);
+	return vcard_extractBasicInfo($cardinfo);
+}
+
+?>
diff -rbNu squirrelmail/include/load_prefs.php /usr/share/squirrelmail/include/load_prefs.php
--- squirrelmail/include/load_prefs.php	2007-05-10 20:24:16.000000000 +0900
+++ /usr/share/squirrelmail/include/load_prefs.php	2008-11-07 17:17:51.000000000 +0900
@@ -180,6 +180,7 @@
 $editor_height = getPref($data_dir, $username, 'editor_height', 20 );
 $use_signature = getPref($data_dir, $username, 'use_signature', SMPREF_OFF );
 $prefix_sig = getPref($data_dir, $username, 'prefix_sig');
+$use_vcard = getPref($data_dir, $username, 'use_vcard', SMPREF_OFF );
 
 /* Load timezone preferences */
 $timezone = getPref($data_dir, $username, 'timezone', SMPREF_NONE );
diff -rbNu squirrelmail/include/options/personal.php /usr/share/squirrelmail/include/options/personal.php
--- squirrelmail/include/options/personal.php	2006-07-09 04:04:05.000000000 +0900
+++ /usr/share/squirrelmail/include/options/personal.php	2008-11-17 09:25:50.000000000 +0900
@@ -117,6 +117,29 @@
         'save'    => 'save_option_signature'
     );
 
+	$optvals[SMOPT_GRP_CONTACT][] = array(
+		'name'    => 'vcard',
+		'caption' => _("Upload vCard"),
+		'type'    => SMOPT_TYPE_FILE,
+		'refresh' => SMOPT_REFRESH_NONE,
+		'value'   => '10485760',
+		'save'    => 'save_option_vcard'
+	);
+
+    $filename = getHashedFile($username, $data_dir, "$username.vcard");
+	if (file_exists($filename)) {
+		$view_vard_link_value = '<a href="view_personal_vcard.php">'
+			. _("View vCard")
+			. '</a> ';
+		$optvals[SMOPT_GRP_CONTACT][] = array(
+			'name'    => 'vcard',
+			'caption' => _("Current vCard"),
+			'type'    => SMOPT_TYPE_COMMENT,
+			'refresh' => SMOPT_REFRESH_NONE,
+			'comment' =>  $view_vard_link_value
+		);
+	}
+
     if ($edit_identity) {
         $identities_link_value = '<a href="options_identities.php">'
                                . _("Edit Advanced Identities")
@@ -237,6 +260,13 @@
         'refresh' => SMOPT_REFRESH_NONE
     );
 
+    $optvals[SMOPT_GRP_SIG][] = array(
+        'name'    => 'use_vcard',
+        'caption' => _("Use vCard"),
+        'type'    => SMOPT_TYPE_BOOLEAN,
+        'refresh' => SMOPT_REFRESH_NONE
+    );
+
     /* Assemble all this together and return it as our result. */
     $result = array(
         'grps' => $optgrps,
@@ -257,4 +287,59 @@
     setSig($data_dir, $username, 'g', $option->new_value);
 }
 
+/**
+ * Saves the vcard option.
+ *
+ * mostly taken from
+ * plugins/abook_import_export/address_book_import.php
+ *
+ */
+function save_option_vcard($option) {
+    global $data_dir, $username;
+
+    $vcard = $_FILES['new_' . $option->name];
+
+    if ($vcard['tmp_name'] == '' || $vcard['size'] == 0) {
+        // Detect PHP 4.2.0+ upload error codes (http://www.php.net/features.file-upload.errors)
+        $upload_error = _("Please select a file for uploading.");
+        if (isset($vcard['error']) && $vcard['error']!=0 ) {
+            switch($vcard['error']) {
+            case 1:
+                $upload_error = _("The uploaded file exceeds PHP upload_max_filesize limits.");
+                break;
+            case 2:
+                $upload_error = _("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML.");
+                break;
+            case 3:
+                $upload_error = _("The uploaded file was only partially uploaded.");
+                break;
+            case 4:
+                $upload_error = _("No file was uploaded.");
+                break;
+            case 6:
+                $upload_error = _("Missing a temporary directory.");
+                break;
+            case 7:
+                $upload_error = _("Failed to write file to disk.");
+                break;
+            case 8:
+                // File upload stopped by extension. 'security library' is more user friendly.
+                $upload_error = _("File upload stopped by security library.");
+                break;
+            default:
+                $upload_error = _("Unknown upload error.");
+                break;
+            }
+        }
+		plain_error_message( $upload_error, $color);
+	}
+	elseif (isset($vcard['type']) && $vcard['type'] != 'text/x-vcard') {
+		$upload_error = _("Please upload a vCard.");
+		plain_error_message( $upload_error, $color);
+	}
+	else {
+	    setVcard($data_dir, $username, 'd', $vcard['tmp_name']);
+	} 
+}
+
 ?>
\ No newline at end of file
diff -rbNu squirrelmail/src/compose.php /usr/share/squirrelmail/src/compose.php
--- squirrelmail/src/compose.php	2007-05-10 20:22:51.000000000 +0900
+++ /usr/share/squirrelmail/src/compose.php	2008-11-10 16:29:11.000000000 +0900
@@ -80,6 +80,7 @@
 sqgetGlobalVar('mail_sent',$mail_sent, $SQ_GLOBAL);
 sqgetGlobalVar('passed_id',$passed_id, $SQ_GLOBAL);
 sqgetGlobalVar('passed_ent_id',$passed_ent_id, $SQ_GLOBAL);
+sqgetGlobalVar('usevcard',$usevcard, $SQ_GLOBAL);
 
 sqgetGlobalVar('attach',$attach, SQ_POST);
 sqgetGlobalVar('draft',$draft, SQ_POST);
@@ -333,7 +334,7 @@
             'passed_body','use_signature','signature','attachments','subject','newmail',
             'send_to_bcc', 'passed_id', 'mailbox', 'from_htmladdr_search', 'identity',
             'draft_id', 'delete_draft', 'mailprio', 'edit_as_new', 'compose_messsages',
-            'composesession', 'request_mdn', 'request_dr');
+            'composesession', 'request_mdn', 'request_dr', 'usevcard');
 
         foreach ($compo_var_list as $var) {
             if ( isset($session_expired_post[$var]) && !isset($$var) ) {
@@ -701,6 +702,8 @@
     if (isset($subject)) {
         $values['subject'] = $subject;
     }
+
+	$usevcard = $use_vcard;
     showInputForm($session, $values);
 }
 
@@ -1400,7 +1403,7 @@
     global $use_javascript_addr_book, $save_as_draft,
         $default_use_priority, $mailprio, $default_use_mdn,
         $request_mdn, $request_dr,
-        $data_dir, $username;
+        $data_dir, $username, $usevcard;
 
     echo '   <tr>' . "\n" .
         '      <td></td>' . "\n" .
@@ -1430,6 +1433,7 @@
         '      <td></td>' . "\n" .
         '      <td>' . "\n" .
         '         <input type="submit" name="sigappend" value="' . _("Signature") . '" />' . "\n";
+	echo addCheckBox('usevcard',  $usevcard  == '1', '1'). _("Use vCard");
     if ($use_javascript_addr_book) {
         echo "         <script type=\"text/javascript\"><!--\n document.write(\"".
             "            <input type=button value=\\\""._("Addresses").
@@ -1549,6 +1553,7 @@
         $request_mdn, $request_dr, $default_charset, $color, $useSendmail,
         $domain, $action, $default_move_to_sent, $move_to_sent;
     global $imapServerAddress, $imapPort, $sent_folder, $key;
+	global $usevcard;
 
     $rfc822_header = $composeMessage->rfc822_header;
 
@@ -1570,6 +1575,19 @@
     }
     $composeMessage->setBody($body);
 
+	if (isset($usevcard) && $usevcard) {
+		if ($identity == 0) {
+			$vcard_path = getHashedFile($username, $data_dir, "$username.vcard");
+		} else {
+			$vcard_path = getHashedFile($username, $data_dir, "$username.vcar$identity");
+		}
+		if (file_exists($vcard_path)) {
+			$vcard_attached = tempnam(getHashedDir($username, $attachment_dir), $username . ".vcf");
+			copy($vcard_path, $vcard_attached);
+			$composeMessage->initAttachment('text/x-vcard', $username . ".vcf", $vcard_attached);
+		}
+    }
+
     if (ereg("^([^@%/]+)[@%/](.+)$", $username, $usernamedata)) {
         $popuser = $usernamedata[1];
         $domain  = $usernamedata[2];
diff -rbNu squirrelmail/src/options_identities.php /usr/share/squirrelmail/src/options_identities.php
--- squirrelmail/src/options_identities.php	2006-07-09 04:05:34.000000000 +0900
+++ /usr/share/squirrelmail/src/options_identities.php	2008-11-14 11:42:02.000000000 +0900
@@ -65,7 +65,7 @@
 do_hook('options_identities_top');
 
 $td_str = '';
-$td_str .= '<form name="f" action="options_identities.php" method="post"><br />' . "\n";
+$td_str .= '<form name="f" action="options_identities.php" method="post" enctype="multipart/form-data"><br />' . "\n";
 $td_str .= '<table border="0" cellspacing="0" cellpadding="0" width="100%">' . "\n";
 $cnt = count($identities);
 foreach( $identities as $iKey=>$ident ) {
@@ -128,7 +128,7 @@
  * @since 1.5.1 and 1.4.5 (was called ShowTableInfo() in 1.1.3-1.4.4 and 1.5.0)
  */
 function ShowIdentityInfo($title, $identity, $id ) {
-    global $color;
+    global $color, $username, $data_dir;
 
     if (empty($identity['full_name']) && empty($identity['email_address']) && empty($identity['reply_to']) && empty($identity['signature'])) {
         $bg = '';
@@ -150,6 +150,21 @@
     $return_str .= sti_input( _("E-Mail Address") , sprintf($name, $id, 'email_address'), $identity['email_address'], $bg);
     $return_str .= sti_input( _("Reply To"), sprintf($name, $id, 'reply_to'), $identity['reply_to'], $bg);
     $return_str .= sti_textarea( _("Signature"), sprintf($name, $id, 'signature'), $identity['signature'], $bg);
+    $return_str .= sti_file( _("Upload vCard"), sprintf($name, $id, 'vcard'), $bg);
+	
+	if ($id == 0) {
+		$filename = getHashedFile($username, $data_dir, "$username.vcard");
+	} else {
+		$filename = getHashedFile($username, $data_dir, "$username.vcar" . $id);
+	}
+	if (file_exists($filename)) {
+		$return_str .= '';
+		$return_str .= '<tr' . $bg . ">\n";
+		$return_str .= '  <td style="white-space: nowrap;text-align:right;">' . _("Current vCard") . ' </td>' . "\n";
+		$return_str .= '  <td> <a href="view_personal_vcard.php?identity=' . $id .'">' . _("View vCard") . '</a> </td>' . "\n";
+		$return_str .= '</tr>';
+	}
+
     $return_str .= concat_hook_function('options_identities_table', array($bg, $empty, $id));
     $return_str .= '<tr' . $bg . '> ' . "\n";
     $return_str .= '  <td> &nbsp; </td>' . "\n";
@@ -221,4 +236,24 @@
 
 }
 
+/**
+ * Creates html formated table row with upload file input field
+ * @param string $title Name displayed next to input field
+ * @param string $name Name of textarea field
+ * @param string $bgcolor html attributes added to row element (tr)
+ * @return string html formated table row with textarea
+ * @todo check right-to-left language issues
+ * @access private
+ */
+function sti_file( $title, $name, $bgcolor ) {
+    $str = '';
+    $str .= '<tr' . $bgcolor . ">\n";
+    $str .= '  <td style="white-space: nowrap;text-align:right;">' . $title . ' </td>' . "\n";
+	$str .= '  <td> <input type="file" name="' . $name . '" /> </td>' . "\n";
+    $str .= '</tr>';
+
+    return $str;
+
+}
+
 ?>
\ No newline at end of file
diff -rbNu squirrelmail/src/options.php /usr/share/squirrelmail/src/options.php
--- squirrelmail/src/options.php	2006-07-09 04:05:34.000000000 +0900
+++ /usr/share/squirrelmail/src/options.php	2008-11-13 09:38:22.000000000 +0900
@@ -58,7 +58,8 @@
                . "new_value = '$option->new_value'\n";
             echo "<br />";
             */
-            if ($option->changed()) {
+			// error = 4 == file not uploaded
+			if ($option->changed() || isset($_FILES['new_'.$option->name]['error']) && $_FILES['new_'.$option->name]['error'] != 4) {
                 $option->save();
                 $max_refresh = max($max_refresh, $option->refresh_level);
             }
@@ -425,7 +426,7 @@
 /* If we are not looking at the main option page, display the page here. */
 /*************************************************************************/
 } else {
-    echo addForm('options.php', 'post', 'f')
+    echo addForm('options.php', 'post', 'f', 'multipart/form-data')
        . create_optpage_element($optpage)
        . create_optmode_element(SMOPT_MODE_SUBMIT)
        . html_tag( 'table', '', '', '', 'width="100%" cellpadding="2" cellspacing="0" border="0"' ) . "\n";
diff -rbNu squirrelmail/src/vcard.php /usr/share/squirrelmail/src/vcard.php
--- squirrelmail/src/vcard.php	2006-07-09 04:05:34.000000000 +0900
+++ /usr/share/squirrelmail/src/vcard.php	2008-11-14 15:41:56.000000000 +0900
@@ -21,6 +21,7 @@
 include_once(SM_PATH . 'include/validate.php');
 require_once(SM_PATH . 'functions/mime.php');
 require_once(SM_PATH . 'functions/url_parser.php');
+require_once(SM_PATH . 'functions/vcard.php');
 
 /* globals */
 sqgetGlobalVar('username', $username, SQ_SESSION);
@@ -40,7 +41,7 @@
 
 echo '<br /><table width="100%" border="0" cellspacing="0" cellpadding="2" ' .
         'align="center">' . "\n" .
-     '<tr><td bgcolor="' . $color[0] . '"><b><div style="text-align: center;">' .
+     '<tr><td colspan="2" bgcolor="' . $color[0] . '"><b><div style="text-align: center;">' .
      _("Viewing a Business Card") . " - ";
 
 $msg_url = 'read_body.php?mailbox='.urlencode($mailbox).
@@ -58,86 +59,14 @@
 
 $vcard = mime_fetch_body($imapConnection, $passed_id, $ent_id);
 $vcard = decodeBody($vcard, $entity_vcard->header->encoding);
-$vcard = explode ("\n",$vcard);
-foreach ($vcard as $l) {
-    $k = substr($l, 0, strpos($l, ':'));
-    $v = substr($l, strpos($l, ':') + 1);
-    $attributes = explode(';', $k);
-    $k = strtolower(array_shift($attributes));
-    foreach ($attributes as $attr)     {
-        if ($attr == 'quoted-printable')
-        $v = quoted_printable_decode($v);
-        else
-            $k .= ';' . strtolower($attr);
-    }
-
-    $v = str_replace(';', "\n", $v);
-    $vcard_nice[$k] = $v;
-}
-
-if ($vcard_nice['version'] == '2.1') {
-    // get firstname and lastname for sm addressbook
-    $vcard_nice['firstname'] = substr($vcard_nice['n'],
-    strpos($vcard_nice['n'], "\n") + 1, strlen($vcard_nice['n']));
-    $vcard_nice['lastname'] = substr($vcard_nice['n'], 0,
-        strpos($vcard_nice['n'], "\n"));
-    // workaround for Outlook, should be fixed in a better way,
-    // maybe in new 'vCard' class.
-    if (isset($vcard_nice['email;pref;internet'])) {
-       $vcard_nice['email;internet'] = $vcard_nice['email;pref;internet'];
-    }
-} else {
-    echo '<tr><td align="center">' .
-         sprintf(_("vCard Version %s is not supported. Some information might not be converted correctly."),
-                 htmlspecialchars($vcard_nice['version'])) .
-         "</td></tr>\n";
-    $vcard_nice['firstname'] = '';
-    $vcard_nice['lastname'] = '';
-}
-
-foreach ($vcard_nice as $k => $v) {
-    $v = htmlspecialchars($v);
-    $v = trim($v);
-    $vcard_safe[$k] = trim(nl2br($v));
-}
-
-$ShowValues = array(
-    'fn' =>             _("Name"),
-    'title' =>          _("Title"),
-    'email;internet' => _("E-mail"),
-    'url' =>            _("Web Page"),
-    'org' =>            _("Organization / Department"),
-    'adr' =>            _("Address"),
-    'tel;work' =>       _("Work Phone"),
-    'tel;home' =>       _("Home Phone"),
-    'tel;cell' =>       _("Cellular Phone"),
-    'tel;fax' =>        _("Fax"),
-    'note' =>           _("Note"));
-
-echo '<tr><td><br />' .
-     '<table border="0" cellpadding="2" cellspacing="0" align="center">' . "\n";
-
-if (isset($vcard_safe['email;internet'])) {
-    $vcard_safe['email;internet'] = makeComposeLink('src/compose.php?send_to='.urlencode($vcard_safe['email;internet']),
-        $vcard_safe['email;internet']);
-}
-
-if (isset($vcard_safe['url'])) {
-    $vcard_safe['url'] = '<a href="' . $vcard_safe['url'] . '">' .
-        $vcard_safe['url'] . '</a>';
-}
-
-foreach ($ShowValues as $k => $v) {
-    if (isset($vcard_safe[$k]) && $vcard_safe[$k])     {
-        echo "<tr><td align=\"right\" valign=\"top\"><b>$v:</b></td><td>" .
-            $vcard_safe[$k] . "</td><tr>\n";
-    }
-}
 
+echo "<tr><td><br />";
+$vcard_safe = vcard_fromText($vcard);
+echo "</td></tr>";
 ?>
-</table>
-<br />
-</td></tr></table>
+
+
+
 <table width="100%" border="0" cellspacing="0" cellpadding="2" align="center">
 <tr><td bgcolor="<?php echo $color[0]; ?>">
 <div style="text-align: center;"><b><?php echo _("Add to address book"); ?></b></div>
diff -rbNu squirrelmail/src/view_personal_vcard.php /usr/share/squirrelmail/src/view_personal_vcard.php
--- squirrelmail/src/view_personal_vcard.php	1970-01-01 09:00:00.000000000 +0900
+++ /usr/share/squirrelmail/src/view_personal_vcard.php	2008-11-14 16:18:38.000000000 +0900
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * view_personal_vcard.php
+ *
+ * This file shows an vcard defined is the user's options
+ *
+ * Vincent Touchard - 14/11/2008
+ *
+ */
+
+/**
+ * Path for SquirrelMail required files.
+ * @ignore
+ */
+Define('SM_PATH','../');
+
+/* SquirrelMail required files. */
+include_once(SM_PATH . 'include/validate.php');
+require_once(SM_PATH . 'functions/url_parser.php');
+require_once(SM_PATH . 'functions/vcard.php');
+
+/* globals */
+sqgetGlobalVar('username', $username, SQ_SESSION);
+sqgetGlobalVar('key', $key, SQ_COOKIE);
+sqgetGlobalVar('onetimepad', $onetimepad, SQ_SESSION);
+
+sqgetGlobalVar('identity',     $identity);
+/* end globals */
+
+displayPageHeader($color, 'None');
+
+echo '<table width="100%" border="0" cellspacing="0" cellpadding="2" ' .
+	'align="center">' . "\n";
+
+
+// title bar + url to go back to options
+$options_url = ($identity == "") ? "options.php?optpage=personal" : "options_identities.php";
+echo '<tr><td colspan="2" bgcolor="' . $color[0] . '"><b><div style="text-align: center;">' .
+     _("Viewing a Business Card") . " - ";
+echo '<a href="' . $options_url . '">' . _("Go back to account options") . '</a>';
+echo '</td></tr>' . "\n";
+
+// display vcard
+echo "<tr><td><br />";
+// 0 and "" considered as empty
+if (empty($identity)) {
+	$vcard = getHashedFile($username, $data_dir, "$username.vcard");
+} else {
+	$vcard = getHashedFile($username, $data_dir, "$username.vcar$identity");
+}
+vcard_fromFile($vcard);
+echo "</td></tr>" . "\n";
+
+echo "</table>";
+
+$oTemplate->display('footer.tpl');
+?>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.