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

Last change on this file since 15648 was 15648, checked in by mistic100, 12 years ago

check email validity before subscribe

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