<? /* Jorge - frontend for mod_logdb - ejabberd server-side message archive module. Copyright (C) 2009 Zbigniew Zolkiewski This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ if (__FILE__==$_SERVER['SCRIPT_FILENAME']) { header("Location: index.php?act=logout"); exit; } function get_user_agent($_SERVER) { if (preg_match("/Macintosh/i",$_SERVER['HTTP_USER_AGENT'])) { return true; } else{ return false; } return false; } function getmicrotime(){ list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); } function query_nick_name($ejabberd_roster,$talker, $server="") { $nickname = $ejabberd_roster->get_nick("$talker"."@"."$server"); if ($nickname=="") { $nickname=$talker; } return $nickname; } function validate_date($tslice) { list($ye, $mo, $da) = split("-", $tslice); return checkdate($mo,$da,$ye); } function check_registered_user ($sess,$ejabberd_rpc,$enc) { if (!$sess->is_registered('uid_l') OR !$sess->is_registered('uid_p')) { return false; } else { if ($enc->decrypt_url($sess->get('uid_p')) === true) { $uid_p = $enc->single; } else { return false; } $ejabberd_rpc->set_user($sess->get('uid_l'),$uid_p); if ($ejabberd_rpc->auth() === true) { return true; } else { return false; } } return false; } function is_query_from($query) { list($from,$talker,$query_p) = split(":",$query); $from=trim($from); if ($from=="from") { $qquery[from] = "t"; $qquery[talker] = trim($talker); $qquery[talker] = str_replace("//","@",$qquery[talker]); // hack for parametrized search if ($query_p) { $qquery[query] = $query_p; $qquery[words] = "t"; return $qquery; } else { $qquery[words] = "f"; return $qquery; } } else { // normal search return "f"; } } function verbose_date($raw_date,$months_names = null,$weekdays = null,$t = false,$y = false) { // English calendar arrays. Here we convert names from english calendar to other language. Make sure your locale in php work with default set to english. $english_months = array("January","February", "March", "April", "May","June","July","August","September","October", "November","December"); $english_days = array("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"); // Various formats if ($t === true) { return str_replace($english_days,$weekdays,strftime("%e.%m (%A)",strtotime("$raw_date"))); } elseif($y === true) { return str_replace($english_months,$months_names,strftime("%B %Y", strtotime("$raw_date"))); } else{ return str_replace($english_months,$months_names,strftime("%e %B %Y", strtotime("$raw_date"))); } } function validate_start($start) { if (!ctype_digit($start)) { return false; } if (fmod($start,10)=="0") { return true; } else { return false; } } function db_size() { $result = mysql_query("show table status"); $size = 0; while($row = mysql_fetch_array($result)) { $size += $row["Data_length"]; } $size = round(($size/1024)/1024, 1); return $size; } function verbose_split_line($in_minutes,$verb_h,$in_min) { if ($in_minutes>60) { return $verb_h; } elseif ($in_minutes<60) { return $in_minutes." ".$in_min; } } function cut_nick($nick) { if (strlen($nick)> 25) { $nick=substr($nick,0,25)."..."; } return $nick; } function new_parse_url($text) { $text = ereg_replace("([[:alpha:]]+://www|[[:alpha:]]+://)[^<>[:space:]]+[[:alnum:]/]", "<a class=\"clickl\" href=\"\\0\" target=\"_blank\">\\0</a>", $text); // disabled for now #$text = ereg_replace("[^://]?www[^<>[:space:]]+[[:alnum:]/]", # "<a class=\"clickl\" href=\"http://\\0\" target=\"_blank\">\\0</a>", $text); return $text; } function calendar($db,$user_id,$xmpp_host,$y,$m,$days,$token,$url_key,$left,$right,$selected,$lang,$view_type,$c_type,$name_peer=0,$server_peer=0,$cal_days=0,$enc=null,$months_names,$weekdays) { $days=$days; $month = $m; $year = $y; //create arrays for the calendar $months_days = array("31","28","31","30","31","30","31","31", "30","31","30","31"); $days_array = array("Mon","Tue","Wed","Thu","Fri","Sat","Sun"); //removes the 0 from start of month - can't find array key with 0 if(strlen($month)==1){ $month= str_replace("0","",$month); } else{ $month=$month; } //reset month to the array key match (array starts at 0) $month= $month-1; //find the days in the month $days_in_month = $months_days[$month]; //$m is used to find month $m = $month+1; //find the first day of the month $time = date("M D Y H:i:s", mktime(0, 0, 0, $m, 1, $year)); $first_day = explode(" ",$time); $time = $first_day[1]; //create the links to next and previous months $next = $month+2; $x = $year; //if month is 13 then new year if($next==13){ $next=1; $x = $x+1; } $prev = $month; $y = $year; //if month is 0, then previous year if($prev==0){ $prev=12; $y=$y-1; } $calendar = ""; //Build the calendar with css //links to next and previous month only for browser if ($c_type=="1") { // encode links $link_left = $enc->crypt_url("tslice=$y-$prev"); $link_right = $enc->crypt_url("tslice=$x-$next"); // check if we have chats in prev and next mo $db->is_left_or_right("$y-$prev"); $i_left = $db->result; $db->is_left_or_right("$x-$next"); $i_right = $db->result; } else { $i_left=0; $i_right=0; } $calendar .=' <table width="200" border="0" cellpadding="0" cellspacing="0" class="calbck"> <tr> <td><img src="img/cal_corn_11.png" width="15" height="7" alt="cal_img"></td> <td style="background-image: url(img/cal_bck_top.gif);"></td> <td><img src="img/cal_corn_12.png" width="14" height="7" alt="cal_img"></td> </tr> <tr> <td width="15" valign="top" class="calbckleft"><img src="img/cal_bck_left.png" width="15" height="116" alt="cal_img"> </td> <td width="100%" valign="top"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td height="15" align="center" class="caldays"> '; if ($i_left!=0) { $calendar.='<a href="?left='.$link_left.'"><<<</a>'; } $verb_date = "$year-$m-1"; $calendar.=' </td> <td colspan="5" align="center" class="calhead">'.verbose_date($verb_date,$months_names,$weekdays,false,true).'</td> <td align="center" class="caldays"> '; if ($i_right!=0) { $calendar.='<a href="?right='.$link_right.'">>>></a>'; } $calendar.=' </td> </tr> <tr align="center" class="calweek"> <td width="14%" height="15">'.$cal_days[$lang][1].'</td> <td width="14%">'.$cal_days[$lang][2].'</td> <td width="14%">'.$cal_days[$lang][3].'</td> <td width="14%">'.$cal_days[$lang][4].'</td> <td width="14%">'.$cal_days[$lang][5].'</td> <td width="14%">'.$cal_days[$lang][6].'</td> <td width="14%">'.$cal_days[$lang][7].'</td> </tr> '; //checks for leap years and add 1 to February if(($year % 4 =="") && ($month==1)){ $days_in_month=$days_in_month+1; } else{ $days_in_month=$days_in_month; } $new_time=""; //find how many blank spaces at beginning of the month foreach($days_array as $key=>$value){ if($value == $time){ $new_time .= $key+1; } else{ $new_time .=""; } } //loop through the days in the month $c=0; for($k=1;$k<($days_in_month+$new_time);$k++){ $c++; if ($c==1) { $calendar.='<tr align="center" class="caldays">'; } //blank space if($k<$new_time){ $calendar.='<td height="15"> </td> '; continue; } //start the actual days $n = $k-$new_time+1; if(in_array($n,$days)){ if ($c_type=="1") { $to_base = $enc->crypt_url("tslice=$year-$m-$n"); $loc_orign=""; } elseif($c_type=="2") { $to_base = $enc->crypt_url("tslice=$year-$m-$n&peer_name_id=$name_peer&peer_server_id=$server_peer"); $loc_orign="&loc=2"; } if ($selected==$n) { $bgcolor = 'bgcolor="#6daae7"'; } else { $bgcolor=""; } $calendar .= '<td height="15" '.$bgcolor.' onclick="window.location=\''.$view_type.'?a='.$to_base.$loc_orign.'\'"><b><a class="caldays2" href="'.$view_type.'?a='.$to_base.$loc_orign.'">'.$n.'</a></b></td> '; } else{ $calendar .= '<td height="15">'.$n.'</td> '; } if ($c==7) { $calendar.='</tr>'; $c=0; } } $calendar .= ' </table> </td> <td width="14" valign="top" class="calbckright"><img src="img/cal_bck_right.png" width="14" height="116" alt="cal_img"></td> </tr> <tr> <td><img src="img/cal_corn_21.png" width="15" height="16" alt="cal_img"></td> <td style="background-image: url(img/cal_bck_bot.png);"></td> <td><img src="img/cal_corn_22.png" width="14" height="16" alt="cal_img"></td> </tr> </table> '; return($calendar); } function check_thread($db,$peer_name_id,$peer_server_id,$at,$xmpp_host,$dir=NULL) { #adjust this hours as needed, we assume if chat is +/- 1 hour on the edge of day, then chat is related if ($dir=="1") { $day="+1 day"; $bhour="00:00:00"; $ehour="00:30:00"; } elseif($dir=="2"){ $day="-1 day"; $bhour="23:30:00"; $ehour="23:59:59"; } $get_date = date("Y-n-j", strtotime($day, strtotime(date("$at")))); $db->check_thread($get_date,$peer_name_id,$peer_server_id,$bhour,$ehour); if ($db->result > 0) { return true; } else{ return false; } return false; } function check_rpc_server($rpc_arr,$rpc_port) { foreach($rpc_arr as $rpc_host) { // assume if response time is greater then 1 second RPC server is down $fp=fsockopen("$rpc_host", $rpc_port, $errno, $errstr, 1); if ($fp!=false) { return $rpc_host; } } return false; } function debug($debug=false,$string) { if ($debug===true) { print "<small>".htmlspecialchars($string)."</small><br>"; } return; } function message_processor($tslice,$server_name,$start,$nickname,$result_messages,$db,$html,$enc,$token,$split_line,$lang_pack,$lang,$spec_mark,$e_string,$to_base_prev,$to_base_next) { /* This function perform message processing for message archives tslice - date of chat server_name - name of server start - from what point of time of day should chat be displayed nickname - peer nickname result_messages - array of messages to be parsed db - database object html - html object enc - encryption object token - owner name split_line - config option lang_pack - array of translations lang - language pack spec_mark - marker used to distinguish what we are doing e_string - url */ // Check if user have set up OwnName $db->get_own_name(); if ($db->result->own_name) { $own_name = $db->result->own_name; } else{ $own_name = false; } // Main loop foreach($result_messages as $entry) { // always get resource_id if message is type of groupchat if ($entry[type] !== "groupchat") { if ($resource_last !== $entry[peer_resource_id]) { if ($db->get_resource_name($entry[peer_resource_id]) === false) { return false; } $resource = $db->result->resource_name; } } else{ if ($db->get_resource_name($entry[peer_resource_id]) === false) { return false; } $resource = $db->result->resource_name; } $resource_last = $entry[peer_resource_id]; $licz++; // marking messages if ($entry["type"] === "chat" OR $entry["type"] == "") { if ($entry["direction"] === "to") { $col="main_row_a"; } else { $col="main_row_b"; } } elseif($entry["type"] === "error") { $col="main_row_error"; } elseif($entry["type"] === "normal") { $col="main_row_message"; } elseif($entry["type"] === "headline") { $col="main_row_headline"; } $ts = strstr($entry["ts"], ' '); // time calc $pass_to_next = $entry["ts"]; $new_d = $entry["ts"]; $time_diff = abs((strtotime("$old_d") - strtotime(date("$new_d")))); $old_d = $pass_to_next; // end time calc if ($time_diff>$split_line AND $licz>1) { $in_minutes = round(($time_diff/60),0); $html->set_body('<tr class="splitl"> <td colspan="7" style="font-size: 10px;"><i>'.verbose_split_line($in_minutes,$lang_pack[7],$lang_pack[8]).'</i> <hr size="1" noshade="noshade" style="color: #cccccc;"></td></tr> '); } // check if chat is continuation from previous day (work only for calendar view) if ($to_base_prev !== NULL) { if ($ts_mark!="1" AND substr($ts, 0 , strpos($ts, ":")) == 00 ) { if ( check_thread($db,$talker,$server,$tslice,$xmpp_host,2) === true) { $html->set_body('<tr><td colspan="6" style="text-align: left; padding-left: 5px;" class="message"><a href="calendar_view.php?a='.$to_base_prev.'">'.$lang_pack[0].'</a></td></tr>'); } // check only first line $ts_mark="1"; } } // run code only if type is not groupchat if ($entry["type"] !== "groupchat") { // setting subject if ($col==="main_row_message" OR $col==="main_row_headline") { if ($entry["subject"]) { $subject = ": ".$entry["subject"]; } else{ unset($subject); } } // add line in case of special message if ($col==="main_row_message") { $html->set_body('<tr class="main_row_message"><td colspan="7" class="main_row_special">'.$lang_pack[1].' '.htmlspecialchars($subject).'</td></tr>'); } if ($col==="main_row_error") { $html->set_body('<tr class="main_row_error"><td colspan="7" class="main_row_special">'.$lang_pack[2].'</td></tr>'); } if ($col==="main_row_headline") { $html->set_body('<tr class="main_row_headline"><td colspan="7" class="main_row_special">'.$lang_pack[3].' '.htmlspecialchars($subject).'</td></tr>'); } } // calculate chat direction, whether to display nick... if ($entry["direction"] == "from") { $out=$nickname; $tt=$tt+1; $aa=0; } else{ $out = $token; $aa=$aa+1; $tt=0; } // timestamp, beginning of the chatline if ($entry["type"] !== "groupchat") { $html->set_body('<tr class="'.$col.'"><td class="time_chat" style="padding-left: 10px; padding-right: 10px;";>'.$ts.'</td>'); } else{ if ($out!==$token) { // colorize if ($resource_group === $resource OR !$resource_group) { if (!$col) { $col = "main_row_group_to"; } $col=$col; } else{ if($col === "main_row_group_from") { $col="main_row_group_to"; } else{ $col="main_row_group_from"; } } $html->set_body('<tr class="'.$col.'"><td class="time_chat" style="padding-left: 10px; padding-right: 10px;";>'.$ts.'</td>'); } } // different bahaviour for groupchat and other messages if ($entry["type"] !== "groupchat") { if ($aa<2 AND $tt<2) { $html->set_body('<td style="padding-left: 5px; padding-right: 10px; nowrap="nowrap">'); if ($out === TOKEN) { // display of Own Name if ($own_name !== false) { $html->set_body(cut_nick(htmlspecialchars($own_name))); } else{ $html->set_body(cut_nick(htmlspecialchars($out))); } } else{ $html->set_body(cut_nick(htmlspecialchars($out))); } $html->set_body('<a name="'.$licz.'"></a>'); if ($out !== $token) { if ($spec_mark === false) { $html->set_body(' <br><div style="text-align: left; padding-left: 5px;"> <a class="export" id="pretty" title="'.$lang_pack[4].'" href="?a='.$e_string.'&b='.$entry[peer_resource_id].'"> <small><i>'.cut_nick(htmlspecialchars($resource)).'</i></small></a></div> '); } else{ $html->set_body('<br><div style="text-align: left; padding-left: 5px;"> <small><i>'.cut_nick(htmlspecialchars($server_name)).'</i></small></div> '); } } $html->set_body('</td>'); $here = "1"; } else { $html->set_body('<td style="text-align: right; padding-right: 5px">-</td>'); $here = "0"; } } else{ // do not display own chats sent to MUC. Here resource is actualy nickname as MUC standard specify if ($out !== $token) { if ($resource_group !== $resource) { // if message is sent without resource, that must be channel message, advise user. if ($resource === "") { $resource = $lang_pack[5]; } $html->set_body('<td style="padding-left: 5px; padding-right: 10px; nowrap="nowrap"><small>MUC: <i>'.cut_nick($out).'</i></small><a name="'.$licz.'"></a> <br><div style="text-align: left; padding-left: 5px;">'.cut_nick(htmlspecialchars($resource)).'</div></td> '); $here = "1"; $resource_group = $resource; } else{ $html->set_body('<td style="text-align: right; padding-right: 5px">-</td>'); $here = "0"; } } else{ $here = "0"; } } // process body part, do not show chat if message is type of groupchat // this is sadly funny i write this 'if' and i dont know what exacly it do :/ if ($out !== $token OR $entry["type"] !== "groupchat") { // prepare body $new_s = htmlspecialchars($entry["body"]); $to_r = array("\n"); $t_ro = array("<br>"); $new_s = str_replace($to_r,$t_ro,$new_s); $new_s = wordwrap($new_s,107,"<br>",true); $new_s = new_parse_url($new_s); $html->set_body('<td width="800" colspan="3">'.$new_s.'</td>'); // generate mylink only on selected lines if ($here==="1") { $lnk = $enc->crypt_url("tslice=$tslice&peer_name_id=$entry[peer_name_id]&peer_server_id=$entry[peer_server_id]"); $to_base2 = $enc->crypt_url("tslice=$tslice&peer_name_id=$entry[peer_name_id]&peer_server_id=$entry[peer_server_id]&ismylink=1&linktag=$licz&lnk=$lnk&strt=$start"); $html->set_body('<td colspan="2" style="padding-left: 2px; font-size: 9px;"><a style="color: #1466bc" href="my_links.php?a='.$to_base2.'">'.$lang_pack[6].'</a></td>'); } else { $html->set_body('<td></td>'); } if ($t=2) { $c=1; $t=0; } // WTF!? $html->set_body('</tr>'); } } $html->set_body('</tbody>'); // Check thread. Work only for calendar view. if ($to_base_next !== NULL) { if (substr($ts, 0 , strpos($ts, ":")) == 23 AND date("Y-n-j") !== $tslice) { if ( check_thread($db,$talker,$server,$tslice,$xmpp_host,1) === true) { $html->set_body('<tr><td colspan="6" style="text-align: right; padding-right: 5px;" class="message"><a href="calendar_view.php?a='.$to_base_next.'">'.$lang_pack[9].'</a></td></tr>'); } } } return true; } function is_language_supported($l_query,$language_support,$l_key = 0, $return_val = false) { while (array_keys($language_support)) { $lang_key = key($language_support); if ($l_query === $language_support[$lang_key][$l_key]) { if ($return_val === true) { return $language_support[$lang_key][0]; } else { return true; } } array_shift($language_support); } return false; } ?>