4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
5 * Copyright (C) 2002-2007 The Nucleus Group
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 * (see nucleus/documentation/index.html#license for more info)
14 * A class representing a single comment
16 * @license http://nucleuscms.org/license.txt GNU General Public License
17 * @copyright Copyright (C) 2002-2007 The Nucleus Group
18 * @version $Id: COMMENT.php 1844 2012-05-13 11:14:38Z sakamocchi $
23 * Comment::getComment()
24 * Returns the requested comment
27 * @param integer $commentid id for comment
28 * @return array comment information
31 static function getComment($commentid)
33 $query = 'SELECT cnumber AS commentid,'
38 . ' cmember AS memberid,'
44 . ' FROM %s LEFT OUTER JOIN %s ON cmember = mnumber'
45 . ' WHERE cnumber = %d;';
47 $query = sprintf($query, sql_table('comment'), sql_table('member'), (integer) $commentid);
48 $aCommentInfo = DB::getRow($query);
52 $aCommentInfo['timestamp'] = strtotime($aCommentInfo['ctime']);
60 * Prepares a comment to be saved
63 * @param array $comment comment data
64 * @return array comment date
67 static function prepare($comment)
69 $comment['user'] = strip_tags($comment['user']);
70 $comment['userid'] = strip_tags($comment['userid']);
71 $comment['email'] = strip_tags($comment['email']);
73 // remove newlines from user; remove quotes and newlines from userid and email; trim whitespace from beginning and end
74 $comment['user'] = trim(strtr($comment['user'], "\n", ' ') );
75 $comment['userid'] = trim(strtr($comment['userid'], "\'\"\n", '-- ') );
76 $comment['email'] = trim(strtr($comment['email'], "\'\"\n", '-- ') );
78 // begin if: a comment userid is supplied, but does not have an "http://" or "https://" at the beginning - prepend an "http://"
79 if ( array_key_exists('userid', $comment)
80 && !empty($comment['userid'])
81 && (i18n::strpos($comment['userid'], 'http://') !== 0)
82 && (i18n::strpos($comment['userid'], 'https://') !== 0) )
84 $comment['userid'] = 'http://' . $comment['userid'];
87 $comment['body'] = Comment::prepareBody($comment['body']);
93 * Comment::prepareBody()
94 * Prepares the body of a comment
97 * @param string $body string for comment body
98 * @return string validate string for comment body
100 static public function prepareBody($body)
102 // convert Windows and Mac style 'returns' to *nix newlines
103 $body = preg_replace("/\r\n/", "\n", $body);
104 $body = preg_replace("/\r/", "\n", $body);
106 // then remove newlines when too many in a row (3 or more newlines get converted to 1 newline)
107 $body = preg_replace("/\n{3,}/", "\n\n", $body);
109 // encode special characters as entities
110 $body = Entity::hsc($body);
112 // trim away whitespace and newlines at beginning and end
116 $body = addBreaks($body);
118 // create hyperlinks for http:// addresses
119 // there's a testcase for this in /build/testcases/urllinking.txt
120 $replace_from = array(
121 '/([^:\/\/\w]|^)((https:\/\/)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i',
122 '/([^:\/\/\w]|^)((http:\/\/|www\.)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i',
123 '/([^:\/\/\w]|^)((ftp:\/\/|ftp\.)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i',
124 '/([^:\/\/\w]|^)(mailto:(([a-zA-Z\@\%\.\-\+_])+))/i'
127 return preg_replace_callback($replace_from, array(__CLASS__, 'prepareBody_cb'), $body);
131 * Comment::createLinkCode()
132 * Creates a link code for unlinked URLs with different protocols
135 * @param string $pre Prefix of comment
136 * @param string $url URL
137 * @param string $protocol http, mailto and so on
138 * @return string string including anchor element and child text
140 static private function createLinkCode($pre, $url, $protocol = 'http')
144 // it's possible that $url ends contains entities we don't want,
145 // since htmlspecialchars is applied _before_ URL linking
146 // move the part of URL, starting from the disallowed entity to the 'post' link part
147 $aBadEntities = array('"', '>', '<');
148 foreach ( $aBadEntities as $entity )
150 $pos = i18n::strpos($url, $entity);
154 $post = i18n::substr($url, $pos) . $post;
155 $url = i18n::substr($url, 0, $pos);
159 // remove entities at end (&&&&)
160 if ( preg_match('/(&\w+;)+$/i', $url, $matches) )
162 $post = $matches[0] . $post; // found entities (1 or more)
163 $url = i18n::substr($url, 0, i18n::strlen($url) - i18n::strlen($post) );
166 // move ending comma from url to 'post' part
167 if ( i18n::substr($url, i18n::strlen($url) - 1) == ',' )
169 $url = i18n::substr($url, 0, i18n::strlen($url) - 1);
173 if ( !preg_match('#^' . $protocol . '://#', $url) )
175 $linkedUrl = $protocol . ( ($protocol == 'mailto') ? ':' : '://') . $url;
182 if ( $protocol != 'mailto' )
184 $displayedUrl = $linkedUrl;
188 $displayedUrl = $url;
191 return $pre . '<a href="' . $linkedUrl . '" rel="nofollow">' . Entity::hsc(Entity::shorten($displayedUrl,30,'...')) . '</a>' . $post;
195 * Comment::prepareBody_cb()
196 * This method is a callback for creating link codes
198 * @param array $match elements for achor
199 * @return string including anchor element and child text
202 static public function prepareBody_cb($match)
204 if ( !preg_match('/^[a-z]+/i', $match[2], $protocol) )
209 switch( strtolower($protocol[0]) )
212 return self::createLinkCode($match[1], $match[2], 'https');
216 return self::createLinkCode($match[1], $match[2], 'ftp');
220 return self::createLinkCode($match[1], $match[3], 'mailto');
224 return self::createLinkCode($match[1], $match[2], 'http');