├── .gitignore ├── manifest.json ├── composer.json ├── CHANGELOG.textile ├── LICENSE ├── README.textile └── com_connect.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | .Spotlight-V100 4 | .Trashes 5 | Icon? 6 | ehthumbs.db 7 | Thumbs.db 8 | *~ 9 | zem_tpl.php 10 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com_connect", 3 | "description": "Form and contact mailer plugin for Textpattern CMS", 4 | "version": "4.7.0", 5 | "type": 0, 6 | "author": "Textpattern Community", 7 | "author_uri": "https://forum.textpattern.io/viewtopic.php?id=47913", 8 | "order": 5, 9 | "flags": 0, 10 | "help": {"file" : ["./README.textile"]} 11 | } 12 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "textpattern/com_connect", 3 | "description": "Form mailer plugin for Textpattern CMS.", 4 | "keywords": ["textpattern", "plugin", "forms", "html-forms", "email-sender"], 5 | "homepage": "https://github.com/textpattern/com_connect", 6 | "license": "GPL-2.0", 7 | "type": "textpattern-plugin", 8 | "support": { 9 | "issues": "https://github.com/textpattern/com_connect/issues", 10 | "source": "https://github.com/textpattern/com_connect" 11 | }, 12 | "require": { 13 | "textpattern/composer-lock": ">=4.7.0", 14 | "textpattern/composer-installer": "*" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CHANGELOG.textile: -------------------------------------------------------------------------------- 1 | h1. Changelog 2 | 3 | h2. 4.7.1 - 2024-02-28 4 | 5 | * Use self-closing tags to keep validators happy (thanks, jools-r). 6 | * Fix for concatenated headers/line endings on some servers (thanks, hidalgo, Kjeld, Gallex, and phiw13). 7 | * Add @replyto@ attribute. 8 | 9 | h2. 4.7.0 - 2022-01-28 10 | 11 | * Fix a few PHP 8.x warnings. 12 | * Load lang strings in a Textpattern 4.7.0-ish way. 13 | * Add en language designators to Textpack (thanks, cara-tm). 14 | * Introduce @@ for supporting HTML content. 15 | * Only display labels if they've been specified (thanks, dragondz and jools-r). 16 | * Fallback on name if label is empty. 17 | * Use 'expire' attribute value in deletion of old tokens. 18 | * Sanitize field names so forms still submit if names contain spaces. 19 | * Permit {Option label} syntax to specify empty select entry that validates 20 | (thanks, phiw13 and colak). 21 | * Fix @@ to actually match labels. 22 | * Remove use of deprecated EvalElse(). 23 | * Replace deprecated Txp core functions with Txp::get(). 24 | * Pass @$redirect@ into delivery callback. 25 | 26 | h2. 4.6.0 - 2020-01-31 27 | 28 | * Final Textpattern 4.6-compatible release. 29 | 30 | h2. 4.6.0-beta.3 - 2018-10-05 31 | 32 | * Update Composer installation. 33 | * Add code syntax highlighting. 34 | 35 | h2. 4.6.0-beta.2 - 2018-04-11 36 | 37 | * @zcr_file_attach@ has been renamed with @ext_@ prefix. 38 | * Documentation updates and typos. 39 | 40 | h2. 4.6.0-beta - 2017-07-19 41 | 42 | * Rename to com_connect and put under community control. 43 | * Fix zem_contact_options and labels. Thanks, trenc. 44 | * Remove call to is_windows(). 45 | * Third party plugins can return error info. 46 | * Remove unnecessary div in fieldset. Thanks, NicolasGraph. 47 | * Add nl-nl and de-de Textpacks. Thanks, keesbran and rwetzlmayr. 48 | 49 | h2. 4.5.0.0 - 2016-12-02 50 | 51 | * Replace @split()@ (deprecated since PHP 5.3) with @explode()@. 52 | * Remove @zem_contact_mailheader()@ function, switch to using Textpattern's @encode_mailheader@ function (Textpattern 4.0.4+). 53 | * Parse the @thanks_form@. 54 | * Make email work when the mailserver requires the SMTP envelope sender (in Textpattern preferences page). 55 | * Use "From: " instead of "From: email@example.com" to avoid triggering Spamassassin rule. 56 | * Add @body_form@ attribute. Not to be confused with the ladies' sanitary product. 57 | * Add @class@, @expire@ and @label_position@ attributes. 58 | * Add @@ tag. 59 | * Add a host of HTML5 attributes to tags. 60 | * Add @zemcontact.delivery@ callback for enhanced mailing through other plugins. 61 | * Remove deprecated @button@ attribute in @@. 62 | * Add plugin Textpack, removing the need for separate zem_contact_lang plugin. Translations welcome! 63 | 64 | h2. 4.0.3.20 - 2007-08-23 65 | 66 | * Escape @label@ attribute values when showing the form in the browser (not in email, plain text there). 67 | * Don't display empty input values in the email. 68 | 69 | h2. 4.0.3.19 - 2007-02-14 70 | 71 | * @send_article@ functionality revised, requiring changes when upgrading from earlier versions. 72 | * New language strings: @send_article@ and @recipient@ (replaces @receiver@). 73 | * Sets of radio buttons require the new @group@ attribute. 74 | * @yes@/@no@ values deprecated in favour of the Textpattern standard @1@/@0@ values (@yes@/@no@ still work in this version). 75 | 76 | h2. 4.0.3.18 - 2006-11-20 77 | 78 | * IDs @zemContactForm@ and @zemSubmit@ have changed to classes to allow multiple forms per page. 79 | * New language strings: @form_used@, @invalid_utf8@, @max_warning@, @name@, @refresh@, @secret@. 80 | 81 | h2. 4.0.3.17 - 2006-03-12 82 | 83 | * @@ function added to enable the use of radio buttons (thanks Robert). 84 | * New attribute @button="yes"@ has been added to the @@ function to enable the user to choose a @'; 1555 | } else { 1556 | return '' : '>'); 1557 | } 1558 | } 1559 | 1560 | /** 1561 | * Tag: Render a link to allow someone to forward a page to a friend. 1562 | * 1563 | * @param array $atts Tag attributes 1564 | * @return string HTML 1565 | */ 1566 | function com_connect_send_article($atts) 1567 | { 1568 | if (!isset($_REQUEST['com_connect_send_article'])) { 1569 | $linktext = (empty($atts['linktext'])) ? gTxt('com_connect_send_article') : $atts['linktext']; 1570 | $join = (empty($_SERVER['QUERY_STRING'])) ? '?' : '&'; 1571 | $href = $_SERVER['REQUEST_URI'] . $join . 'com_connect_send_article=yes'; 1572 | 1573 | return '' . txpspecialchars($linktext) . ''; 1574 | } 1575 | 1576 | return; 1577 | } 1578 | 1579 | /** 1580 | * Replace mime tags with boundary text 1581 | * 1582 | * @param array $atts Tag attributes 1583 | * @return string Boundary 1584 | */ 1585 | function com_connect_mime($atts) 1586 | { 1587 | global $com_connect_flags; 1588 | 1589 | $boundary = $com_connect_flags['boundary']; 1590 | $charset = $com_connect_flags['charset']; 1591 | $encoding = $com_connect_flags['xfer_encoding']; 1592 | 1593 | extract(lAtts(array( 1594 | 'type' => 'text', 1595 | ), $atts)); 1596 | 1597 | // Build mimes - trailing blank line is necessary. 1598 | $text_mime = << $grp) { 1648 | foreach ($grp as $id => $atts) { 1649 | $flags[$key]['label'] = $atts['label']; 1650 | 1651 | if (!empty($atts['req']) && !isset($flags[$key]['req'])) { 1652 | $flags[$key]['req'] = 1; 1653 | } 1654 | 1655 | if (!empty($atts['isSet']) && !isset($flags[$key]['isSet'])) { 1656 | $flags[$key]['isSet'] = 1; 1657 | } 1658 | } 1659 | } 1660 | 1661 | foreach ($flags as $key => $data) { 1662 | if (!empty($data['req']) && !isset($data['isSet'])) { 1663 | $com_connect_error[] = gTxt('com_connect_field_missing', array('{field}' => txpspecialchars($data['label']))); 1664 | } 1665 | } 1666 | } 1667 | } 1668 | 1669 | /** 1670 | * Process tag attributes and set defaults. 1671 | * 1672 | * Handles HTML 'global' attributes too, though what we consider global differs slightly 1673 | * from the W3C: any attributes that apply to most of the tags is considered 1674 | * global. Just saves repetitive code in each tag handler. 1675 | * 1676 | * Note that 'class' is omitted, because that has different default values per input 1677 | * widget, so it is dealt with explicitly in each tag handler. 1678 | * 1679 | * @param array $arr Acceptable tag attributes 1680 | * @param array $atts User-submitted attribute values 1681 | * @return array 1682 | */ 1683 | function com_connect_lAtts($pairs, $atts) 1684 | { 1685 | $doctype = get_pref('doctype', 'xhtml'); 1686 | 1687 | foreach (array('button', 'copysender', 'checked', 'required', 'send_article', 'show_input', 'show_error') as $key) { 1688 | if (isset($atts[$key])) { 1689 | $atts[$key] = ($atts[$key] === 'yes' || intval($atts[$key])) ? 1 : 0; 1690 | } 1691 | } 1692 | 1693 | if (isset($atts['break']) && $atts['break'] === 'br') { 1694 | $atts['break'] = ($doctype === 'xhtml') ? '
' : '
'; 1695 | } 1696 | 1697 | $com_connect_globals = array( 1698 | 'accesskey' => '', 1699 | 'autofocus' => '', 1700 | 'dir' => '', 1701 | 'disabled' => '', 1702 | 'hidden' => '', 1703 | 'id' => '', 1704 | 'lang' => '', 1705 | 'list' => '', 1706 | 'readonly' => '', 1707 | 'spellcheck' => '', 1708 | 'style' => '', 1709 | 'tabindex' => '', 1710 | 'title' => '', 1711 | 'translate' => '', 1712 | ); 1713 | 1714 | foreach ($atts as $name => $value) { 1715 | if (array_key_exists($name, $pairs) || substr($name, 0, 2) === 'on' || array_key_exists($name, $com_connect_globals)) { 1716 | $pairs[$name] = $value; 1717 | } elseif (get_pref('production_status') != 'live') { 1718 | trigger_error(gTxt('unknown_attribute', array('{att}' => $name))); 1719 | } 1720 | } 1721 | 1722 | $pairs['com_connect_globals'] = $com_connect_globals; 1723 | 1724 | // Prevent global attributes from interfering. 1725 | // See https://github.com/textpattern/textpattern/pull/893 1726 | lAtts(deNull($pairs), $atts, false); 1727 | 1728 | return ($pairs) ? $pairs : false; 1729 | } 1730 | 1731 | /** 1732 | * Build a sanitized, unique attribute array from the given pairs. 1733 | * 1734 | * If called multiple times, earlier values supersede later values 1735 | * if the keys clash. 1736 | * 1737 | * @param array $pairs Attribute tuples to compile 1738 | * @param array $defaults Attribute values to use if the $pairs tuple value is empty 1739 | * @return array 1740 | */ 1741 | function com_connect_build_atts($pairs, $defaults = array()) 1742 | { 1743 | $attr = array(); 1744 | 1745 | $booleans = array( 1746 | 'autofocus', 1747 | 'checked', 1748 | 'disabled', 1749 | 'hidden', 1750 | 'multiple', 1751 | 'readonly', 1752 | 'required', 1753 | 'selected', 1754 | ); 1755 | 1756 | foreach ($pairs as $key => $value) { 1757 | if ($value !== '' && $value !== null) { 1758 | $attr[$key] = $key . (in_array($key, $booleans) ? '' : '="' . txpspecialchars($value) . '"'); 1759 | } else { 1760 | if (isset($defaults[$key])) { 1761 | $attr[$key] = $key . (in_array($key, $booleans) ? '' : '="' . txpspecialchars($defaults[$key]) . '"'); 1762 | } 1763 | } 1764 | } 1765 | 1766 | return $attr; 1767 | } 1768 | 1769 | /** 1770 | * Replace nulls and newlines in content with spaces. 1771 | * 1772 | * @param string $str String to sanitize 1773 | * @param bool $header Whether the string is a header or not 1774 | */ 1775 | function com_connect_strip($str, $header = true) 1776 | { 1777 | if ($header) { 1778 | $str = Txp::get('\Textpattern\Mail\Encode')->escapeHeader($str); 1779 | } 1780 | 1781 | return preg_replace('/[\x00]/', ' ', $str); 1782 | } 1783 | 1784 | /** 1785 | * Handle content delivery of payload. 1786 | * 1787 | * Triggers a 'comconnect.deliver' callback event to override or augment the 1788 | * delivery mechanism. Third party plugins can make alterations to the $payload, 1789 | * then return one of the strings: 1790 | * -> "comconnect.send" (or no return value) to allow the plugin to continue mailing after the 3rd party plugin completes 1791 | * -> "comconnect.skip" to skip com_connect's mailing (i.e. the 3rd party handles mailing) and return 'success' 1792 | * -> "comconnect.fail" to skip com_connect's mailing and return 'fail' 1793 | * 1794 | * By hooking into the callback's step you can target either the main 'send' 1795 | * process or the 'copysender' process. Examples of things you could do: 1796 | * -> Add Multi-part MIME headers for HTML emails. 1797 | * -> Add CC: or BCC: fields. 1798 | * -> Subscribe people to mailing lists. 1799 | * -> Handle the mailing process independently of Textpattern. 1800 | * 1801 | * @param string $to Delivery address 1802 | * @param string $subject Subject of message 1803 | * @param string $body Message content 1804 | * @param array $headers Message headers as tuples 1805 | * @param array $fields Message field names and content as tuples 1806 | * @param array $flags Signals to govern delivery / callback behaviour 1807 | */ 1808 | function com_connect_deliver($to, $subject, $body, $headers, $fields, $flags) 1809 | { 1810 | $payload = array( 1811 | 'to' => $to, 1812 | 'subject' => $subject, 1813 | 'headers' => $headers, 1814 | 'body' => $body, 1815 | 'fields' => $fields, 1816 | 'flags' => $flags, 1817 | ); 1818 | 1819 | $flavour = ($flags['isCopy'] === true) ? 'copysender' : 'send'; 1820 | 1821 | // Allow plugins to override or alter default action (mail) if required. 1822 | $ret = callback_event_ref('comconnect.deliver', $flavour, 0, $payload); 1823 | 1824 | if (in_array('comconnect.fail', $ret)) { 1825 | return false; 1826 | } elseif (in_array('comconnect.skip', $ret)) { 1827 | return true; 1828 | } 1829 | 1830 | extract($payload); 1831 | 1832 | $smtp_from = get_pref('smtp_from'); 1833 | 1834 | if (!is_callable('mail')) { 1835 | return (get_pref('production_status') === 'live') 1836 | ? gTxt('com_connect_mail_sorry') 1837 | : gTxt('warn_mail_unavailable'); 1838 | } 1839 | 1840 | $sep = (!empty($headers['separator'])) ? $headers['separator'] : (IS_WIN ? "\r\n" : "\n"); 1841 | $sep = !IS_WIN && ini_get('cgi.rfc2616_headers') != 0 ? "\r\n": $sep; 1842 | $xfer_encoding = (!empty($headers['xfer_encoding'])) ? $headers['xfer_encoding'] : '8bit'; 1843 | $content_type = (!empty($headers['content_type'])) ? $headers['content_type'] : 'text/plain'; 1844 | $reply = (!empty($headers['reply'])) ? $headers['reply'] : ''; 1845 | $charset = (!empty($headers['charset'])) ? $headers['charset'] : 'UTF-8'; 1846 | $x_mailer = (!empty($headers['x_mailer'])) ? $headers['x_mailer'] : 'Textpattern (com_connect)'; 1847 | 1848 | // @todo remove enforced charset in content-type declaration if it's multipart. 1849 | $header_string = 'From: ' . $headers['from'] . 1850 | ($reply ? ($sep . 'Reply-To: ' . $reply) : '') . 1851 | $sep . 'X-Mailer: ' . $x_mailer . 1852 | $sep . 'X-Originating-IP: ' . com_connect_strip((!empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] . ' via ' : '') . $_SERVER['REMOTE_ADDR']) . 1853 | $sep . 'Content-Transfer-Encoding: ' . $xfer_encoding . 1854 | $sep . 'Content-Type: ' . $content_type . (strpos($content_type, 'boundary=') !== false ? '' : '; charset="' . $charset . '"'); 1855 | 1856 | // Remove all the header entries that have already been handled. 1857 | unset( 1858 | $headers['separator'], 1859 | $headers['xfer_encoding'], 1860 | $headers['content_type'], 1861 | $headers['reply'], 1862 | $headers['charset'], 1863 | $headers['x_mailer'], 1864 | $headers['from'] 1865 | ); 1866 | 1867 | // Any remaining headers set by plugins are appended as-is. 1868 | foreach ($headers as $name => $value) { 1869 | $header_string .= $sep . $name . ': ' . $value; 1870 | } 1871 | 1872 | if (is_valid_email($smtp_from)) { 1873 | if (IS_WIN) { 1874 | ini_set('sendmail_from', $smtp_from); 1875 | } elseif (!ini_get('safe_mode')) { 1876 | return mail($to, $subject, $body, $header_string, '-f'.$smtp_from); 1877 | } 1878 | } 1879 | 1880 | return mail($to, $subject, $body, $header_string); 1881 | } 1882 | 1883 | /** 1884 | * Checks if a value or values are in the haystack. 1885 | * 1886 | * @param string|array $needles Scalar or array of values to check 1887 | * @param array $haystack Set of things to compare them against 1888 | * @return bool 1889 | */ 1890 | function com_connect_in_array($needles, $haystack) 1891 | { 1892 | if (is_array($needles)) { 1893 | return (count(array_intersect($needles, $haystack)) === count($needles)); 1894 | } else { 1895 | return in_array($needles, $haystack); 1896 | } 1897 | } 1898 | 1899 | /** 1900 | * Evaluate return values from plugins. 1901 | */ 1902 | class comconnect_evaluation 1903 | { 1904 | private $status; 1905 | private $reason = array(); 1906 | 1907 | /** 1908 | * Constructor. 1909 | */ 1910 | function __construct() 1911 | { 1912 | $this->status = 0; 1913 | } 1914 | 1915 | /** 1916 | * Append the given status to the counter. 1917 | */ 1918 | function add_comconnect_status($check) 1919 | { 1920 | $this->status += $check; 1921 | } 1922 | 1923 | /** 1924 | * Append the given reason to the array. 1925 | */ 1926 | function add_comconnect_reason($reason) 1927 | { 1928 | $this->reason[] = $reason; 1929 | } 1930 | 1931 | /** 1932 | * Fetch the current evaluator status. 1933 | */ 1934 | function get_comconnect_status() 1935 | { 1936 | return $this->status; 1937 | } 1938 | 1939 | /** 1940 | * Fetch the current evaluator reason. 1941 | */ 1942 | function get_comconnect_reason() 1943 | { 1944 | if (empty($this->reason)) { 1945 | $this->reason[] = gTxt('com_connect_spam'); 1946 | } 1947 | 1948 | return join(br, $this->reason); 1949 | } 1950 | } 1951 | 1952 | /** 1953 | * Evaluator singleton for checking return values from plugins. 1954 | */ 1955 | function &get_comconnect_evaluator() 1956 | { 1957 | static $instance; 1958 | 1959 | if (!isset($instance)) { 1960 | $instance = new comconnect_evaluation(); 1961 | } 1962 | 1963 | return $instance; 1964 | } 1965 | 1966 | /** 1967 | * Convert the given label to a suitably unique name. 1968 | * 1969 | * @param string $label Label to convert to name. 1970 | */ 1971 | function com_connect_label2name($label) 1972 | { 1973 | $label = trim($label); 1974 | 1975 | if (strlen($label) == 0) { 1976 | return 'invalid'; 1977 | } 1978 | 1979 | if (strlen($label) <= 32 && preg_match('/^[a-zA-Z][A-Za-z0-9:_-]*$/', $label)) { 1980 | return $label; 1981 | } else { 1982 | return 'q' . md5($label); 1983 | } 1984 | } 1985 | 1986 | /** 1987 | * Store the given names/values in the global arrays. 1988 | * 1989 | * @param string $name Parameter name 1990 | * @param string $label Parameter label 1991 | * @param string $value Parameter value 1992 | */ 1993 | function com_connect_store($name, $label, $value) 1994 | { 1995 | global $com_connect_form, $com_connect_labels, $com_connect_values; 1996 | 1997 | $label = (empty($label)) ? $name : $label; 1998 | $com_connect_form[$label] = $value; 1999 | $com_connect_labels[$name] = $label; 2000 | $com_connect_values[$name] = $value; 2001 | } 2002 | 2003 | /** 2004 | * Override the language strings if necessary. 2005 | * 2006 | * @param string $lang Language designator (e.g. fr-fr) 2007 | * @return array Partial language array to merge with current loaded strings 2008 | */ 2009 | function com_connect_load_lang($lang = LANG) 2010 | { 2011 | $out = array(); 2012 | 2013 | if ($lang != LANG) { 2014 | $rs = safe_rows("name, data", 'txp_lang', "lang = '" . doSlash($lang) . "' AND name like 'com\_connect\_%'"); 2015 | 2016 | if (!empty($rs)) { 2017 | foreach ($rs as $a) { 2018 | $out[$a['name']] = $a['data']; 2019 | } 2020 | } 2021 | } 2022 | 2023 | return $out; 2024 | } 2025 | 2026 | /** 2027 | * Return the value of the given attribute, by name or its label. 2028 | * 2029 | * @param array $atts Attribute to return 2030 | * @return string 2031 | */ 2032 | function com_connect_value($atts) 2033 | { 2034 | global $com_connect_values, $com_connect_form, $com_connect_item; 2035 | 2036 | extract(lAtts(array( 2037 | 'break' => ', ', 2038 | 'class' => '', 2039 | 'label' => '', 2040 | 'name' => '', 2041 | 'wraptag' => '', 2042 | ), $atts)); 2043 | 2044 | $str = ''; 2045 | 2046 | if (empty($name) && !empty($com_connect_item)) { 2047 | $name = $com_connect_item; 2048 | } 2049 | 2050 | if ($name) { 2051 | $str = isset($com_connect_values[$name]) ? $com_connect_values[$name] : ''; 2052 | } elseif ($label) { 2053 | $str = isset($com_connect_form[$label]) ? $com_connect_form[$label] : ''; 2054 | } 2055 | 2056 | $str = doArray($str, 'trim'); 2057 | 2058 | return doWrap($str, $wraptag, $break, $class); 2059 | } 2060 | 2061 | /** 2062 | * Return the label for the given attribute. 2063 | * 2064 | * @param array $atts Attribute name to return 2065 | * @return string 2066 | */ 2067 | function com_connect_label($atts) 2068 | { 2069 | global $com_connect_labels, $com_connect_item; 2070 | 2071 | extract(lAtts(array( 2072 | 'name' => '', 2073 | ), $atts)); 2074 | 2075 | if (empty($name) && !empty($com_connect_item)) { 2076 | $name = $com_connect_item; 2077 | } 2078 | 2079 | if ($name) { 2080 | return isset($com_connect_labels[$name]) ? $com_connect_labels[$name] : ''; 2081 | } 2082 | 2083 | return ''; 2084 | } 2085 | 2086 | /** 2087 | * Conditional tag for checking variable conditions. 2088 | * 2089 | * @param array $atts Attributes to check 2090 | * @param string $thing Tag's container content 2091 | * @return string 2092 | */ 2093 | function com_connect_if($atts, $thing = '') 2094 | { 2095 | global $com_connect_item; 2096 | 2097 | extract(lAtts(array( 2098 | 'label' => '', 2099 | 'name' => '', 2100 | 'value' => null, 2101 | ), $atts)); 2102 | 2103 | if (empty($label) && empty($name) && !empty($com_connect_item)) { 2104 | $name = $com_connect_item; 2105 | } 2106 | 2107 | $val = com_connect_value(array( 2108 | 'label' => $label, 2109 | 'name' => $name, 2110 | )); 2111 | 2112 | if ($val) { 2113 | $cond = ($value === null || $val == $value); 2114 | } else { 2115 | $cond = false; 2116 | } 2117 | 2118 | return parse($thing, $cond); 2119 | } 2120 | 2121 | /** 2122 | * Iterate over the submitted fields 2123 | * 2124 | * @param array $atts Tag attributes 2125 | * @param string $thing Container content 2126 | * @return HTML 2127 | */ 2128 | function com_connect_fields($atts, $thing = '') 2129 | { 2130 | global $com_connect_labels, $com_connect_item; 2131 | 2132 | extract(lAtts(array( 2133 | 'break' => ', ', 2134 | 'class' => '', 2135 | 'label' => '', 2136 | 'name' => '', 2137 | 'wraptag' => '', 2138 | ), $atts)); 2139 | 2140 | $out = array(); 2141 | 2142 | $labels = do_list($label); 2143 | $names = do_list($name); 2144 | 2145 | foreach ($com_connect_labels as $nm => $lbl) { 2146 | if ((empty($label) && empty($name)) || ($label && in_array($lbl, $labels)) || ($name && in_array($nm, $names))) { 2147 | $com_connect_item = $nm; 2148 | $out[] = parse($thing); 2149 | } 2150 | } 2151 | 2152 | $com_connect_item = null; 2153 | 2154 | return doWrap($out, $wraptag, $break, $class); 2155 | } 2156 | # --- END PLUGIN CODE --- 2157 | if (0) { 2158 | ?> 2159 | 3245 | 3248 | --------------------------------------------------------------------------------