source: extensions/Subscribe_to_comments/include/functions.inc.php @ 21608

Last change on this file since 21608 was 21608, checked in by mistic100, 11 years ago

code clean, add admin list of all subscribers

File size: 20.3 KB
Line 
1<?php
2if (!defined('SUBSCRIBE_TO_PATH')) die('Hacking attempt!');
3
4include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
5
6/**
7 * Send comment to subscribers
8 * @param: array comment (author, content, image_id|category_id)
9 */
10function send_comment_to_subscribers($comm)
11{
12  if ( empty($comm) or !is_array($comm) )
13  {
14    trigger_error('send_comment_to_subscribers: undefineded comm', E_USER_WARNING);
15    return false;
16  }
17 
18  global $conf, $page, $user, $template;
19 
20  // create search clauses
21  $where_clauses = array();
22  if (isset($comm['image_id']))
23  {
24    $element_id = $comm['image_id'];
25    $element_type = 'image';
26   
27    array_push($where_clauses, 'type = "image" AND element_id = '.$element_id.'');
28    if (!empty($page['category']['id'])) array_push($where_clauses, 'type = "album-images" AND element_id = '.$page['category']['id'].'');
29    array_push($where_clauses, 'type = "all-images"');
30  }
31  else if (isset($comm['category_id']))
32  {
33    $element_id = $comm['category_id'];
34    $element_type = 'category';
35   
36    array_push($where_clauses, 'type = "album" AND element_id = '.$element_id.'');
37    array_push($where_clauses, 'type = "all-albums"');
38  }
39  else
40  {
41    return;
42  }
43 
44  // exclude current user
45  $exclude = null;
46  if (!empty($_POST['stc_mail']))
47  {
48    $exclude = pwg_db_real_escape_string($_POST['stc_mail']);
49  }
50  else if (!is_a_guest())
51  {
52    $exclude = $user['email'];
53  }
54 
55  // get subscribers datas
56  $query = '
57SELECT
58    id,
59    email,
60    language
61  FROM '.SUBSCRIBE_TO_TABLE.'
62  WHERE (
63      ('.implode(")\n      OR (", $where_clauses).')
64    )
65    AND validated = true
66    AND email != "'.$exclude.'"
67';
68  $subscriptions = hash_from_query($query, 'id');
69 
70  if (count($subscriptions)==0) return;
71 
72  set_make_full_url();
73 
74  // get element infos
75  if ($element_type == 'image')
76  {
77    $element = get_picture_infos($comm['image_id']);
78  }
79  else
80  {
81    $element = get_category_infos($comm['category_id']);
82  }
83 
84  // format comment
85  if ($comm['author'] == 'guest') $comm['author'] = l10n('guest');
86  $comm['author'] = trigger_event('render_comment_author', $comm['author']);
87  $comm['content'] = trigger_event('render_comment_content', $comm['content']);
88 
89  // mail content
90  $subject = '['.strip_tags($conf['gallery_title']).'] Re:'.$element['name'];
91   
92  $template->set_filename('stc_mail', realpath(SUBSCRIBE_TO_PATH . 'template/mail/notification.tpl'));
93
94  foreach ($subscriptions as $row)
95  {
96    // get subscriber id
97    if ( ($uid = get_userid_by_email($row['email'])) !== false )
98    {
99      $row['user_id'] = $uid;
100    }
101    else
102    {
103      $row['user_id'] = $conf['guest_id'];
104    }
105   
106    // check permissions
107    if (!user_can_view_element($row['user_id'], $element_id, $element_type))
108    {
109      continue;
110    }
111   
112    // send mail
113    switch_lang_to($row['language']);
114    load_language('plugin.lang', SUBSCRIBE_TO_PATH);
115   
116    $comm['caption'] = sprintf('<b>%s</b> wrote on <i>%s</i>', $comm['author'], format_date(date('Y-m-d H:i:s')));
117   
118    $template->assign('STC', array(
119      'element' => $element,
120      'comment' => $comm,
121      'UNSUB_URL' => make_stc_url('unsubscribe', $row['email'], $row['id']),
122      'MANAGE_URL' => make_stc_url('manage', $row['email']),
123      'GALLERY_TITLE' => $conf['gallery_title'],
124      ));
125   
126    $content = $template->parse('stc_mail', true);
127
128    stc_send_mail($row['email'], $content, $subject);
129    switch_lang_back();
130  }
131 
132  load_language('plugin.lang', SUBSCRIBE_TO_PATH);
133  unset_make_full_url();
134}
135
136
137/**
138 * add an email to subscribers list
139 * @param: string email
140 * @param: string type (image|album-images|all-images|album|all-albums)
141 * @param: int element_id
142 * @return: bool
143 */
144function subscribe_to_comments($email, $type, $element_id='NULL')
145{
146  if (empty($type))
147  {
148    trigger_error('subscribe_to_comment: missing type', E_USER_WARNING);
149    return false;
150  }
151 
152  if ( !in_array($type, array('all-images','all-albums')) and $element_id == 'NULL' )
153  {
154    trigger_error('subscribe_to_comment: missing element_id', E_USER_WARNING);
155    return false;
156  }
157 
158  global $page, $conf, $user, $template, $picture;
159 
160  // check email
161  if ( !empty($email) and !email_check_format($email) )
162  {
163    array_push($page['errors'], l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)'));
164    return false;
165  }
166  if ( ( is_a_guest() or empty($user['email']) ) and empty($email) )
167  {
168    array_push($page['errors'], l10n('Invalid email adress, your are not subscribed to comments.'));
169    return false;
170  }
171  else if ( !is_a_guest() and empty($email) )
172  {
173    $email = $user['email'];
174  }
175 
176  // search if already registered (can't use ODKU because we want to get the id of inserted OR updated row)
177  $query = '
178SELECT id
179  FROM '.SUBSCRIBE_TO_TABLE.'
180  WHERE
181    type = "'.$type.'"
182    AND element_id = '.$element_id.'
183    AND email = "'.pwg_db_real_escape_string($email).'"
184;';
185  $result = pwg_query($query);
186 
187  if (pwg_db_num_rows($result))
188  {
189    list($inserted_id) = pwg_db_fetch_row($result);
190  }
191  else
192  {
193    $query = '
194INSERT INTO '.SUBSCRIBE_TO_TABLE.'(
195    type,
196    element_id,
197    language,
198    email,
199    registration_date,
200    validated
201  )
202  VALUES(
203    "'.$type.'",
204    '.$element_id.',
205    "'.$user['language'].'",
206    "'.pwg_db_real_escape_string($email).'",
207    NOW(),
208    "'.(is_a_guest() ? "false" : "true").'"
209  )
210;';
211    pwg_query($query);
212   
213    $inserted_id = pwg_db_insert_id();
214  }
215 
216  // notify admins
217  if ( pwg_db_changes() != 0 and $conf['Subscribe_to_Comments']['notify_admin_on_subscribe'] )
218  {
219    stc_mail_notification_admins($email, $type, $element_id, $inserted_id);
220  }
221 
222  // send validation mail
223  if ( is_a_guest() and pwg_db_changes() != 0 )
224  {
225    set_make_full_url();
226   
227    $template->set_filename('stc_mail', realpath(SUBSCRIBE_TO_PATH . 'template/mail/confirm.tpl'));
228   
229    $subject = '['.strip_tags($conf['gallery_title']).'] '.l10n('Confirm your subscribtion to comments');
230     
231    switch ($type)
232    {
233      case 'image':
234        $element = get_picture_infos($element_id);
235        $element['on'] = sprintf(l10n('the picture <a href="%s">%s</a>'), $element['url'], $element['name']);
236        break;
237      case 'album-images':
238        $element = get_category_infos($element_id);
239        $element['on'] = sprintf(l10n('all pictures of the album <a href="%s">%s</a>'), $element['url'], $element['name']);
240        break;
241      case 'all-images':
242        $element['thumbnail'] = null;
243        $element['on'] = l10n('all pictures of the gallery');
244        break;
245      case 'album':
246        $element = get_category_infos($element_id);
247        $element['on'] = sprintf(l10n('the album <a href="%s">%s</a>'), $element['url'], $element['name']);
248        break;
249      case 'all-albums':
250        $element['thumbnail'] = null;
251        $element['on'] = l10n('all albums of the gallery');
252        break;
253    }
254   
255    $template->assign('STC', array(
256      'element' => $element,
257      'VALIDATE_URL' => make_stc_url('validate', $email, $inserted_id),
258      'MANAGE_URL' => make_stc_url('manage', $email),
259      'GALLERY_TITLE' => $conf['gallery_title'],
260      ));
261   
262    $content = $template->parse('stc_mail', true);
263
264    stc_send_mail($email, $content, $subject);
265    unset_make_full_url();
266   
267    array_push($page['infos'], l10n('Please check your email inbox to confirm your subscription.'));
268    return true;
269  }
270  // just display confirmation message
271  else if (pwg_db_changes() != 0)
272  {
273    array_push($page['infos'], l10n('You have been added to the list of subscribers.'));
274    return true;
275  }
276 
277  return false;
278}
279
280
281/**
282 * remove an email from subscribers list
283 * @param: string email
284 * @param: int subscription id
285 * @return: bool
286 */
287function un_subscribe_to_comments($email, $id)
288{ 
289  if ( !empty($email) and !email_check_format($email) )
290  {
291    trigger_error('un_subscribe_to_comment: bad email', E_USER_WARNING);
292    return false;
293  }
294 
295  if (!preg_match('#^[0-9]+$#', $id))
296  {
297    trigger_error('un_subscribe_to_comment: bad id', E_USER_WARNING);
298    return false;
299  }
300 
301  global $template, $user;
302 
303  // check email
304  if ( ( is_a_guest() or empty($user['email']) ) and empty($email) )
305  {
306    return false;
307  }
308  else if ( !is_a_guest() and empty($email) )
309  {
310    $email = $user['email'];
311  }
312 
313  // delete subscription
314  $query = '
315DELETE FROM '.SUBSCRIBE_TO_TABLE.'
316  WHERE
317    email = "'.pwg_db_real_escape_string($email).'"
318    AND id = '.$id.'
319;';
320  pwg_query($query);
321 
322  return (pwg_db_changes() != 0);
323}
324
325
326/**
327 * validate a subscription
328 * @param: string email
329 * @param: int subscription id
330 * @return: bool
331 */
332function validate_subscriptions($email, $id)
333{
334  if (!email_check_format($email))
335  {
336    trigger_error('validate_subscriptions: bad email', E_USER_WARNING);
337    return false;
338  }
339 
340  if (!preg_match('#^[0-9]+$#', $id))
341  {
342    trigger_error('validate_subscriptions: bad id', E_USER_WARNING);
343    return false;
344  }
345 
346  $query = '
347UPDATE '.SUBSCRIBE_TO_TABLE.'
348  SET validated = "true"
349  WHERE
350    email = "'.pwg_db_real_escape_string($email).'"
351    AND id = '.$id.'
352;';
353  pwg_query($query);
354 
355  return (pwg_db_changes() != 0);
356}
357
358
359/**
360 * send notification to admins
361 * @param: string email
362 * @param: string type (image|album-images|all-images|album|all-albums)
363 * @param: int element_id
364 * @param: int subscription id
365 */
366function stc_mail_notification_admins($email, $type, $element_id, $inserted_id)
367{
368  global $user, $conf, $template;
369 
370  $admins = get_admins_email();
371  if (empty($admins)) return;
372 
373  set_make_full_url();
374  switch_lang_to(get_default_language());
375  load_language('plugin.lang', SUBSCRIBE_TO_PATH);
376 
377  $template->set_filename('stc_mail', realpath(SUBSCRIBE_TO_PATH . 'template/mail/admin.tpl'));
378   
379  $subject = '['.strip_tags($conf['gallery_title']).'] '.sprintf(l10n('%s has subscribed to comments on %s.'), is_a_guest()?$email:$user['username'], null);
380   
381  switch ($type)
382  {
383    case 'image':
384      $element = get_picture_infos($element_id, false);
385      $element['on'] = sprintf(l10n('the picture <a href="%s">%s</a>'), $element['url'], $element['name']);
386      break;
387    case 'album-images':
388      $element = get_category_infos($element_id, false);
389      $element['on'] = sprintf(l10n('all pictures of the album <a href="%s">%s</a>'), $element['url'], $element['name']);
390      break;
391    case 'all-images':
392      $element['on'] = l10n('all pictures of the gallery');
393      break;
394    case 'album':
395      $element = get_category_infos($element_id, false);
396      $element['on'] = sprintf(l10n('the album <a href="%s">%s</a>'), $element['url'], $element['name']);
397      break;
398    case 'all-albums':
399      $element['on'] = l10n('all albums of the gallery');
400      break;
401  }
402 
403  $technical_infos[] = sprintf(l10n('Connected user: %s'), stripslashes($user['username']));
404  $technical_infos[] = sprintf(l10n('IP: %s'), $_SERVER['REMOTE_ADDR']);
405  $technical_infos[] = sprintf(l10n('Browser: %s'), $_SERVER['HTTP_USER_AGENT']);
406 
407  $template->assign('STC', array(
408    'ELEMENT' => $element['on'],
409    'USER' => is_a_guest() ? '<b>'.$email.'</b>' : '<b>'.$user['username'].'</b> ('.$email.')', 
410    'GALLERY_TITLE' => $conf['gallery_title'],
411    'TECHNICAL' => implode('<br>', $technical_infos),
412    ));
413 
414  $content = $template->parse('stc_mail', true);
415
416  stc_send_mail($admins, $content, $subject);
417 
418  unset_make_full_url();
419  switch_lang_back();
420  load_language('plugin.lang', SUBSCRIBE_TO_PATH);
421}
422
423
424/**
425 * create absolute url to subscriptions section
426 * @param: string action
427 * @param: string email
428 * @param: int optional
429 * @return: string
430 */
431function make_stc_url($action, $email, $id=null)
432{
433  if ( empty($action) or empty($email) )
434  {
435    trigger_error('make_stc_url: missing action and/or mail', E_USER_WARNING);
436    return null;
437  }
438 
439  global $conf;
440  set_make_full_url();
441 
442  $url_params = array(
443    'action' => $action,
444    'email' => $email,
445    );
446 
447  if (!empty($id))
448  {
449    $url_params['id'] = $id;
450  }
451 
452  $url_params['key'] = crypt_value(
453    $action.$email.(isset($url_params['id'])?$url_params['id']:null), 
454    $conf['secret_key']
455    );
456 
457  $url = add_url_params(
458    make_index_url( array('section' => 'subscriptions') ),
459    $url_params
460    );
461   
462  unset_make_full_url();
463  return $url;
464}
465
466
467/**
468 * send mail with STC style
469 * @param: string to
470 * @param: string content
471 * @param: string subject
472 * @return: bool
473 */
474function stc_send_mail($to, $content, $subject)
475{
476  global $conf, $conf_mail, $page, $template;
477 
478  // inputs
479  if (empty($to))
480  {
481    return false;
482  }
483
484  if (empty($content))
485  {
486    return false;
487  }
488 
489  if (empty($subject))
490  {
491    $subject = 'Piwigo';
492  }
493  else
494  {
495    $subject = trim(preg_replace('#[\n\r]+#s', '', $subject));
496    $subject = encode_mime_header($subject);
497  }
498 
499  if (!isset($conf_mail))
500  {
501    $conf_mail = get_mail_configuration();
502  }
503
504  $args['from'] = $conf_mail['formated_email_webmaster'];
505 
506  set_make_full_url();
507 
508  // hearders
509  $headers = 'From: '.$args['from']."\n"; 
510  $headers.= 'MIME-Version: 1.0'."\n";
511  $headers.= 'X-Mailer: Piwigo Mailer'."\n";
512  $headers.= 'Content-Transfer-Encoding: 8bit'."\n";
513  $headers.= 'Content-Type: text/html; charset="'.get_pwg_charset().'";'."\n";
514 
515  // template
516  $template->set_filenames(array(
517    'stc_mail_header' => realpath(SUBSCRIBE_TO_PATH . 'template/mail/header.tpl'),
518    'stc_mail_footer' => realpath(SUBSCRIBE_TO_PATH . 'template/mail/footer.tpl'),
519    ));
520  $stc_mail_css = file_get_contents(realpath(SUBSCRIBE_TO_PATH . 'template/mail/style.css'));
521   
522  $template->assign(array(
523    'GALLERY_URL' => get_gallery_home_url(),
524    'PHPWG_URL' => PHPWG_URL,
525    'STC_MAIL_CSS' => str_replace("\n", null, $stc_mail_css),
526    ));
527 
528  $content = $template->parse('stc_mail_header', true) . $content . $template->parse('stc_mail_footer', true);
529 
530  $content = wordwrap($content, 70, "\n", false);
531
532  unset_make_full_url();
533 
534  // send mail
535  return
536    trigger_event('send_mail',
537      false, /* Result */
538      trigger_event('send_mail_to', get_strict_email_list($to)),
539      trigger_event('send_mail_subject', $subject),
540      trigger_event('send_mail_content', $content),
541      trigger_event('send_mail_headers', $headers),
542      $args
543    );
544}
545
546
547/**
548 * get name, url and thumbnail of a picture
549 * @param: int image_id
550 * @param: bool return thumbnail
551 * @return: array (id, name, url, thumbnail)
552 */
553function get_picture_infos($image_id, $with_thumb=true)
554{
555  if (empty($image_id)) return array();
556 
557  $query = '
558SELECT
559    id,
560    file,
561    name,
562    path
563  FROM '.IMAGES_TABLE.'
564  WHERE id = '.$image_id.'
565;';
566  $element = pwg_db_fetch_assoc(pwg_query($query));
567   
568  if (empty($element['name']))
569  {
570    $element['name'] = get_name_from_file($element['file']);
571  }
572  $element['name'] = trigger_event('render_element_name', $element['name']);
573 
574  $element['url'] = make_picture_url(array(
575    'image_id'=>$element['id']
576    ));
577 
578  if ($with_thumb)
579  {
580    $element['thumbnail'] = DerivativeImage::thumb_url($element);
581  }
582 
583  return $element;
584}
585
586/**
587 * get name, url and thumbnail of a category
588 * @param: int cat_id
589 * @param: int return thumbnail
590 * @return: array (id, name, url, thumbnail)
591 */
592function get_category_infos($cat_id, $with_thumb=true, $user_id=null)
593{
594  global $conf;
595 
596  if ($user_id===null) $user_id = $conf['guest_id'];
597 
598  $query = '
599SELECT
600    cat.id,
601    cat.name,
602    cat.permalink,
603    ucc.count_images,
604    cat.uppercats,
605    img.id AS image_id,
606    img.path
607  FROM '.CATEGORIES_TABLE.' AS cat
608    LEFT JOIN '.USER_CACHE_CATEGORIES_TABLE.' AS ucc
609      ON ucc.cat_id = cat.id AND ucc.user_id = '.$user_id.'
610    LEFT JOIN '.IMAGES_TABLE.' AS img
611      ON img.id = ucc.user_representative_picture_id
612  WHERE cat.id = '.$cat_id.'
613;';
614  $element = pwg_db_fetch_assoc(pwg_query($query));
615 
616  $element['url'] = make_index_url(array(
617    'section'=>'categories',
618    'category'=>$element,
619    ));
620   
621  $element['name'] = trigger_event('render_category_name', $element['name']);
622 
623  if ($with_thumb)
624  {
625    if (empty($element['image_id']) and $conf['allow_random_representative'])
626    {
627      $image = get_picture_infos(get_random_image_in_category($element));
628      $element['thumbnail'] = $image['thumbnail'];
629    }
630    else
631    {
632      $element['thumbnail'] = DerivativeImage::thumb_url(array(
633        'id'=>$element['image_id'],
634        'path'=>$element['path'],
635        ));
636    }
637  }
638 
639  return $element;
640}
641
642/**
643 * get list of admins email
644 * @return: string
645 */
646function get_admins_email()
647{
648  global $conf, $user;
649 
650  $admins = array();
651 
652  $query = '
653SELECT
654    u.'.$conf['user_fields']['username'].' AS username,
655    u.'.$conf['user_fields']['email'].' AS email
656  FROM '.USERS_TABLE.' AS u
657    JOIN '.USER_INFOS_TABLE.' AS i
658      ON i.user_id =  u.'.$conf['user_fields']['id'].'
659  WHERE i.status IN ("webmaster", "admin")
660    AND '.$conf['user_fields']['email'].' IS NOT NULL
661    AND i.user_id != '.$user['id'].'
662  ORDER BY username
663;';
664
665  $datas = pwg_query($query);
666  if (!empty($datas))
667  {
668    while ($admin = pwg_db_fetch_assoc($datas))
669    {
670      array_push($admins, format_email($admin['username'], $admin['email']));
671    }
672  }
673
674  return implode(',', $admins);
675}
676
677
678/**
679 * check if the given user can view the category/image
680 * @param: int user_id
681 * @param: int element_id
682 * @param: string type (image|category)
683 * @return: bool
684 */
685function user_can_view_element($user_id, $element_id, $type)
686{
687  global $conf;
688 
689  $old_conf = $conf['external_authentification'];
690  $conf['external_authentification'] = false;
691  $user = getuserdata($user_id, true);
692  $conf['external_authentification'] = $old_conf;
693 
694  if ($type == 'image')
695  {
696    return !in_array($element_id, explode(',', $user['image_access_list']));
697  }
698  else if ($type == 'category')
699  {
700    return !in_array($element_id, explode(',', $user['forbidden_categories']));
701  }
702  else
703  {
704    return false;
705  }
706}
707
708
709/**
710 * crypt a string using mcrypt extension or
711 * http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php/802957#802957
712 * @param: string value to crypt
713 * @param: string key
714 * @return: string
715 */
716function crypt_value($value, $key)
717{ 
718  if (extension_loaded('mcrypt'))
719  {
720    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
721    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
722    $result = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $value, MCRYPT_MODE_ECB, $iv);
723  }
724  else
725  {
726    $result = null;
727    for($i = 0; $i < strlen($value); $i++)
728    {
729      $char = substr($value, $i, 1);
730      $keychar = substr($key, ($i % strlen($key))-1, 1);
731      $char = chr(ord($char) + ord($keychar));
732      $result .= $char;
733    }
734  }
735 
736  $result = base64url_encode($result);
737  return trim($result); 
738}
739
740/**
741 * decrypt a string crypted with previous function
742 * @param: string value to decrypt
743 * @param: string key
744 * @return: string
745 */
746function decrypt_value($value, $key)
747{
748  $value = base64url_decode($value); 
749 
750  if (extension_loaded('mcrypt'))
751  {
752    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
753    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
754    $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $value, MCRYPT_MODE_ECB, $iv);
755  }
756  else
757  {
758    $result = null;
759    for($i = 0; $i < strlen($value); $i++)
760    {
761      $char = substr($value, $i, 1);
762      $keychar = substr($key, ($i % strlen($key))-1, 1);
763      $char = chr(ord($char) - ord($keychar));
764      $result .= $char;
765    }
766  }
767 
768  return trim($result);
769}
770
771/**
772 * variant of base64 functions usable into url
773 * http://php.net/manual/en/function.base64-encode.php#103849
774 */
775function base64url_encode($data)
776{
777  return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
778}
779function base64url_decode($data)
780{
781  return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
782} 
783
784?>
Note: See TracBrowser for help on using the repository browser.