TikiDB($db);
$this->now = (int) date('U');
}
/*shared*/
function httprequest($url, $reqmethod = "GET") {
global $prefs;
// test url :
// rewrite url if sloppy # added a case for https urls
if ( (substr($url,0,7) <> "http://") and
(substr($url,0,8) <> "https://")
) {
$url = "http://" . $url;
}
// (cdx) params for HTTP_Request.
// The timeout may be defined by a DEFINE("HTTP_TIMEOUT",5) in some file...
$aSettingsRequest=array("method"=>$reqmethod,"timeout"=>5);
if (substr_count($url, "/") < 3) {
$url .= "/";
}
//handle url embedded user:pass
$spliturl=parse_url($url);
if(!empty($spliturl['user']) && !empty($spliturl['pass'])) {
$aSettingsRequest["pass"]=$spliturl['pass'];
$aSettingsRequest["user"]=$spliturl['user'];
$url=str_replace($spliturl['user'].":".$spliturl['pass']."@", null, $url);
}
if (!preg_match("/^[-_a-zA-Z0-9:\/\.\?&;=\+~%,]*$/",$url)) return false;
// Proxy settings
if ($prefs['use_proxy'] == 'y') {
$aSettingsRequest["proxy_host"]=$prefs['proxy_host'];
$aSettingsRequest["proxy_port"]=$prefs['proxy_port'];
}
include_once ('lib/pear/HTTP/Request.php');
$req = &new HTTP_Request($url, $aSettingsRequest);
$data="";
// (cdx) return false when can't connect
// I prefer throw a PEAR_Error. You decide ;)
if (PEAR::isError($oError=$req->sendRequest())) {
return(false);
/* Please people, don't use fopen. It's potentially unsafe
* because if any form does not check the url, you can upload
* /etc/passwd and other file from the local host.
* it's also more safe to use httprequest, because the admin can set
* a proxy so that noone can upload files in tiki from behind a
* firewall (safes the net where tiki runs in).
$fp = fopen($url, "r");
if ($fp) {
$data = '';
while(!feof($fp)) {
$data .= fread($fp,4096);
}
fclose ($fp);
}
if ($data =="") return false;
*/
} else {
$data = $req->getResponseBody();
}
return $data;
}
/*shared*/
function get_dsn_by_name($name) {
if ($name == 'local') {
return true;
}
return $this->getOne("select `dsn` from `tiki_dsn` where `name`='$name'");
}
/* convert data to iso-8601 format */
// used for atom export. date() use is okay, as we use server timezone in such case
function iso_8601 ($timestamp) {
$main_date = $this->date_format("%Y-%m-%d\T%H:%M:%S", $timestamp);
$tz = $this->date("%O", $timestamp);
$return = $main_date . $tz;
return $return;
}
/*shared*/
// Returns IP address or if 127.0.0.1 looks for a proxy address
function get_ip_address() {
$ip = "127.0.0.1"; // assume localhost
if (isset($_SERVER["REMOTE_ADDR"])) {
$ip = $_SERVER["REMOTE_ADDR"];
}
if ($ip == "127.0.0.1") {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$fwips = explode(',', $_SERVER["HTTP_X_FORWARDED_FOR"]);
$ip = $fwips[0]; // There may be several but using first IP
// This might need improvement for configurations with multiple proxies.
}
}
return $ip;
}
/*shared*/
function check_rules($user, $section) {
// Admin is never banned
if ($user == 'admin')
return false;
$ips = $this->get_ip_address();
$query = "select tb.`message`,tb.`user`,tb.`ip1`,tb.`ip2`,tb.`ip3`,tb.`ip4`,tb.`mode` from `tiki_banning` tb, `tiki_banning_sections` tbs where tbs.`banId`=tb.`banId` and tbs.`section`=? and ( (tb.`use_dates` = ?) or (tb.`date_from` <= ? and tb.`date_to` >= ?))";
$result = $this->query($query,array($section,'n',(int)$this->now,(int)$this->now));
while ($res = $result->fetchRow()) {
if (!$res['message']) {
$res['message'] = tra('You are banned from'). ':' . $section;
}
if ($user && $res['mode'] == 'user') {
// check user
$pattern = '/' . $res['user'] . '/';
if (preg_match($pattern, $user)) {
return $res['message'];
}
} else {
// check ip
if (count($ips) == 4) {
if (($ips[0] == $res['ip1'] || $res['ip1'] == '*') && ($ips[1] == $res['ip2'] || $res['ip2'] == '*')
&& ($ips[2] == $res['ip3'] || $res['ip3'] == '*') && ($ips[3] == $res['ip4'] || $res['ip4'] == '*')) {
return $res['message'];
}
}
}
}
return false;
}
/*shared*/
function replace_note($user, $noteId, $name, $data, $parse_mode = null) {
$size = strlen($data);
if ($noteId) {
$query = "update `tiki_user_notes` set `name` = ?, `data` = ?, `size` = ?, `lastModif` = ?, `parse_mode` = ? where `user`=? and `noteId`=?";
$this->query($query,array($name,$data,(int)$size,(int)$this->now,$parse_mode,$user,(int)$noteId));
} else {
$query = "insert into `tiki_user_notes`(`user`,`noteId`,`name`,`data`,`created`,`lastModif`,`size`,`parse_mode`) values(?,?,?,?,?,?,?,?)";
$this->query($query,array($user,(int)$noteId,$name,$data,(int)$this->now,(int)$this->now,(int)$size,$parse_mode));
$noteId = $this->getOne( "select max(`noteId`) from `tiki_user_notes` where `user`=? and `name`=? and `created`=?",array($user,$name,(int)$this->now));
}
return $noteId;
}
function list_watches($offset, $maxRecords, $sort_mode, $find) {
$mid = '';
$mid2 = '';
$bindvars = $bindvars1 = $bindvars2 = array();
if ($find) {
$mid = ' where `event` like ? or `email` like ? or `user` like ? or `object` like ? or `type` like ?';
$mid2 = ' where `event` like ? or `group` like ? or `object` like ? or `type` like ?';
$bindvars1 = array("%$find%", "%$find%", "%$find%", "%$find%", "%$find%");
$bindvars2 = array("%$find%", "%$find%", "%$find%", "%$find%");
}
$query = "select 'user' as watchtype, `watchId`, `user`, `event`, `object`, `title`, `type`, `url`, `email` from `tiki_user_watches` $mid
UNION ALL
select 'group' as watchtype, `watchId`, `group`, `event`, `object`, `title`, `type`, `url`, '' as `email`
from `tiki_group_watches` $mid2
order by ".$this->convert_sortmode($sort_mode);
$query_cant = 'select count(*) from `tiki_user_watches` '.$mid;
$query_cant2 = 'select count(*) from `tiki_group_watches` '. $mid2;
$result = $this->query($query, array_merge($bindvars1, $bindvars2), $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars1) + $this->getOne($query_cant2, $bindvars2);
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/*shared*/
function add_user_watch($user, $event, $object, $type, $title, $url, $email='') {
if (empty($email)) {
global $userlib;
$email = $userlib->get_user_email($user);
}
$this->remove_user_watch( $user, $event, $object, $type );
$query = "insert into `tiki_user_watches`(`user`,`event`,`object`,`email`,`type`,`title`,`url`) ";
$query.= "values(?,?,?,?,?,?,?)";
$this->query($query,array($user,$event,$object,$email,$type,$title,$url));
return true;
}
function add_group_watch($group, $event, $object, $type, $title, $url) {
$this->remove_group_watch( $group, $event, $object, $type );
$query = "insert into `tiki_group_watches`(`group`,`event`,`object`,`type`,`title`,`url`) ";
$query.= "values(?,?,?,?,?,?)";
$this->query($query,array($group,$event,$object,$type,$title,$url));
return true;
}
/*shared*/
function remove_user_watch_by_id($id) {
$query = "delete from `tiki_user_watches` where `watchId`=?";
$this->query($query,array($id));
}
function remove_group_watch_by_id($id) {
$query = "delete from `tiki_group_watches` where `watchId`=?";
$this->query($query,array($id));
}
/*shared*/
function remove_user_watch($user, $event, $object, $type = 'wiki page') {
$query = "delete from `tiki_user_watches` where ".$this->convert_binary()." `user`=? and `event`=? and `object`=? and `type` = ?";
$this->query($query,array($user,$event,$object,$type));
}
function remove_group_watch($group, $event, $object, $type = 'wiki page') {
$query = "delete from `tiki_group_watches` where ".$this->convert_binary()." `group`=? and `event`=? and `object`=? and `type` = ?";
$this->query($query,array($group,$event,$object,$type));
}
/*shared*/
function get_user_watches($user, $event = '') {
$mid = '';
$bindvars=array($user);
if ($event) {
$mid = " and `event`=? ";
$bindvars[]=$event;
}
$query = "select * from `tiki_user_watches` where ".$this->convert_binary()." `user`=? $mid";
$result = $this->query($query,$bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
return $ret;
}
/*shared*/
function get_watches_events() {
$query = "select distinct `event` from `tiki_user_watches`";
$result = $this->query($query,array());
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res['event'];
}
return $ret;
}
/*shared*/
function user_watches($user, $event, $object, $type) {
if (is_array($event)) {
$query = "select `event` from `tiki_user_watches` where `user`=? and `object`=? and `type`=? and `event` in (".implode(',',array_fill(0, count($event),'?')).")";
$result = $this->query($query, array_merge(array($user,$object,$type),$event));
if (!$result->numRows()) {
return false;
}
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res['event'];
}
return $ret;
} else {
$query = "select count(*) from `tiki_user_watches` where `user`=? and `object`=? and `type`=? and `event`=? ";
return $this->getOne($query,array($user,$object,$type,$event));
}
}
function get_groups_watching( $type, $object, $event ) {
$result = $this->query( 'SELECT `group` FROM tiki_group_watches WHERE object = ? AND type = ? AND event = ?',
array( $object, $type, $event ) );
$groups = array();
while( $row = $result->fetchRow() ) {
$groups[] = $row['group'];
}
return $groups;
}
/*shared*/
function get_user_event_watches($user, $event, $object) {
$query = "select * from `tiki_user_watches` where `user`=? and `event`=? and `object`=?";
$result = $this->query($query,array($user,$event,$object));
if (!$result->numRows())
return false;
$res = $result->fetchRow();
return $res;
}
/*shared*/
function get_event_watches($event, $object, $info=null) {
global $prefs, $dbTiki;
$ret = array();
$where = array();
$mid = '';
if( $prefs['feature_user_watches_translations'] == 'y' && $event == 'wiki_page_changed') {
// If $prefs['feature_user_watches_translations'] is turned on, also look for
// pages in a translation group.
$mid = "`event`=?";
$bindvars[] = $event;
global $multilinguallib;
include_once("lib/multilingual/multilinguallib.php");
$page_info = $this->get_page_info( $object );
$pages = $multilinguallib->getTranslations('wiki page', $page_info['page_id'], $object, '' );
foreach ($pages as $page) {
$mids[] = "`object`=?";
$bindvars[] = $page['objName'];
}
$mid .= 'and ('.implode(' or ', $mids).')';
} elseif ( $prefs['feature_user_watches_translations'] == 'y'
&& $event == 'wiki_page_created' ) {
$page_info = $this->get_page_info( $object );
$mid = "`event`='wiki_page_in_lang_created' and `object`=? and `type`='lang'";
$bindvars[] = $page_info['lang'];
} elseif ($event == 'forum_post_topic') {
$mid = "(`event`=? or `event`=?) and `object`=?";
$bindvars[] = $event;
$bindvars[] = 'forum_post_topic_and_thread';
$bindvars[] = $object;
} elseif ($event == 'forum_post_thread') {
$mid = "(`event`=? and `object`=?) or ( `event`=? and `object`=?)";
$bindvars[] = $event;
$bindvars[] = $object;
$bindvars[] = 'forum_post_topic_and_thread';
$forumId = $info['forumId'];
$bindvars[] = $forumId;
} else {
$mid = "`event`=? and `object`=?";
$bindvars[] = $event;
$bindvars[] = $object;
}
// Obtain the list of watches on event/object for user watches
// Union obtains all users member of groups being watched
// Distinct union insures there are no duplicates
$query = "select tuw.*, tup1.`value` as language, tup2.`value` as mailCharset from `tiki_user_watches` tuw
left join `tiki_user_preferences` tup1 on (tup1.`user`=tuw.`user` and tup1.`prefName`='language')
left join `tiki_user_preferences` tup2 on (tup2.`user`=tuw.`user` and tup2.`prefName`='mailCharset')
where $mid
UNION DISTINCT
select tgw.watchId, uu.login, tgw.event, tgw.object, tgw.title, tgw.type, tgw.url, uu.email,
tup1.value as language, tup2.value as mailCharset
from
tiki_group_watches tgw
inner join users_usergroups ug on tgw.`group` = ug.groupName
inner join users_users uu on ug.userId = uu.userId and uu.email is not null and uu.email <> ''
left join `tiki_user_preferences` tup1 on (tup1.`user`=uu.`login` and tup1.`prefName`='language')
left join `tiki_user_preferences` tup2 on (tup2.`user`=uu.`login` and tup2.`prefName`='mailCharset')
where $mid
";
$result = $this->query($query,array_merge( $bindvars, $bindvars ));
if ($result->numRows()) {
while ($res = $result->fetchRow()) {
switch($event) {
case 'wiki_page_changed':
case 'wiki_page_created':
$res['perm']=($this->user_has_perm_on_object($res['user'],$object,'wiki page','tiki_p_view') ||
$this->user_has_perm_on_object($res['user'],$object,'wiki page','tiki_p_admin_wiki'));
break;
case 'tracker_modified':
$res['perm'] = $this->user_has_perm_on_object($res['user'],$object,'tracker','tiki_p_view_trackers');
break;
case 'tracker_item_modified':
$res['perm'] = $this->user_has_perm_on_object($res['user'],$info['trackerId'],'tracker','tiki_p_view_trackers');
break;
case 'blog_post':
$res['perm']=($this->user_has_perm_on_object($res['user'],$object,'blog','tiki_p_read_blog') ||
$this->user_has_perm_on_object($res['user'],$object,'blog','tiki_p_admin_blog'));
break;
case 'map_changed':
$res['perm']=$this->user_has_perm_on_object($res['user'],$object,'map','tiki_p_map_view');
break;
case 'forum_post_topic':
$res['perm']=($this->user_has_perm_on_object($res['user'],$object,'forum','tiki_p_forum_read') ||
$this->user_has_perm_on_object($res['user'],$object,'forum','tiki_p_admin_forum'));
break;
case 'forum_post_thread':
$res['perm']=($this->user_has_perm_on_object($res['user'],$forumId,'forum','tiki_p_forum_read') ||
$this->user_has_perm_on_object($res['user'],$object,'forum','tiki_p_admin_forum'));
break;
case 'file_gallery_changed':
$res['perm']=($this->user_has_perm_on_object($res['user'],$object,'file gallery','tiki_p_view_file_gallery') ||
$this->user_has_perm_on_object($res['user'],$object,'file gallery','tiki_p_download_files'));
break;
case 'article_submitted':
case 'topic_article_created':
case 'article_edited':
case 'topic_article_edited':
case 'article_deleted':
case 'topic_article_deleted':
global $userlib, $topicId;
$res['perm']= ($userlib->user_has_permission($res['user'],'tiki_p_read_article') &&
(empty($topicId) || $this->user_has_perm_on_object($res['user'],$topicId,'topic','tiki_p_topic_read')));
break;
case 'calendar_changed':
$res['perm']= $this->user_has_perm_on_object($res['user'],$object,'calendar','tiki_p_view_calendar');
break;
case 'image_gallery_changed':
$res['perm'] = $this->user_has_perm_on_object($res['user'],$object,'image gallery','tiki_p_view_image_gallery');
break;
case 'category_changed':
global $categlib;
$res['perm']= $categlib->has_view_permission($res['user'],$object);
break;
default:
// for security we deny all others.
$res['perm']=FALSE;
break;
}
if($res['perm']) {
$ret[] = $res;
}
}
}
// Also include users that are watching a category to which this object belongs to.
if ( $event != 'category_changed' ) {
if ($prefs['feature_categories'] == 'y') {
global $categlib; require_once('lib/categories/categlib.php');
$objectType="";
switch($event) {
case 'wiki_page_changed': $objectType="wiki page"; break;
case 'blog_post': $objectType="blog"; break;
case 'map_changed': $objectType="map_changed"; break;
case 'forum_post_topic': $objectType="forum"; break;
case 'forum_post_thread': $objectType="forum"; break;
case 'file_gallery_changed': $objectType="file gallery"; break;
case 'article_submitted': $objectType="topic"; break;
case 'image_gallery_changed': $objectType="image gallery"; break;
case 'tracker_modified': $objectType="tracker"; break;
case 'tracker_item_modified': $objectType="tracker"; break;
case 'calendar_changed': $objectType="calendar"; break;
}
if ( $objectType != "") {
// If a forum post was changed, check the categories of the forum.
if ( $event == "forum_post_thread" ) {
include_once ("lib/commentslib.php");
global $commentslib;
$object = $commentslib->get_comment_forum_id($object);
}
// If a tracker item was changed, check the categories of the tracker.
if ( $event == "tracker_item_modified" ) {
include_once ("lib/trackers/trackerlib.php");
global $trklib;
$object = $trklib->get_tracker_for_item($object);
}
$categs = $categlib->get_object_categories($objectType, $object);
foreach ($categs as $category) {
$watching_users = $this->get_event_watches('category_changed', $category);
// Add all users that are not already included
foreach ($watching_users as $wu) {
$included = false;
foreach ($ret as $item) {
if ($item['user'] == $wu['user']) {
$included = true;
}
}
if (!$included) {
$ret[] = $wu;
}
}
}
}
}
}
return $ret;
}
/*shared*/
function dir_stats() {
$aux = array();
$aux["valid"] = $this->getOne("select count(*) from `tiki_directory_sites` where `isValid`=?",array('y'));
$aux["invalid"] = $this->getOne("select count(*) from `tiki_directory_sites` where `isValid`=?",array('n'));
$aux["categs"] = $this->getOne("select count(*) from `tiki_directory_categories`",array());
$aux["searches"] = $this->getOne("select sum(`hits`) from `tiki_directory_search`",array());
$aux["visits"] = $this->getOne("select sum(`hits`) from `tiki_directory_sites`",array());
return $aux;
}
/*shared*/
function dir_list_all_valid_sites2($offset, $maxRecords, $sort_mode, $find) {
if ($find) {
$mid = " where `isValid`=? and (`name` like ? or `description` like ?)";
$bindvars=array('y','%'.$find.'%','%'.$find.'%');
} else {
$mid = " where `isValid`=? ";
$bindvars=array('y');
}
$query = "select * from `tiki_directory_sites` $mid order by ".$this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_directory_sites` $mid";
$result = $this->query($query,$bindvars,$maxRecords,$offset);
$cant = $this->getOne($query_cant,$bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/*shared*/
function get_directory($categId) {
$query = "select * from `tiki_directory_categories` where `categId`=?";
$result = $this->query($query,array($categId));
if (!$result->numRows()) return false;
$res = $result->fetchRow();
return $res;
}
/*shared*/
function user_unread_messages($user) {
$cant = $this->getOne("select count(*) from `messu_messages` where `user`=? and `isRead`=?",array($user,'n'));
return $cant;
}
/*shared*/
function get_online_users() {
if ( ! isset($this->online_users_cache) ) {
$this->update_session();
$this->online_users_cache=array();
$query = "select s.`user`, p.`value` as 'realName', `timestamp`, `tikihost` from `tiki_sessions` s left join `tiki_user_preferences` p on s.`user`<>? and s.`user` = p.`user` and p.`prefName` = 'realName' where s.`user` is not null;";
$result = $this->query($query,array(''));
$ret = array();
while ($res = $result->fetchRow()) {
$res['user_information'] = $this->get_user_preference($res['user'], 'user_information', 'public');
$res['allowMsgs'] = $this->get_user_preference($res['user'], 'allowMsgs', 'y');
$this->online_users_cache[$res['user']] = $res;
}
}
return $this->online_users_cache;
}
/*shared*/
function is_user_online($whichuser) {
if(!isset($this->online_users_cache)) {
$this->get_online_users();
}
return(isset($this->online_users_cache[$whichuser]));
}
/*shared*/
function get_user_items($user) {
$items = array();
$query = "select ttf.`trackerId`, tti.`itemId` from `tiki_tracker_fields` ttf, `tiki_tracker_items` tti, `tiki_tracker_item_fields` ttif";
$query .= " where ttf.`fieldId`=ttif.`fieldId` and ttif.`itemId`=tti.`itemId` and `type`=? and tti.`status`=? and `value`=?";
$result = $this->query($query,array('u','o',$user));
$ret = array();
while ($res = $result->fetchRow()) {
if (!$this->user_has_perm_on_object($user, $res['trackerId'], 'tracker', 'tiki_p_view_trackers')) {
continue;
}
$itemId = $res["itemId"];
$trackerId = $res["trackerId"];
// Now get the isMain field for this tracker
$fieldId = $this->getOne("select `fieldId` from `tiki_tracker_fields` ttf where `isMain`=? and `trackerId`=?",array('y',(int)$trackerId));
// Now get the field value
$value = $this->getOne("select `value` from `tiki_tracker_item_fields` where `fieldId`=? and `itemId`=?",array((int)$fieldId,(int)$itemId));
$tracker = $this->getOne("select `name` from `tiki_trackers` where `trackerId`=?",array((int)$trackerId));
$aux["trackerId"] = $trackerId;
$aux["itemId"] = $itemId;
$aux["value"] = $value;
$aux["name"] = $tracker;
if (!in_array($itemId, $items)) {
$ret[] = $aux;
$items[] = $itemId;
}
}
$groups = $this->get_user_groups($user);
foreach ($groups as $group) {
$query = "select ttf.`trackerId`, tti.`itemId` from `tiki_tracker_fields` ttf, `tiki_tracker_items` tti, `tiki_tracker_item_fields` ttif ";
$query .= " where ttf.`fieldId`=ttif.`fieldId` and ttif.`itemId`=tti.`itemId` and `type`=? and tti.`status`=? and `value`=?";
$result = $this->query($query,array('g','o',$group));
while ($res = $result->fetchRow()) {
$itemId = $res["itemId"];
$trackerId = $res["trackerId"];
// Now get the isMain field for this tracker
$fieldId = $this->getOne("select `fieldId` from `tiki_tracker_fields` ttf where `isMain`=? and `trackerId`=?",array('y',(int)$trackerId));
// Now get the field value
$value = $this->getOne("select `value` from `tiki_tracker_item_fields` where `fieldId`=? and `itemId`=?",array((int)$fieldId,(int)$itemId));
$tracker = $this->getOne("select `name` from `tiki_trackers` where `trackerId`=?",array((int)$trackerId));
$aux["trackerId"] = $trackerId;
$aux["itemId"] = $itemId;
$aux["value"] = $value;
$aux["name"] = $tracker;
if (!in_array($itemId, $items)) {
$ret[] = $aux;
$items[] = $itemId;
}
}
}
return $ret;
}
/*shared*/
function get_actual_content($fieldvalue) {
$query = 'SELECT `data` FROM `tiki_programmed_content` WHERE `contentId`=? AND `publishDate`<=? ORDER BY `publishDate` DESC';
$data = $this->getOne($query, array((int)$fieldvalue, $this->now));
return $data;
}
function get_actual_content_by_label($fieldvalue) {
$query = 'SELECT tpc.`data`'
.' FROM `tiki_programmed_content` AS tpc, `tiki_content` AS tc'
.' WHERE tpc.`contentId` = tc.`contentId` AND tc.`contentLabel`=? AND `publishDate`<=? ORDER BY `publishDate` DESC';
$data = $this->getOne($query, array($fieldvalue, $this->now));
return $data;
}
/*shared*/
function get_quiz($quizId) {
$query = "select * from `tiki_quizzes` where `quizId`=?";
$result = $this->query($query,array((int) $quizId));
if (!$result->numRows())
return false;
$res = $result->fetchRow();
return $res;
}
function compute_quiz_stats() {
$query = "select `quizId` from `tiki_user_quizzes`";
$result = $this->query($query,array());
while ($res = $result->fetchRow()) {
$quizId = $res["quizId"];
$quizName = $this->getOne("select `name` from `tiki_quizzes` where `quizId`=?",array((int)$quizId));
$timesTaken = $this->getOne("select count(*) from `tiki_user_quizzes` where `quizId`=?",array((int)$quizId));
$avgpoints = $this->getOne("select avg(`points`) from `tiki_user_quizzes` where `quizId`=?",array((int)$quizId));
$maxPoints = $this->getOne("select max(`maxPoints`) from `tiki_user_quizzes` where `quizId`=?",array((int)$quizId));
$avgavg = ($maxPoints != 0) ? $avgpoints / $maxPoints * 100 : 0.0;
$avgtime = $this->getOne("select avg(`timeTaken`) from `tiki_user_quizzes` where `quizId`=?",array((int)$quizId));
$querydel = "delete from `tiki_quiz_stats_sum` where `quizId`=?";
$resultdel = $this->query($querydel,array((int)$quizId),-1,-1,false);
$query2 = "insert into `tiki_quiz_stats_sum`(`quizId`,`quizName`,`timesTaken`,`avgpoints`,`avgtime`,`avgavg`)
values(?,?,?,?,?,?)";
$result2 = $this->query($query2,array((int)$quizId,$quizName,(int)$timesTaken,(float)$avgpoints,$avgtime,$avgavg));
}
}
function list_quizzes($offset, $maxRecords, $sort_mode = 'name_desc', $find) {
$bindvars = array();
$mid = '';
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where (`name` like ? or `description` like ?)";
$bindvars = array($findesc, $findesc);
}
$query = "select `quizId` from `tiki_quizzes` $mid";
$result = $this->query($query, $bindvars);
$res = $ret = $retids = array();
$n = 0;
while ( $res = $result->fetchRow() ) {
global $user;
$objperm = $this->get_perm_object($res['quizId'], 'quizzes', '', false);
if ( $objperm['tiki_p_take_quiz'] == 'y' ) {
if ( ($maxRecords == -1) || (($n >= $offset) && ($n < ($offset + $maxRecords))) ) {
$retids[] = $res['quizId'];
}
$n++;
}
}
if ($n > 0) {
$query = 'select * from `tiki_quizzes` where quizId in (' . implode(',', $retids) . ') order by ' . $this->convert_sortmode($sort_mode);
$result = $this->query($query);
while ( $res = $result->fetchRow() ) {
$res['questions'] = $this->getOne('select count(*) from `tiki_quiz_questions` where `quizId`=?', array( (int) $res['quizId'] ));
$res['results'] = $this->getOne('select count(*) from `tiki_quiz_results` where `quizId`=?', array( (int) $res['quizId'] ));
$ret[] = $res;
}
}
$retval['data'] = $ret;
$retval['cant'] = $n;
return $retval;
}
/*shared*/
function list_quiz_sum_stats($offset, $maxRecords, $sort_mode, $find) {
$this->compute_quiz_stats();
if ($find) {
$findesc = '%' . $find . '%';
$mid = ' where `quizName` like ? ';
$bindvars=array($findesc);
} else {
$mid = " ";
$bindvars=array();
}
$query = "select * from `tiki_quiz_stats_sum` $mid order by " . $this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_quiz_stats_sum` $mid";
$result = $this->query($query,$bindvars,$maxRecords,$offset);
$cant = $this->getOne($query_cant,$bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
function get_tracker($trackerId) {
$query = "select * from `tiki_trackers` where `trackerId`=?";
$result = $this->query($query,array((int) $trackerId));
if (!$result->numRows()) return false;
$res = $result->fetchRow();
return $res;
}
/*shared*/
function list_trackers($offset=0, $maxRecords=-1, $sort_mode='name_asc', $find='') {
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where (`name` like ? or `description` like ?)";
$bindvars=array($findesc,$findesc);
} else {
$mid = "";
$bindvars=array();
}
$query = "select * from `tiki_trackers` $mid order by ".$this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_trackers` $mid";
$result = $this->query($query,$bindvars,$maxRecords,$offset);
$cant = $this->getOne($query_cant,$bindvars);
$ret = array();
$list = array();
while ($res = $result->fetchRow()) {
global $user;
$add=$this->user_has_perm_on_object($user,$res['trackerId'],'tracker','tiki_p_view_trackers');
if ($add) {
$qu = "select count(*) from`tiki_tracker_items` where `trackerId`=? ";
$res['items'] = $this->getOne($qu,array((int)$res['trackerId']));
$ret[] = $res;
$list[$res['trackerId']] = $res['name'];
}
}
$retval = array();
$retval["list"] = $list;
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
function list_surveys($offset, $maxRecords, $sort_mode, $find) {
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where (`name` like ? or `description` like ?)";
$bindvars=array($findesc, $findesc);
} else {
$mid = '';
$bindvars=array();
}
$query = "select `surveyId` from `tiki_surveys` $mid";
$result = $this->query($query, $bindvars);
$res = $ret = $retids = array();
$n = 0;
while ( $res = $result->fetchRow() ) {
global $user;
$objperm = $this->get_perm_object( $res['surveyId'], 'survey', '', false );
if ( $objperm['tiki_p_take_survey'] ) {
if ( ($maxRecords == -1) || (($n >= $offset) && ($n < ($offset + $maxRecords))) ) {
$retids[] = $res['surveyId'];
}
$n++;
}
}
if ( $n > 0 ) {
$query = 'select * from `tiki_surveys` where `surveyId` in (' . implode(',',$retids) . ') order by ' . $this->convert_sortmode($sort_mode);
$result = $this->query($query);
while ( $res = $result->fetchRow() ) {
$res["questions"] = $this->getOne( 'select count(*) from `tiki_survey_questions` where `surveyId`=?', array( (int) $res['surveyId']) );
$ret[] = $res;
}
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $n;
return $retval;
}
/* experimental shared */
function get_item_id($trackerId,$fieldId,$value) {
$query = "select ttif.`itemId` from `tiki_tracker_items` tti, `tiki_tracker_fields` ttf, `tiki_tracker_item_fields` ttif ";
$query.= " where tti.`trackerId`=ttf.`trackerId` and ttif.`fieldId`=ttf.`fieldId` and ttf.`trackerId`=? and ttf.`fieldId`=? and ttif.`value`=?";
$itemId = $this->getOne($query,array((int) $trackerId,(int)$fieldId,$value));
return $itemId;
}
/*shared*/
function list_tracker_items($trackerId, $offset, $maxRecords, $sort_mode, $fields, $status = '', $initial = '') {
$filters = array();
if ($fields) {
$temp_max = count($fields["data"]);
for ($i = 0; $i < $temp_max; $i++) {
$fieldId = $fields["data"][$i]["fieldId"];
$filters[$fieldId] = $fields["data"][$i];
}
}
$csort_mode = '';
if (substr($sort_mode,0,2) == "f_") {
list($a,$csort_mode,$corder) = split('_',$sort_mode);
}
$trackerId = (int) $trackerId;
if ($trackerId == -1) {
$mid = " where 1=1 ";
$bindvars = array();
} else {
$mid = " where tti.`trackerId`=? ";
$bindvars = array($trackerId);
}
if ($status) {
$mid.= " and tti.`status`=? ";
$bindvars[] = $status;
}
if ($initial) {
$mid.= "and ttif.`value` like ?";
$bindvars[] = $initial.'%';
}
if (!$sort_mode) {
$temp_max = count($fields["data"]);
for ($i = 0; $i < $temp_max; $i++) {
if ($fields['data'][$i]['isMain'] == 'y') {
$csort_mode = $fields['data'][$i]['name'];
break;
}
}
}
if ($csort_mode) {
$sort_mode = $csort_mode."_desc";
$bindvars[] = $csort_mode;
$query = "select tti.*, ttif.`value` from `tiki_tracker_items` tti, `tiki_tracker_item_fields` ttif, `tiki_tracker_fields` ttf ";
$query.= " $mid and tti.`itemId`=ttif.`itemId` and ttf.`fieldId`=ttif.`fieldId` and ttf.`name`=? order by ttif.`value`";
$query_cant = "select count(*) from `tiki_tracker_items` tti, `tiki_tracker_item_fields` ttif, `tiki_tracker_fields` ttf ";
$query_cant.= " $mid and tti.`itemId`=ttif.`itemId` and ttf.`fieldId`=ttif.`fieldId` and ttf.`name`=? ";
} else {
if (!$sort_mode) {
$sort_mode = "lastModif_desc";
}
$query = "select * from `tiki_tracker_items` tti $mid order by ".$this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_tracker_items` tti $mid ";
}
$result = $this->query($query,$bindvars,$maxRecords,$offset);
$cant = $this->getOne($query_cant,$bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$fields = array();
$itid = $res["itemId"];
$query2 = "select ttif.`fieldId`,`name`,`value`,`type`,`isTblVisible`,`isMain`,`position`
from `tiki_tracker_item_fields` ttif, `tiki_tracker_fields` ttf
where ttif.`fieldId`=ttf.`fieldId` and `itemId`=? order by `position` asc";
$result2 = $this->query($query2,array((int) $res["itemId"]));
$pass = true;
$kx = "";
while ($res2 = $result2->fetchRow()) {
// Check if the field is visible!
$fieldId = $res2["fieldId"];
if (count($filters) > 0) {
if (isset($filters["$fieldId"]["value"]) and $filters["$fieldId"]["value"]) {
if ($filters["$fieldId"]["type"] == 'a' || $filters["$fieldId"]["type"] == 't') {
if (!stristr($res2["value"], $filters["$fieldId"]["value"]))
$pass = false;
} else {
if (strtolower($res2["value"]) != strtolower($filters["$fieldId"]["value"])) {
$pass = false;
}
}
}
if (ereg_replace("[^a-zA-Z0-9]","",$res2["name"]) == $csort_mode) {
$kx = $res2["value"].$itid;
}
}
$fields[] = $res2;
}
$res["field_values"] = $fields;
$res["comments"] = $this->getOne("select count(*) from `tiki_tracker_item_comments` where `itemId`=?",array((int) $itid));
if ($pass) {
$kl = $kx.$itid;
$ret["$kl"] = $res;
}
}
ksort($ret);
//$ret=$this->sort_items_by_condition($ret,$sort_mode);
$retval = array();
$retval["data"] = array_values($ret);
$retval["cant"] = $cant;
return $retval;
}
/*
* Score methods begin
*/
// All information about an event type
// shared
function get_event($event) {
$query = "select * from `tiki_score` where `event`=?";
$result = $this->query($query,array($event));
return $result->fetchRow();
}
/*
* Checks if an event should be scored and grants points to proper user
* $multiplier is for rating events, in which the score will
* be multiplied by other user's rating. Not yet used
*
* shared
*/
function score_event($user, $event_type, $id = '', $multiplier=false) {
global $scorelib,$prefs;
if (!is_object($scorelib)) {
include_once("lib/score/scorelib.php");
}
if ($user == 'admin' || !$user) {
return true;
}
$event = $scorelib->get_event($event_type);
if (!$event || !$event['score']) {
return true;
}
$score = $event['score'];
if ($multiplier) {
$score *= $multiplier;
}
if ($id || $event['expiration']) {
$expire = $event['expiration'];
$event_id = $event_type . '_' . $id;
$query = "select count(*) from `tiki_users_score` where `user`=? and `event_id`=?";
$bindvars = array($user, $event_id);
if ($expire) {
$query .= " and `expire` > ?";
$bindvars[] = time();
}
if ($this->getOne($query, $bindvars)) {
return true;
}
$query = "delete from `tiki_users_score` where `user`=? and `event_id`=?";
$this->query($query, array($user, $event_id));
$query = "insert into `tiki_users_score` (`user`, `event_id`, `expire`) values (?, ?, ?)";
$this->query($query, array($user, $event_id, time() + ($expire*60)));
}
// Perform check to make sure score does not go below 0 with negative scores
if( $prefs['fgal_prevent_negative_score'] == 'y' && strpos( $event_type, 'fgallery' ) === 0 ) {
$result = $this->query( "select userId from users_users where score + ? >= 0 and login = ?",
array( $score, $user ) );
if( ! $row = $result->fetchRow( $result ) )
return false;
}
$query = "update `users_users` set `score` = `score` + ? where `login`=?";
$event['id'] = $id; // just for debug
$this->query($query, array($score, $user));
return true;
}
// List users by best scoring
// shared
function rank_users($limit = 10, $start = 0) {
if (!$start) {
$start = "0";
}
// admin doesn't go on ranking
$query = "select `userId`, `login`, `score` from `users_users` where `login` <> 'admin' order by `score` desc";
$result = $this->query($query,array(),$limit,$start);
$ranking = array();
while ($res = $result->fetchRow()) {
$res['position'] = ++$start;
$ranking[] = $res;
}
return $ranking;
}
// Returns html tag to star corresponding to user's score
// shared
function get_star($score) {
$star = '';
$star_colors = array(0 => 'grey',
100 => 'blue',
500 => 'green',
1000 => 'yellow',
2500 => 'orange',
5000 => 'red',
10000 => 'purple');
foreach ($star_colors as $boundary => $color) {
if ($score >= $boundary) {
$star = 'star_'.$color.'.gif';
}
}
if (!empty($star)) {
$alt = sprintf(tra("%d points"), $score);
$star = " ";
}
return $star;
}
/*
* Score methods end
*/
//shared
// \todo remove all hardcoded html in get_user_avatar()
function get_user_avatar($user, $float = "") {
global $userlib;
if (empty($user))
return '';
$query = "select `login`,`avatarType`,`avatarLibName` from `users_users` where `login`=?";
$result = $this->query($query,array($user));
$res = $result->fetchRow();
if (!$res) {
return '';
}
$type = $res["avatarType"];
$libname = $res["avatarLibName"];
$ret = '';
$style = '';
if (strcasecmp($float, "left") == 0) {
$style = "style='float:left;margin-right:5px;'";
} else if (strcasecmp($float, "right") == 0) {
$style = "style='float:right;margin-left:5px;'";
}
switch ($type) {
case 'n':
$ret = '';
break;
case 'l':
$ret = "";
break;
case 'u':
$ret = "";
break;
}
return $ret;
}
/*shared*/
function get_forum_sections() {
$query = "select distinct `section` from `tiki_forums` where `section`<>?";
$result = $this->query($query,array(''));
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res["section"];
}
return $ret;
}
/* Referer stats */
/*shared*/
function register_referer($referer) {
$cant = $this->getOne("select count(*) from `tiki_referer_stats` where `referer`=?",array($referer));
if ($cant) {
$query = "update `tiki_referer_stats` set `hits`=`hits`+1,`last`=? where `referer`=?";
} else {
$query = "insert into `tiki_referer_stats`(`last`,`referer`,`hits`) values(?,?,1)";
}
$result = $this->query($query,array((int)$this->now,$referer));
}
// File attachments functions for the wiki ////
/*shared*/
function add_wiki_attachment_hit($id) {
global $prefs, $user;
if ($prefs['count_admin_pvs'] == 'y' || $user != 'admin') {
$query = "update `tiki_wiki_attachments` set `hits`=`hits`+1 where `attId`=?";
$result = $this->query($query,array((int)$id));
}
return true;
}
/*shared*/
function get_wiki_attachment($attId) {
$query = "select * from `tiki_wiki_attachments` where `attId`=?";
$result = $this->query($query,array((int)$attId));
if (!$result->numRows()) return false;
$res = $result->fetchRow();
return $res;
}
/*shared*/
/*
function get_random_image($galleryId = -1) {
$whgal = "";
$bindvars = array();
if (((int)$galleryId) != -1) {
$whgal = " where `galleryId`=? ";
$bindvars[] = (int) $galleryId;
}
$query = "select count(*) from `tiki_images` $whgal";
$cant = $this->getOne($query,$bindvars);
$ret = array();
if ($cant) {
$pick = rand(0, $cant - 1);
$query = "select `imageId` ,`galleryId`,`name` from `tiki_images` $whgal";
$result = $this->query($query,$bindvars,1,$pick);
$res = $result->fetchRow();
$ret["galleryId"] = $res["galleryId"];
$ret["imageId"] = $res["imageId"];
$ret["name"] = $res["name"];
$query = "select `name` from `tiki_galleries` where `galleryId` = ?";
$ret["gallery"] = $this->getOne($query,array((int)$res["galleryId"]));
} else {
$ret["galleryId"] = 0;
$ret["imageId"] = 0;
$ret["name"] = tra("No image yet, sorry.");
}
return ($ret);
}
*/ /* Sept */
/*shared*/
function get_gallery($id) {
$query = "select * from `tiki_galleries` where `galleryId`=?";
$result = $this->query($query,array((int) $id));
$res = $result->fetchRow();
return $res;
}
// Last visit module ////
/*shared*/
function get_news_from_last_visit($user) {
if (!$user) return false;
$last = $this->getOne("select `lastLogin` from `users_users` where `login`=?",array($user));
$ret = array();
if (!$last) {
$last = time();
}
$ret["lastVisit"] = $last;
$ret["images"] = $this->getOne("select count(*) from `tiki_images` where `created`>?",array((int)$last));
$ret["pages"] = $this->getOne("select count(*) from `tiki_pages` where `lastModif`>?",array((int)$last));
$ret["files"] = $this->getOne("select count(*) from `tiki_files` where `created`>?",array((int)$last));
$ret["comments"] = $this->getOne("select count(*) from `tiki_comments` where `commentDate`>?",array((int)$last));
$ret["users"] = $this->getOne("select count(*) from `users_users` where `registrationDate`>? and `provpass`=?",array((int)$last, ''));
$ret["trackers"] = $this->getOne("select count(*) from `tiki_tracker_items` where `lastModif`>?",array((int)$last));
$ret["calendar"] = $this->getOne("select count(*) from `tiki_calendar_items` where `lastmodif`>?",array((int)$last));
return $ret;
}
// Templates ////
/*shared*/
function list_templates($section, $offset, $maxRecords, $sort_mode, $find) {
$bindvars = array($section);
if ($find) {
$findesc = '%'.$find.'%';
$mid = " and (`content` like ?)";
$bindvars[] = $findesc;
} else {
$mid = "";
}
$query = "select `name` ,`created`,tcts.`templateId` from `tiki_content_templates` tct, `tiki_content_templates_sections` tcts ";
$query.= " where tcts.`templateId`=tct.`templateId` and `section`=? $mid order by ".$this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_content_templates` tct, `tiki_content_templates_sections` tcts ";
$query_cant.= "where tcts.`templateId`=tct.`templateId` and `section`=? $mid";
$result = $this->query($query,$bindvars,$maxRecords,$offset);
$cant = $this->getOne($query_cant,$bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$query2 = "select `section` from `tiki_content_templates_sections` where `templateId`=?";
$result2 = $this->query($query2,array((int)$res["templateId"]));
$sections = array();
while ($res2 = $result2->fetchRow()) {
$sections[] = $res2["section"];
}
$res["sections"] = $sections;
$ret[] = $res;
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/*shared*/
function get_template($templateId) {
$query = "select * from `tiki_content_templates` where `templateId`=?";
$result = $this->query($query,array((int)$templateId));
if (!$result->numRows()) return false;
$res = $result->fetchRow();
return $res;
}
// templates ////
/*shared*/
function list_games($offset, $maxRecords, $sort_mode, $find) {
$bindvars = array();
if ($find) {
$findesc = '%'.$find.'%';
$mid = " where (`gameName` like ?)";
$bindvars[] = $findesc;
} else {
$mid = "";
}
$query = "select * from `tiki_games` $mid order by ".$this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_games` $mid";
$result = $this->query($query,$bindvars,$maxRecords,$offset);
$cant = $this->getOne($query_cant,$bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$parts = explode('.', $res["gameName"]);
$res["thumbName"] = $parts[0];
$ret[] = $res;
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/*shared*/
function pick_cookie() {
$cant = $this->getOne("select count(*) from `tiki_cookies`",array());
if (!$cant) return '';
$bid = rand(0, $cant - 1);
//$cookie = $this->getOne("select `cookie` from `tiki_cookies` limit $bid,1"); getOne seems not to work with limit
$result = $this->query("select `cookie` from `tiki_cookies`",array(),1,$bid);
if ($res = $result->fetchRow()) {
$cookie = str_replace("\n", "", $res['cookie']);
return preg_replace('/^(.+?)(\s*--.+)?$/','"$1"$2',$cookie);
} else {
return "";
}
}
function get_pv_chart_data($days) {
$now = $this->make_time(0, 0, 0, $this->date_format("%m"), $this->date_format("%d"), $this->date_format("%Y"));
$dfrom = 0;
if ($days != 0) $dfrom = $now - ($days * 24 * 60 * 60);
$query = "select `day`, `pageviews` from `tiki_pageviews` where `day`<=? and `day`>=?";
$result = $this->query($query,array((int)$now,(int)$dfrom));
$ret = array();
$n = ceil($result->numRows() / 10);
$i = 0;
$xdata=array();
$ydata=array();
while ($res = $result->fetchRow()) {
if ($i % $n == 0) {
$xdata[] = $this->date_format("%e %b", $res["day"]);
} else {
$xdata = '';
}
$ydata[] = $res["pageviews"];
}
$ret['xdata']=$xdata;
$ret['ydata']=$ydata;
return $ret;
}
function add_pageview() {
$dayzero = $this->make_time(0, 0, 0, $this->date_format("%m",$this->now), $this->date_format("%d",$this->now), $this->date_format("%Y",$this->now));
$cant = $this->getOne("select count(*) from `tiki_pageviews` where `day`=?",array((int)$dayzero));
if ($cant) {
$query = "update `tiki_pageviews` set `pageviews`=`pageviews`+1 where `day`=?";
} else {
$query = "insert into `tiki_pageviews`(`day`,`pageviews`) values(?,1)";
}
$result = $this->query($query,array((int)$dayzero),-1,-1,false);
}
function get_usage_chart_data() {
$this->compute_quiz_stats();
$data['xdata'][] = tra('wiki');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_pages`',array());
$data['xdata'][] = tra('img-g');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_galleries`',array());
$data['xdata'][] = tra('file-g');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_file_galleries`',array());
$data['xdata'][] = tra('faqs');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_faqs`',array());
$data['xdata'][] = tra('quizzes');
$data['ydata'][] = $this->getOne('select sum(`timesTaken`) from `tiki_quiz_stats_sum`',array());
$data['xdata'][] = tra('arts');
$data['ydata'][] = $this->getOne('select sum(`nbreads`) from `tiki_articles`',array());
$data['xdata'][] = tra('blogs');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_blogs`',array());
$data['xdata'][] = tra('forums');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_forums`',array());
$data['xdata'][] = tra('games');
$data['ydata'][] = $this->getOne('select sum(`hits`) from `tiki_games`',array());
return $data;
}
// User assigned modules ////
/*shared*/
function get_user_login($id) {
$login = $this->getOne("select `login` from `users_users` where `userId`=?", array((int)$id));
return $login;
}
function get_user_id($u) {
// Anonymous is not in db
if ( $u == '' ) return -1;
// If we ask for the current user id and if we already know it in session
$current = ( $u == $_SESSION['u_info']['login'] );
if ( isset($_SESSION['u_info']['id']) && $current ) return $_SESSION['u_info']['id'];
// In other cases, we look in db
$id = $this->getOne("select `userId` from `users_users` where `login`=?", array($u));
$id = ($id === NULL) ? -1 : $id;
if ( $current ) $_SESSION['u_info']['id'] = $id;
return $id;
}
/*shared*/
function get_groups_all($group) {
$query = "select `groupName` from `tiki_group_inclusion` where `includeGroup`=?";
$result = $this->query($query, array($group));
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res["groupName"];
$ret2 = $this->get_groups_all($res["groupName"]);
$ret = array_merge($ret, $ret2);
}
return array_unique($ret);
}
/*shared*/
function get_included_groups($group) {
$query = "select `includeGroup` from `tiki_group_inclusion` where `groupName`=?";
$result = $this->query($query, array($group));
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res["includeGroup"];
$ret2 = $this->get_included_groups($res["includeGroup"]);
$ret = array_merge($ret, $ret2);
}
return array_unique($ret);
}
/*shared*/
function get_user_groups($user) {
global $prefs, $userlib;
if (!$user) {
$ret = array();
$ret[] = "Anonymous";
return $ret;
}
if ($prefs['feature_intertiki'] == 'y' and empty($prefs['feature_intertiki_mymaster']) and strstr($user,'@')) {
$realm = substr($user,strpos($user,'@')+1);
$user = substr($user,0,strpos($user,'@'));
if (isset($prefs['interlist'][$realm])) {
$groups = $prefs['interlist'][$realm]['groups'].',Anonymous';
return split(',',$prefs['interlist'][$realm]['groups']);
}
}
if (!isset($this->usergroups_cache[$user])) {
$userid = $this->get_user_id($user);
$query = "select `groupName` from `users_usergroups` where `userId`=?";
$result=$this->query($query,array((int) $userid));
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res["groupName"];
$included = $userlib->get_included_groups($res["groupName"]);
$ret = array_merge($ret, $included);
}
$ret[] = "Registered";
$ret[] = "Anonymous";
$ret = array_unique($ret);
$this->usergroups_cache[$user] = $ret;
return $ret;
} else {
return $this->usergroups_cache[$user];
}
}
function invalidate_usergroups_cache($user) {
unset($this->usergroups_cache[$user]);
}
function get_user_cache_id($user) {
$groups = $this->get_user_groups($user);
sort($groups, SORT_STRING);
$cacheId = implode(":", $groups);
if ($user == 'admin') {
// in this case user get permissions from no group
$cacheId = 'ADMIN:'.$cacheId;
}
return $cacheId;
}
// Functions for FAQs ////
function list_faqs($offset, $maxRecords, $sort_mode, $find) {
$mid = '';
if ( $find ) {
$findesc = '%' . $find . '%';
$mid = ' where (`title` like ? or `description` like ?)';
$bindvars = array($findesc, $findesc);
} else $bindvars = array();
$query = "select `faqId` from `tiki_faqs` $mid";
$result = $this->query($query, $bindvars);
$res = $ret = $retids = array();
$n=0;
while ( $res = $result->fetchRow() ) {
global $user;
$objperm = $this->get_perm_object($res['faqId'], 'faq', '', false);
if ($objperm['tiki_p_view_faqs'] == 'y') {
if (($maxRecords == -1) || (($n>=$offset) && ($n < ($offset + $maxRecords)))) {
$retids[] = $res['faqId'];
}
$n++;
}
}
if ($n > 0) {
$query = "select * from `tiki_faqs` where faqId in (" . implode(',',$retids) . ") order by " . $this->convert_sortmode($sort_mode);
$result = $this->query($query);
while ( $res = $result->fetchRow() ) {
$res['suggested'] = $this->getOne('select count(*) from `tiki_suggested_faq_questions` where `faqId`=?', array((int) $res['faqId']));
$res['questions'] = $this->getOne('select count(*) from `tiki_faq_questions` where `faqId`=?', array((int) $res['faqId']));
$ret[] = $res;
}
}
$retval['data'] = $ret;
$retval['cant'] = $n;
return $retval;
}
/*shared */
function get_faq($faqId) {
$query = "select * from `tiki_faqs` where `faqId`=?";
$result = $this->query($query,array((int)$faqId));
if (!$result->numRows()) return false;
$res = $result->fetchRow();
return $res;
}
// End Faqs ////
/*shared*/
function genPass() {
$length=8;
$vocales = "aeiouAEIOU";
$consonantes = "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ0123456789_";
$r = '';
for ($i = 0; $i < $length; $i++) {
if ($i % 2) {
$r .= $vocales{rand(0, strlen($vocales) - 1)};
} else {
$r .= $consonantes{rand(0, strlen($consonantes) - 1)};
}
}
return $r;
}
// generate a random string (for unsubscription code etc.)
function genRandomString($base="") {
if ($base == "") $base = $this->genPass();
$base .= microtime();
return md5($base);
}
// This function calculates the pageRanks for the tiki_pages
// it can be used to compute the most relevant pages
// according to the number of links they have
// this can be a very interesting ranking for the Wiki
// More about this on version 1.3 when we add the pageRank
// column to tiki_pages
function pageRank($loops = 16) {
$query = "select `pageName` from `tiki_pages`";
$result = $this->query($query,array());
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res["pageName"];
}
// Now calculate the loop
$pages = array();
foreach ($ret as $page) {
$val = 1 / count($ret);
$pages[$page] = $val;
// Fixed query. -rlpowell
$query = "update `tiki_pages` set `pageRank`=? where `pageName`= ?";
$result = $this->query($query, array((int)$val, $page) );
}
for ($i = 0; $i < $loops; $i++) {
foreach ($pages as $pagename => $rank) {
// Get all the pages linking to this one
// Fixed query. -rlpowell
$query = "select `fromPage` from `tiki_links` where `toPage` = ? and `fromPage` not like 'objectlink:%'";
// page rank does not count links from non-page objects TODO: full feature allowing this with options
$result = $this->query($query, array( $pagename ) );
$sum = 0;
while ($res = $result->fetchRow()) {
$linking = $res["fromPage"];
if (isset($pages[$linking])) {
// Fixed query. -rlpowell
$q2 = "select count(*) from `tiki_links` where `fromPage`= ? and `fromPage` not like 'objectlink:%'";
// page rank does not count links from non-page objects TODO: full feature allowing this with options
$cant = $this->getOne($q2, array($linking) );
if ($cant == 0) $cant = 1;
$sum += $pages[$linking] / $cant;
}
}
$val = (1 - 0.85) + 0.85 * $sum;
$pages[$pagename] = $val;
// Fixed query. -rlpowell
$query = "update `tiki_pages` set `pageRank`=? where `pageName`=?";
$result = $this->query($query, array((int)$val, $pagename) );
// Update
}
}
arsort ($pages);
return $pages;
}
// Spellchecking routine
// Parameters:
// what: what to spell check (a text)
// where: where to replace (maybe the same text)
// language: language to use
// element: element where the text is going to be replaced (a textarea or similar)
/*shared*/
// \todo replace the hardcoded html by smarty template
function spellcheckreplace($what, $where, $language, $element) {
global $smarty,$headerlib;
$words = preg_split("/\s/", $what);
foreach ($words as $word) {
if (preg_match("/^[A-Z]?[a-z]+$/", $word) && strlen($word) > 1) {
$result = $this->spellcheckword($word, $language);
if (count($result) > 0) {
// Replace the word with a warning color in the edit_data
// Prepare the replacement
$sugs = $result[$word];
$first = 1;
$repl = '';
$popup_text = '';
if (count($sugs) > 0) {
$asugs = array_keys($sugs);
$temp_max = count($asugs);
for ($i = 0; $i < $temp_max && $i < 5; $i++) {
$sug = $asugs[$i];
// If you want to use the commented out line below, please remove the \ in <\/script>; it was breaking vim highlighting. -rlpowell
// $repl.="";
else
$replacements[] = "\\1\\2@\\3";
$patterns[] = "#([\n ])magnet\:\?([^,< \n\r]+)#i";
$replacements[] = "\\1magnet:?\\2";
$text = preg_replace($patterns, $replacements, $text);
// strip the space we added
$text = substr($text, 1);
return $text;
// } else {
// return $text;
// }
}
//Updates a dynamic variable found in some object
/*Shared*/
function update_dynamic_variable($name,$value) {
$query = "delete from `tiki_dynamic_variables` where `name`=?";
$this->query($query,array($name),-1,-1,false);
$query = "insert into `tiki_dynamic_variables`(`name`,`data`) values(?,?)";
$this->query($query,Array($name,$value));
return true;
}
// split string into a list of
function split_tag( $string, $cleanup = TRUE ) {
$_splts = split('"', $string);
$inside = FALSE;
$parts = array();
$index=0;
foreach ($_splts as $i) {
if ($cleanup) {
$i = str_replace('}', '', $i);
$i = str_replace('{', '', $i);
$i = str_replace('\'', '', $i);
$i = str_replace('"', '', $i);
// IE silently removes null-byte html char \0, so let's remove it anyways
$i = str_replace('\\0', '', $i);
}
if ($inside) { // inside "foo bar" - append
if ($index>0) {
$parts[$index-1] .= $i;
} else { // else: first element (should never happen)
$parts[] = $i;
}
} else { //
$_spl = split(" ", $i);
foreach($_spl as $j) {
$parts[$index++] = $j;
}
}
$inside = ! $inside;
}
return $parts;
}
function split_assoc_array($parts, $assoc) {
//$assoc = array();
foreach($parts as $part) {
$res=array();
$assoc[$part] = '';
preg_match("/(\w+)\s*=\s*(.*)/", $part, $res);
if ($res) {
$assoc[$res[1]] = $res[2];
}
}
return $assoc;
}
/**
* close_blocks - Close out open paragraph, lists, and div's
*
* During parse_data, information is kept on blocks of text (paragraphs, lists, divs)
* that need to be closed out. This function does that, rather than duplicating the
* code inline.
*
* @param $data - Output data
* @param $in_paragraph - TRUE if there is an open paragraph
* @param $listbeg - array of open list terminators
* @param $divdepth - array indicating how many div's are open
* @param $close_paragraph - TRUE if open paragraph should be closed.
* @param $close_lists - TRUE if open lists should be closed.
* @param $close_divs - TRUE if open div's should be closed.
*/
/* private */
function close_blocks(&$data, &$in_paragraph, &$listbeg, &$divdepth, $close_paragraph, $close_lists, $close_divs) {
$closed = 0; // Set to non-zero if something has been closed out
// Close the paragraph if inside one.
if ($close_paragraph && $in_paragraph) {
$data .= "
";
$in_paragraph = 0;
$closed++;
}
// Close open lists
if ($close_lists) {
while (count($listbeg)) {
$data .= array_shift($listbeg);
$closed++;
}
}
// Close open divs
if ($close_divs) {
$temp_max = count($divdepth);
for ($i = 1; $i <= $temp_max; $i++) {
$data .= '';
$closed++;
}
}
if ($closed) {
$data .= "\n";
}
return $closed;
}
//PARSEDATA
// options defaults : is_html => false, absolute_links => false, language => ''
function parse_data($data, $options = null) {
// Don't bother if there's nothing...
if (function_exists('mb_strlen')) {
if( mb_strlen( $data ) < 1 ) {
return;
}
}
global $page_regex, $slidemode, $prefs, $ownurl_father, $tiki_p_admin_drawings, $tiki_p_edit_drawings, $tiki_p_edit_dynvar, $tiki_p_upload_picture, $page, $page_ref_id, $rsslib, $dbTiki, $structlib, $user, $tikidomain, $tikiroot;
global $wikilib; include_once('lib/wiki/wikilib.php');
// Handle parsing options
if ( $options == null ) $options = array();
$options['is_html'] = $is_html = isset($options['is_html']) ? $options['is_html'] : false;
$options['absolute_links'] = $absolute_links = isset($options['absolute_links']) ? $options['absolute_links'] : false;
$options['language'] = $language = isset($options['language']) ? $options['language'] : '';
$options['noparseplugins'] = $noparseplugins = isset($options['noparseplugins']) ? $options['noparseplugins'] : false;
$options['noheaderinc'] = $noheaderinc = isset($options['noheaderinc']) ? $options['noheaderinc'] : false;
$options['page'] = isset($options['page']) ? $options['page'] : $page;
$options['print'] = isset($options['print']) ? $options['print'] : false;
$options['parseimgonly'] = isset($options['parseimgonly']) ? $options['parseimgonly'] : false;
$options['preview_mode'] = isset($options['preview_mode']) ? (bool)$options['preview_mode'] : false;
// if simple_wiki is true, disable some wiki syntax
// basically, allow wiki plugins, wiki links and almost
// everything between {}
$simple_wiki = false;
if ($prefs['feature_wysiwyg'] == 'y' and $is_html) {
if ($prefs['wysiwyg_wiki_semi_parsed'] == 'y') {
$simple_wiki = true;
} elseif ($prefs['wysiwyg_wiki_parsed'] == 'n') {
return $data;
}
}
if( $prefs['feature_wiki_argvariable'] == 'y' ) {
if (preg_match_all("/\\{\\{((\w+)(\\|([^\\}]+))?)\\}\\}/",$data,$args, PREG_SET_ORDER)) {
$needles = array();
$replacements = array();
foreach( $args as $arg ) {
$value = $arg[4];
$name = $arg[2];
switch( $name ) {
case 'user':
$value = $user;
break;
case 'page':
$value = $options['page'];
break;
default:
if( isset($_GET[$name]) )
$value = $_GET[$name];
break;
}
if( ! empty( $value ) ) {
$needles[] = $arg[0];
$replacements[] = $value;
}
}
$data = str_replace( $needles, $replacements, $data );
}
}
/* XSS Sanitization handling */
// Converts <x> ( tag using HTML entities) into the tag . This tag comes from the input sanitizer (XSS filter).
// This is not HTML valid and avoids using in a wiki text,
// but hide '' text inside some words like 'style' that are considered as dangerous by the sanitizer.
$data = str_replace( array( '<x>', '~np~', '~/np~' ), array( '', ' ~np~', '~/np~ ' ), $data );
// Fix false positive in wiki syntax
// It can't be done in the sanitizer, that can't know if the input will be wiki parsed or not
$data = preg_replace('/(\{img [^\}]+li)(nk[^\}]+\})/i', '\\1\\2', $data);
// Process pre_handlers here
if (is_array($this->pre_handlers)) {
foreach ($this->pre_handlers as $handler) {
$data = $handler($data);
}
}
// Handle pre- and no-parse sections and plugins
$preparsed = array('data'=>array(),'key'=>array());
$noparsed = array('data'=>array(),'key'=>array());
if (!$noparseplugins) {
$this->parse_first($data, $preparsed, $noparsed, $options);
}
// Handle |# anchor links by turning them into ALINK module calls.
preg_match_all("/\(\(([^)]*\|#[^)]*)\)\)/", $data, $anchors);
foreach( array_unique($anchors[1]) as $anchor_line ) {
$parts1 = explode( "|#", $anchor_line );
$anchor_page = "";
$anchor_desc = "";
$anchor = "";
// Break out |desc bits from whatever section they happen to be in
if( strpos( $parts1[0], "|" ) ) {
$parts2 = explode( "|", $parts1[0] );
$anchor_page = $parts2[0];
$anchor_desc = $parts2[1];
$anchor = $parts1[1];
} elseif( strpos( $parts1[1], "|" ) ) {
$parts2 = explode( "|", $parts1[1] );
$anchor_page = $parts1[0];
$anchor = $parts2[0];
$anchor_desc = $parts2[1];
} else {
// No |desc bit
$anchor_page = $parts1[0];
$anchor_desc = $parts1[0];
$anchor = $parts1[1];
}
if ( !$anchor_page && $options['page'] ) {
$anchor_page = $options['page'];
if ( !$anchor_desc ) $anchor_desc = $options['page'];
}
$repl = "{ALINK(pagename=>".$anchor_page.",aname=>".$anchor.")}".$anchor_desc."{ALINK}";
$data = str_replace( "((".$anchor_line."))", $repl, $data);
}
if (!$noparseplugins) {
$this->parse_first($data, $preparsed, $noparsed, $options);
}
// Handle ~pre~...~/pre~ sections
$data = preg_replace(';~pre~(.*?)~/pre~;s', '
$1
', $data);
// Strike-deleted text --text--
if (!$simple_wiki) {
$data = preg_replace("/--(.+?)--/", "$1", $data);
}
// Handle comment sections
$data = preg_replace(';~tc~(.*?)~/tc~;s', '', $data);
$data = preg_replace(';~hc~(.*?)~/hc~;s', '', $data);
// Replace special characters
// done after url catching because otherwise urls of dyn. sites will be modified
// not done in wysiwyg mode, i.e. $prefs['feature_wysiwyg'] set to something other than 'no' or not set at all
// if (!$simple_wiki and $prefs['feature_wysiwyg'] == 'n')
//above line changed by mrisch - special functions were not parsing when wysiwyg is set but wysiswyg is not enabled
// further changed by nkoth - why not parse in wysiwyg mode as well, otherwise it won't parse for display/preview?
// must be done before color as we can have ~hs~~hs
if (!$simple_wiki) {
$this->parse_htmlchar($data);
}
// Extract [link] sections (to be re-inserted later)
$noparsedlinks = array();
if (!$simple_wiki) {
// Replace colors ~~foreground[,background]:text~~
// must be done before []as the description may contain color change
$data = preg_replace("/\~\~([^\:\,]+)(,([^\:]+))?:(.*)\~\~/u", "$4", $data);
}
// This section matches [...].
// Added handling for [[foo] sections. -rlpowell
if (!$simple_wiki) {
preg_match_all("/(?genPass()).'§';
$aux["key"] = $key;
$aux["data"] = $np;
$noparsedlinks[] = $aux;
$data = preg_replace('/(^|[^a-zA-Z0-9])'.preg_quote($np,'/').'([^a-zA-Z0-9]|$)/', '\1'.$key.'\2', $data);
}
}
// BiDi markers
$bidiCount = 0;
$bidiCount = preg_match_all("/(\{l2r\})/", $data, $pages);
$bidiCount += preg_match_all("/(\{r2l\})/", $data, $pages);
$data = preg_replace("/\{l2r\}/", "
", $data);
$data = preg_replace("/\{r2l\}/", "
", $data);
$data = preg_replace("/\{lm\}/", "", $data);
$data = preg_replace("/\{rm\}/", "", $data);
// smileys
$data = $this->parse_smileys($data);
// linebreaks using %%%
$data = str_replace("%%%", " ", $data);
// Replace dynamic variables
// Dynamic variables are similar to dynamic content but they are editable
// from the page directly, intended for short data, not long text but text
// will work too
// Now won't match HTML-style '%nn' letter codes and some special utf8 situations...
if (preg_match_all("/%([^% 0-9A-Z][^% 0-9A-Z][^% ]*)%/",$data,$dvars)) {
// remove repeated elements
$dvars = array_unique($dvars[1]);
// Now replace each dynamic variable by a pair composed of the
// variable value and a text field to edit the variable. Each
foreach($dvars as $dvar) {
$query = "select `data` from `tiki_dynamic_variables` where `name`=?";
$result = $this->query($query,Array($dvar));
if($result->numRows()) {
$value = $result->fetchRow();
$value = $value["data"];
} else {
//Default value is NULL
$value = "NaV";
}
// Now build 2 divs
$id = 'dyn_'.$dvar;
if(isset($tiki_p_edit_dynvar)&& $tiki_p_edit_dynvar=='y') {
$span1 = "$value";
$span2 = "".'';
} else {
$span1 = "$value";
$span2 = '';
}
$html = $span1.$span2;
//It's important to replace only once
$dvar_preg = preg_quote( $dvar );
$data = preg_replace("+%$dvar_preg%+",$html,$data,1);
//Further replacements only with the value
$data = str_replace("%$dvar%",$value,$data);
}
//At the end put an update button
//
$data='';
}
if (!$simple_wiki) {
// Replace boxes
$data = preg_replace("/\^([^\^]+)\^/", "
$1
", $data);
// Underlined text
$data = preg_replace("/===(.+?)===/", "$1", $data);
// Center text
$data = preg_replace("/::(.+?)::/", "
$1
", $data);
}
// definitively put out the protected words ))protectedWord((
preg_match_all("/\)\)(\S*?)\(\(/", $data, $matches);
$noParseWikiLinksK = array();
$noParseWikiLinksT = array();
foreach ($matches[0] as $mi=>$match) {
do {
$randNum = chr(0xff).rand(0, 1048576).chr(0xff);
} while (strstr($data, $randNum));
$data = str_replace($match, $randNum, $data);
$noParseWikiLinksK[] = $randNum;
$noParseWikiLinksT[] = $matches[1][$mi];
}
// New syntax for wiki pages ((name|desc)) Where desc can be anything
// preg_match_all("/\(\(($page_regex)\|(.+?)\)\)/", $data, $pages);
// match ((name|desc)) as well as ((name|))
preg_match_all("/\(([a-z0-9-]+)?\(($page_regex)\|([^\)]*?)\)\)/", $data, $pages);
$temp_max = count($pages[1]);
for ($i = 0; $i < $temp_max; $i++) {
$exactMatch = $pages[0][$i];
$replacement = $this->get_wiki_link_replacement( $pages[2][$i], array(
'description' => $pages[6][$i],
'reltype' => $pages[1][$i] ) );
$data = str_replace($exactMatch, $replacement, $data);
}
// New syntax for wiki pages ((name)) Where name can be anything
preg_match_all("/\(([a-z0-9-]+)?\( *($page_regex) *\)\)/", $data, $pages);
foreach ($pages[2] as $idx => $page_parse) {
$exactMatch = $pages[0][$idx];
$replacement = $this->get_wiki_link_replacement( $page_parse, array( 'reltype' => $pages[1][$idx] ) );
$data = str_replace($exactMatch, $replacement, $data);
}
// Links to internal pages
// If they are parenthesized then don't treat as links
// Prevent ))PageName(( from being expanded \"\'
//[A-Z][a-z0-9_\-]+[A-Z][a-z0-9_\-]+[A-Za-z0-9\-_]*
if ( ! $simple_wiki && $prefs['feature_wiki'] == 'y' && $prefs['feature_wikiwords'] == 'y' ) {
// The first part is now mandatory to prevent [Foo|MyPage] from being converted!
if ($prefs['feature_wikiwords_usedash'] == 'y') {
preg_match_all("/(?<=[ \n\t\r\,\;]|^)([A-Z][a-z0-9_\-\x80-\xFF]+[A-Z][a-z0-9_\-\x80-\xFF]+[A-Za-z0-9\-_\x80-\xFF]*)(?=$|[ \n\t\r\,\;\.])/", $data, $pages);
} else {
preg_match_all("/(?<=[ \n\t\r\,\;]|^)([A-Z][a-z0-9\x80-\xFF]+[A-Z][a-z0-9\x80-\xFF]+[A-Za-z0-9\x80-\xFF]*)(?=$|[ \n\t\r\,\;\.])/", $data, $pages);
}
//TODO to have a real utf8 Wikiword where the capitals can be a utf8 capital
$words = ( $prefs['feature_hotwords'] == 'y' ) ? $this->get_hotwords() : array();
foreach ( array_unique($pages[1]) as $page_parse ) {
if ( ! array_key_exists($page_parse, $words) ) {
$repl = $this->get_wiki_link_replacement( $page_parse, array(
'plural' => $prefs['feature_wiki_plurals'] == 'y' ) );
$data = preg_replace("/(?<=[ \n\t\r\,\;]|^)$page_parse(?=$|[ \n\t\r\,\;\.])/", "$1" . $repl . "$2", $data);
}
}
}
// Reinsert ))Words((
$data = str_replace($noParseWikiLinksK, $noParseWikiLinksT, $data);
// reinsert hash-replaced links into page
foreach ($noparsedlinks as $np) {
$data = str_replace($np["key"], $np["data"], $data);
}
// *****
// This section handles external links of the form [url] and such.
// *****
$links = $this->get_links($data);
$notcachedlinks = $this->get_links_nocache($data);
$cachedlinks = array_diff($links, $notcachedlinks);
$this->cache_links($cachedlinks);
// Note that there're links that are replaced
foreach ($links as $link) {
$target = '';
$class = 'class="wiki"';
$ext_icon = '';
$rel='';
if ($prefs['popupLinks'] == 'y') {
$target = 'target="_blank"';
}
if (!isset($_SERVER['SERVER_NAME']) && isset($_SERVER['HTTP_HOST'])) {
$_SERVER['SERVER_NAME'] = $_SERVER['HTTP_HOST'];
}
if (empty($_SERVER['SERVER_NAME']) || strstr($link, $_SERVER["SERVER_NAME"]) || !strstr($link, '://')) {
$target = '';
} else {
$class = 'class="wiki external"';
if ($prefs['feature_wiki_ext_icon'] == 'y') {
$ext_icon = "";
}
$rel='external';
}
// The (?is_cached($link)) {
//use of urlencode for using cached versions of dynamic sites
$cosa = "(cache)";
//$link2 = str_replace("/","\/",$link);
//$link2 = str_replace("?","\?",$link2);
//$link2 = str_replace("&","\&",$link2);
$link2 = str_replace("/", "\/", preg_quote($link));
$pattern = "/(?$1$ext_icon", $data);
$pattern = "/(?$1$ext_icon", $data);
} else {
$data = preg_replace($pattern, "$1$ext_icon $cosa", $data);
}
$pattern = "/(?$1$ext_icon $cosa", $data);
$pattern = "/(?$link$ext_icon $cosa", $data);
} else {
//$link2 = str_replace("/","\/",$link);
//$link2 = str_replace("?","\?",$link2);
//$link2 = str_replace("&","\&",$link2);
$link2 = str_replace("/", "\/", preg_quote($link));
$data = str_replace("|nocache", "", $data);
$pattern = "/(?$1$ext_icon", $data);
$pattern = "/(?$1$ext_icon", $data);
$pattern = "/(?$link$ext_icon", $data);
}
}
// Handle double square brackets. -rlpowell
$data = str_replace( "[[", "[", $data );
/*
* Wiki Tables syntax
*/
// tables in old style
if ($prefs['feature_wiki_tables'] != 'new') {
if (preg_match_all("/\|\|(.*)\|\|/", $data, $tables)) {
$maxcols = 1;
$cols = array();
$temp_max = count($tables[0]);
for ($i = 0; $i < $temp_max; $i++) {
$rows = explode('||', $tables[0][$i]);
$temp_max2 = count($rows);
for ($j = 0; $j < $temp_max2; $j++) {
$cols[$i][$j] = explode('|', $rows[$j]);
if (count($cols[$i][$j]) > $maxcols)
$maxcols = count($cols[$i][$j]);
}
} // for ($i ...
$temp_max3 = count($tables[0]);
for ($i = 0; $i < $temp_max3; $i++) {
$repl = '
';
$data = str_replace($tables[0][$i], $repl, $data);
}
}
}
}
if (!$simple_wiki) {
$this->parse_data_process_maketoc( $data, $options);
} // closing if ($simple_wiki)
// Close BiDi DIVs if any
for ($i = 0; $i < $bidiCount; $i++) {
$data .= "
";
}
// Put removed strings back.
$this->replace_preparse($data, $preparsed, $noparsed);
// Process pos_handlers here
foreach ($this->pos_handlers as $handler) {
$data = $handler($data);
}
return $data;
}
function parse_data_process_maketoc( &$data, $options) {
global $prefs;
$need_maketoc = strpos($data, "{maketoc") ;
$need_autonumbering = ( preg_match('/^\!+[\-\+]?#/m', $data) > 0 );
$anch = array();
global $anch;
$pageNum = 1;
// 08-Jul-2003, by zaufi
// HotWords will be replace only in ordinal text
// It looks __really__ goofy in Headers or Titles
if ( $prefs['feature_hotwords'] == 'y' ) {
// Get list of HotWords
$words = $this->get_hotwords();
}
// Now tokenize the expression and process the tokens
// Use tab and newline as tokenizing characters as well ////
$lines = explode("\n", $data);
$data = '';
$listbeg = array();
$divdepth = array();
$hdr_structure = array();
$show_title_level = array();
$last_hdr = array();
$nb_last_hdr = 0;
$nb_hdrs = 0;
$inTable = 0;
$inPre = 0;
$inComment = 0;
$inTOC = 0;
$inScript = 0;
$title_text = '';
// loop: process all lines
$in_paragraph = 0;
foreach ($lines as $line) {
$current_title_num = '';
$numbering_remove = 0;
$line = rtrim($line); // Trim off trailing white space
// Check for titlebars...
// NOTE: that title bar should start at the beginning of the line and
// be alone on that line to be autoaligned... otherwise, it is an old
// styled title bar...
if (substr(ltrim($line), 0, 2) == '-=' && substr($line, -2, 2) == '=-') {
// Close open paragraph and lists, but not div's
$this->close_blocks($data, $in_paragraph, $listbeg, $divdepth, 1, 1, 0);
//
$align_len = strlen($line) - strlen(ltrim($line));
// My textarea size is about 120 space chars.
//define('TEXTAREA_SZ', 120);
// NOTE: That strict math formula (split into 3 areas) gives
// bad visual effects...
// $align = ($align_len < (TEXTAREA_SZ / 3)) ? "left"
// : (($align_len > (2 * TEXTAREA_SZ / 3)) ? "right" : "center");
//
// Going to introduce some heuristic here :)
// Visualy (remember that space char is thin) center starts at 25 pos
// and 'right' from 60 (HALF of full width!) -- thats all :)
//
// NOTE: Guess align only if more than 10 spaces before -=title=-
if ($align_len > 10) {
$align = ($align_len < 25) ? "left" : (($align_len > 60) ? "right" : "center");
$align = ' style="text-align: ' . $align . ';"';
} else {
$align = '';
}
//
$line = trim($line);
$line = '
' . substr($line, 2, strlen($line) - 4). '
';
$data .= $line . "\n";
// TODO: Case is handled ... no need to check other conditions
// (it is apriori known that they are all false, moreover sometimes
// check procedure need > O(0) of compexity)
// -- continue to next line...
// MUST replace all remaining parse blocks to the same logic...
continue;
}
// Replace old styled titlebars
if (strlen($line) != strlen($line = preg_replace("/-=(.+?)=-/", "
$1
", $line))) {
// Close open paragraph, but not lists (why not?) or div's
$this->close_blocks($data, $in_paragraph, $listbeg, $divdepth, 1, 0, 0);
$data .= $line . "\n";
continue;
}
// check if we are inside a ~hc~ block and, if so, ignore
// monospaced and do not insert
$inComment += substr_count(strtolower($line), "");
// check if we are inside a ~pre~ block and, if so, ignore
// monospaced and do not insert
$inPre += substr_count(strtolower($line), "
$inTable += substr_count(strtolower($line), "
$inTOC += substr_count(strtolower($line), "
$inScript += substr_count(strtolower($line), "';
array_unshift($divdepth, $hdrlevel);
$addremove += 1;
}
// Generate the final title text
$title_text_base = substr($line, $hdrlevel + $addremove);
$title_text = $current_title_num.$title_text_base;
// create stable anchors for all headers
// use header but replace non-word character sequences
// with one underscore (for XHTML 1.0 compliance)
// Workaround pb with plugin replacement and header id
// first we remove hash from title_text for headings beginning
// with images and HTML tags
$thisid = ereg_replace('§[a-z0-9]{32}§', '', $title_text);
$thisid = ereg_replace('?[^>]+>', '', $thisid);
$thisid = ereg_replace('[^a-zA-Z0-9\:\.\-\_]+', '_', $thisid);
$thisid = ereg_replace('^[^a-zA-Z]*', '', $thisid);
if (empty($thisid)) $thisid = 'a'.md5($title_text);
// Add a number to the anchor if it already exists, to avoid duplicated anchors
if ( isset($all_anchors[$thisid]) ) {
$all_anchors[$thisid]++;
$thisid .= '_'.$all_anchors[$thisid];
} else {
$all_anchors[$thisid] = 1;
}
//==================================================================================================================================
// Collect TOC entry if any {maketoc} is present on the page
if ( $need_maketoc !== false && strpos($data, title) ){
$anch[] = array(
'id' => $thisid,
'hdrlevel' => $hdrlevel,
'pagenum' => $pageNum,
'title' => $title_text_base,
'title_displayed_num' => $current_title_num,
'title_real_num' => $current_title_real_num
);
}
global $tiki_p_edit, $section;
if ($prefs['wiki_edit_section'] == 'y' && $section == 'wiki page' && $tiki_p_edit == 'y' and ( $prefs['wiki_edit_section_level'] == 0 or $hdrlevel <= $prefs['wiki_edit_section_level']) && (empty($options['print']) ) ) {
global $smarty;
include_once('lib/smarty_tiki/function.icon.php');
$button = '
';
} else {
$button = '';
}
// Use $hdrlevel + 1 because the page title is H1, so none of the other headers should be.
// Except when page title is off
// Or when in wysiwyg mode
$headerInc = 0;
if( $prefs['feature_page_title'] == 'y' && ! $options['noheaderinc'] )
++$headerInc;
if ( $prefs['feature_wiki_show_hide_before'] == 'y' ) {
$line = $button.''.$aclose.' '.$title_text.''.$aclose2;
} else {
$line = $button.''.$title_text.''.$aclose.$aclose2;
}
} elseif (!strcmp($line, $prefs['wiki_page_separator'])) {
// Close open paragraph, lists, and div's
$this->close_blocks($data, $in_paragraph, $listbeg, $divdepth, 1, 1, 1);
// Leave line unchanged... tiki-index.php will split wiki here
$line = $prefs['wiki_page_separator'];
$pageNum += 1;
} else {
/** Usual paragraph.
*
* If the
* $prefs['feature_wiki_paragraph_formatting']
* is on, then consecutive lines of
* text will be gathered into a block
* that is surrounded by HTML
* paragraph tags. One or more blank
* lines, or another special Wiki line
* (e.g., heading, titlebar, etc.)
* signifies the end of the
* paragraph. If the paragraph
* formatting feature is off, the
* original Tikiwiki behavior is used,
* in which each line in the source is
* terminated by an explicit line
* break (br tag).
*
* @since Version 1.9
*/
if ($inTable == 0 && $inPre == 0 && $inComment == 0 && $inTOC == 0 && $inScript == 0
// Don't put newlines at comments' end!
&& ! substr_count(strtolower($line), "-->")
) {
if ($prefs['feature_wiki_paragraph_formatting'] == 'y') {
if ($in_paragraph && ( 0 == strcmp("", trim($line)) || substr(trim($line),0,5) == '
close_blocks($data, $in_paragraph, $listbeg, $divdepth, 1, 0, 0);
} elseif (!$in_paragraph && (0 != strcmp("", trim($line))) && substr(trim($line),0,4) != '' . $line;
} else {
// A normal in-paragraph line or a consecutive blank line.
// Leave it as is.
}
} else {
$line .= ' ';
}
}
}
}
}
$data .= $line . "\n";
}
// Close open paragraph, lists, and div's
$this->close_blocks($data, $in_paragraph, $listbeg, $divdepth, 1, 1, 1);
/*
* Replace special "maketoc" plugins
* Valid arguments :
* - type (look of the maketoc),
* - maxdepth (max level displayed),
* - title (replace the default title),
* - showhide (if set to y, add the Show/Hide link)
* - nolinks (if set to y, don't add links on toc entries)
* - nums :
* * 'n' means 'no title autonumbering' in TOC,
* * 'force' means :
* ~ same as 'y' if autonumbering is used in the page,
* ~ 'number each toc entry as if they were all autonumbered'
* * any other value means 'same as page's headings autonumbering',
*
* (Note that title will be translated if a translation is available)
*
* Examples: {maketoc}, {maketoc type=box maxdepth=1 showhide=y}, {maketoc title="Page Content" maxdepth=3}, ...
* Obsolete syntax: {maketoc:box}
*/
$new_data = '';
$search_start = 0;
while ( ($maketoc_start = strpos($data, "{maketoc", $search_start)) !== false ) {
$maketoc_length = strpos($data, "}", $maketoc_start) + 1 - $maketoc_start;
$maketoc_string = substr($data, $maketoc_start, $maketoc_length);
// Handle old type definition for type "box" (and preserve environment for the title also)
if ( $maketoc_length > 12 && strtolower(substr($maketoc_string, 8, 4)) == ':box' ) {
$maketoc_string = "{maketoc type=box showhide=y title='".tra('index', $options['language'], true).'"'.substr($maketoc_string, 12);
}
$maketoc_string = str_replace('"', '"', $maketoc_string);
$maketoc_regs = array();
if ( $maketoc_length == 9 || preg_match_all("/([^\s=\(]+)=([^\"\s=\)\}]+|\"[^\"]*\")/", $maketoc_string, $maketoc_regs) ) {
if ( $maketoc_start > 0 ) {
$new_data .= substr($data, 0, $maketoc_start);
}
// Set maketoc default values
$maketoc_args = array(
'type' => '',
'maxdepth' => 0, // No limit
'title' => tra('Table of contents', $options['language'], true),
'showhide' => '',
'nolinks' => '',
'nums' => ''
);
// Build maketoc arguments list (and remove " chars if they are around the value)
if ( isset($maketoc_regs[1]) ) {
$nb_args = count($maketoc_regs[1]);
for ( $a = 0; $a < $nb_args ; $a++ ) {
$maketoc_args[strtolower($maketoc_regs[1][$a])] = trim($maketoc_regs[2][$a], '"');
}
}
if ( $maketoc_args['title'] != '' ) {
// Translate maketoc title
$maketoc_summary = ' summary="'.tra($maketoc_args['title'], $options['language'], true).'"';
$maketoc_title = "
', $maketoc);
if ( $link_class != 'link' ) {
$maketoc = ereg_replace("'link'", "'$link_class'", $maketoc);
}
}
//=====
global $TOC_newstring, $TOC_oldstring ;
$TOC_newstring = $maketoc ; //===== get a copy of the newest TOC before we do anything to it
if ( strpos($maketoc, $TOC_oldstring) ) //=====if this MAKETOC contains previous chapter's TOC entries, remove that portion of the string
{ $maketoc = substr($maketoc, 0 , strpos($maketoc, $TOC_oldstring)).substr($maketoc, strpos($maketoc, $TOC_oldstring)+ strlen($TOC_oldstring)) ; }
$maketoc = $maketoc_header.$maketoc.$maketoc_footer ;
//=====prepare this chapter's TOC entry to be compared with the next chapter's string]
$TOC_oldstring = substr($TOC_newstring, strpos($TOC_newstring, '
' )) ; //===== trim the underline stuff from the tail of the string
echo($TOC_oldstring);
// Add a Show/Hide link ========[do not print show/hide for "PRINT" routines==&& !$options['print']==ADDED !PRINT 2009-10-01 LARRYG ==========================
if ( isset($maketoc_args['showhide']) && $maketoc_args['showhide'] == 'y' && !$options['print'] ) {
$maketoc .= "\n";
}
$new_data .= $maketoc;
$data = substr($data, $maketoc_start + $maketoc_length);
$search_start = 0; //===== Reinitialize search start cursor, since data now begins after the last replaced maketoc
} else {
$search_start = $maketoc_start + $maketoc_length;
}
}
$data = $new_data.$data;
// Add icon to edit the text before the first section (if there is some)
if ($prefs['wiki_edit_section'] == 'y' && isset($section) && $section == 'wiki page' && $tiki_p_edit == 'y' && (empty($options['print']) || !$options['print']) && strpos($data, '
') != 0){
global $smarty;
include_once('lib/smarty_tiki/function.icon.php');
$button = '
';
$data = $button.$data;
}
}
function get_wiki_link_replacement( $pageLink, $extra = array() ) {
global $prefs, $wikilib, $semanticlib;
$displayLink = $pageLink;
// HTML entities encoding breaks page lookup
$pageLink = html_entity_decode( $pageLink, ENT_COMPAT, 'UTF-8' );
$description = null;
$reltype = null;
$processPlural = false;
$bestLang = ($prefs['feature_multilingual'] == 'y' && $prefs['feature_best_language'] == 'y')? "&bl=y" : "";
if( array_key_exists( 'description', $extra ) )
$description = $extra['description'];
if( array_key_exists( 'reltype', $extra ) )
$reltype = $extra['reltype'];
if( array_key_exists( 'plural', $extra ) )
$processPlural = (boolean) $extra['plural'];
// Replace links to external wikis
if (strpos($pageLink, ':')) {
$wexs = explode(':', $pageLink);
if (count($wexs) == 2) {
$wkname = $wexs[0];
if ($this->getOne("select count(*) from `tiki_extwiki` where `name`=?",array($wkname)) == 1) {
$wkurl = $this->getOne("select `extwiki` from `tiki_extwiki` where `name`=?",array($wkname));
$wkurl = '' . $wexs[1] . '';
return $wkurl;
}
}
}
// 24-Jun-2003, by zaufi
// TODO: future optimize: get page description and modification time at once.
// text[0] = link description (previous format)
// text[1] = timeout in seconds (new field)
// text[2..N] = drop
$text = explode("|", $description);
if ($desc = $this->page_exists_desc($pageLink, true)) {
// why the preg_replace? ex: ((page||Page-Desc)) the desc must stay Page-Desc, and not ))Page-Desc((
$uri_ref = $wikilib->sefurl($pageLink).$bestLang;
// check to see if desc is blank in ((page|desc))
if (strlen(trim($text[0])) > 0) {
$linktext = $text[0];
} elseif ($desc != $pageLink && $description !== null) {
// desc is blank; use the page description instead
$linktext = $displayLink . ': ' . $desc;
} else {
// there is no page description
$linktext = $displayLink;
}
$repl = '' . $linktext . '';
// Check is timeout expired?
if (isset($text[1]) && (time() - intval($this->page_exists_modtime($pageLink))) < intval($text[1])) {
// Append small 'new' image. TODO: possible 'updated' image more suitable...
$repl .= ' ';
}
return $repl;
}
if( $processPlural ) {
$plural_tmp = $pageLink;
// Plurals like policy / policies
$plural_tmp = preg_replace("/ies$/", "y", $plural_tmp);
// Plurals like address / addresses
$plural_tmp = preg_replace("/sses$/", "ss", $plural_tmp);
// Plurals like box / boxes
$plural_tmp = preg_replace("/([Xx])es$/", "$1", $plural_tmp);
// Others, excluding ending ss like address(es)
$plural_tmp = preg_replace("/([A-Za-rt-z])s$/", "$1", $plural_tmp);
if($desc = $this->page_exists_desc($plural_tmp, true)) {
$repl = "$displayLink";
return $repl;
}
}
$uri_ref = "tiki-editpage.php?page=" . urlencode($pageLink);
if( $prefs['feature_multilingual'] == 'y' && isset( $GLOBALS['pageLang'] ) ) {
$uri_ref .= '&lang=' . urlencode($GLOBALS['pageLang']);
}
$repl = (strlen(trim($text[0])) > 0 ? $text[0] : $pageLink) . '?';
return $repl;
}
function parse_smileys($data) {
global $prefs;
if ($prefs['feature_smileys'] == 'y') {
$data = preg_replace("/\(:([^:]+):\)/", "", $data);
}
return $data;
}
function get_pages($data,$withReltype = false) {
global $page_regex, $prefs;
preg_match_all("/\(([a-z0-9-]+)?\( *($page_regex) *\)\)/", $data, $normal);
preg_match_all("/\(([a-z0-9-]+)?\( *($page_regex) *\|(.+?)\)\)/", $data, $withDesc);
if ($prefs['feature_wikiwords'] == 'y') {
preg_match_all("/([ \n\t\r\,\;]|^)?([A-Z][a-z0-9_\-]+[A-Z][a-z0-9_\-]+[A-Za-z0-9\-_]*)($|[ \n\t\r\,\;\.])/", $data, $wikiLinks);
$pageList = array_merge( $normal[2], $withDesc[2], $wikiLinks[2] );
if( $withReltype ) {
$relList = array_merge(
$normal[1],
$withDesc[1],
count($wikiLinks[2]) ? array_fill( 0, count($wikiLinks[2]), null ) : array()
);
}
} else {
$pageList = array_merge( $normal[2], $withDesc[2] );
if( $withReltype ) {
$relList = array_merge(
$normal[1],
$withDesc[1]
);
}
}
if( $withReltype ) {
$complete = array();
foreach( $pageList as $idx => $name ) {
if( ! array_key_exists( $name, $complete ) )
$complete[$name] = array();
if( ! empty( $relList[$idx] ) && ! in_array( $relList[$idx], $complete[$name] ) )
$complete[$name][] = $relList[$idx];
}
return $complete;
} else {
return array_unique( $pageList );
}
}
function clear_links($page) {
$query = "delete from `tiki_links` where `fromPage`=?";
$result = $this->query($query, array($page));
}
function replace_link($pageFrom, $pageTo, $types = array()) {
$query = "delete from `tiki_links` where `fromPage`=? and `toPage`=?";
$result = $this->query($query, array($pageFrom,$pageTo));
if( count($types) == 0 ) {
$query = "insert into `tiki_links`(`fromPage`,`toPage`) values(?, ?)";
$result = $this->query($query, array($pageFrom,$pageTo));
} else {
sort($types);
$query = "insert into `tiki_links`(`fromPage`,`toPage`, `reltype`) values(?, ?, ?)";
$result = $this->query($query, array( $pageFrom, $pageTo, implode(',', $types) ));
}
}
function invalidate_cache($page) {
unset( $this->cache_page_info[urlencode($page)] );
$query = "update `tiki_pages` set `cache_timestamp`=? where `pageName`=?";
$this->query($query, array(0,$page) );
}
/** Update a wiki page
@param array $hash- lock_it,contributions, contributors
**/
function update_page($pageName, $edit_data, $edit_comment, $edit_user, $edit_ip, $edit_description = '', $minor = false, $lang='', $is_html=false, $hash=null, $saveLastModif=null, $wysiwyg='', $wiki_authors_style) {
global $smarty, $prefs, $dbTiki, $histlib, $quantifylib;
include_once ("lib/wiki/histlib.php");
include_once ("lib/commentslib.php");
if( $wysiwyg == 'y' ) {
$is_html = 1;
}
if( ! $is_html ) {
$edit_data = str_replace( '<x>', '', $edit_data );
}
$commentslib = new Comments($dbTiki);
if (!$edit_user) $edit_user = 'anonymous';
$this->invalidate_cache($pageName);
// Collect pages before modifying edit_data (see update of links below)
$pages = $this->get_pages($edit_data, true);
if (!$this->page_exists($pageName))
return false;
// Get this page information
$info = $this->get_page_info($pageName);
// Use largest version +1 in history table rather than tiki_page because versions used to be bugged
// tiki_history is also bugged as not all changes get stored in the history, like minor changes
// and changes that do not modify the body of the page. Both numbers are wrong, but the largest of
// them both is right.
$old_version = max(
$info["version"],
$histlib->get_page_latest_version($pageName) + 1
);
$lastModif = $info["lastModif"];
$user = $info["user"];
if (!$user) $user = 'anonymous';
$ip = $info["ip"];
$comment = $info["comment"];
$description = $info['description'];
$data = $info["data"];
$version = $old_version + 1;
if( $prefs['quantify_changes'] == 'y' && $prefs['feature_multilingual'] == 'y' ) {
include_once 'lib/wiki/quantifylib.php';
$quantifylib->recordChangeSize( $info['page_id'], $version, $info['data'], $edit_data );
}
$html=$is_html?1:0;
if ($html && $prefs['feature_purifier'] != 'n') {
require "lib/htmlpurifier/HTMLPurifier.auto.php";
$purifier = new HTMLPurifier();
$edit_data = $purifier->purify($edit_data);
}
$mid = '';
if( is_null( $saveLastModif ) ) {
$saveLastModif = $this->now;
}
$bindvars = array($edit_description,$edit_data,$edit_comment,(int) $saveLastModif,$version,$edit_user,$edit_ip,(int)strlen($data),$html,$wysiwyg, $wiki_authors_style);
if ($lang) {
$mid .= ', `lang`=? ';
$bindvars[] = $lang;
}
if (!empty($hash['lock_it']) && ($hash['lock_it'] == 'y' || $hash['lock_it'] == 'on')) {
$mid .= ', `flag`=?, `lockedby`=? ';
$bindvars[] = 'L';
$bindvars[] = $user;
} else if (empty($hash['lock_it']) || $hash['lock_it'] == 'n') {
$mid .= ', `flag`=?, `lockedby`=? ';
$bindvars[] = '';
$bindvars[] = '';
}
if (empty($hash['contributions'])) {
$hash['contributions'] = '';
}
if (empty($hash['contributors'])) {
$hash2 = '';
} else {
foreach ($hash['contributors'] as $c) {
$hash3['contributor'] = $c;
$hash2[] = $hash3;
}
}
$bindvars[] = $pageName;
$query = "update `tiki_pages` set `description`=?, `data`=?, `comment`=?, `lastModif`=?, `version`=?, `user`=?, `ip`=?, `page_size`=?, `is_html`=?, `wysiwyg`=?, `wiki_authors_style`=? $mid where `pageName`=?";
$result = $this->query($query,$bindvars);
// Parse edit_data updating the list of links from this page
$this->clear_links($pageName);
// Pages collected above
foreach ($pages as $page => $types) {
$this->replace_link($pageName, $page, $types);
}
if (strtolower($pageName) != 'sandbox' && !$minor) {
$maxversions = $prefs['maxVersions'];
if ($maxversions && ($nb = $histlib->get_nb_history($pageName)) > $maxversions) {
// Select only versions older than keep_versions days
$keep = $prefs['keep_versions'];
$oktodel = $saveLastModif - ($keep * 24 * 3600);
$query = "select `pageName` ,`version`, `historyId` from `tiki_history` where `pageName`=? and `lastModif`<=? order by `lastModif` asc";
$result = $this->query($query,array($pageName,$oktodel),$nb - $maxversions);
$toelim = $result->numRows();
while ($res = $result->fetchRow()) {
$page = $res["pageName"];
$version = $res["version"];
$query = "delete from `tiki_history` where `pageName`=? and `version`=?";
$this->query($query,array($pageName,$version));
if ($prefs['feature_contribution'] == 'y') {
global $contributionlib; include_once('lib/contribution/contributionlib.php');
$contributionlib->remove_history($res['historyId']);
}
}
}
}
// This if no longer checks for minor-ness of the change; sendWikiEmailNotification does that.
if( $prefs['feature_wiki_history_full'] == 'y' || $data != $edit_data || $description != $edit_description || $comment != $edit_comment ) {
if (strtolower($pageName) != 'sandbox') {
$query = "insert into `tiki_history`(`pageName`, `version`, `lastModif`, `user`, `ip`, `comment`, `data`, `description`,`is_html`)
values(?,?,?,?,?,?,?,?,?)";
# echo "
";print_r(get_defined_vars());echo "
";die();
$result = $this->query($query,array($pageName,(int) $old_version,(int) $lastModif,$user,$ip,$comment,$data,$description,(int)$info['is_html']));
if ($prefs['feature_contribution'] == 'y') {// transfer page contributions to the history
global $contributionlib; include_once('lib/contribution/contributionlib.php');
$query = 'select max(`historyId`) from `tiki_history`where `pageName`=? and `version`=?';
$historyId = $this->getOne($query, array($pageName,(int) $old_version));
$contributionlib->change_assigned_contributions($pageName, 'wiki page', $historyId, 'history', '', $pageName.'/'.$old_version, "tiki-pagehistory.php?page=$pageName&preview=$old_version");
}
}
if (strtolower($pageName) != 'sandbox') {
global $logslib; include_once('lib/logs/logslib.php');
include_once('lib/diff/difflib.php');
$bytes = diff2($data , $edit_data, 'bytes');
$logslib->add_action('Updated', $pageName, 'wiki page', $bytes, $edit_user, $edit_ip, '', $this->now, $hash['contributions'], $hash2);
if ($prefs['feature_contribution'] == 'y') {
global $contributionlib; include_once('lib/contribution/contributionlib.php');
$contributionlib->assign_contributions($hash['contributions'], $pageName, 'wiki page', $description, $pageName, "tiki-index.php?page=".urlencode($pageName));
}
}
if ($prefs['feature_multilingual'] == 'y' && $lang ) {
// Need to update the translated objects table when an object's language changes.
$this->query( "UPDATE tiki_translated_objects SET lang = ? WHERE objId = ? AND type = 'wiki page'",
array( $lang, $info['page_id'] ) );
}
if ($prefs['wiki_watch_minor'] != 'n' || !$minor) {
// Deal with mail notifications.
include_once('lib/notifications/notificationemaillib.php');
global $histlib; include_once ("lib/wiki/histlib.php");
$old = $histlib->get_version($pageName, $old_version);
$foo = parse_url($_SERVER["REQUEST_URI"]);
$machine = $this->httpPrefix(). dirname( $foo["path"] );
require_once('lib/diff/difflib.php');
$diff = diff2($old["data"] , $edit_data, "unidiff");
sendWikiEmailNotification('wiki_page_changed', $pageName, $edit_user, $edit_comment, $old_version, $edit_data, $machine, $diff, $minor, $hash['contributions']);
}
$query = "delete from `tiki_page_drafts` where `user`=? and `pageName`=?";
$this->query($query, array($GLOBALS['user'], $pageName));
if ($prefs['feature_score'] == 'y') {
$this->score_event($user, 'wiki_edit');
}
}
if ( $prefs['feature_search'] == 'y' && $prefs['feature_search_fulltext'] != 'y' && $prefs['search_refresh_index_mode'] == 'normal' ) {
require_once('lib/search/refresh-functions.php');
refresh_index('pages', $pageName);
}
}
function update_page_version($pageName, $version, $edit_data, $edit_comment, $edit_user, $edit_ip, $lastModif, $description = '', $lang='') {
global $smarty;
if (strtolower($pageName) == 'sandbox')
return;
// Collect pages before modifying edit_data
$pages = $this->get_pages($edit_data, true);
if (!$this->page_exists($pageName))
return false;
$query = "delete from `tiki_history` where `pageName`=? and `version`=?";
$result = $this->query($query, array($pageName,(int) $version));
$query = "insert into `tiki_history`(pageName, version, lastModif, user, ip, comment, data,description) values(?,?,?, ?,?,?, ?,?)";
$result = $this->query($query, array($pageName,(int) $version, (int) $lastModif, $edit_user, $edit_ip, $edit_comment, $edit_data, $description)
);
//print("version: $version ");
// Get this page information
$info = $this->get_page_info($pageName);
if ($version >= $info["version"]) {
if ($lang) { // not sure it is necessary
$query = "update `tiki_pages` set `data`=?, `comment`=?, `lastModif`=?, `version`=?, `user`=?, `ip`=?, `description`=?,`page_size`=?,`lang`=? where `pageName`=?";
$result = $this->query($query, array($edit_data, $edit_comment, (int) $this->now, (int) $version, $edit_user, $edit_ip, $description, (int) strlen($edit_data), $lang, $pageName));
} else {
$query = "update `tiki_pages` set `data`=?, `comment`=?, `lastModif`=?, `version`=?, `user`=?, `ip`=?, `description`=?,`page_size`=? where `pageName`=?";
$result = $this->query($query, array($edit_data, $edit_comment, (int) $this->now, (int) $version, $edit_user, $edit_ip, $description, (int) strlen($edit_data), $pageName));
}
// Parse edit_data updating the list of links from this page
$this->clear_links($pageName);
// Pages are collected at the top of the function before adding slashes
foreach ($pages as $page => $types) {
$this->replace_link($pageName, $page, $types);
}
}
}
function get_display_timezone($_user = false) {
global $prefs, $user;
if ( $_user === false || $_user == $user ) {
// If the requested timezone is the current user timezone
$tz = $prefs['display_timezone'];
} elseif ( $_user ) {
// ... else, get the user timezone preferences from DB
$tz = $this->get_user_preference($_user, 'display_timezone');
if ( ! TikiDate::TimezoneIsValidId($tz) ) {
$tz = $prefs['server_timezone'];
}
}
return $tz;
}
function get_long_date_format() {
global $prefs;
return $prefs['long_date_format'];
}
function get_short_date_format() {
global $prefs;
return $prefs['short_date_format'];
}
function get_long_time_format() {
global $prefs;
return $prefs['long_time_format'];
}
function get_short_time_format() {
global $prefs;
return $prefs['short_time_format'];
}
function get_long_datetime_format() {
static $long_datetime_format = false;
if (!$long_datetime_format) {
$t = trim($this->get_long_time_format());
if (!empty($t)) {
$t = ' ['.$t.']';
}
$long_datetime_format = $this->get_long_date_format().$t;
}
return $long_datetime_format;
}
function get_short_datetime_format() {
static $short_datetime_format = false;
if (!$short_datetime_format) {
$t = trim($this->get_short_time_format());
if (!empty($t)) {
$t = ' ['.$t.']';
}
$short_datetime_format = $this->get_short_date_format().$t;
}
return $short_datetime_format;
}
function date_format2($format, $timestamp = false, $_user = false, $input_format = DATE_FORMAT_UNIXTIME) {
global $tikilib;
return $tikilib->date_format($format, $timestamp, $_user, $input_format, false);
}
function date_format($format, $timestamp = false, $_user = false, $input_format = DATE_FORMAT_UNIXTIME, $is_strftime_format = true) {
global $tikidate, $tikilib;
if ( ! $timestamp ) {
$timestamp = time();
}
$tikidate->setTZbyID('UTC');
$tikidate->setDate($timestamp, $input_format);
$tz = $tikilib->get_display_timezone($_user);
// If user timezone is not also in UTC, convert the date
if ( $tz != 'UTC' ) {
$tikidate->convertTZByID($tz);
}
return $tikidate->format($format, $is_strftime_format);
}
function make_time($hour,$minute,$second,$month,$day,$year) {
global $tikidate, $tikilib, $prefs;
$display_tz = $tikilib->get_display_timezone();
if ( $display_tz == '' ) $display_tz = 'UTC';
$tikidate->setTZbyID($display_tz);
$tikidate->setLocalTime($day,$month,$year,$hour,$minute,$second,0);
return $tikidate->getTime();
}
function get_long_date($timestamp, $user = false) {
return $this->date_format($this->get_long_date_format(), $timestamp, $user);
}
function get_short_date($timestamp, $user = false) {
return $this->date_format($this->get_short_date_format(), $timestamp, $user);
}
function get_long_time($timestamp, $user = false) {
return $this->date_format($this->get_long_time_format(), $timestamp, $user);
}
function get_short_time($timestamp, $user = false) {
return $this->date_format($this->get_short_time_format(), $timestamp, $user);
}
function get_long_datetime($timestamp, $user = false) {
return $this->date_format($this->get_long_datetime_format(), $timestamp, $user);
}
function get_short_datetime($timestamp, $user = false) {
return $this->date_format($this->get_short_datetime_format(), $timestamp, $user);
}
/**
Per http://www.w3.org/TR/NOTE-datetime
*/
function get_iso8601_datetime($timestamp, $user = false) {
return $this->date_format('%Y-%m-%dT%H:%M:%S%O', $timestamp, $user);
}
function get_compact_iso8601_datetime($timestamp, $user = false) {
// no dashes and no tz info - latter should be fixed
return $this->date_format('%Y%m%dT%H%M%S', $timestamp, $user);
}
function list_languages($path = false, $short=null, $all=false) {
$languages = array();
if (!$path)
$path = "lang";
if (!is_dir($path))
return array();
$h = opendir($path);
while ($file = readdir($h)) {
if (strpos($file,'.') === false && $file != 'CVS' && $file != 'index.php' && is_dir("$path/$file") && file_exists("$path/$file/language.php")) {
$languages[] = $file;
}
}
closedir ($h);
// Format and return the list
return TikiLib::format_language_list($languages, $short, $all);
}
function is_valid_language( $language ) {
return preg_match("/^[a-zA-Z-_]*$/", $language)
&& file_exists('lang/' . $language . '/language.php');
}
/**
* @return array of css files in the style dir
*/
function list_styles() {
global $tikidomain, $csslib;
$sty = array();
$style_base_path = $this->get_style_path(); // knows about $tikidomain
if ($style_base_path) {
$sty = $csslib->list_css($style_base_path);
}
if ($tikidomain) {
$sty = array_unique(array_merge($sty, $csslib->list_css('styles')));
}
foreach($sty as &$s) { // add the .css back onto the end of the style names
$s .= '.css'; // i started to change this but it hits too many places
} // Another TODO for 4.0 (sorry)
sort($sty);
return $sty;
/* What is this $tikidomain section?
* Some files that call this method used to list styles without considering
* $tikidomain, now they do. They're listed below:
*
* tiki-theme_control.php
* tiki-theme_control_objects.php
* tiki-theme_control_sections.php
* tiki-my_tiki.php
* modules/mod-switch_theme.php
*
* lfagundes
*
* Tiki 3.0 - now handled by get_style_path()
* jonnybradley
*/
}
/**
* @param $a_style - main style (e.g. "thenews.css")
* @return array of css files in the style options dir
*/
function list_style_options($a_style='') {
global $prefs, $csslib;
if (empty($a_style)) {
$a_style = $prefs['style'];
}
$sty = array();
$option_base_path = $this->get_style_path($a_style).'options/';
if (is_dir($option_base_path)) {
$sty = $csslib->list_css($option_base_path);
}
if (count($sty)) {
foreach($sty as &$s) { // add .css back as above
$s .= '.css';
}
sort($sty);
array_unshift ( $sty, tra('None'));
return $sty;
} else {
return false;
}
}
/**
* @param $stl - main style (e.g. "thenews.css")
* @return string - style passed in up to - | or . char (e.g. "thenews")
*/
function get_style_base($stl) {
$parts = split("-|\.", $stl);
if (count($parts) > 0) {
return $parts[0];
} else {
return '';
}
}
/**
* @param $stl - main style (e.g. "thenews.css" - can be empty to return main styles dir)
* @param $opt - optional option file name (e.g. "purple.css")
* @param $filename - optional filename to look for (e.g. "purple.png")
* @return path to dir or file if found or empty if not - e.g. "styles/mydomain.tld/thenews/options/purple/"
*/
function get_style_path($stl = '', $opt = '', $filename = '') {
global $tikidomain;
$path = '';
$dbase = '';
if ($tikidomain && is_dir("styles/$tikidomain")) {
$dbase = $tikidomain.'/';
}
$sbase = '';
if (!empty($stl)) {
$sbase = $this->get_style_base($stl).'/';
}
if (!is_dir('styles/'.$dbase.$sbase)) { // if the style dir doesn't exist in tikidomain, use root/styles
$dbase = '';
}
$obase = '';
if (!empty($opt)) {
$obase = 'options/';
if ($opt != $filename) { // exception for getting option.css as it doesn't live in it's own dir
$obase .= substr($opt, 0, strlen($opt) - 4).'/';
}
}
if (is_dir('styles/'.$dbase.$sbase)) {
if (empty($filename)) {
if (is_dir('styles/'.$dbase.$sbase.$obase)) {
$path = 'styles/'.$dbase.$sbase.$obase;
} else {
$path = 'styles/'.$dbase.$sbase; // fall back to "parent" style dir if no option one
}
} else {
if (is_file('styles/'.$dbase.$sbase.$obase.$filename)) {
$path = 'styles/'.$dbase.$sbase.$obase.$filename;
} else if (is_file('styles/'.$dbase.$sbase.$filename)) { // try "parent" style dir if no option one
$path = 'styles/'.$dbase.$sbase.$filename;
} else if (is_file('styles/'.$sbase.$obase.$filename)) { // try non-tikidomain dirs if not found
$path = 'styles/'.$sbase.$obase.$filename;
} else if (is_file('styles/'.$sbase.$filename)) {
$path = 'styles/'.$sbase.$filename; // fall back to "parent" style dir if no option one
}
}
}
return $path;
}
// Comparison function used to sort languages by their name in the
// current locale.
function formatted_language_compare($a, $b) {
return strcmp($a['name'], $b['name']);
}
// Returns a list of languages formatted as a twodimensionel array
// with 'value' being the language code and 'name' being the name of
// the language.
// if $short is 'y' returns only the localized language names array
function format_language_list($languages, $short=null, $all=false) {
// The list of available languages so far with both English and
// translated names.
global $langmapping, $prefs;
include_once("lang/langmapping.php");
$formatted = array();
// run through all the language codes:
if (isset($short) && $short == "y") {
foreach ($languages as $lc) {
if ( empty($prefs['available_languages'] ) || (!$all and in_array($lc,$prefs['available_languages']))) {
if (isset($langmapping[$lc]))
$formatted[] = array('value' => $lc, 'name' => $langmapping[$lc][0]);
else
$formatted[] = array('value' => $lc, 'name' => $lc);
}
usort($formatted, array('TikiLib', 'formatted_language_compare'));
}
return $formatted;
}
foreach ($languages as $lc) {
if (empty($prefs['available_languages']) || (!$all and in_array($lc,$prefs['available_languages'])) or $all) {
if (isset($langmapping[$lc])) {
// known language
if ($langmapping[$lc][0] == $langmapping[$lc][1]) {
// Skip repeated text, 'English (English, en)' looks silly.
$formatted[] = array(
'value' => $lc,
'name' => $langmapping[$lc][0] . " ($lc)"
);
} else {
$formatted[] = array(
'value' => $lc,
'name' => $langmapping[$lc][1] . " (" . $langmapping[$lc][0] . ', ' . $lc . ")"
);
}
} else {
// unknown language
$formatted[] = array(
'value' => $lc,
'name' => tra("Unknown language"). " ($lc)"
);
}
}
}
// Sort the languages by their name in the current locale
usort($formatted, array('TikiLib', 'formatted_language_compare'));
return $formatted;
}
function get_language($user = false) {
global $prefs;
static $language = false;
if (!$language) {
if ($user) {
$language = $this->get_user_preference($user, 'language', 'default');
if (!$language || $language == 'default') {
$language = $prefs['language'];
}
} else {
$language = $prefs['language'];
}
}
return $language;
}
function read_raw($text) {
$file = split("\n",$text);
$back = '';
foreach ($file as $line) {
$r = $s = '';
if (substr($line,0,1) != "#") {
if( ereg("^\[([A-Z0-9]+)\]",$line,$r) ) {
$var = strtolower($r[1]);
}
if (isset($var) and (ereg("^([-_/ a-zA-Z0-9]+)[ \t]+[:=][ \t]+(.*)",$line,$s))) {
$back[$var][trim($s[1])] = trim($s[2]);
}
}
}
return $back;
}
function httpScheme() {
global $url_scheme;
return $url_scheme;
}
function httpPrefix() {
global $url_scheme, $url_host, $url_port;
return $url_scheme.'://'.$url_host.(($url_port!='')?":$url_port":'');
}
function distance($lat1,$lon1,$lat2,$lon2) {
// This function uses a pure spherical model
// it could be improved to use the WGS84 Datum
// Franck Martin
$lat1rad=deg2rad($lat1);
$lon1rad=deg2rad($lon1);
$lat2rad=deg2rad($lat2);
$lon2rad=deg2rad($lon2);
$distance=6367*acos(sin($lat1rad)*sin($lat2rad)+cos($lat1rad)*cos($lat2rad)*cos($lon1rad-$lon2rad));
return($distance);
}
/**
* returns a list of usergroups where the user is a member and the group has the right perm
* sir-b
**/
function get_groups_to_user_with_permissions($user,$perm) {
$userid = $this->get_user_id($user);
$query = "SELECT DISTINCT `users_usergroups`.`groupName` AS `groupName`";
$query.= "FROM `users_grouppermissions`, `users_usergroups` ";
$query.= "WHERE `users_usergroups`.`userId` = ? AND ";
$query.= "`users_grouppermissions`.`groupName` = `users_usergroups`.`groupName` AND ";
$query.= "`users_grouppermissions`.`permName` = ? ";
$query.= "ORDER BY `groupName`";
$result = $this->query($query, array((int)$userid, $perm));
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
return $ret;
}
function other_value_in_tab_line($tab, $valField1, $field1, $field2) {
foreach ($tab as $line) {
if ($line[$field1] == $valField1)
return $line[$field2];
}
}
function get_attach_hash_file_name($file_name) {
global $prefs;
do {
$fhash = '§'.md5($file_name.date('U').rand()).'§';
} while (file_exists($prefs['w_use_dir'].$fhash));
return $fhash;
}
function attach_file($file_name, $file_tmp_name, $store_type) {
global $prefs;
$tmp_dest = $prefs['tmpDir'] . "/" . $file_name.".tmp";
if (!move_uploaded_file($file_tmp_name, $tmp_dest))
return array("ok"=>false, "error"=>tra('Errors detected'));
$fp = fopen($tmp_dest, "rb");
$data = '';
$fhash = '';
$chunk = '';
if ($store_type == 'dir') {
$fhash = $this->get_attach_hash_file_name($file_name);
$fw = fopen($prefs['w_use_dir'].$fhash, "wb");
if (!$fw)
return array("ok"=>false, "error"=>tra('Cannot write to this file:').$prefs['w_use_dir'].$fhash);
}
while(!feof($fp)) {
$chunk = fread($fp, 8192*16);
if ($store_type == 'dir') {
fwrite($fw, $chunk);
}
$data .= $chunk;
}
fclose($fp);
unlink($tmp_dest);
if ($store_type == 'dir') {
fclose($fw);
$data = "";
}
return array("ok"=>true, "data"=>$data, "fhash"=>$fhash);
}
/* to get the length of a data without the quoted part (very
approximative) */
function strlen_quoted($data) {
global $prefs;
$data = preg_replace('/{QUOTE\([^\)]*\)}.*{QUOTE}/Ui', '', $data);
if ($prefs['feature_use_quoteplugin'] != 'y') {
$data = preg_replace('/^>.*\\n?/m', '', $data);
}
return strlen($data);
}
function list_votes($id, $offset=0, $maxRecords=-1, $sort_mode='user_asc', $find='', $table='', $column='', $from='', $to='') {
$mid = 'where `id`=?';
$bindvars[] = $id;
$select = '';
$join = '';
if (!empty($find)) {
$mid .= ' and (`user` like ? or `title` like ? or `ip` like ?)';
$bindvars[] = '%'.$find.'%';
$bindvars[] = '%'.$find.'%';
$bindvars[] = '%'.$find.'%';
}
if (!empty($from) && !empty($to)) {
$mid .= ' and ((time >= ? and time <= ?) or time = ?)';
$bindvars[] = $from;
$bindvars[] = $to;
$bindvars[] = 0;
}
if (!empty($table) && !empty($column)) {
$select = ", `$table`.`$column` as title";
$join = "left join `$table` on (`tiki_user_votings`.`optionId` = `$table`.`optionId`)";
}
$query = "select * $select from `tiki_user_votings` $join $mid order by ".$this->convert_sortmode($sort_mode);
$query_cant = "select count(*) from `tiki_user_votings` $join $mid";
$result = $this->query($query, $bindvars, $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars);
$ret = array();
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
$retval = array();
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/* get explicit message on upload problem */
function uploaded_file_error($iError) {
switch($iError) {
case 0: return tra('You are not allowed to upload this type of file.');
case 1: return tra('Cannot upload this file maximum upload size exceeded').'(upload_max_filesize)';
case 2: return tra('Cannot upload this file maximum upload size exceeded');
case 3: return tra('The file you are trying upload was only partially uploaded.');
case 4: return tra('You must select a file.');
default: return tra('The file you are trying upload was only partially uploaded.');
}
}
function get_flags($with_names = false, $translate = false, $sort_names = false) {
$flags = array();
$h = opendir("img/flags/");
while ($file = readdir($h)) {
if (strstr($file, ".gif")) {
$parts = explode('.', $file);
$flags[] = $parts[0];
}
}
closedir ($h);
sort($flags);
if ( $with_names ) {
$ret = array();
foreach ( $flags as $f ) {
$ret[$f] = strtr($f, '_', ' ');
if ( $translate ) {
$ret[$f] = tra($ret[$f]);
}
}
if ( $sort_names ) {
asort($ret, SORT_STRING);
}
return $ret;
}
return $flags;
}
function get_snippet($data, $is_html='n', $highlight='', $length=240) {
global $prefs;
if ($prefs['search_parsed_snippet'] == 'y') {
$_REQUEST['redirectpage'] = 'y'; //do not interpret redirect
$data = $this->parse_data($data, array('is_html' => $is_html));
$data = strip_tags($data);
}
return substr($data, 0, $length);
}
function htmldecode($string, $quote_style = ENT_COMPAT, $translation_table = HTML_ENTITIES) {
if ( $translation_table == HTML_ENTITIES && version_compare(phpversion(), '5', '>=') ) {
// Use html_entity_decode with UTF-8 only with PHP 5.0 or later, since
// this function was available in PHP4 but _without_ multi-byte charater sets support
$string = html_entity_decode($string, $quote_style, 'utf-8');
} elseif ( $translation_table == HTML_SPECIALCHARS && version_compare(phpversion(), '5.1.0', '>=') ) {
// Only available in PHP 5.1.0 or later
$string = htmlspecialchars_decode($string, $quote_style);
} else {
// For compatibility purposes with php < 5
$trans_tbl = array_flip(get_html_translation_table($translation_table));
// Not translating double quotes
if ($quote_style & ENT_NOQUOTES) {
// Remove double quote from translation table
unset($trans_tbl['"']);
}
$string = strtr($string, $trans_tbl);
if (function_exists('recode_string')) {
$string = recode_string('iso-8859-15..utf-8', $string);
}
}
$string = preg_replace('~([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
$string = preg_replace('~([0-9]+);~e', 'chr(\\1)', $string);
return $string;
}
function take_away_accent($str) {
$accents = explode(' ', 'À Á Â Ã Ä Å Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ù Ú Û Ü Ý ß à á â ã ä å ç è é ê ë ì í î ï ñ ò ó ô õ ö ù ú û ü ý Æ æ');
$convs = explode(' ', 'A A A A A A C E E E E I I I I D N O O O O O U U U U Y s a a a a a a c e e e e i i i i n o o o o o u u u u y AE ae');
return str_replace($accents, $convs, $str);
}
/* return the positions in data where the hdr-nth header is find
*/
function get_wiki_section($data, $hdr) {
$start = 0;
$end = strlen($data);
$lines = explode("\n", $data);
$header = 0;
$pp_level = 0;
$np_level = 0;
for ($i = 0; $i < count($lines); ++$i) {
$pp_level += preg_match ('/~pp~/',$lines[$i]);
$pp_level -= preg_match ('/~\/pp~/',$lines[$i]);
$np_level += preg_match ('/~np~/',$lines[$i]);
$np_level -= preg_match ('/~\/np~/',$lines[$i]);
// We test if we are inside nonparsed or pre section to ignore !*
if ($pp_level%2 == 0 and $np_level%2 == 0) {
if (substr($lines[$i], 0, 1) == '!') {
++$header;
if ($header == $hdr) { // we are on it - now find the next header at same or lower level
$level = $this->how_many_at_start($lines[$i], '!');
$end = strlen($lines[$i]) + 1;
for (++$i; $i < count($lines); ++$i) {
if (substr($lines[$i], 0, 1) == '!' && $level >= $this->how_many_at_start($lines[$i], '!')) {
return (array($start, $end));
}
$end += strlen($lines[$i]) + 1;
}
break;
}
}
}
$start += strlen($lines[$i]) + 1;
}
return (array($start, $end));
}
/**
* \brief Function to embed a flash object (using JS method by default when JS in user's browser is detected)
*
* So far it's being called from wikiplugin_flash.php and tiki-edit_banner.php
*
* @param javascript = y or n to force to generate a version with javascript or not, ='' user prefs
*/
function embed_flash($params, $javascript='', $flashvars = false) {
global $prefs;
global $headerlib; include_once('lib/headerlib.php');
if (! isset($params['movie']) ) {
return false;
}
$defaults = array(
'width' => 425,
'height' => 350,
'quality' => 'high',
'version' => '9.0.0',
);
$params = array_merge( $defaults, $params );
if ( ((empty($javascript) && $prefs['javascript_enabled'] == 'y') || $javascript == 'y')) {
$myId = (!empty($params['id'])) ? ($params['id']) : 'wp-flash-' . md5($params['movie']);
$movie = '"'.$params['movie'].'"';
$div = json_encode( $myId );
$width = (int) $params['width'];
$height = (int) $params['height'];
$version = json_encode( $params['version'] );
unset( $params['movie'], $params['width'], $params['height'], $params['version'] );
$params = json_encode($params);
if (!$flashvars) {
$flashvars = '{}';
} else {
$flashvars = json_encode($flashvars);
$flashvars = str_replace('\\/', '/', $flashvars);
}
$js = <<add_jsfile( 'lib/swfobject/swfobject.js' );
return "
" . tra('Flash player not available.') . "
\n";
} else { // link on the movie will not work with IE6
extract ($params,EXTR_SKIP);
$asetup = "";
return $asetup;
}
}
// TikiWiki version of parse_str, that:
// - uses a workaround for a bug in PHP 5.2.0
// - Handle the value of magic_quotes_gpc to stripslashes when needed (as already done for GET/POST/... in tiki-setup_base.php)
function parse_str($str, &$arr) {
parse_str($str, $arr);
/* From PHP Manual comments (quoting Vladimir Kornea):
* parse_str() contained a bug (#39763) in PHP 5.2.0 that caused it to apply magic quotes twice.
* This bug was marked as fixed in the release notes of PHP 5.2.1, but there were apparently some
* issues with getting the fix through CVS on time, as our install of PHP 5.2.1 was still affected by it.
*/
if ( version_compare(PHP_VERSION, '5.2.0', '>=') && version_compare(PHP_VERSION, '5.2.1', '<') ) {
$arr = array_map('stripslashes', $arr);
}
// parse_str's behavior also depends on magic_quotes_gpc...
global $magic_quotes_gpc;
if ( $magic_quotes_gpc ) remove_gpc($arr);
}
function bindvars_to_sql_in(&$bindvars, $remove_duplicates = false, $cast_to_int = false) {
if ( ! is_array($bindvars) ) return false;
$query = ' IN (';
$bindvars2 = array();
foreach ( $bindvars as $id ) {
if ( $cast_to_int ) $id = (int)$id;
if ( $remove_duplicates && in_array($id, $bindvars2) ) continue;
$bindvars2[] = $id;
if ( $query == '' ) $query .= ',';
$query .= '?';
}
if ( $remove_duplicates ) $bindvars = $bindvars2;
return ' IN (' . $query . ')';
}
}
// end of class ------------------------------------------------------
// function to check if a file or directory is in the path
// returns FALSE if incorrect
// returns the canonicalized absolute pathname otherwise
function inpath($file,$dir) {
$realfile=realpath($file);
$realdir=realpath($dir);
if (!$realfile) return (FALSE);
if (!$realdir) return (FALSE);
if (substr($realfile,0,strlen($realdir))!= $realdir) {
return(FALSE);
} else {
return($realfile);
}
}
function compare_links($ar1, $ar2) {
return $ar1["links"] - $ar2["links"];
}
function compare_backlinks($ar1, $ar2) {
return $ar1["backlinks"] - $ar2["backlinks"];
}
function r_compare_links($ar1, $ar2) {
return $ar2["links"] - $ar1["links"];
}
function r_compare_backlinks($ar1, $ar2) {
return $ar2["backlinks"] - $ar1["backlinks"];
}
function compare_images($ar1, $ar2) {
return $ar1["images"] - $ar2["images"];
}
function r_compare_images($ar1, $ar2) {
return $ar2["images"] - $ar1["images"];
}
function compare_files($ar1, $ar2) {
return $ar1["files"] - $ar2["files"];
}
function r_compare_files($ar1, $ar2) {
return $ar2["files"] - $ar1["files"];
}
function compare_versions($ar1, $ar2) {
return $ar1["versions"] - $ar2["versions"];
}
function r_compare_versions($ar1, $ar2) {
return $ar2["versions"] - $ar1["versions"];
}
function compare_changed($ar1, $ar2) {
return $ar1["lastChanged"] - $ar2["lastChanged"];
}
function r_compare_changed($ar1, $ar2) {
return $ar2["lastChanged"] - $ar1["lastChanged"];
}
function chkgd2() {
if (!isset($_SESSION['havegd2'])) {
# TODO test this logic in PHP 4.3
# if (version_compare(phpversion(), "4.3.0") >= 0) {
# $_SESSION['havegd2'] = true;
# } else {
ob_start();
phpinfo (INFO_MODULES);
$_SESSION['havegd2'] = preg_match('/GD Version.*2.0/', ob_get_contents());
ob_end_clean();
# }
}
return $_SESSION['havegd2'];
}
function detect_browser_language() {
// Get supported languages
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
$supported = preg_split('/\s*,\s*/', preg_replace('/;q=[0-9.]+/','',$_SERVER['HTTP_ACCEPT_LANGUAGE']));
else
return '';
// Get available languages
$available = array();
$available_aprox = array();
if (is_dir("lang")) {
$dh = opendir("lang");
while ($lang = readdir($dh)) {
if (!strpos($lang,'.') and is_dir("lang/$lang") and file_exists("lang/$lang/language.php")) {
$available[strtolower($lang)] = $lang;
$available_aprox[substr(strtolower($lang), 0, 2)] = $lang;
}
}
}
// Check better language
// Priority has been changed in 2.0 to that defined in RFC 4647
$aproximate_lang = '';
foreach ($supported as $supported_lang) {
$lang = strtolower($supported_lang);
if (in_array($lang, array_keys($available))) {
// exact match is always good
return $available[$lang];
} elseif (in_array($lang, array_keys($available_aprox))) {
// otherwise if supported language matches any available dialect, ok also
return $available_aprox[$lang];
} elseif ($aproximate_lang == '') {
// otherwise if supported dialect matches language, store as possible fallback
$lang = substr($lang, 0, 2);
if (in_array($lang, array_keys($available_aprox))) {
$aproximate_lang = $available_aprox[$lang];
}
}
}
return $aproximate_lang;
}
function alterprefs() {
global $tikilib;
if (!$tikilib->query( "ALTER TABLE `tiki_preferences` MODIFY `value` BLOB", array())) {
$smarty->assign("msg", tra('Altering database table failed'));
$smarty->display("error.tpl");
die;
}
return true;
}
function validate_email($email,$checkserver='n') {
global $prefs;
$valid_syntax = eregi($prefs['valid_email_regex'], $email);
if (!$valid_syntax) {
return false;
} elseif ($checkserver == 'y') {
include_once('Net/DNS.php');
$resolver = new Net_DNS_Resolver();
$domain = substr(strstr($email,'@'),1);
$answer = $resolver->query($domain,'MX');
if (!$answer) {
return false;
} else {
foreach ($answer->answer as $server) {
$mxserver[$server->preference] = $server->exchange;
}
krsort($mxserver);
foreach ($mxserver as $server) {
$test = fsockopen($server,25,$errno,$errstr,15);
if ($test) {
fclose($test);
return true;
}
fclose($test);
}
return false;
}
} else {
return true;
}
}
function tiki_get_remote_file( $url ) {
if( ini_get( 'allow_url_fopen' ) )
return file_get_contents( $url );
elseif( function_exists( 'curl_init' ) ) {
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_HEADER, false );
curl_setopt( $ch, CURLOPT_NOBODY, false );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, false );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
return curl_exec( $ch );
} else {
return false;
}
}
/* Editor configuration
Local Variables:
tab-width: 4
c-basic-offset: 4
End:
* vim: fdm=marker tabstop=4 shiftwidth=4 noet:
*/
?>