Overview

Packages

  • Auth
  • Core
  • Horde
    • Imsp
  • None
  • Notification

Classes

  • Horde
  • Horde_Config
  • Horde_Config_Form
  • Horde_Core_ActiveSync_Connector
  • Horde_Core_ActiveSync_Driver
  • Horde_Core_Ajax_Application
  • Horde_Core_Ajax_Imple
  • Horde_Core_Ajax_Imple_AutoCompleter
  • Horde_Core_Ajax_Imple_Geocoder_Geonames
  • Horde_Core_Ajax_Imple_SpellChecker
  • Horde_Core_Alarm_Handler_Notify
  • Horde_Core_Auth_Application
  • Horde_Core_Auth_Composite
  • Horde_Core_Auth_Ldap
  • Horde_Core_Auth_Msad
  • Horde_Core_Auth_Shibboleth
  • Horde_Core_Auth_Signup_Base
  • Horde_Core_Auth_Signup_Form
  • Horde_Core_Auth_Signup_Null
  • Horde_Core_Auth_Signup_Sql
  • Horde_Core_Auth_Signup_SqlObject
  • Horde_Core_Autoloader_Callback_Mime
  • Horde_Core_Autoloader_Callback_Nls
  • Horde_Core_Block
  • Horde_Core_Block_Collection
  • Horde_Core_Block_Layout
  • Horde_Core_Block_Layout_Manager
  • Horde_Core_Block_Layout_View
  • Horde_Core_Block_Upgrade
  • Horde_Core_Browser
  • Horde_Core_Bundle
  • Horde_Core_Cli
  • Horde_Core_Controller_NotFound
  • Horde_Core_Controller_RequestConfiguration
  • Horde_Core_Controller_RequestMapper
  • Horde_Core_Controller_SettingsFinder
  • Horde_Core_Db_Migration
  • Horde_Core_Factory_ActiveSyncBackend
  • Horde_Core_Factory_ActiveSyncServer
  • Horde_Core_Factory_ActiveSyncState
  • Horde_Core_Factory_Ajax
  • Horde_Core_Factory_Alarm
  • Horde_Core_Factory_Auth
  • Horde_Core_Factory_AuthSignup
  • Horde_Core_Factory_Base
  • Horde_Core_Factory_BlockCollection
  • Horde_Core_Factory_Browser
  • Horde_Core_Factory_Cache
  • Horde_Core_Factory_Crypt
  • Horde_Core_Factory_Data
  • Horde_Core_Factory_Db
  • Horde_Core_Factory_DbBase
  • Horde_Core_Factory_DbPear
  • Horde_Core_Factory_Dns
  • Horde_Core_Factory_Editor
  • Horde_Core_Factory_Facebook
  • Horde_Core_Factory_Group
  • Horde_Core_Factory_History
  • Horde_Core_Factory_HttpClient
  • Horde_Core_Factory_Identity
  • Horde_Core_Factory_Image
  • Horde_Core_Factory_Imple
  • Horde_Core_Factory_Imsp
  • Horde_Core_Factory_ImspAuth
  • Horde_Core_Factory_Injector
  • Horde_Core_Factory_KolabServer
  • Horde_Core_Factory_KolabSession
  • Horde_Core_Factory_KolabStorage
  • Horde_Core_Factory_Ldap
  • Horde_Core_Factory_Lock
  • Horde_Core_Factory_Logger
  • Horde_Core_Factory_LoginTasks
  • Horde_Core_Factory_Mail
  • Horde_Core_Factory_Mapper
  • Horde_Core_Factory_Matcher
  • Horde_Core_Factory_Memcache
  • Horde_Core_Factory_MimeViewer
  • Horde_Core_Factory_Notification
  • Horde_Core_Factory_Perms
  • Horde_Core_Factory_PermsCore
  • Horde_Core_Factory_Prefs
  • Horde_Core_Factory_Request
  • Horde_Core_Factory_Secret
  • Horde_Core_Factory_SessionHandler
  • Horde_Core_Factory_Share
  • Horde_Core_Factory_ShareBase
  • Horde_Core_Factory_Template
  • Horde_Core_Factory_TextFilter
  • Horde_Core_Factory_ThemesCache
  • Horde_Core_Factory_Token
  • Horde_Core_Factory_Tree
  • Horde_Core_Factory_Twitter
  • Horde_Core_Factory_UrlShortener
  • Horde_Core_Factory_Vfs
  • Horde_Core_Factory_View
  • Horde_Core_Factory_Weather
  • Horde_Core_Group_Ldap
  • Horde_Core_Log_Logger
  • Horde_Core_LoginTasks
  • Horde_Core_LoginTasks_Backend_Horde
  • Horde_Core_LoginTasks_SystemTask_Upgrade
  • Horde_Core_Mime_Viewer_Syntaxhighlighter
  • Horde_Core_Mime_Viewer_Vcard
  • Horde_Core_Notification_Event_Status
  • Horde_Core_Notification_Handler_Decorator_Hordelog
  • Horde_Core_Notification_Storage_Session
  • Horde_Core_Perms
  • Horde_Core_Perms_Ui
  • Horde_Core_Prefs_Cache_Session
  • Horde_Core_Prefs_Identity
  • Horde_Core_Prefs_Storage_Configuration
  • Horde_Core_Prefs_Storage_Hooks
  • Horde_Core_Prefs_Storage_Upgrade
  • Horde_Core_Prefs_Ui
  • Horde_Core_Prefs_Ui_Widgets
  • Horde_Core_Share_Driver
  • Horde_Core_Share_FactoryCallback
  • Horde_Core_Sidebar
  • Horde_Core_Text_Filter_Bbcode
  • Horde_Core_Text_Filter_Emails
  • Horde_Core_Text_Filter_Emoticons
  • Horde_Core_Text_Filter_Highlightquotes
  • Horde_Core_Translation
  • Horde_Core_Tree_Html
  • Horde_Core_Tree_Javascript
  • Horde_Core_Tree_Simplehtml
  • Horde_Core_Ui_FlagImage
  • Horde_Core_Ui_JsCalendar
  • Horde_Core_Ui_Language
  • Horde_Core_Ui_Layout
  • Horde_Core_Ui_ModalFormRenderer
  • Horde_Core_Ui_Pager
  • Horde_Core_Ui_Tabs
  • Horde_Core_Ui_TagCloud
  • Horde_Core_Ui_VarRenderer
  • Horde_Core_Ui_VarRenderer_Html
  • Horde_Core_Ui_VarRenderer_TablesetHtml
  • Horde_Core_Ui_Widget
  • Horde_ErrorHandler
  • Horde_Help
  • Horde_Menu
  • Horde_Registry
  • Horde_Registry_Api
  • Horde_Registry_Application
  • Horde_Registry_Caller
  • Horde_Registry_Nlsconfig
  • Horde_Script_Files
  • Horde_Session
  • Horde_Session_Null
  • Horde_Themes
  • Horde_Themes_Cache
  • Horde_Themes_Css
  • Horde_Themes_Element
  • Horde_Themes_Image
  • Horde_Themes_Sound

Exceptions

  • Horde_Exception_HookNotSet
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Horde_Core_Mime_Viewer_Vcard class renders out vCards in HTML format.
  4:  *
  5:  * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author   Jan Schneider <jan@horde.org>
 11:  * @category Horde
 12:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 13:  * @package  Core
 14:  */
 15: class Horde_Core_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Base
 16: {
 17:     /**
 18:      * This driver's display capabilities.
 19:      *
 20:      * @var array
 21:      */
 22:     protected $_capability = array(
 23:         'full' => true,
 24:         'info' => false,
 25:         'inline' => true,
 26:         'raw' => false
 27:     );
 28: 
 29:     /**
 30:      * URL that can be used as a callback for displaying images.
 31:      *
 32:      * @var Horde_Url
 33:      */
 34:     protected $_imageUrl;
 35: 
 36:     /**
 37:      * Constructor.
 38:      *
 39:      * @param Horde_Mime_Part $mime_part  The object with the data to be
 40:      *                                    rendered.
 41:      * @param array $conf                 Configuration:
 42:      * <pre>
 43:      * 'browser' - (Horde_Browser) Browser object.
 44:      * 'notification' - (Horde_Notification_Base) Notification object.
 45:      * 'prefs' - (Horde_Prefs) Prefs object.
 46:      * 'registry' - (Horde_Registry) Registry object.
 47:      * </pre>
 48:      *
 49:      * @throws InvalidArgumentException
 50:      */
 51:     public function __construct(Horde_Mime_Part $part, array $conf = array())
 52:     {
 53:         $this->_required = array_merge($this->_required, array(
 54:             'browser',
 55:             'notification',
 56:             'prefs',
 57:             'registry'
 58:         ));
 59: 
 60:         parent::__construct($part, $conf);
 61:     }
 62: 
 63:     /**
 64:      * Return the full rendered version of the Horde_Mime_Part object.
 65:      *
 66:      * @return array  See parent::render().
 67:      */
 68:     protected function _render()
 69:     {
 70:         $ret = $this->_renderInline();
 71: 
 72:         if (!empty($ret)) {
 73:             $templates = $this->getConfigParam('registry')->get('templates', 'horde');
 74: 
 75:             reset($ret);
 76:             Horde::startBuffer();
 77:             include $templates . '/common-header.inc';
 78:             echo $ret[key($ret)]['data'];
 79:             include $templates . '/common-footer.inc';
 80:             $ret[key($ret)]['data'] = Horde::endBuffer();
 81:         }
 82: 
 83:         return $ret;
 84:     }
 85: 
 86:     /**
 87:      * Return the rendered inline version of the Horde_Mime_Part object.
 88:      *
 89:      * @return array  See parent::render().
 90:      */
 91:     protected function _renderInline()
 92:     {
 93:         $browser = $this->getConfigParam('browser');
 94:         $notification = $this->getConfigParam('notification');
 95:         $prefs = $this->getConfigParam('prefs');
 96:         $registry = $this->getConfigParam('registry');
 97: 
 98:         $app = false;
 99:         $data = $this->_mimepart->getContents();
100:         $html = '';
101:         $import_msg = null;
102:         $title = Horde_Core_Translation::t("vCard");
103: 
104:         $iCal = new Horde_Icalendar();
105:         if (!$iCal->parsevCalendar($data, 'VCALENDAR', $this->_mimepart->getCharset())) {
106:             $notification->push(Horde_Core_Translation::t("There was an error reading the contact data."), 'horde.error');
107:         }
108: 
109:         if (Horde_Util::getFormData('import') &&
110:             Horde_Util::getFormData('source') &&
111:             $registry->hasMethod('contacts/import')) {
112:             $source = Horde_Util::getFormData('source');
113:             $count = 0;
114:             foreach ($iCal->getComponents() as $c) {
115:                 if ($c->getType() == 'vcard') {
116:                     try {
117:                         $contacts = $registry->call('contacts/import', array($c, null, $source));
118:                         ++$count;
119:                     } catch (Horde_Exception $e) {
120:                         $notification->push(Horde_Core_Translation::t("There was an error importing the contact data:") . ' ' . $e->getMessage(), 'horde.error');
121:                     }
122:                 }
123:             }
124:             $notification->push(sprintf(Horde_Core_Translation::ngettext(
125:                 "%d contact was successfully added to your address book.",
126:                 "%d contacts were successfully added to your address book.",
127:                 $count),
128:                                         $count),
129:                                 'horde.success');
130:         }
131: 
132:         $html .= '<table cellspacing="1" border="0" cellpadding="1">';
133: 
134:         foreach ($iCal->getComponents() as $i => $vc) {
135:             if ($i > 0) {
136:                 $html .= '<tr><td colspan="2">&nbsp;</td></tr>';
137:             }
138: 
139:             $addresses = $vc->getAllAttributes('EMAIL');
140: 
141:             $html .= '<tr><td colspan="2" class="header">';
142:             if (($fullname = $vc->getAttributeDefault('FN', false)) === false) {
143:                 $fullname = count($addresses)
144:                     ? $addresses[0]['value']
145:                     : Horde_Core_Translation::t("[No Label]");
146:             }
147:             $html .= htmlspecialchars($fullname) . '</td></tr>';
148: 
149:             $n = $vc->printableName();
150:             if (!empty($n)) {
151:                 $html .= $this->_row(Horde_Core_Translation::t("Name"), $n);
152:             }
153: 
154:             try {
155:                 $html .= $this->_row(Horde_Core_Translation::t("Alias"), implode("\n", $vc->getAttributeValues('ALIAS')));
156:             } catch (Horde_Icalendar_Exception $e) {}
157: 
158:             try {
159:                 $birthdays = $vc->getAttributeValues('BDAY');
160:                 $birthday = new Horde_Date($birthdays[0]);
161:                 $html .= $this->_row(
162:                     Horde_Core_Translation::t("Birthday"),
163:                     $birthday->strftime($prefs->getValue('date_format')));
164:             } catch (Horde_Icalendar_Exception $e) {}
165: 
166:             $photos = $vc->getAllAttributes('PHOTO');
167:             foreach ($photos as $p => $photo) {
168:                 if (isset($photo['params']['VALUE']) &&
169:                     Horde_String::upper($photo['params']['VALUE']) == 'URI') {
170:                     $html .= $this->_row(Horde_Core_Translation::t("Photo"),
171:                                          '<img src="' . htmlspecialchars($photo['value']) . '" />',
172:                                          false);
173:                 } elseif (isset($photo['params']['ENCODING']) &&
174:                           Horde_String::upper($photo['params']['ENCODING']) == 'B' &&
175:                           isset($photo['params']['TYPE'])) {
176:                     if ($browser->hasFeature('datauri') === true ||
177:                         $browser->hasFeature('datauri') >= strlen($photo['value'])) {
178:                         $html .= $this->_row(Horde_Core_Translation::t("Photo"),
179:                                              '<img src="data:' . htmlspecialchars($photo['params']['TYPE'] . ';base64,' . $photo['value']) . '" />',
180:                                              false);
181:                     } elseif ($this->_imageUrl) {
182:                         $html .= $this->_row(Horde_Core_Translation::t("Photo"),
183:                                              '<img src="' . htmlspecialchars($this->_imageUrl->add(array('c' => $i, 'p' => $p))) . '" />',
184:                                              false);
185:                     }
186:                 }
187:             }
188: 
189:             $labels = $vc->getAllAttributes('LABEL');
190:             foreach ($labels as $label) {
191:                 if (isset($label['params']['TYPE'])) {
192:                     if (!is_array($label['params']['TYPE'])) {
193:                         $label['params']['TYPE'] = array($label['params']['TYPE']);
194:                     }
195:                 } else {
196:                     $label['params']['TYPE'] = array_keys($label['params']);
197:                 }
198:                 $types = array();
199:                 foreach ($label['params']['TYPE'] as $type) {
200:                     switch(Horde_String::upper($type)) {
201:                     case 'HOME':
202:                         $types[] = Horde_Core_Translation::t("Home Address");
203:                         break;
204: 
205:                     case 'WORK':
206:                         $types[] = Horde_Core_Translation::t("Work Address");
207:                         break;
208: 
209:                     case 'DOM':
210:                         $types[] = Horde_Core_Translation::t("Domestic Address");
211:                         break;
212: 
213:                     case 'INTL':
214:                         $types[] = Horde_Core_Translation::t("International Address");
215:                         break;
216: 
217:                     case 'POSTAL':
218:                         $types[] = Horde_Core_Translation::t("Postal Address");
219:                         break;
220: 
221:                     case 'PARCEL':
222:                         $types[] = Horde_Core_Translation::t("Parcel Address");
223:                         break;
224: 
225:                     case 'PREF':
226:                         $types[] = Horde_Core_Translation::t("Preferred Address");
227:                         break;
228:                     }
229:                 }
230:                 if (!count($types)) {
231:                     $types = array(Horde_Core_Translation::t("Address"));
232:                 }
233:                 $html .= $this->_row(implode('/', $types), $label['value']);
234:             }
235: 
236:             $adrs = $vc->getAllAttributes('ADR');
237:             foreach ($adrs as $item) {
238:                 if (isset($item['params']['TYPE'])) {
239:                     if (!is_array($item['params']['TYPE'])) {
240:                         $item['params']['TYPE'] = array($item['params']['TYPE']);
241:                     }
242:                 } else {
243:                     $item['params']['TYPE'] = array_keys($item['params']);
244:                 }
245: 
246:                 $address = $item['values'];
247:                 $a = array();
248:                 $a_list = array(
249:                     Horde_Icalendar_Vcard::ADR_STREET,
250:                     Horde_Icalendar_Vcard::ADR_LOCALITY,
251:                     Horde_Icalendar_Vcard::ADR_REGION,
252:                     Horde_Icalendar_Vcard::ADR_POSTCODE,
253:                     Horde_Icalendar_Vcard::ADR_COUNTRY
254:                 );
255: 
256:                 foreach ($a_list as $val) {
257:                     if (isset($address[$val])) {
258:                         $a[] = $address[$val];
259:                     }
260:                 }
261: 
262:                 $types = array();
263:                 foreach ($item['params']['TYPE'] as $type) {
264:                     switch(Horde_String::upper($type)) {
265:                     case 'HOME':
266:                         $types[] = Horde_Core_Translation::t("Home Address");
267:                         break;
268: 
269:                     case 'WORK':
270:                         $types[] = Horde_Core_Translation::t("Work Address");
271:                         break;
272: 
273:                     case 'DOM':
274:                         $types[] = Horde_Core_Translation::t("Domestic Address");
275:                         break;
276: 
277:                     case 'INTL':
278:                         $types[] = Horde_Core_Translation::t("International Address");
279:                         break;
280: 
281:                     case 'POSTAL':
282:                         $types[] = Horde_Core_Translation::t("Postal Address");
283:                         break;
284: 
285:                     case 'PARCEL':
286:                         $types[] = Horde_Core_Translation::t("Parcel Address");
287:                         break;
288: 
289:                     case 'PREF':
290:                         $types[] = Horde_Core_Translation::t("Preferred Address");
291:                         break;
292:                     }
293:                 }
294:                 if (!count($types)) {
295:                     $types = array(Horde_Core_Translation::t("Address"));
296:                 }
297:                 $html .= $this->_row(implode('/', $types), implode("\n", $a));
298:             }
299: 
300:             $numbers = $vc->getAllAttributes('TEL');
301: 
302:             foreach ($numbers as $number) {
303:                 if (isset($number['params']['TYPE'])) {
304:                     if (!is_array($number['params']['TYPE'])) {
305:                         $number['params']['TYPE'] = array($number['params']['TYPE']);
306:                     }
307:                     foreach ($number['params']['TYPE'] as $type) {
308:                         $number['params'][Horde_String::upper($type)] = true;
309:                     }
310:                 }
311:                 if (isset($number['params']['FAX'])) {
312:                     $html .= $this->_row(Horde_Core_Translation::t("Fax"), $number['value']);
313:                 } else {
314:                     if (isset($number['params']['HOME'])) {
315:                         $html .= $this->_row(Horde_Core_Translation::t("Home Phone"),
316:                                              $number['value']);
317:                     } elseif (isset($number['params']['WORK'])) {
318:                         $html .= $this->_row(Horde_Core_Translation::t("Work Phone"),
319:                                              $number['value']);
320:                     } elseif (isset($number['params']['CELL'])) {
321:                         $html .= $this->_row(Horde_Core_Translation::t("Cell Phone"),
322:                                              $number['value']);
323:                     } else {
324:                         $html .= $this->_row(Horde_Core_Translation::t("Phone"),
325:                                              $number['value']);
326:                     }
327:                 }
328:             }
329: 
330:             $emails = array();
331:             foreach ($addresses as $address) {
332:                 if (isset($address['params']['TYPE'])) {
333:                     if (!is_array($address['params']['TYPE'])) {
334:                         $address['params']['TYPE'] = array($address['params']['TYPE']);
335:                     }
336:                     foreach ($address['params']['TYPE'] as $type) {
337:                         $address['params'][Horde_String::upper($type)] = true;
338:                     }
339:                 }
340:                 $email = '<a href="';
341:                 if ($registry->hasMethod('mail/compose')) {
342:                     $email .= $registry->call(
343:                         'mail/compose',
344:                         array(array('to' => $address['value'])));
345:                 } else {
346:                     $email .= 'mailto:' . htmlspecialchars($address['value']);
347:                 }
348:                 $email .= '">' . htmlspecialchars($address['value']) . '</a>';
349:                 if (isset($address['params']['PREF'])) {
350:                     array_unshift($emails, $email);
351:                 } else {
352:                     $emails[] = $email;
353:                 }
354:             }
355: 
356:             if (count($emails)) {
357:                 $html .= $this->_row(Horde_Core_Translation::t("Email"), implode("\n", $emails), false);
358:             }
359: 
360:             try {
361:                 $title = $vc->getAttributeValues('TITLE');
362:                 $html .= $this->_row(Horde_Core_Translation::t("Title"), $title[0]);
363:             } catch (Horde_Icalendar_Exception $e) {}
364: 
365:             try {
366:                 $role = $vc->getAttributeValues('ROLE');
367:                 $html .= $this->_row(Horde_Core_Translation::t("Role"), $role[0]);
368:             } catch (Horde_Icalendar_Exception $e) {}
369: 
370:             try {
371:                 $org = $vc->getAttributeValues('ORG');
372:                 $html .= $this->_row(Horde_Core_Translation::t("Company"), $org[0]);
373:                 if (isset($org[1])) {
374:                     $html .= $this->_row(Horde_Core_Translation::t("Department"), $org[1]);
375:                 }
376:             } catch (Horde_Icalendar_Exception $e) {}
377: 
378:             try {
379:                 $notes = $vc->getAttributeValues('NOTE');
380:                 $html .= $this->_row(Horde_Core_Translation::t("Notes"), $notes[0]);
381:             } catch (Horde_Icalendar_Exception $e) {}
382: 
383:             try {
384:                 $url = $vc->getAttributeValues('URL');
385:                 $html .= $this->_row(
386:                     Horde_Core_Translation::t("URL"),
387:                     '<a href="' . htmlspecialchars($url[0])
388:                         . '" target="_blank">' . htmlspecialchars($url[0])
389:                         . '</a>',
390:                     false);
391:             } catch (Horde_Icalendar_Exception $e) {}
392:         }
393: 
394:         if ($registry->hasMethod('contacts/import') &&
395:             $registry->hasMethod('contacts/sources')) {
396:             $html .= '<tr><td colspan="2" class="smallheader"><form action="'
397:                 . Horde::selfUrl() . '" method="get" name="vcard_import">'
398:                 . Horde_Util::formInput();
399:             foreach ($_GET as $key => $val) {
400:                 $html .= '<input type="hidden" name="' . htmlspecialchars($key)
401:                     . '" value="' . htmlspecialchars($val) . '" />';
402:             }
403: 
404:             $sources = $registry->call('contacts/sources', array(true));
405:             if (count($sources) > 1) {
406:                 $html .=
407:                     '<input type="submit" class="button" name="import" value="'
408:                     . Horde_Core_Translation::t("Add to address book:") . '" />'
409:                     . '<label for="add_source" class="hidden">'
410:                     . Horde_Core_Translation::t("Address Book") . '</label>'
411:                     . '<select id="add_source" name="source">';
412:                 foreach ($sources as $key => $label) {
413:                     $selected = ($key == $prefs->getValue('add_source'))
414:                         ? ' selected="selected"' : '';
415:                     $html .= '<option value="' . htmlspecialchars($key) . '"'
416:                         . $selected . '>' . htmlspecialchars($label)
417:                         . '</option>';
418:                 }
419:             } else {
420:                 reset($sources);
421:                 $html .=
422:                     '<input type="submit" class="button" name="import" value="'
423:                     . Horde_Core_Translation::t("Add to my address book") . '" />'
424:                     . '<input type="hidden" name="source" value="'
425:                     . htmlspecialchars(key($sources)) . '" />';
426:             }
427: 
428:             $html .= '</form></td></tr><tr><td>&nbsp;</td></tr>';
429:         }
430: 
431:         $html .=  '</table>';
432: 
433:         Horde::startBuffer();
434:         $notification->notify(array('listeners' => 'status'));
435: 
436:         return $this->_renderReturn(
437:             Horde::endBuffer() . $html,
438:             'text/html; charset=' . $this->getConfigParam('charset')
439:         );
440:     }
441: 
442:     /**
443:      * TODO
444:      */
445:     protected function _row($label, $value, $encode = true)
446:     {
447:         if ($encode) {
448:             $label = htmlspecialchars($label);
449:             $value = htmlspecialchars($value);
450:         }
451:         return '<tr><td class="item" valign="top">' . $label .
452:             '</td><td class="item" valign="top">' . nl2br($value) .
453:             "</td></tr>\n";
454:     }
455: 
456: }
457: 
API documentation generated by ApiGen