<?php
	/**************************************************************************\
	* Simple Groupware 0.700                                                   *
	* http://www.simple-groupware.de                                           *
	* Copyright (C) 2002-2011 by Thomas Bley                                   *
	* ------------------------------------------------------------------------ *
	*  This program is free software; you can redistribute it and/or           *
	*  modify it under the terms of the GNU General Public License Version 2   *
	*  as published by the Free Software Foundation; only version 2            *
	*  of the License, no 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       *
	*  Version 2 along with this program; if not, write to the Free Software   *
	*  Foundation, Inc., 59 Temple Place - Suite 330, Boston,                  *
	*  MA  02111-1307, USA.                                                    *
	\**************************************************************************/

define("MAIN_SCRIPT",basename($_SERVER["PHP_SELF"]));

error_reporting(E_ALL);
define("SIMPLE_STORE","../simple_store");
@include(SIMPLE_STORE."/config.php");
if (!defined("SETUP_DB_HOST")) exit;

require("core/functions.php");

set_error_handler("debug_handler");
if (ini_get("register_globals")) modify::dropglobals();
@ignore_user_abort(1);

header("Content-Type: text/plain; charset=utf-8");

if (!defined("SETUP_DB_HOST") or !sql_connect(SETUP_DB_HOST, SETUP_DB_USER, sys_decrypt(SETUP_DB_PW,sha1(SETUP_ADMIN_USER)), SETUP_DB_NAME)) {
  exit(sql_error());
}

$lock_file = SIMPLE_STORE."/cron/lock_cron";

$frequence = CRON_FREQUENCE - 1;
if ($frequence < 299) $frequence = 299;

@set_time_limit(180);
if (!DEBUG and file_exists($lock_file) and filemtime($lock_file)+150 > time() and !isset($_REQUEST["debug"])) {
  exit("already running.");
}
if (!DEBUG and file_exists($lock_file."_last") and filemtime($lock_file."_last")+$frequence > time()) {
  exit("too frequent.");
}
touch($lock_file);

$_SESSION["username"] = "cron";
$_SESSION["password"] = "";

$cron_conf = trigger::sendmail_getconn("cron","");
if (empty($cron_conf["smtp"])) {
  sys_log_message_log("php-fail",sprintf("{t}SMTP not configured for %s{/t}","cron"));
}
$notifications = array();

// syntax: minutes, hours, days, months, weekdays

$where = array("activated=1","(pwdexpires < @time@+(86400*5) or (neverexp!=1 and expires < @time@+(86400*5)))","length(notification)!=0");
cron_notify_module("0 17 * * 1-6","sys_users",array("username","lastname","firstname","email","pwdexpires","expires"),$where,"");

cron_notify_module("0 17 * * 1-6","sys_users",array("lastname","firstname","email","birthday"),array("activated=1","birthday!=0","(birthday_str='".sys_date("m-d",strtotime("+1 day"))."' or birthday_str='".sys_date("m-d",strtotime("+2 days"))."')","length(notification)!=0"),"lastname,firstname");
cron_notify_module("0 17 * * 1-6","contacts",array("lastname","firstname","company","email","birthday"),array("birthday!=0","(birthday_str='".sys_date("m-d",strtotime("+1 day"))."' or birthday_str='".sys_date("m-d",strtotime("+2 days"))."')","length(notification)!=0"),"lastname,firstname");
cron_notify_module("0 17 * * 1-6","sys_users",array("lastname","firstname","email","anniversary"),array("activated=1","anniversary!=0","(anniversary_str='".sys_date("m-d",strtotime("+1 day"))."' or anniversary_str='".sys_date("m-d",strtotime("+2 days"))."')","length(notification)!=0"),"lastname,firstname");

$today = strtotime("00:00:00 +1 day");
$then = strtotime("23:59:59 +1 day");
cron_notify_module("0 17 * * 1-6","calendar",array("subject","begin","ending","allday","location"),array("length(notification)!=0"),"begin",$today,$then);

$today = NOW;
$then = NOW + $frequence;
cron_notify_module("* * * * *","calendar",array("subject","begin","ending","allday","location","reminder_begin"),array("reminder!=0","length(notification)!=0"),"begin",$today,$then);

cron_notify_module("0 5 * * 1-6","tasks",array("subject","begin","ending"),array("begin <= @time@+(86400*2)","closed=0","length(notification)!=0"),"begin");
cron_notify_module("0 17 * * 1-6","contactactivities",array("contactid","subject","begin","ending"),array("begin <= @time@+(86400*2)","finished=0","length(notification)!=0"),"begin");

if (is_array($notifications) and count($notifications)>0) {
  out("sending mails:\n");
  $log = "";
  foreach ($notifications as $email=>$modules) {
    $message = "";
	foreach ($modules as $module=>$notification) {
	  $line = str_repeat("-",strlen($module));
	  $message .= $module."\n".$line."\n\n".implode("\n\n\n",$notification)."\n\n\n";
	}
	$smtp_data = array(
      "efrom"=>"",
      "eto"=>$email,
      "subject"=>SMTP_REMINDER." - ".sys_date("{t}m/d/Y g:i a{/t}"),
      "message"=>trim($message),
      "attachment"=>"",
      "folder"=>"cron",
    );
    $result = asset_process_trigger("sendmail","",$smtp_data);
    if ($result!="") {
      echo "ERROR ".$email.": ".$result."\n";
      sys_log_message_log("php-fail",$result,var_export($smtp_data,true));
    } else {
      $log .= $smtp_data["eto"]." ".$smtp_data["subject"]."\n";
	}
  }
  out($log);
  sys_log_message_log("info","{t}Sent reminders{/t}",$log);
}

// TODO2 process output GLOBALS["alert"] ??

@unlink($lock_file);
touch($lock_file."_last");
out("finished.");

function _cron_build_notification($table,$data,$id) {
  $tfields = $table["fields"];
  $details = "http".(sys_https()?"s":"")."://".$_SERVER['HTTP_HOST'].dirname($_SERVER["SCRIPT_NAME"]).
	"/index.php?view=details&folder=".$data["folder"]."&item%5B%5D=".$id;

  $message = "";
  foreach ($data as $key=>$value) {
    if (strlen($value)==0 or in_array($key,array("id","folder","notification"))) continue;
	if (!isset($tfields[$key]["DISPLAYNAME"]) or !isset($tfields[$key]["SIMPLE_TYPE"])) continue;
	if (empty($tfields[$key]["NO_SEARCH_INDEX"])) {
	  $value = trim(asset::build_history($tfields[$key]["SIMPLE_TYPE"],$value,""));
	  if ($value!="") {
	    $message .= $tfields[$key]["DISPLAYNAME"].": ".$value."\n";
	  }
	}
  }
  $message .= "\n{t}Details{/t}: ".$details;
  if (DEBUG) $message = sys_remove_trans($message);
  
  $recipients = explode(",",$data["notification"]);
  $module = $table["att"]["MODULENAME"];
  foreach ($recipients as $recipient) {
    $GLOBALS["notifications"][trim($recipient)][$module][] = $message;
  }
}

function _cron_build_calendar_where($today,$then,$start="begin",$end="ending") {
  $today_arr = sys_getdate($today);
  $then_arr = sys_getdate($then);

  $rec = "recurrence";
  $until = "until";
  $rstart = "repeatbegin";
  $rend = "repeatend";

  $wtoday = $today_arr["wday"];
  $wthen = $then_arr["wday"];

  $mtoday = $today_arr["mday"];
  $mthen = $then_arr["mday"];

  $ytoday = $today_arr["yday"];
  $ythen = $then_arr["yday"];

  $sql = "(($end between $today and $then) or ($then between $start and $end)";
  $sql .= " or ($start < $then and ($until=0 or $until > $today) and ($rec='days'";
  $sql .= " or ($rec='weeks' and (($rend between $wtoday and $wthen) or ($rend>=$rstart and $wthen between $rstart and $rend) or ($rend<$rstart and $wthen not between $rend+1 and $rstart-1)) )";
  $sql .= " or ($rec='months' and (($rend between $mtoday and $mthen) or ($rend>=$rstart and $mthen between $rstart and $rend) or ($rend<$rstart and $mthen not between $rend+1 and $rstart-1)) )";
  $sql .= " or ($rec='years' and (($rend between $ytoday and $ythen) or ($rend>=$rstart and $ythen between $rstart and $rend) or ($rend<$rstart and $ythen not between $rend+1 and $rstart-1)) )";
  $sql .= ")))";

  return $sql;
}

function _cron_check_time($time) {
  $time = explode(" ",trim($time));
  if (count($time)!=5) return false;
  
  if ($time[0]!="*") {
    $time[0] -= $time[0]%5;
    $time[0] = (string)$time[0];
  }
  $trackback = 288;
  $now = NOW - (sys_date("i",NOW)%5)*60;
  while ($trackback > 0) {
	if (_cron_check_times($time,$now)) break;
    $now -= 300;
	$trackback--;
  }
  if ($trackback==0) return false; else return sys_date("m-d_H-i",$now);
}

function _cron_check_times($time,$now) {
  $today_arr = sys_getdate($now);
  if ($time[0]!="*" and !_cron_match_time($time[0],$today_arr["minutes"])) return false;
  if ($time[1]!="*" and !_cron_match_time($time[1],$today_arr["hours"])) return false;
  if ($time[2]!="*" and !_cron_match_time($time[2],$today_arr["mday"])) return false;
  if ($time[3]!="*" and !_cron_match_time($time[3],$today_arr["mon"])) return false;
  if ($time[4]!="*" and !_cron_match_time($time[4],$today_arr["wday"])) return false;
  return true;
}

function _cron_match_time($val,$today) {
  $vals = explode(",",$val);
  foreach ($vals as $val) {
	if (strpos($val,"-")) {
	  $val = explode("-",$val);
	  if (count($val)==2 and $val[0] <= $today and $val[1] >= $today) return true;
	} else if ($today == $val) return true;
  }
  return false;
}

function cron_notify_module($time,$ftype,$tfields,$where,$order,$today=0,$then=0) {
  $time = _cron_check_time($time);
  if (!$time) return;

  $filename = SIMPLE_STORE."/cron/".$ftype."_".$time."_".md5(implode("_",$where)).".log";
  if (file_exists($filename)) return;

  $schemafile = sys_find_module($ftype);
  $table = db_get_schema($schemafile);
  $tname = $table["att"]["NAME"];
  $vars = array("time"=>NOW);

  if (!isset($table["fields"]["notification"])) return;

  foreach (array("id","folder","notification") as $field) {
    if (!in_array($field,$tfields)) $tfields[] = $field;
  }
  $log = array();
  if ($today) {
    if (strpos(implode("",$where),"reminder")!==false) {
      $begin_field = "reminder_begin";
	  $end_field = "reminder_begin";
    } else {
      $begin_field = "begin";
      $end_field = "ending";
	}
    $cfields = array("recurrence","repeatinterval","repeatexcludes","until","allday");
	$tfields = array_unique(array_merge($tfields,$cfields));

	$where[] = _cron_build_calendar_where($today,$then,$begin_field,$end_field);
    $rows = db_select($tname,$tfields,$where,$order,"",$vars);

    if (is_array($rows) and count($rows) > 0) {
      foreach ($rows as $row) {
	    $folder = $row["folder"];
		if (folder_in_trash($folder)) continue;
	    if ($row["repeatexcludes"]!="") {
	      $item_exclusions = explode("|",trim($row["repeatexcludes"],"|"));
		} else $item_exclusions = array();

	    $normalized = date::build_check_hitdate($today,getdate($today),$then,$row[$begin_field],$row[$end_field],$row["until"],$row["recurrence"],$row["repeatinterval"],$item_exclusions);
	    if (count($normalized)==0) continue;

	    if (empty($row["allday"])) {
		  $table["fields"]["begin"]["SIMPLE_TYPE"] = "datetime";
		  $table["fields"]["ending"]["SIMPLE_TYPE"] = "datetime";
		} else {
		  $table["fields"]["begin"]["SIMPLE_TYPE"] = "date";
		  $table["fields"]["ending"]["SIMPLE_TYPE"] = "date";
	 	}
		foreach ($cfields as $field) unset($row[$field]);
		  
	    _cron_build_notification($table,$row,$row["id"]);
		$log[] = $row;
	  }
    }
  } else {
    $rows = db_select($tname,$tfields,$where,$order,"",$vars);
    if (is_array($rows) and count($rows) > 0) {
	  foreach ($rows as $row) {
	    $folder = $row["folder"];
		if (folder_in_trash($folder)) continue;
      	_cron_build_notification($table,$row,$row["id"]);
		$log[] = $row;
  } } }
  
  $msg = ", time=".sys_date("{t}m/d/Y g:i a{/t}",NOW);
  sys_log_message_log("info",sprintf("{t}Running mail reminder for %s{/t}",$ftype)." (".implode(", ",$tfields).")",implode(" and ",$where).$msg);
  if (count($log)>0) file_put_contents($filename,var_export($log,true)); else touch($filename);
  out($ftype."\n".var_export($log,true)."\n");
}

function out($str) {
  if (!isset($_REQUEST["debug"])) return;
  echo $str."\n";
  flush();
  @ob_flush();
}