caldav.php 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396
  1. <?php
  2. require_once(INSTALL_PATH . 'plugins/calendar/program/backend/backend.php');
  3. require_once(INSTALL_PATH . 'plugins/calendar/program/backend/caldav/caldav-client.php');
  4. final class calendar_caldav extends Backend
  5. {
  6. private $rcmail;
  7. private $type;
  8. public $utils;
  9. private $usertimezone;
  10. private $username;
  11. private $caldav;
  12. public $caldavs = array();
  13. private $account;
  14. public function __construct($rcmail, $type) {
  15. $this->rcmail = $rcmail;
  16. $this->type = $type;
  17. $url = $this->rcmail->config->get('caldav_url', false);
  18. if(!$url)
  19. return;
  20. if ($rcmail->config->get('timezone') === "auto") {
  21. $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600;
  22. }
  23. else {
  24. $tz = $rcmail->config->get('timezone');
  25. if($rcmail->config->get('dst_active')) {
  26. $tz++;
  27. }
  28. }
  29. $this->usertimezone = $tz;
  30. $user = $this->rcmail->config->get('caldav_user','demo');
  31. $pass = $this->rcmail->config->get('caldav_password',$this->rcmail->encrypt('pass'));
  32. $auth = $this->rcmail->config->get('caldav_auth','basic');
  33. $extr = $this->rcmail->config->get('caldav_extr','1');
  34. $account = array(
  35. 'user' => $user,
  36. 'pass' => $pass,
  37. 'url' => $url,
  38. 'auth' => $auth,
  39. 'extr' => $extr,
  40. );
  41. $this->account = $account;
  42. $this->connect($account['url'], $account['user'], $account['pass'], $account['auth']);
  43. $public_caldavs = $rcmail->config->get('public_caldavs', array());
  44. foreach($public_caldavs as $category => $caldav){
  45. $public_caldavs[$category]['pass'] = $rcmail->encrypt($caldav['pass']);
  46. }
  47. $caldavs = array_merge($rcmail->config->get('caldavs', array()), $public_caldavs);
  48. $this->caldavs = $caldavs;
  49. }
  50. private function connect($url, $user, $pass, $auth = 'basic'){
  51. if($this->type == 'caldav'){
  52. $rcmail = $this->rcmail;
  53. $googleuser = $rcmail->config->get('googleuser', false);
  54. $googlepass= $rcmail->config->get('googlepass', false);
  55. if($user == '%gu'){
  56. if($googleuser){
  57. $user = str_replace('%gu', $googleuser, $user);
  58. }
  59. }
  60. else if($user == '%u'){
  61. $user = str_replace('%u', $_SESSION['username'], $user);
  62. }
  63. $pass_clear = false;
  64. if($pass == '%gp'){
  65. if($googlepass){
  66. $pass = str_replace('%gp', $rcmail->decrypt($googlepass), $pass);
  67. $pass_clear = true;
  68. }
  69. }
  70. else if($pass == '%p'){
  71. $pass = str_replace('%p', $rcmail->decrypt($_SESSION['password']), $pass);
  72. $pass_clear = true;
  73. }
  74. if(!$pass_clear){
  75. $pass = $this->rcmail->decrypt($pass);
  76. if($pass == '%gp'){
  77. if($googlepass){
  78. $pass = str_replace('%gp', $rcmail->decrypt($googlepass), $pass);
  79. }
  80. }
  81. else if($pass == '%p'){
  82. $pass = str_replace('%p', $rcmail->decrypt($_SESSION['password']), $pass);
  83. }
  84. }
  85. if(strpos($url,'%gu'))
  86. $url = str_replace('%gu', $googleuser, $url);
  87. if(strpos($url,'%u'))
  88. $url = str_replace('%u', $_SESSION['username'], $url);
  89. $url = slashify($url);
  90. if($url == "/"){
  91. $url = 'https://www.google.com/calendar/dav/john.doe@gmail.com/events/';
  92. }
  93. if(!$auth)
  94. $auth = 'basic';
  95. if($user != '%u' && $user != '%gu' && $pass !='%p' && $pass != '%gp' && strpos($url, '%u') === false && strpos($url, '%gu') === false)
  96. $ret = $this->caldav = new CalDAVClient(trim($url), trim($user), trim($pass), trim($auth));
  97. if(!$ret){
  98. write_log('calendar',"CalDAV Invalid URL: '".$account['url']."'");
  99. $ret = $this->caldav = new CalDAVClient('', '', '', '');
  100. }
  101. }
  102. }
  103. private function q($str) {
  104. return $this->rcmail->db->quoteIdentifier($str);
  105. }
  106. private function table($str) {
  107. return $this->rcmail->db->quoteIdentifier(get_table_name($str));
  108. }
  109. private function generateId(){
  110. $letters="abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  111. for($i = 0; $i<=6; $i++){
  112. $rndStr .= $letters[(rand() % strlen($letters))];
  113. }
  114. $icalStamp = date("Ymd\THis\Z");
  115. return $icalStamp."-".$rndStr;
  116. }
  117. private function syncCalDAV($events,$request='PUT',$categories=false){
  118. $return = false;
  119. if($this->type == 'caldav'){
  120. $event = $this->utils->exportEvents(0,0,$events);
  121. $caldav_props = unserialize($events[0]['caldav']);
  122. $this->connect($this->account['url'], $this->account['user'], $this->account['pass'], $this->account['auth']);
  123. if($categories){
  124. $caldavs = $this->caldavs;
  125. if(!empty($caldavs[$categories])){
  126. $this->connect($caldavs[$categories]['url'],$caldavs[$categories]['user'],$caldavs[$categories]['pass'],$caldavs[$categories]['auth']);
  127. }
  128. }
  129. if($request == 'DELETE'){
  130. $this->caldav->DoDELETERequest($caldav_props[0] . '.ics');
  131. $return = true;
  132. }
  133. else if($request == 'PUT'){
  134. $ret = $this->caldav->DoPUTRequest($caldav_props[0].'.ics', $event, $caldav_props[1]);
  135. if($ret){
  136. if(stripos($ret,'HTTP/1.1') !== false){
  137. if(stripos($ret,'HTTP/1.1 204') !== false || $caldav_props[2] == '*'){
  138. $ret = $this->caldav->GetEntryByHref($caldav_props[0]);
  139. $count = preg_match('/Etag:(.*?)\n/i',$ret,$temp);
  140. if($count > 0){
  141. $etag = trim(str_replace('"','',$temp[1]));
  142. $caldav_props = array($caldav_props[0], $etag, $caldav_props[2]);
  143. }
  144. }
  145. else{
  146. $caldav_props = null;
  147. }
  148. }
  149. else{
  150. $caldav_props = array($caldav_props[0], $ret, $caldav_props[2]);
  151. }
  152. if(is_array($caldav_props)){
  153. $query = $this->rcmail->db->query(
  154. "UPDATE " . $this->table('events') . "
  155. SET ".$this->q('caldav')."=?
  156. WHERE ".$this->q('uid')."=?
  157. AND ".$this->q('user_id')."=?",
  158. serialize($caldav_props),
  159. $events[0]['uid'],
  160. $this->rcmail->user->ID
  161. );
  162. $return = true;
  163. }
  164. else{
  165. $this->replicateEvents($events[0]['start'],$events[0]['start'] + 86400,$events[0]['categories']);
  166. }
  167. }
  168. }
  169. }
  170. else{
  171. $return = true;
  172. }
  173. return $return;
  174. }
  175. public function searchEvents($str) {
  176. if (!empty($this->rcmail->user->ID)) {
  177. $cal_searchset = $this->rcmail->config->get('cal_searchset', array('summary'));
  178. $all_day = '';
  179. $str = str_replace(array('\\'),array(''),$str);
  180. $str = str_replace('%','\%',$str);
  181. $str = str_replace('*','%',$str);
  182. $method = 'LIKE';
  183. $wildcard = '%';
  184. if(strlen($str) > 2){
  185. $sql_filter = " AND (" . $this->rcmail->db->ilike($cal_searchset[0], $wildcard.$str.$wildcard);
  186. if(count($cal_searchset) > 1){
  187. for($i=1;$i<count($cal_searchset);$i++){
  188. if($cal_searchset[$i] == 'all_day'){
  189. $all_day .= " AND " . $this->q('all_day') . "=1";
  190. }
  191. else{
  192. $sql_filter .= " OR " . $this->rcmail->db->ilike($cal_searchset[$i], $wildcard.$str.$wildcard);
  193. }
  194. }
  195. $sql_filter .= ")";
  196. }
  197. $sql_result = $this->rcmail->db->query(
  198. "SELECT * FROM ".$this->table('events').
  199. " WHERE " . $this->q('del') . "<>1".
  200. " AND " . $this->q('user_id') . "=?".
  201. $all_day.
  202. $sql_filter.
  203. " ORDER BY " . $this->q('summary'),
  204. $this->rcmail->user->ID);
  205. while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
  206. $results[$sql_arr['event_id']] = $sql_arr;
  207. }
  208. if(!$_SESSION['removelayers']){
  209. $events_table = $this->rcmail->config->get('db_table_events', 'events');
  210. $this->rcmail->config->set('db_table_events',$this->rcmail->config->get('db_table_events_cache', 'events_cache'));
  211. $sql_result = $this->rcmail->db->query(
  212. "SELECT * FROM ".$this->table('events').
  213. " WHERE " . $this->q('del') . "<>1".
  214. " AND " . $this->q('user_id') . "=?".
  215. $all_day.
  216. $sql_filter.
  217. " ORDER BY " . $this->q('summary'),
  218. $this->rcmail->user->ID);
  219. while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
  220. $results['c'.$sql_arr['event_id']] = $sql_arr;
  221. }
  222. $feeds = array_merge((array)$this->rcmail->config->get('public_calendarfeeds',array()),(array)$this->rcmail->config->get('calendarfeeds',array()));
  223. foreach($feeds as $url => $category){
  224. $arr = parse_url($url);
  225. if($arr['path'] == './'){
  226. if($_SERVER['HTTPS'])
  227. $https = 's';
  228. else
  229. $https = '';
  230. $url = 'http' . $https . "://" . $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'] . substr($url,1);
  231. $arr = parse_url($url);
  232. }
  233. $con = '?';
  234. if(strstr($url,'?'))
  235. $con = '&';
  236. if(stripos($arr['query'],'plugin.calendar_showlayer') && strtolower($arr['host']) == strtolower($_SERVER['HTTP_HOST'])){
  237. $user_id = $this->rcmail->user->ID;
  238. $temparr = explode('&',$arr['query']);
  239. foreach($temparr as $key => $val){
  240. if(strpos($val,'_userid=') === 0){
  241. $temp = explode("=",$val);
  242. $remote_user = $temp[1];
  243. $this->rcmail->user->ID = $remote_user;
  244. $sql_result = $this->rcmail->db->query(
  245. "SELECT * FROM ".$this->table('events').
  246. " WHERE " . $this->q('del') . "<>1".
  247. " AND " . $this->q('user_id') . "=?".
  248. $all_day.
  249. $sql_filter.
  250. " ORDER BY " . $this->q('summary'),
  251. $this->rcmail->user->ID);
  252. while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
  253. $results['c'.$sql_arr['event_id']] = $sql_arr;
  254. }
  255. $this->rcmail->user->ID = $user_id;
  256. break;
  257. }
  258. }
  259. }
  260. }
  261. $this->rcmail->config->set('db_table_events', $events_table);
  262. $arr = $this->utils->getUser($remote_user);
  263. $prefs = unserialize($arr['preferences']);
  264. $events_table = $this->rcmail->config->get('db_table_events', 'events');
  265. $db_table = str_replace('_caldav','',$events_table);
  266. $map = $this->rcmail->config->get('backend_db_table_map',array());
  267. if($prefs['backend'] == 'caldav'){
  268. $db_table .= $map['caldav'];
  269. }
  270. else{
  271. $db_table .= $map['database'];
  272. }
  273. foreach($feeds as $url => $category){
  274. $arr = parse_url($url);
  275. $con = '?';
  276. if(strstr($url,'?'))
  277. $con = '&';
  278. if(stripos($arr['query'],'plugin.calendar_showlayer') && strtolower($arr['host']) == strtolower($_SERVER['HTTP_HOST'])){
  279. $user_id = $this->rcmail->user->ID;
  280. $temparr = explode('&',$arr['query']);
  281. foreach($temparr as $key => $val){
  282. if(strpos($val,'_userid=') === 0){
  283. $temp = explode("=",$val);
  284. $remote_user = $temp[1];
  285. $this->rcmail->user->ID = $remote_user;
  286. $sql_result = $this->rcmail->db->query(
  287. "SELECT * FROM ".$db_table.
  288. " WHERE " . $this->q('del') . "<>1".
  289. " AND " . $this->q('user_id') . "=?".
  290. $all_day.
  291. $sql_filter.
  292. " ORDER BY " . $this->q('summary'),
  293. $this->rcmail->user->ID);
  294. while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
  295. $results[$sql_arr['event_id']] = $sql_arr;
  296. }
  297. $this->rcmail->user->ID = $user_id;
  298. break;
  299. }
  300. }
  301. }
  302. }
  303. $this->rcmail->config->set('db_table_events', $events_table);
  304. }
  305. }
  306. }
  307. if(is_array($results)){
  308. $ret = $results;
  309. }
  310. else
  311. $ret = false;
  312. return $ret;
  313. }
  314. public function scheduleReminders($event){
  315. if (!empty($this->rcmail->user->ID) && $event) {
  316. $map = $this->rcmail->config->get('backend_db_table_map');
  317. if(stripos($this->table('events'),$map['caldav'])){
  318. $col = 'caldav';
  319. }
  320. else{
  321. if($this->rcmail->config->get('db_table_events_cache') == get_table_name('events')){
  322. $col = 'cache';
  323. }
  324. else{
  325. $col = 'events';
  326. }
  327. }
  328. $query = $this->rcmail->db->query(
  329. "DELETE FROM " . $this->table('reminders') . "
  330. WHERE ".$this->q($col)."=? AND ".$this->q('user_id')."=?",
  331. $event['event_id'],
  332. $this->rcmail->user->ID
  333. );
  334. if($event['del'] == '1'){
  335. return;
  336. }
  337. if($event['recurring'] != 0){
  338. $events = $this->getEvents(
  339. time() - 86400,
  340. time() + 86400,
  341. array(),
  342. false,
  343. array('uid',$event['uid'])
  344. );
  345. }
  346. else{
  347. $events[0] = $event;
  348. }
  349. if(is_array($events)){
  350. $start = time();
  351. $props = array();
  352. $props['user_id'] = $this->rcmail->user->ID;
  353. if($_SESSION['username'])
  354. $props['username'] = $_SESSION['username'];
  355. else{
  356. $user = $this->utils->getUser($props['user_id']);
  357. $props['username'] = $user['username'];
  358. }
  359. $props['user_data'] = $this->rcmail->user->data;
  360. $props['lang'] = $this->rcmail->user->language;
  361. foreach($events as $key => $event){
  362. if($event['reminderservice'] != '0'){
  363. $next = $event['start'] - $event['reminder'];
  364. $schedule = false;
  365. if($event['reminderservice'] == 'popup'){
  366. if(!$event['remindersent'])
  367. $schedule = true; // schedule missed reminders
  368. if($next > $start)
  369. $schedule = true; // always schedule future reminders
  370. }
  371. else if($event['reminderservice'] == 'email'){
  372. if($next > $start && $event['clone'])
  373. $schedule = true; // schedule future reminders for recurring events
  374. if(!$event['remindersent'] && !$event['clone'] && $next > $start)
  375. $schedule = true; // schedule future reminders for single events
  376. if(!empty($this->caldavs[$event['categories']])){
  377. if($this->caldavs[$event['categories']]['extr'] == 'external')
  378. $schedule = false;
  379. }
  380. else{
  381. if($this->account['extr'] == 'external')
  382. $schedule = false;
  383. }
  384. }
  385. if($schedule){
  386. $mapped = $this->utils->eventArrayMap($event);
  387. $props['event'] = $mapped;
  388. $props['ics'] = $this->utils->exportEvents(0,0,array(0=>$event), false, true);
  389. $query = $this->rcmail->db->query(
  390. "INSERT INTO " . $this->table('reminders') . "
  391. (".
  392. $this->q('user_id').", ".
  393. $this->q($col).", ".
  394. $this->q('type').", ".
  395. $this->q('props').", ".
  396. $this->q('runtime').")
  397. VALUES (?, ?, ?, ?, ?)",
  398. $this->rcmail->user->ID,
  399. $event['event_id'],
  400. $event['reminderservice'],
  401. serialize($props),
  402. $next
  403. );
  404. if($event['reminderservice'] == 'email'){
  405. break;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. }
  412. }
  413. public function newEvent(
  414. $start,
  415. $end,
  416. $summary,
  417. $description,
  418. $location,
  419. $categories,
  420. $allDay,
  421. $recur,
  422. $expires,
  423. $occurrences,
  424. $byday=false,
  425. $bymonth=false,
  426. $bymonthday=false,
  427. $recurrence_id=false,
  428. $exdates=false,
  429. $reminderbefore=false,
  430. $remindertype=false,
  431. $remindermailto=false,
  432. $uid=false,
  433. $client=false
  434. ) {
  435. if (!empty($this->rcmail->user->ID)) {
  436. $srecur = (string) $recur;
  437. $rr = substr($recur,0,1);
  438. $recur = substr($recur,1);
  439. // PostgreSQL sets 'f' instead of '0' for false, which messes up our conditionals!
  440. if ($byday==false) $byday='0';
  441. if ($bymonth==false) $bymonth='0';
  442. if ($bymonthday==false) $bymonthday='0';
  443. if ($recurrence_id==false) $recurrence_id='0';
  444. if ($exdates==false) $exdates='0';
  445. if ($recur==false) $recur='0';
  446. if ($reminderbefore==false) $reminderbefore='0';
  447. if ($remindertype==false) $remindertype='0';
  448. if ($remindermailto==false) $remindermailto='0';
  449. if ($uid==false) $uid='0';
  450. if ($client==false) $client='0';
  451. //
  452. if(!$uid)
  453. $uid = $this->generateId();
  454. $exists = $this->getEventByUID($uid, $recurrence_id);
  455. if(is_array($exists)){
  456. if($exists['del'] != '0'){
  457. $query = $this->rcmail->db->query(
  458. "UPDATE " . $this->table('events') . "
  459. SET ".$this->q('del')."=?
  460. WHERE ".$this->q('event_id')."=?
  461. AND ".$this->q('user_id')."=?",
  462. 0,
  463. $exists['event_id'],
  464. $this->rcmail->user->ID
  465. );
  466. }
  467. if(
  468. $start != $exists['start'] ||
  469. $end != $exists['end'] ||
  470. $summary != $exists['summary'] ||
  471. $description != $exists['description'] ||
  472. $location != $exists['location'] ||
  473. $categories != $exists['categories'] ||
  474. $recurrence_id != $exists['recurrence_id'] ||
  475. $exdates != $exists['exdates'] ||
  476. $reminderbefore != $exists['reminder'] ||
  477. $remindertype != $exists['reminderservice'] ||
  478. $remindermailto != $exists['remindermailto'] ||
  479. $srecur != $exists['rr'] . $exists['recurring'] ||
  480. $expires != $exists['expires'] ||
  481. $occurences != $exists['occurences'] ||
  482. $byday != $exists['byday'] ||
  483. $bymonth != $exists['bymonth'] ||
  484. $bymonthday != $exists['bymonthday'] ||
  485. $allDay != $exists['all_day']
  486. ){
  487. $ret = $this->editEvent(
  488. $exists['event_id'],
  489. $start,
  490. $end,
  491. $summary,
  492. $description,
  493. $location,
  494. $categories,
  495. $srecur,
  496. $expires,
  497. $occurrences,
  498. $byday,
  499. $bymonth,
  500. $bymonthday,
  501. $recurrence_id,
  502. $exdates,
  503. $reminderbefore,
  504. $remindertype,
  505. $remindermailto,
  506. $allDay
  507. );
  508. }
  509. else{
  510. $ret = $exists;
  511. }
  512. $ret['edit'] = 1;
  513. return $ret;
  514. }
  515. $query = $this->rcmail->db->query(
  516. "INSERT INTO " . $this->table('events') . "
  517. (".
  518. $this->q('user_id').", ".
  519. $this->q('start').", ".
  520. $this->q('end').", ".
  521. $this->q('summary').", ".
  522. $this->q('description').", ".
  523. $this->q('location').", ".
  524. $this->q('categories').", ".
  525. $this->q('all_day').", ".
  526. $this->q('recurring').", ".
  527. $this->q('rr').", ".
  528. $this->q('expires').", ".
  529. $this->q('occurrences').", ".
  530. $this->q('byday').", ".
  531. $this->q('bymonth').", ".
  532. $this->q('bymonthday').", ".
  533. $this->q('reminder').", ".
  534. $this->q('reminderservice').", ".
  535. $this->q('remindermailto').", ".
  536. $this->q('remindersent').", ".
  537. $this->q('recurrence_id').", ".
  538. $this->q('exdates').", ".
  539. $this->q('uid').", ".
  540. $this->q('client').", ".
  541. $this->q('caldav').", ".
  542. $this->q('timestamp').")
  543. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
  544. $this->rcmail->user->ID,
  545. $start,
  546. $end,
  547. $summary,
  548. $description,
  549. $location,
  550. $categories,
  551. $allDay,
  552. $recur,
  553. $rr,
  554. $expires,
  555. $occurrences,
  556. $byday,
  557. $bymonth,
  558. $bymonthday,
  559. $reminderbefore,
  560. $remindertype,
  561. $remindermailto,
  562. 0,
  563. $recurrence_id,
  564. $exdates,
  565. $uid,
  566. $client,
  567. serialize(array(0 => $uid, 1 => false, 2 => '*')),
  568. date('Y-m-d H:i:s', time())
  569. );
  570. $id = $this->rcmail->db->insert_id($this->rcmail->config->get('db_sequencs_events'));
  571. $events = $this->getEventsByUID($uid);
  572. //find me: investigate why this is here ...
  573. if($this->rcmail->action == 'plugin.newEvent' || $this->rcmail->action == 'plugin.editEvent' || $this->rcmail->action == 'plugin.saveical' || $this->rcmail->action == 'plugin.calendar_upload' || $this->rcmail->action == 'plugin.moveEvent'|| $this->rcmail->action == 'plugin.resizeEvent' || $this->rcmail->action == 'plugin.calendar_showlayer'){
  574. $events[0]['sync'] = $this->syncCalDAV($events,'PUT',$categories);
  575. }
  576. $this->calModified($this->rcmail->user->ID);
  577. $this->scheduleReminders($events[0]);
  578. return $events[0];
  579. }
  580. }
  581. public function editEvent(
  582. $id,
  583. $start,
  584. $end,
  585. $summary,
  586. $description,
  587. $location,
  588. $categories,
  589. $recur,
  590. $expires,
  591. $occurrences,
  592. $byday=false,
  593. $bymonth=false,
  594. $bymonthday=false,
  595. $recurrence_id=false,
  596. $exdates=false,
  597. $reminderbefore=false,
  598. $remindertype=false,
  599. $remindermailto=false,
  600. $allDay=false,
  601. $old_categories=false
  602. ) {
  603. if (!empty($this->rcmail->user->ID)) {
  604. $srecur = $recur;
  605. $rr = substr($recur,0,1);
  606. $recur = substr($recur,1);
  607. // PostgreSQL sets 'f' instead of '0' for false, which messes up our conditionals!
  608. if ($byday==false) $byday='0';
  609. if ($bymonth==false) $bymonth='0';
  610. if ($bymonthday==false) $bymonthday='0';
  611. if ($recurrence_id==false) $recurrence_id='0';
  612. if ($exdates==false) $exdates='0';
  613. if ($reminderbefore==false) $reminderbefore='0';
  614. if ($remindertype==false) $remindertype='0';
  615. if ($remindermailto==false) $remindermailto='0';
  616. if ($allday==false) $allday='0';
  617. if ($recurrence_id==false) $recurrence_id='0';
  618. if ($recur==false) $recur='0';
  619. if ($uid==false) $uid='0';
  620. if ($client==false) $client='0';
  621. //
  622. $query = $this->rcmail->db->query(
  623. "UPDATE " . $this->table('events') . "
  624. SET ".
  625. $this->q('summary')."=?, ".
  626. $this->q('start')."=?, ".
  627. $this->q('end')."=?, ".
  628. $this->q('description')."=?, ".
  629. $this->q('location')."=?, ".
  630. $this->q('categories')."=?, ".
  631. $this->q('rr')."=?, ".
  632. $this->q('recurring')."=?, ".
  633. $this->q('expires')."=?, ".
  634. $this->q('occurrences')."=?, ".
  635. $this->q('byday')."=?, ".
  636. $this->q('bymonth')."=?, ".
  637. $this->q('bymonthday')."=?, ".
  638. $this->q('recurrence_id')."=?, ".
  639. $this->q('exdates')."=?, ".
  640. $this->q('all_day')."=?, ".
  641. $this->q('reminder')."=?, ".
  642. $this->q('reminderservice')."=?, ".
  643. $this->q('remindermailto')."=?, ".
  644. $this->q('remindersent')."=?, ".
  645. $this->q('timestamp')."=?, ".
  646. $this->q('del')."=?, ".
  647. $this->q('notified')."=?
  648. WHERE ".$this->q('event_id')."=?
  649. AND ".$this->q('user_id')."=?",
  650. $summary,
  651. $start,
  652. $end,
  653. $description,
  654. $location,
  655. $categories,
  656. $rr,
  657. $recur,
  658. $expires,
  659. $occurrences,
  660. $byday,
  661. $bymonth,
  662. $bymonthday,
  663. $recurrence_id,
  664. $exdates,
  665. $allDay,
  666. $reminderbefore,
  667. $remindertype,
  668. $remindermailto,
  669. 0,
  670. date('Y-m-d H:i:s', time()),
  671. 0,
  672. 0,
  673. $id,
  674. $this->rcmail->user->ID
  675. );
  676. $this->calModified($this->rcmail->user->ID);
  677. $event = $this->getEvent($id);
  678. // find me: get uid from GUI and calendar.php
  679. $events = $this->getEventsByUID($event['uid']);
  680. $this->scheduleReminders($events[0]);
  681. if($this->type == 'caldav'){
  682. //find me: investigate why this is here ...
  683. if($this->rcmail->action == 'plugin.editEvent' || $this->rcmail->action == 'plugin.newEvent' || $this->rcmail->action == 'plugin.calendar_upload' || $this->rcmail->action == 'plugin.calendar_showlayer'){
  684. $caldavs = $this->caldavs;
  685. if($categories != $old_categories){
  686. if(!empty($caldavs[$old_categories]) || !empty($caldavs[$categories])){
  687. $sync = $this->newEvent($start, $end, $summary, $description, $location, $categories, $allDay, $srecur, $expires, $occurrences, $byday, $bymonth, $bymonthday);
  688. if($sync)
  689. $events[0] = $this->removeEvent($id, $old_categories);
  690. }
  691. else{
  692. $events[0]['sync'] = $this->syncCalDAV($events);
  693. }
  694. }
  695. else{
  696. $events[0]['sync'] = $this->syncCalDAV($events);
  697. }
  698. }
  699. }
  700. else{
  701. $events[0]['sync'] = true;
  702. }
  703. return $events[0];
  704. }
  705. }
  706. public function moveEvent(
  707. $id,
  708. $start,
  709. $end,
  710. $allDay,
  711. $reminder
  712. ) {
  713. if (!empty($this->rcmail->user->ID)) {
  714. $query = $this->rcmail->db->query(
  715. "UPDATE " . $this->table('events') . "
  716. SET ".$this->q('start')."=?, ".
  717. $this->q('end')."=?, ".
  718. $this->q('all_day')."=?, ".
  719. $this->q('remindersent')."=?, ".
  720. $this->q('timestamp')."=?, ".
  721. $this->q('notified')."=?
  722. WHERE ".$this->q('event_id')."=?
  723. AND ".$this->q('user_id')."=?",
  724. $start,
  725. $end,
  726. $allDay,
  727. 0,
  728. date('Y-m-d H:i:s', time()),
  729. 0,
  730. $id,
  731. $this->rcmail->user->ID
  732. );
  733. $this->calModified($this->rcmail->user->ID);
  734. $event = $this->getEvent($id);
  735. // find me: get uid from GUI and calendar.php
  736. $events = $this->getEventsByUID($event['uid']);
  737. if($this->rcmail->action == 'plugin.moveEvent'){
  738. $events[0]['sync'] = $this->syncCalDAV($events,'PUT',$events[0]['categories']);
  739. }
  740. $this->scheduleReminders($events[0]);
  741. return $events[0];
  742. }
  743. }
  744. public function resizeEvent(
  745. $id,
  746. $start,
  747. $end,
  748. $reminder
  749. ) {
  750. if (!empty($this->rcmail->user->ID)) {
  751. $query = $this->rcmail->db->query(
  752. "UPDATE " . $this->table('events') . "
  753. SET ".$this->q('start')."=?, ".
  754. $this->q('end')."=?, ".
  755. $this->q('remindersent')."=?, ".
  756. $this->q('timestamp')."=?, ".
  757. $this->q('notified')."=?
  758. WHERE ".$this->q('event_id')."=?
  759. AND ".$this->q('user_id')."=?",
  760. $start,
  761. $end,
  762. 0,
  763. date('Y-m-d H:i:s', time()),
  764. 0,
  765. $id,
  766. $this->rcmail->user->ID
  767. );
  768. $this->calModified($this->rcmail->user->ID);
  769. $event = $this->getEvent($id);
  770. // find me: get uid from GUI and calendar.php
  771. $events = $this->getEventsByUID($event['uid']);
  772. if($this->rcmail->action == 'plugin.resizeEvent'){
  773. $events[0]['sync'] = $this->syncCalDAV($events,'PUT',$events[0]['categories']);
  774. }
  775. $this->scheduleReminders($events[0]);
  776. return $events[0];
  777. }
  778. }
  779. public function removeEvent($id, $categories=false) {
  780. if (!empty($this->rcmail->user->ID)) {
  781. $query = $this->rcmail->db->query(
  782. "UPDATE " . $this->table('events') . "
  783. SET ".$this->q('del')."=?, ".$this->q('timestamp')."=?
  784. WHERE ".$this->q('event_id')."=?
  785. AND ".$this->q('user_id')."=?",
  786. 1,
  787. date('Y-m-d H:i:s', time()),
  788. $id,
  789. $this->rcmail->user->ID
  790. );
  791. $event = $this->getEvent($id);
  792. // find me: get uid from GUI and calendar.php
  793. $events = $this->getEventsByUID($event['uid']);
  794. //find me: investigate why this is here ...
  795. if($this->rcmail->action == 'plugin.editEvent' || $this->rcmail->action == 'plugin.removeEvent' || $this->rcmail->action == 'plugin.calendar_showlayer'){
  796. $caldav_props = unserialize($event['caldav']);
  797. $caldavs = $this->caldavs;
  798. if($event['recurrence_id'] != 0){
  799. $initialevent = $this->getEventByUID($event['uid']);
  800. if($initialevent['exdates']){
  801. $exdates = (array) @unserialize($initialevent['exdates']);
  802. $exdates[] = (int) $event['start'];
  803. }
  804. else{
  805. $exdates = array((int) $event['start']);
  806. }
  807. $initialevent['exdates'] = serialize($exdates);
  808. $initialevent['recurrence_id'] = null;
  809. $events[0]['sync'] = $this->syncCalDAV(array(0 => $initialevent),'PUT',$initialevent['categories']);
  810. }
  811. else{
  812. if(!$categories)
  813. $categories = $events[0]['categories'];
  814. $events[0]['sync'] = $this->syncCalDAV($events,'DELETE',$categories);
  815. }
  816. }
  817. $this->calModified($this->rcmail->user->ID);
  818. $this->scheduleReminders($events[0]);
  819. return $events[0];
  820. }
  821. }
  822. public function purgeEvents() {
  823. if (!empty($this->rcmail->user->ID)) {
  824. $query = $this->rcmail->db->query(
  825. "DELETE FROM " . $this->table('events') . "
  826. WHERE ".$this->q('user_id')."=?
  827. AND ".$this->q('del')."<>?",
  828. $this->rcmail->user->ID,
  829. 0
  830. );
  831. }
  832. }
  833. public function removeDuplicate($id) {
  834. if (!empty($this->rcmail->user->ID)) {
  835. $query = $this->rcmail->db->query(
  836. "DELETE FROM " . $this->table('events') . "
  837. WHERE ".$this->q('user_id')."=? AND ".$this->q('event_id')."=?",
  838. $this->rcmail->user->ID,
  839. $id
  840. );
  841. $this->calModified($this->rcmail->user->ID, true);
  842. }
  843. }
  844. public function truncateEvents($mode=0) {
  845. if (!empty($this->rcmail->user->ID)) {
  846. if($mode == 0){
  847. $query = $this->rcmail->db->query(
  848. "DELETE FROM " . $this->table('events') . "
  849. WHERE ".$this->q('user_id')."=? AND ".$this->q('del')."=?",
  850. $this->rcmail->user->ID,
  851. 1
  852. );
  853. $this->calModified($this->rcmail->user->ID, true);
  854. }
  855. else if($mode == 1){
  856. $query = $this->rcmail->db->query(
  857. "UPDATE " . $this->table('events') . "
  858. SET ".$this->q('del')."=?, ".$this->q('timestamp')."=?
  859. WHERE ".$this->q('user_id')."=?",
  860. 2,
  861. date('Y-m-d H:i:s', time()),
  862. $this->rcmail->user->ID
  863. );
  864. }
  865. else if($mode == 2){
  866. $query = $this->rcmail->db->query(
  867. "UPDATE " . $this->table('events') . "
  868. SET ".$this->q('del')."=?, ".$this->q('timestamp')."=?
  869. WHERE ".$this->q('user_id')."=?",
  870. 0,
  871. date('Y-m-d H:i:s', time()),
  872. $this->rcmail->user->ID
  873. );
  874. }
  875. else if($mode == 3){
  876. $query = $this->rcmail->db->query(
  877. "DELETE FROM " . $this->table('events') . "
  878. WHERE ".$this->q('user_id')."=?",
  879. $this->rcmail->user->ID
  880. );
  881. }
  882. }
  883. }
  884. public function exportEvents($categories=false){
  885. if($this->type == 'caldav'){
  886. if($categories){
  887. $caldavs = $this->caldavs;
  888. if(is_array($caldavs[$categories])){
  889. $this->connect($caldavs[$categories]['url'],$caldavs[$categories]['user'],$caldavs[$categories]['pass'],$caldavs[$categories]['auth']);
  890. }
  891. }
  892. $response = trim($this->caldav->DoRequest());
  893. $temparr = explode("\r\n\r\n", $response,2);
  894. return $temparr[1];
  895. }
  896. }
  897. private function _getEvents(
  898. $estart,
  899. $eend,
  900. $category=false,
  901. $type='events'
  902. ) {
  903. if($this->type == 'caldav'){
  904. $events = array();
  905. $map = $this->rcmail->config->get('backend_db_table_map');
  906. if(stripos($this->table('events'),$map['caldav'])){
  907. $startYear = date('Y',$estart);
  908. $startMonth = date('m',$estart);
  909. $startDay = date('d',$estart);
  910. $endYear = date('Y',$eend );
  911. $endMonth = date('m',$eend );
  912. $endDay = date('d',$eend );
  913. $caldavs = $this->caldavs;
  914. if(!$category || ($category && !$caldavs[$category])){
  915. if($type == 'events'){
  916. $events = (array) $this->caldav->GetEvents($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
  917. }
  918. else if($type == 'alarms'){
  919. // cron login successful ?
  920. if(method_exists($this->caldav, 'GetEventAlarms')){
  921. $events = (array) $this->caldav->GetEventAlarms($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
  922. }
  923. }
  924. }
  925. else{
  926. if($category && $caldavs[$category]){
  927. $caldav = $caldavs[$category];
  928. $this->connect($caldav['url'],$caldav['user'],$caldav['pass'],$caldav['auth']);
  929. $startYear = date('Y',$estart);
  930. $startMonth = date('m',$estart);
  931. $startDay = date('d',$estart);
  932. if($type == 'events'){
  933. $layers = (array) $this->caldav->GetEvents($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
  934. }
  935. else if($type == 'alarms'){
  936. $layers = (array) $this->caldav->GetEventAlarms($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
  937. }
  938. foreach($layers as $key => $layer){
  939. $layers[$key]['data'] = str_replace("\nCATEGORIES:","\nX-CATEGORIES:",$layers[$key]['data']);
  940. $insert = "\nCATEGORIES:" . $category;
  941. $layers[$key]['data'] = str_replace("\nBEGIN:VEVENT", "\nBEGIN:VEVENT" . $insert, $layers[$key]['data']);
  942. }
  943. $events = $layers;
  944. }
  945. }
  946. $concat = '';
  947. foreach($events as $key => $val){
  948. $insert = "\nX-HREF:".$val['href']."\nX-ETAG:".$val['etag'];
  949. $val['data'] = str_replace("\nBEGIN:VEVENT", "\nBEGIN:VEVENT" . $insert, $val['data']);
  950. $concat .= $val['data'];
  951. }
  952. if($concat != ''){
  953. $this->utils->importEvents($concat);
  954. $query = $this->rcmail->db->query(
  955. "UPDATE " . $this->table('events') . "
  956. SET ".$this->q('timestamp')."=?, ".$this->q('notified')."=?
  957. WHERE ".$this->q('user_id')."=?",
  958. '0',
  959. '1',
  960. $this->rcmail->user->ID
  961. );
  962. }
  963. }
  964. }
  965. }
  966. public function removeReminder(
  967. $id,
  968. $event_id,
  969. $ts
  970. ) {
  971. if (!empty($this->rcmail->user->ID)) {
  972. if(!$id && !$event_id){
  973. $reminders = (array) $this->getReminders($ts);
  974. $query = $this->rcmail->db->query(
  975. "DELETE FROM " . $this->table('reminders') . "
  976. WHERE " . $this->q('type') . "=? AND ".$this->q('user_id')."=? AND " . $this->q('runtime') . "<?",
  977. 'popup',
  978. $this->rcmail->user->ID,
  979. $ts
  980. );
  981. foreach($reminders as $reminder){
  982. $query = $this->rcmail->db->query(
  983. "UPDATE " .$this->table('events') . "
  984. SET ". $this->q('remindersent')."=?
  985. WHERE ".$this->q('event_id')."=?
  986. AND ".$this->q('user_id')."=?",
  987. $ts,
  988. $reminder['id'],
  989. $this->rcmail->user->ID
  990. );
  991. }
  992. }
  993. else{
  994. $query = $this->rcmail->db->query(
  995. "DELETE FROM " . $this->table('reminders') . "
  996. WHERE " . $this->q('reminder_id') . "=? AND ".$this->q('user_id')."=?",
  997. $id,
  998. $this->rcmail->user->ID
  999. );
  1000. $query = $this->rcmail->db->query(
  1001. "UPDATE " .$this->table('events') . "
  1002. SET ". $this->q('remindersent')."=?
  1003. WHERE ".$this->q('event_id')."=?
  1004. AND ".$this->q('user_id')."=?",
  1005. $ts,
  1006. $event_id,
  1007. $this->rcmail->user->ID
  1008. );
  1009. }
  1010. }
  1011. }
  1012. public function getReminders(
  1013. $start,
  1014. $type='popup'
  1015. ) {
  1016. $ret = array();
  1017. if (!empty($this->rcmail->user->ID)) {
  1018. $result = $this->rcmail->db->query(
  1019. "SELECT * FROM " . $this->table('reminders') . "
  1020. WHERE ".$this->q('user_id')."=? AND ".$this->q('runtime')."<? AND ".$this->q('type')."=?",
  1021. $this->rcmail->user->ID,
  1022. $start,
  1023. $type
  1024. );
  1025. $reminders = array();
  1026. while ($result && ($reminder = $this->rcmail->db->fetch_assoc($result))) {
  1027. $reminders[] = $reminder;
  1028. }
  1029. foreach($reminders as $key => $val){
  1030. $col = 'events';
  1031. if($val['caldav'] != '0')
  1032. $col = 'caldav';
  1033. else if($val['cache'] != '0')
  1034. $col = 'cache';
  1035. $result = $this->rcmail->db->query(
  1036. "SELECT * FROM " . $this->table('events') . "
  1037. WHERE ".$this->q('user_id')."=? AND ".$this->q('event_id')."=?",
  1038. $this->rcmail->user->ID,
  1039. $val[$col]
  1040. );
  1041. if($result){
  1042. $event = $this->rcmail->db->fetch_assoc($result);
  1043. if($event['recurring'] != '0'){
  1044. $duration = 0;
  1045. if($event['end'] != '0'){
  1046. $duration = (int) $event['end'] - (int) $event['start'];
  1047. }
  1048. $start = (int) $val['runtime'] + (int) $event['reminder'];
  1049. $end = $start + $duration;
  1050. $event['start'] = $start;
  1051. if($event['end'] != '0'){
  1052. $event['end'] = $start + $duration;
  1053. }
  1054. }
  1055. $event['reminder_id'] = $val['reminder_id'];
  1056. $ret[$event['start'] . $event['uid'] . $event['event_id']] = $this->utils->eventArrayMap($event);
  1057. }
  1058. }
  1059. }
  1060. return $ret;
  1061. }
  1062. public function replicateEvents(
  1063. $estart,
  1064. $eend,
  1065. $category=false,
  1066. $type='events'
  1067. ){
  1068. if (!empty($this->rcmail->user->ID)) {
  1069. $this->_getEvents($estart, $eend, $category, $type);
  1070. }
  1071. }
  1072. public function getEvents(
  1073. $estart,
  1074. $eend,
  1075. $labels=array(),
  1076. $category=false,
  1077. $filter=false,
  1078. $client=false,
  1079. $type='events'
  1080. ) {
  1081. if (!empty($this->rcmail->user->ID)) {
  1082. $mem_limit = (int) ini_get('memory_limit');
  1083. $start = -1;
  1084. $end = $eend + 1;
  1085. if($filter){
  1086. $filterfield = $filter[0];
  1087. $filtercomp = '=?';
  1088. $filterval = $filter[1];
  1089. }
  1090. else{
  1091. $filterfield = 'del';
  1092. $filtercomp = '<>?';
  1093. $filterval = 1;
  1094. }
  1095. $result = $this->rcmail->db->query(
  1096. "SELECT * FROM " . $this->table('events') . "
  1097. WHERE ".$this->q('user_id')."=? AND ".
  1098. $this->q('start').">? AND ".
  1099. $this->q('start')."<? AND ".
  1100. $this->q($filterfield) . $filtercomp,
  1101. $this->rcmail->user->ID,
  1102. $start,
  1103. $end,
  1104. $filterval
  1105. );
  1106. $events = array();
  1107. while ($result && ($event = $this->rcmail->db->fetch_assoc($result))) {
  1108. if($this->rcmail->action == 'plugin.getEvents'){
  1109. $db_category = $event['categories'];
  1110. if($category){
  1111. if($db_category != $category){
  1112. continue;
  1113. }
  1114. }
  1115. else{
  1116. $caldavs = $this->caldavs;
  1117. if(!empty($caldavs[$db_category])){
  1118. continue;
  1119. }
  1120. }
  1121. }
  1122. // backwards compatibility
  1123. if(empty($event['rr'])){
  1124. switch($event['recurring']){
  1125. case 86400:
  1126. case 86401:
  1127. $event['rr'] = 'd';
  1128. break;
  1129. case 604800:
  1130. case 1209600:
  1131. case 1814400:
  1132. case 2419200:
  1133. $event['rr'] = 'w';
  1134. break;
  1135. case 2592000:
  1136. $event['rr'] = 'm';
  1137. break;
  1138. case 31536000:
  1139. $event['rr'] = 'y';
  1140. break;
  1141. }
  1142. }
  1143. $append = $event['start'];
  1144. $add = true;
  1145. if($event['exdates']){
  1146. $exdates = @unserialize($event['exdates']);
  1147. if(is_array($exdates) && count($exdates) > 0){
  1148. $exdates = $this->utils->array_flatten($exdates);
  1149. $exdates = array_flip($exdates);
  1150. if(isset($exdates[$event['start']])){
  1151. $add = false;
  1152. }
  1153. }
  1154. }
  1155. if($event['recurrence_id']){
  1156. $append = $event['recurrence_id'];
  1157. }
  1158. if($event['start'] >= $estart || $event['end'] >= $estart || $event['recurring'] != 0){
  1159. if($event['start'] >= $estart || $event['end'] >= $estart){
  1160. if($add){
  1161. $events[md5($event['uid'].$append)]=array(
  1162. 'event_id' => (int) $event['event_id'],
  1163. 'uid' => (string) $event['uid'],
  1164. 'start' => (int) $event['start'],
  1165. 'end' => (int) $event['end'],
  1166. 'expires' => (string) $event['expires'],
  1167. 'rr' => (string) $event['rr'],
  1168. 'recur' => (string) $event['recurring'],
  1169. 'occurrences' => (int) $event['occurrences'],
  1170. 'recurrence_id' => (string) $event['recurrence_id'],
  1171. 'summary' => (string) $event['summary'],
  1172. 'description' => (string) $event['description'],
  1173. 'location' => (string) $event['location'],
  1174. 'categories' => (string) $event['categories'],
  1175. 'all_day' => (int) $event['all_day'],
  1176. 'timestamp' => (string) $event['timestamp'],
  1177. 'del' => (int) $event['del'],
  1178. 'notified' => (int) $event['notified'],
  1179. 'byday' => (string) $event['byday'],
  1180. 'bymonth' => (string) $event['bymonth'],
  1181. 'bymonthday' => (string) $event['bymonthday'],
  1182. 'reminder' => (int) $event['reminder'],
  1183. 'reminderservice' => (string) $event['reminderservice'],
  1184. 'remindermailto' => (string) $event['remindermailto'],
  1185. 'editable' => true,
  1186. 'clone' => false
  1187. );
  1188. }
  1189. }
  1190. if($event['recurring'] != 0 && !$client){
  1191. $rrule = $this->utils->rrule($event);
  1192. if($rrule){
  1193. $basedate = date('Ymd\THis',$event['start']);
  1194. $rule = new RRule(new iCalDate($basedate), $rrule);
  1195. do{
  1196. $date = $rule->GetNext();
  1197. if(isset($date)){
  1198. $clone_date = $date->Render();
  1199. $clone_start = strtotime($clone_date);
  1200. $clone_end = strtotime($clone_date) + $event['end'] - $event['start'];
  1201. $dst_adjust = 0;
  1202. if(date('I', $event['start']) != date('I', $clone_start)){
  1203. if(date('I',$event['start']) == 0 && date('I',$clone_start) == 1)
  1204. $dst_adjust = 3600;
  1205. else
  1206. $dst_adjust = -3600;
  1207. }
  1208. $clone_start = $clone_start + $dst_adjust;
  1209. $clone_end = $clone_end + $dst_adjust;
  1210. if($clone_start > $event['start'] && $clone_start > $estart){
  1211. if(!isset($exdates[$clone_start])){
  1212. if($add){
  1213. $set_clone = (string) $event['start'];
  1214. $set_clone_end = (string) $event['end'];
  1215. }
  1216. else{
  1217. $set_clone = false;
  1218. $set_clone_end = false;
  1219. $add = true;
  1220. }
  1221. $event['editable'] = true;
  1222. $event['recur'] = $event['recurring'];
  1223. $events[md5($event['uid'].$clone_start)] = array(
  1224. 'event_id' => (int) $event['event_id'],
  1225. 'uid' => (string) $event['uid'],
  1226. 'start' => (int) $clone_start,
  1227. 'end' => (int) $clone_end,
  1228. 'expires' => (string) $event['expires'],
  1229. 'rr' => (string) $event['rr'],
  1230. 'recur' => (string) $event['recurring'],
  1231. 'occurrences' => (int) $event['occurrences'],
  1232. 'recurrence_id' => (string) $event['recurrence_id'],
  1233. 'summary' => (string) $event['summary'],
  1234. 'description' => (string) $event['description'],
  1235. 'location' => (string) $event['location'],
  1236. 'categories' => (string) $event['categories'],
  1237. 'all_day' => (int) $event['all_day'],
  1238. 'timestamp' => (string) $event['timestamp'],
  1239. 'del' => (int) $event['del'],
  1240. 'byday' => (string) $event['byday'],
  1241. 'bymonth' => (string) $event['bymonth'],
  1242. 'bymonthday' => (string) $event['bymonthday'],
  1243. 'reminder' => (int) $event['reminder'],
  1244. 'reminderservice' => (string) $event['reminderservice'],
  1245. 'remindermailto' => (string) $event['remindermailto'],
  1246. 'editable' => (bool) $event['editable'],
  1247. 'clone' => $set_clone,
  1248. 'clone_end' => $set_clone_end,
  1249. 'caldav' => (string) $event['caldav'],
  1250. 'notified' => (int) $event['notified'],
  1251. 'initial' => (array) $this->utils->eventArrayMap($event)
  1252. );
  1253. }
  1254. }
  1255. }
  1256. }
  1257. while(isset($date) && strtotime($date->Render()) <= $eend);
  1258. }
  1259. }
  1260. }
  1261. }
  1262. $public_caldavs = $this->rcmail->config->get('public_caldavs', array());
  1263. foreach($events as $key => $event){
  1264. $category = $event['categories'];
  1265. if(!empty($public_caldavs[$category]) && $public_caldavs[$category]['readonly']){
  1266. $events[$key]['editable'] = false;
  1267. }
  1268. }
  1269. return $events;
  1270. }
  1271. }
  1272. private function calModified($userid=false,$del=false) {
  1273. if($userid && !$del){
  1274. file_put_contents('./plugins/calendar/temp/' . $userid . '.pid', time());
  1275. }
  1276. if($userid && $del){
  1277. @unlink('./plugins/calendar/temp/' . $userid . '.pid');
  1278. }
  1279. }
  1280. public function removeTimestamps() {
  1281. if (!empty($this->rcmail->user->ID)) {
  1282. $query = $this->rcmail->db->query(
  1283. "UPDATE " . $this->table('events') . "
  1284. SET ".$this->q('timestamp')."=?
  1285. WHERE ".$this->q('user_id')."=?",
  1286. '0',
  1287. $this->rcmail->user->ID
  1288. );
  1289. }
  1290. }
  1291. public function getEvent($eventid){
  1292. if (!empty($this->rcmail->user->ID)) {
  1293. $result = $this->rcmail->db->query(
  1294. "SELECT * FROM " . $this->table('events') . "
  1295. WHERE ".$this->q('user_id')."=? AND ".$this->q('event_id')."=?",
  1296. $this->rcmail->user->ID,
  1297. $eventid
  1298. );
  1299. $event = $this->rcmail->db->fetch_assoc($result);
  1300. if($event){
  1301. $event['recur'] = $event['recurring'];
  1302. return $event;
  1303. }
  1304. }
  1305. return array();
  1306. }
  1307. public function getEventByUID($uid, $recurrence_id=0){
  1308. $event = array();
  1309. if (!empty($this->rcmail->user->ID)) {
  1310. $result = $this->rcmail->db->query(
  1311. "SELECT * FROM " . $this->table('events') . "
  1312. WHERE ".$this->q('user_id')."=? AND ".$this->q('uid')."=? AND ".$this->q('recurrence_id')."=?",
  1313. $this->rcmail->user->ID,
  1314. $uid,
  1315. $recurrence_id
  1316. );
  1317. while ($result && ($event = $this->rcmail->db->fetch_assoc($result))){
  1318. $events[] = $event;
  1319. }
  1320. if(is_array($events) && count($events) > 1)
  1321. write_log('calendar', "ERROR: Event with UID " . $event['uid'] . " is not unique");
  1322. $event = $events[0];
  1323. }
  1324. return $event;
  1325. }
  1326. public function getEventsByUID($uid){
  1327. if (!empty($this->rcmail->user->ID)) {
  1328. $result = $this->rcmail->db->query(
  1329. "SELECT * FROM " . $this->table('events') . "
  1330. WHERE ".$this->q('user_id')."=? AND ".$this->q('uid')."=?",
  1331. $this->rcmail->user->ID,
  1332. $uid
  1333. );
  1334. while ($result && ($event = $this->rcmail->db->fetch_assoc($result))){
  1335. $temparr[] = $event;
  1336. }
  1337. }
  1338. $i = 0;
  1339. $events = array();
  1340. if(is_array($temparr)){
  1341. foreach($temparr as $key => $event){
  1342. if(!$event['recurrence_id']){
  1343. if(!empty($events[0]))
  1344. write_log('calendar', "ERROR: Event with UID " . $event['uid'] . " is not unique");
  1345. $events[0] = $event;
  1346. }
  1347. else{
  1348. $events[$i] = $event;
  1349. }
  1350. $i++;
  1351. }
  1352. }
  1353. return $events;
  1354. }
  1355. public function test($str = 'db_table_events') {
  1356. $this->rcmail->db->db_handle->loadModule('Manager');
  1357. if(!PEAR::isError($result = $this->rcmail->db->db_handle->listTableFields($this->rcmail->config->get($str))))
  1358. $ret = $result;
  1359. else
  1360. $ret = array();
  1361. return $ret;
  1362. }
  1363. }
  1364. ?>