root/freepbx/branches/2.6/amp_conf/htdocs/recordings/modules/voicemail.module

Revision 13874, 31.8 kB (checked in by p_lindheimer, 1 year ago)

Merged revisions 13873 via svnmerge from
http://www.freepbx.org/v2/svn/freepbx/branches/2.7

................

r13873 | p_lindheimer | 2012-03-23 11:05:28 -0700 (Fri, 23 Mar 2012) | 23 lines


Merged revisions 13872 via svnmerge from
http://www.freepbx.org/v2/svn/freepbx/branches/2.8


................

r13872 | p_lindheimer | 2012-03-23 11:02:49 -0700 (Fri, 23 Mar 2012) | 16 lines


Merged revisions 13871 via svnmerge from
http://www.freepbx.org/v2/svn/freepbx/branches/2.9


................

r13871 | p_lindheimer | 2012-03-23 10:56:36 -0700 (Fri, 23 Mar 2012) | 9 lines


Merged revisions 13870 via svnmerge from
http://www.freepbx.org/v2/svn/freepbx/branches/2.10


........

r13870 | p_lindheimer | 2012-03-23 10:47:34 -0700 (Fri, 23 Mar 2012) | 1 line


fixes RCE security vulnerability reported and solution provided by Martin Tschirsich with some bug fixes present in his original patch

........

................

................

................

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2
3 /**
4  * @file
5  * Functions for the interface to the voicemail recordings
6  */
7
8 /**
9   * Class for voicemail
10   */
11 class Voicemail {
12   var $callme_num = "";
13
14   /*
15    * rank (for prioritizing modules)
16    */
17   function rank() {
18
19     $rank = 1;
20     return $rank;
21   }
22
23   /*
24    * init
25    */
26   function init() {
27     $extension = $_SESSION['ari_user']['extension'];
28     $this->callme_num = callme_getnum($extension);
29     if (empty($this->callme_num)) {
30   $this->callme_num = $extension;   // callme_num defaults to user's extension.
31   callme_setnum($extension, $extension);
32     }
33   }
34
35   /*
36    * Adds menu item to nav menu
37    *
38    * @param $args
39    *   Common arguments
40    */
41   function navMenu($args) {
42
43     global $ARI_NO_LOGIN;
44
45     // check logout
46     if ($_SESSION['ari_user'] && !$ARI_NO_LOGIN) {
47       $logout = 1;
48     }
49
50     if ($logout!='') {
51       $ret .= "<p><small><small><a href='" . $_SESSION['ARI_ROOT'] . "?m=Voicemail&f=display'>" . _("Voicemail") . "</a></small></small></p>";
52     }
53
54     return $ret;
55   }
56
57   /*
58    * Deletes selected voicemails and updates page
59    *
60    * @param $args
61    *   Common arguments
62    */
63   function navSubMenu($args) {
64
65     global $ASTERISK_VOICEMAIL_PATH;
66     global $ASTERISK_VOICEMAIL_FOLDERS;
67
68     // args
69     $m = getArgument($args,'m');
70     $q = getArgument($args,'q');
71     $current_folder = getArgument($args,'folder');
72
73     $context = $_SESSION['ari_user']['context'];
74     $extension = $_SESSION['ari_user']['extension'];
75
76     // check for voicemail enabled or admin
77     if ($_SESSION['ari_user']['voicemail_enabled']!=1 ||
78           $extension=='admin') {
79       return;
80     }
81
82     // make folder list
83     $paths = split(';',$ASTERISK_VOICEMAIL_PATH);
84     $i = 0;
85     while ($ASTERISK_VOICEMAIL_FOLDERS[$i]) {
86
87       $f = $ASTERISK_VOICEMAIL_FOLDERS[$i]['folder'];
88       $fn = $ASTERISK_VOICEMAIL_FOLDERS[$i]['name'];
89
90       foreach($paths as $key => $path) {
91
92         $path = appendPath($path,$context);
93         $path = appendPath($path,$extension);
94
95         if (is_dir($path) && is_readable($path)) {
96           $dh = opendir($path);
97           while (false!== ($folder = readdir($dh))) {
98
99             $folder_path = AppendPath($path,$folder);
100
101             if($folder!="." && $folder!=".." &&
102                  filetype($folder_path)=='dir') {
103
104               if ($f==$folder) {
105
106                 // get message count
107                 $indexes = $this->getVoicemailIndex($folder_path,$q,$order,$sort);
108                 $record_count = 0;
109                 $record_count += $this->getVoicemailCount($indexes);
110
111                 // set current folder color
112                 $class='';
113                 if ($current_folder==$folder ||
114                      ($current_folder=='' && $ASTERISK_VOICEMAIL_FOLDERS[0]['folder']==$folder)) {
115                   $class = "class='current'";
116                 }
117
118                 // add folder to list
119                 $ret .= "<p><small><small>
120                            <a " . $class . " href='" . $_SESSION['ARI_ROOT'] . "?m=Voicemail&q=" . urlencode($q) . "&folder=" . $f. "'>
121                            " . $fn . " (" . $record_count . ")" . "
122                            </a>
123                          </small></small></p>";
124               }
125             }
126           }
127         }
128       }
129       $i++;
130     }
131
132     return $ret;
133   }
134
135   /*
136    * Acts on the selected voicemails in the method indicated by the action and updates page
137    *
138    * @param $args
139    *   Common arguments
140    */
141   function msgAction($args) {
142
143     global $ASTERISK_VOICEMAIL_FOLDERS;
144
145     // args
146     $m = getArgument($args,'m');
147     $a = getArgument($args,'a');
148     $folder = getArgument($args,'folder');
149     $q = getArgument($args,'q');
150     $start = getArgument($args,'start');
151     $span = getArgument($args,'span');
152     $order = getArgument($args,'order');
153     $sort = getArgument($args,'sort');
154
155     // get files
156     $files = array();
157     foreach($_REQUEST as $key => $value) {
158       if (preg_match('/selected/',$key) && isset($_SESSION['ari_user']['recfiles'][$value])) {
159         array_push($files, $_SESSION['ari_user']['recfiles'][$value]);
160       }
161     }
162
163     if ($a=='delete') {
164       if (count($files) > 0) {
165         $this->deleteVoicemailData($files);
166       }
167       else {
168         $_SESSION['ari_error']
169           = _("One or more messages must be selected before clicking delete.");
170       }
171     }
172     else if ($a=='move_to') {
173       $folder_rx = getArgument($args,'folder_rx');
174       if ($folder_rx=='') {
175         $_SESSION['ari_error']
176           = _("A folder must be selected before the message can be moved.");
177       }
178       else if (count($files) > 0) {
179         $context = $_SESSION['ari_user']['context'];
180         $extension = $_SESSION['ari_user']['extension'];
181         $this->moveVoicemailData($files, $context, $extension, $folder_rx);
182       }
183       else {
184         $_SESSION['ari_error']
185           = _("One or more messages must be selected before clicking move_to.");
186       }
187     }
188     else if ($a=='forward_to') {
189
190       $mailbox_rx = getArgument($args,'mailbox_rx');
191       list($context_rx,$extension_rx) = split('/',$mailbox_rx);
192       if ($extension_rx=='') {
193         $_SESSION['ari_error']
194           = _("An extension must be selected before the message can be forwarded.");
195       }
196       else if (count($files) > 0) {
197         $folder_rx = $ASTERISK_VOICEMAIL_FOLDERS[0]['folder'];
198         $this->moveVoicemailData($files, $context_rx, $extension_rx, $folder_rx, false);
199       }
200       else {
201         $_SESSION['ari_error']
202           = _("One or more messages must be selected before clicking forward_to.");
203       }
204     }
205     else if ($a=='email_to') {
206         $em_to = getArgument($args,'email_to_addr');
207         if ($em_to=='') {
208     $_SESSION['ari_error']
209             = _("You must enter one or more email addresses (comma-separated) before clicking email_to.");
210         }
211         else if (count($files) > 0) {
212     $_SESSION['ari_error'] = "";
213     $line_end = "\n";
214     // Check email address(es) and construct address list for TO field.
215     // TO
216     $email_list = split(",", $em_to);
217     foreach ($email_list as $list_elem) {
218       $list_elem = trim($list_elem);
219       if (preg_match("/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i", $list_elem)) {
220         $email_to .= $list_elem . ",";
221       } else {
222         $_SESSION['ari_error'] .= _("Warning: ") . $list_elem . _("is not a valid email address");
223       }
224     }
225     $email_to = trim($email_to, ","); // remove trailing comma
226     if ($email_to != "") {
227       $email_to = "To: " . $email_to;
228       // SUBJECT
229       $email_subject = "Subject: Voicemail forwarded from mailbox " . $_SESSION['ari_user']['extension'];
230       // DATE
231       $email_date = "Date: " . date("Y-m-d");
232       // MIME VERSION
233       $email_mime_ver = "MIME-Version: 1.0";
234
235       // HEADERS
236       $headers = $email_to . $line_end . $email_subject . $line_end . $email_date . $line_end;
237       $headers .= $email_mime_ver . $line_end;
238
239       $semi_rand = md5(time());
240       $boundary = "==VMAIL_MSG_Multipart_Boundary_x{$semi_rand}x";
241
242       $headers .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"" . $line_end;
243
244       $headers .= $line_end;  // end of headers
245
246       $body = "This is a MIME message.  Please use a MIME-capable email client." . $line_end;
247       $body .= "--{$boundary}" . $line_end;
248       $body .= "Content-Type: text/plain; charset=\"iso-8859-1\"" . $line_end;
249       $body .= $line_end;
250
251       if (count($files) == 1) {
252         $body .= "You have been forwarded a voicemail message from mailbox " . $_SESSION['ari_user']['extension'] . "." . $line_end;
253         $body .= "Please listen to the attached recording.  Thank you." . $line_end;
254       } else {
255         $body .= "You have been forwarded " . count($files) . " voicemail messages from mailbox " . $_SESSION['ari_user']['extension'] . "." . $line_end;
256         $body .= "Please listen to the attached recordings.  Thank you." . $line_end;
257       }
258       $body .= $line_end;
259
260       $body .= "--{$boundary}" . $line_end;
261       $wav_pat = '/wav$/i';
262       $gsm_pat = '/gsm$/i';
263       $att_counter = -1;
264       foreach ($files as $f) {
265         if (preg_match($wav_pat, $f)) {
266           $content_type_audio = "Content-Type: audio/x-wav";
267         } else if (preg_match($gsm_pat, $f)) {
268           $content_type_audio = "Content-Type: audio/gsm";
269         } else {
270           $content_type_audio = "Content-Type: application/octet-stream"; // binary file attachment
271           $_SESSION['ari_error'] .= $f . ": " . _("The file type was not recognized.");
272         }
273         // Read in the attachment(s)
274         $file = fopen($f, "rb");
275         $file_data = fread($file, filesize($f));
276         fclose($file);
277
278         $body .= "--" . $boundary . $line_end;
279         $body .= $content_type_audio . $line_end;
280
281         preg_match("/msg[\d]*\.[A-Za-z]*/", $f, $fname_matches);
282         $email_fname = $fname_matches[0];
283
284         $body .= "Content-Disposition: attachment; filename=\"$email_fname\"" . $line_end;
285         $body .= "Content-Transfer-Encoding: base64" . $line_end;
286         $body .= $line_end;
287
288         $att_data = chunk_split(base64_encode($file_data));
289
290         $body .= $attachments[$att_counter] .= $att_data;
291         $body .= $attachments[$att_counter] .= $line_end;
292       }
293
294       $body .= $line_end;
295       $body .= "--{$boundary}--";
296
297       $email_message = $headers . $body;
298
299       // If alternate mailer is defined in voicemail.conf, use it.
300       if (function_exists("parse_voicemailconf")) {
301         global $amp_conf;
302         $vmconf = null;
303         $section = null;
304         $vmail_path = rtrim($amp_conf["ASTETCDIR"],"/") . "/voicemail.conf";
305         parse_voicemailconf($vmail_path, $vmconf, $section);
306       } else {
307         $_SESSION['ari_error'] .= _("Warning: Could not access voicemail.conf.  Using default mailer.");
308       }
309       if (isset($vmconf["general"]["mailcmd"]) && $vmconf["general"]["mailcmd"] != "") {
310         $email_mailcmd = $vmconf["general"]["mailcmd"];
311       } else {
312         $email_mailcmd = "/usr/sbin/sendmail -t";
313       }
314       // Mail it!
315       if (($sendmail_pipe = popen($email_mailcmd, "w"))) {
316         fputs($sendmail_pipe, $email_message);
317         fclose($sendmail_pipe);
318       } else {
319         $_SESSION['ari_error'] .= _("Mail operation failed");
320       }
321
322     } else {
323       $_SESSION['ari_error'] = _("No valid email address given.  Please try again.");
324     }
325   }
326   else {
327     $_SESSION['ari_error'] = _("One or more messages must be selected before clicking email_to.");
328   }
329     }
330
331     // redirect to see updated page
332     $ret .= "
333       <head>
334         <script>
335         <!--
336           window.location = \"" . $_SESSION['ARI_ROOT'] . "?m=" . $m . "&folder=" . $folder . "&q=" . urlencode($q) . "&start=" . $start . "&span=" . $span . "&order=" . $order . "&sort=" . $sort . "\"
337         // -->
338         </script>
339       </head>";
340
341     return $ret;
342   }
343
344   /*
345    * Displays stats page
346    *
347    * @param $args
348    *   Common arguments
349    */
350   function display($args) {
351
352     global $ASTERISK_VOICEMAIL_CONF;
353     global $ASTERISK_VOICEMAIL_PATH;
354     global $ASTERISK_VOICEMAIL_FOLDERS;
355     global $AJAX_PAGE_REFRESH_ENABLE;
356
357     $voicemail_audio_format = $_COOKIE['ari_voicemail_audio_format'];
358
359     $display = new DisplaySearch();
360
361     // args
362     $m = getArgument($args,'m');
363     $f = getArgument($args,'f');
364     $q = getArgument($args,'q');
365     $start = getArgument($args,'start');
366     $span = getArgument($args,'span');
367     $order = getArgument($args,'order');
368     $sort = getArgument($args,'sort');
369
370     $start = $start=='' ? 0 : $start;
371     $span = $span=='' ? 15 : $span;
372     $order = $order=='' ? 'calldate' : $order;
373     $sort = ($sort=='' || strtolower($sort) == 'desc') ? 'desc' : 'asc';
374
375     $paths = split(';',$ASTERISK_VOICEMAIL_PATH);
376
377     $displayname = $_SESSION['ari_user']['displayname'];
378     $extension = $_SESSION['ari_user']['extension'];
379     $context = $_SESSION['ari_user']['context'];
380     $folder = getArgument($args,'folder');
381     if (!$folder) {
382       $folder = $ASTERISK_VOICEMAIL_FOLDERS[0]['folder'];
383     }
384
385     // get data
386     $data = array();
387     foreach($paths as $key => $path) {
388       $path = fixPathSlash($path);
389       $vm_path = $path . "$context/$extension/$folder";
390       $indexes = $this->getVoicemailIndex($vm_path,$q,$order,$sort);
391       $record_count += $this->getVoicemailCount($indexes);
392       $data = array_merge($data,$this->getVoicemailData($indexes,$start,$span));
393     }
394
395     // build controls
396
397     // get the recordings from the asterisk server
398     $filter = '';
399     $recursiveMax = 1;
400     $recursiveCount = 0;
401     $files = array();
402     foreach($paths as $key => $path) {
403       $path_files = GetFiles($path,$filter,$recursiveMax,$recursiveCount);
404       $files = array_merge($files,$path_files);
405     }
406
407     // move options
408     $i=0;
409     while ($ASTERISK_VOICEMAIL_FOLDERS[$i]) {
410       $cf = $ASTERISK_VOICEMAIL_FOLDERS[$i]['folder'];
411       $fn = $ASTERISK_VOICEMAIL_FOLDERS[$i]['name'];
412       if ($cf!=$folder) {
413         $move_options .= "<option VALUE='" . $cf . "'>&nbsp;&nbsp;&nbsp;&nbsp;" .  $fn;
414       }
415       $i++;
416     }
417
418     // forward options
419     if (is_readable($ASTERISK_VOICEMAIL_CONF)) {
420       $lines = file($ASTERISK_VOICEMAIL_CONF);
421       $ext_array = array();
422       foreach ($lines as $key => $line) {
423
424         // get context for forward to mailbox
425         if (preg_match("/\[.*\]/i",$line)) {
426           $forwardContext = trim(preg_replace('/\[|\]/', '', $line));
427         }
428         if ($forwardContext!=$_SESSION['ari_user']['context']) {
429           continue;
430         }
431
432         // get username and add to options
433         if (preg_match("/\=\>/i",$line)) {
434           list($username,$value) = split('=>',$line);
435           $username = trim($username);
436           if ($username!=$_SESSION['ari_user']['extension']) {
437             //$ext_array[] = $username . "|" . $forwardContext;
438             list(,$real_name,) = split(",",$value,3);
439             $ext_array[] = $real_name . "|" . $username . "|" . $forwardContext;
440           }
441         }
442       } //foreach
443       //sort the array
444       sort($ext_array);
445
446       //get the size of the array
447       $array_size = count($ext_array) - 1;
448
449       //loop through the array and build the drop down list
450       foreach ($ext_array as $item)
451       {
452          //split the values apart
453          list($real_name,$username,$context) = explode("|",$item);
454
455          //add it to the drop down
456          $forward_options .= "<option VALUE='" . $context . "/" . $username . "'>" . substr($real_name,0,15) . " <" . $username . ">";
457       }
458     }
459     else {
460       $_SESSION['ari_error'] = "File not readable: " . $ASTERISK_VOICEMAIL_CONF;
461       return;
462     }
463
464     // table controls
465     $controls = "
466           <button class='infobar' type='submit' onclick=\"document.voicemail_form.a.value='delete'\">
467           " . _("delete") . "
468           </button>
469           <button class='infobar' type='submit' onclick=\"document.voicemail_form.a.value='move_to'\">
470           " . _("move_to") . "
471           </button>
472           <select name='folder_rx' style='width:124px;'>
473             <option VALUE=''>" . _("Folder") . "
474             " . $move_options . "
475           </select>
476           <button class='infobar' type='submit' onclick=\"document.voicemail_form.a.value='forward_to'\">
477           " . _("forward_to") . "
478           </button>
479           <select name='mailbox_rx'>
480             <option VALUE=''>
481             " . $forward_options . "
482     </select>
483           <button class='infobar' type='submit' onclick=\"document.voicemail_form.a.value='email_to'\">
484           " . _("email_to") . "
485           </button>
486           <input type='text' name='email_to_addr'/>";
487
488     // table header
489     $recording_delete_header = "<th></th>";
490
491     $fields[0]['field'] = "calldate";
492     $fields[0]['text'] = _("Date");
493     $fields[1]['field'] = "calldate";
494     $fields[1]['text'] = _("Time");
495     $fields[2]['field'] = "clid";
496     $fields[2]['text'] = _("Caller ID");
497     $fields[3]['field'] = "priority";
498     $fields[3]['text'] = _("Priority");
499     $fields[4]['field'] = "origmailbox";
500     $fields[4]['text'] = _("Orig Mailbox");
501     $fields[5]['field'] = "duration";
502     $fields[5]['text'] = _("Duration");
503     $i = 0;
504     while ($fields[$i]) {
505
506       $field = $fields[$i]['field'];
507       $text = $fields[$i]['text'];
508       if ($order==$field) {
509         if ($sort=='asc') {
510           $currentSort = 'desc';
511           $arrowImg = "<img src='theme/images/arrow-asc.gif' alt='sort'>";
512         }
513         else {
514           $currentSort = 'asc';
515           $arrowImg = "<img src='theme/images/arrow-desc.gif' alt='sort'>";
516         }
517
518         if ($i==1) {
519           $arrowImg = '';
520         }
521       }
522       else {
523         $arrowImg = '';
524         $currentSort = 'desc';
525       }
526
527       $unicode_q = urlencode($q);
528       $recording_header .= "<th><a href=" .  $_SESSION['ARI_ROOT'] . "?m=" . $m . "&f=" . $f . "&q=" . $unicode_q . "&folder=" . $folder . "&order=" . $field . "&sort=" . $currentSort . ">" . $text . $arrowImg . "</a></th>";
529
530       $i++;
531     }
532     $recording_header .= "<th>" . _("Playback") . "</th>";
533
534     // Column to provide a download link for each message in voicemail.
535     $download_header .= "<th>" . _("Download"). "</th>";
536     // table body
537     unset($_SESSION['ari_user']['recfiles']);
538     if (isset($data)) {
539       $playbackRow = 2; // Index for where playback control rows used by javascript playback() should appear in the table.
540       // First control row would appear below row 1 (hence $playbackRow starts at 2); control rows are inserted/deleted as needed.
541       foreach($data as $file=>$value) {
542         $i++;
543         // Playback links
544         $voicemail_audio_format = $voicemail_audio_format=='' ? '.wav' : $voicemail_audio_format;
545         $recording = preg_replace('/.txt/', $voicemail_audio_format, $file);
546         $date = GetDateFormat($value['origtime']);
547         $time = GetTimeFormat($value['origtime']);
548         $from = $value[callerid];
549         $priority = $value[priority];
550         $to = $value[origmailbox];
551         $duration = $value[duration];
552         if (is_file($recording)) {
553           $_SESSION['ari_user']['recfiles'][$i] = $recording;
554     $recordingLink = "<a href='#' onClick=\"javascript:playback('play', $playbackRow, 'misc/play_page.php?recindex=" . $i . "'); return false;\"><img src='theme/images/sound.png' title=" . _("Play") . "></img></a>";
555     $callmePage   = "'misc/callme_page.php?recindex=" . $i . "&action=c'";
556     $callme_tooltip = _("Play message at: ") . $this->callme_num;
557     $callmeLink = "<a href='#' onClick=\"javascript:playback('callme', $playbackRow, $callmePage); return false;\"><img src='theme/images/telephone.png' title='" . $callme_tooltip . "'></img></a>";
558     $downloadLink = "<a href=misc/audio.php?recindex=" . $i . "><img src='theme/images/drive_go.png' title=" . _("Download") . "></img></a>";
559         }
560         else {
561           $_SESSION['ari_error'] = _("Voicemail recording(s) was not found.") . "<br>" .
562                                    sprintf(_("On settings page, change voicemail audio format.  It is currently set to %s"),$voicemail_audio_format);
563         }
564
565         $tableText .= "
566           <tr>
567             <td class='checkbox'><input type=checkbox name='selected" . $i . "' value=" . $i . "></td>
568             <td width=68>" . $date . "</td>
569             <td>" . $time . "</td>
570             <td width=100>" . $from . "</td>
571             <td>" . $value[priority] . "</td>
572             <td width=90>" . $to . "</td>
573             <td>" . $duration . " sec</td>
574             <td>" . $recordingLink . "&nbsp;&nbsp;" . $callmeLink . "</td>
575             <td>" . $downloadLink . "</td>
576           </tr>";
577
578   $playbackRow++;
579       }
580     }
581
582     // options
583     $url_opts = array();
584     $url_opts['folder'] = $folder;
585     $url_opts['sort'] = $sort;
586     $url_opts['order'] = $order;
587
588     $error = 0;
589
590     // check for voicemail enabled
591     if ($_SESSION['ari_user']['voicemail_enabled']!=1) {
592       $_SESSION['ari_error'] = _("Voicemail Login not found.") . "<br>" .
593                                _("No access to voicemail");
594       $error = 1;
595     }
596
597     // check admin
598     if ($extension=='admin') {
599       $_SESSION['ari_error'] = _("No Voicemail Recordings for Admin");
600       $error = 1;
601     }
602
603     // build page content
604     $ret .= checkErrorMessage();
605     if ($error) {
606       return $ret;
607     }
608
609     // ajax page refresh script
610     if ($AJAX_PAGE_REFRESH_ENABLE) {
611 //      $ret .= ajaxRefreshScript($args);
612     }
613
614     // header
615     $ret .= $display->displayHeaderText(sprintf(_("Voicemail for %s (%s)"),$displayname,$extension));
616     $ret .= $display->displaySearchBlock('left',$m,$q,$url_opts,true);
617
618     // pb_load_inprogress is a hidden element that is used by the javascript playback()
619     // as a boolean to keep track of whether or not a Playback (Call Me or Computer Play) from this page is in progress ("loading").
620     // start form
621     $ret .= "
622       <form name='voicemail_form' action='" . $_SESSION['ARI_ROOT'] . "' method='GET'>
623         <input type=hidden id='pb_load_inprogress' value='false'>
624         <input type=hidden name=m value=" . $m . ">
625         <input type=hidden name=f value=msgAction>
626         <input type=hidden name=a value=''>
627         <input type=hidden name=q value=" . urlencode($q) . ">
628         <input type=hidden name=folder value=" . $folder . ">
629         <input type=hidden name=start value=" . $start . ">
630         <input type=hidden name=span value=" . $span . ">
631         <input type=hidden name=order value=" . $order . ">
632         <input type=hidden name=sort value=" . $sort . ">";
633
634     $ret .= $display->displayInfoBarBlock($controls,$q,$start,$span,$record_count);
635
636     // Variables used in generating playback() javascript.
637     $callme_status_msg0 = _("Calling: ");
638     $callme_status_msg1 = _(". Please wait patiently...");
639
640     // add javascript for playback and message actions
641     $ret .= "
642       <SCRIPT LANGUAGE='JavaScript'>
643       <!-- Begin
644       function checkAll(form,set) {
645         var elem = 0;
646         var i = 0;
647         while (elem = form.elements[i]) {
648           if (set) {
649             elem.checked = true;
650           } else {
651             elem.checked = false;
652           }
653           i++;
654         }
655         return true;
656       }
657
658       // Playback function
659       function playback(mode, row_num, link) {
660   var playbackId = \"CURRENT__MSG\";
661   var i = 0;
662   var vmTable = document.getElementById('vmail_table');
663   var inprogress = document.getElementById('pb_load_inprogress').value;
664   // Only start a Playback control if another one is NOT in progress.
665   if (inprogress == \"false\") {
666     // Only one Playback control row can be open at a time.
667     // If one is already open (e.g. a call that is now over or a message already loaded for playback), close it.
668     for (i = 0; i < vmTable.rows.length; i++) {
669       if (vmTable.rows[i].id == playbackId) {
670         // Delete the row; it's a Playback control row.
671         vmTable.deleteRow(vmTable.rows[i].rowIndex);
672       }
673     }
674     // Make our Playback row.
675     playback_src = \"<iframe width='100%' height='25px' marginheight='0' marginwidth='0' frameborder='0' scrolling='no' src=\" + link + \"></iframe>\";
676     document.getElementById('pb_load_inprogress').value = \"true\";
677     newRow = vmTable.insertRow(row_num);
678     newRow.id = playbackId;
679     cell_left = newRow.insertCell(0);
680     if (mode == 'callme') {
681       cell_left.colSpan = 4;
682       cell_left.innerHTML = \"<div id='callme_status'>" . $callme_status_msg0 . $this->callme_num . $callme_status_msg1 . "</div>\";
683       cell_right = newRow.insertCell(1);
684       cell_right.colSpan = 5;
685       cell_right.innerHTML = playback_src;
686     } else {
687       cell_left.colSpan = 9;
688       cell_left.innerHTML = playback_src;
689     }
690   } else {
691     // Change background color of status cell to alert user that the playback is still loading.
692     document.getElementById(\"callme_status\").parentNode.style.backgroundColor = 'yellow';
693   }
694       }
695       // End -->
696       </script>";
697
698     // voicemail delete recording controls
699     $ret .= "
700       <table>
701         <tr>
702           <td>
703             <small>" . _("select") . ": </small>
704             <small><a href='' OnClick=\"checkAll(document.voicemail_form,true); return false;\">" . _("all") . "</a></small>
705             <small><a href='' OnClick=\"checkAll(document.voicemail_form,false); return false;\">" . _("none") . "</a></small>
706           </td>
707         </tr>
708       </table>";
709
710     // table
711     $ret .= "
712       <table id='vmail_table' class='voicemail'>
713         <tr>
714            " . $recording_delete_header . "
715            " . $recording_header . "
716            " . $download_header . "
717         </tr>
718         " . $tableText . "
719       </table>";
720
721     // end form
722     $ret .= "</form>";
723
724     $ret .= $display->displaySearchBlock('center',$m,$q,$url_opts,false);
725     $ret .= $display->displayNavigationBlock($m,$q,$url_opts,$start,$span,$record_count);
726
727     return $ret;
728   }
729
730   /*
731    * Gets voicemail data
732    *
733    * @param $data
734    *   Reference to the variable to store the data in
735    * @param $q
736    *   search string
737    */
738   function getVoicemailIndex($path,$q,$order,$sort) {
739
740     $indexes = array();
741
742     $filter = '.txt';
743     $recursiveMax = 0;
744     $recursiveCount = 0;
745     $files = getFiles($path,$filter,$recursiveMax,$recursiveCount);
746
747     if (isset($files)) {
748
749       // ugly, but sorts array by time stamp
750       foreach ($files as $file) {
751
752         if (is_file($file)) {
753
754           $lines = file($file);
755           foreach ($lines as $key => $line) {
756             unset($value);
757             list($key,$value) = split('=',$line);
758             if ($value) {
759
760               if ($key=="origtime") {
761                 $calldate = $value;
762                 $date = GetDateFormat($value);
763                 $time = GetTimeFormat($value);
764               }
765               if ($key=="callerid") {
766                 $callerid = $value;
767               }
768               if ($key=="priority") {
769                 $priority = $value;
770               }
771               if ($key=="origmailbox") {
772                 $origmailbox = $value;
773               }
774               if ($key=="duration") {
775                 $duration = (int)$value;
776               }
777             }
778           }
779
780           // search filter
781           $found = 1;
782           if ($q) {
783
784             $found = 0;
785
786             if (preg_match("/" . $q . "/", $origmailbox) ||
787                   preg_match("/" . $q . "/", $callerid) ||
788                   preg_match("/" . $q . "/", $date) ||
789                   preg_match("/" . $q . "/", $time)) {
790               $found = 1;
791             }
792           }
793         }
794
795         // add to index
796         if ($found) {
797           $indexes[$file] = $$order;
798         }
799       }
800
801       if (count($indexes)) {
802         if ($sort=='desc') {
803           arsort($indexes);
804         }
805         else {
806           asort($indexes);
807         }
808       }
809     }
810
811     return $indexes;
812   }
813
814   /*
815    * Deletes selected voicemails
816    *
817    * @param $files
818    *   Array of files to delete
819    */
820   function deleteVoicemailData($files) {
821
822     foreach($files as $key => $path) {
823
824       // get file parts for search
825       $path_parts = pathinfo($path);
826       $path = fixPathSlash($path_parts['dirname']);
827
828       list($name,$ext) = split("\.",$path_parts['basename']);
829
830       // delete all related files using a wildcard
831       if (is_dir($path)) {
832         $hdl = opendir($path);
833         while ($fn = readdir($hdl)) {
834           if (preg_match("/" . $name ."/",$fn)) {
835             $file = $path . $fn;
836             unlink($file);
837           }
838         }
839         closedir($hdl);
840       }
841     }
842   }
843
844   /*
845    * Moves selected voicemails to a specified folder
846    *
847    * @param $files
848    *   Array of files to delete
849    * @param $extension_rx
850    *   Mailbox to move message to
851    * @param $folder_rx
852    *   Folder to move the messages to
853    * @param $delete_moved
854    *   If original should be deleted, default true (otherwise it is a copy)
855    */
856   function moveVoicemailData($files,$context_rx,$extension_rx,$folder_rx,$delete_moved=true) {
857
858     global $ASTERISK_VOICEMAIL_PATH;
859
860     $perm = fileperms($ASTERISK_VOICEMAIL_PATH);
861     $uid = fileowner($ASTERISK_VOICEMAIL_PATH);
862     $gid = filegroup($ASTERISK_VOICEMAIL_PATH);
863
864     // recieving path
865     $paths = split(';',$ASTERISK_VOICEMAIL_PATH);
866     $path_rx = appendPath($paths[0],$context_rx);
867     if (!is_dir($path_rx)) {
868       mkdir($path_rx, $perm);
869       chown($path_rx,intval($uid));
870       chgrp($path_rx,intval($gid));
871     }
872     $path_rx = appendPath($path_rx,$extension_rx);
873     if (!is_dir($path_rx)) {
874       mkdir($path_rx, $perm);
875       chown($path_rx,intval($uid));
876       chgrp($path_rx,intval($gid));
877     }
878     $path_rx = appendPath($path_rx,$folder_rx);
879     if (!is_dir($path_rx)) {
880       mkdir($path_rx, $perm);
881       chown($path_rx,intval($uid));
882       chgrp($path_rx,intval($gid));
883     }
884
885     // get recieving folder last message number
886     if (is_dir($path_rx)) {
887
888       $lastNum = -1;
889       $lastNumLen = 4;
890
891       $dh = opendir($path_rx);
892       while (false != ($filename = readdir($dh))) {
893         if($filename!="." && $filename!="..") {
894
895           $msg_path = $path_rx;
896           $msg_path = appendPath($msg_path,$filename);
897           if (is_file($msg_path)) {
898             $path_parts = pathinfo($msg_path);
899             //fix for Serge Mankovski's "Voicemail RSS"
900             //split file basename into two pieces at the first '.'
901             //so that files like msg0000.7025f35d463ebbafa101db8a88c71b681aa8443d.mp3
902             //don't interfere with finding the true last file number
903             list($name,$ext) = split("\.",$path_parts['basename'],2);
904             $num = preg_replace("/[a-zA-Z]/",'', $name);
905             if ($num > $lastNum) {
906               $lastNum = $num;
907               $lastNumLen = strlen($lastNum);
908             }
909           }
910         }
911       }
912     }
913     else {
914       $_SESSION['ari_error'] = sprintf(_("Could not create mailbox folder %s on the server"),$folder_rx);
915       return;
916     }
917
918     foreach($files as $key => $pathPlain) {
919       // add plain path to new array
920       $filesPlain[] = $pathPlain;
921     }
922
923     // copy files to new location, incrementing each message number
924     asort($files);
925     foreach($files as $key => $path) {
926
927       // get file parts for search
928       $path_parts = pathinfo($path);
929       $path = $path_parts['dirname'];
930       $path = fixPathSlash($path);
931       list($name,$ext) = split("\.",$path_parts['basename']);
932       if (is_dir($path)) {
933
934         $lastNum++;
935         $hdl = opendir($path);
936         while ($fn = readdir($hdl)) {
937           if (preg_match("/" . $name . "/",$fn)) {
938             $src = $path . $fn;
939             $path_parts = pathinfo($src);
940             //fix for Serge Mankovski's "Voicemail RSS"
941             //split file basename into two pieces at the first '.'
942             //so that files like msg0000.7025f35d463ebbafa101db8a88c71b681aa8443d.mp3
943             //don't get clobbered by preg_replace() of digits
944             list($name,$ext) = split("\.",$path_parts['basename'],2);
945             $folder_rx = preg_replace("/\d+/",sprintf("%0" . $lastNumLen . "d",$lastNum),$name) . "." . $ext;
946             $dst = appendPath($path_rx,$folder_rx);
947             if (is_writable($src) && is_writable($path_rx)) {
948
949               $perm = fileperms($src);
950               $uid = fileowner($src);
951               $gid = filegroup($src);
952
953               copy($src,$dst);
954
955               if (is_writable($dst)) {
956                 chmod($dst, $perm);
957                 chown($dst,intval($uid));
958                 chgrp($dst,intval($gid));
959               }
960
961               if ($delete_moved) {
962                 unlink($src);
963               }
964             }
965             else {
966               $_SESSION['ari_error'] = sprintf(_("Permission denied on folder %s or %s"),$src,$path_rx);
967               return;
968             }
969           }
970         }
971         closedir($hdl);
972       }
973     }
974   }
975
976   /*
977    * Gets voicemail record count
978    *
979    * @param $indexes
980    *   array of files to be counted
981    * @return $count
982    *   number of cdr records counted
983    */
984   function getVoicemailCount($indexes) {
985
986     $count = count($indexes);
987
988     return $count;
989   }
990
991   /*
992    * Gets voicemail data
993    *
994    * @param $indexes
995    *   array of voicemail files
996    * @param $start
997    *   message number to start page with
998    * @param $span
999    *   number of messages to display on page
1000    * @param $data
1001    *   Reference to the variable to store the data in
1002    */
1003   function getVoicemailData($indexes,$start,$span) {
1004
1005     $data = array();
1006
1007     if (!isset($indexes)) {
1008       return;
1009     }
1010
1011     // populate array
1012     $i = 0;
1013     foreach ($indexes as $file => $index) {
1014       if ($i>$start-1+$span) {
1015         return $data;
1016       }
1017       elseif ($i>$start-1 && $i<$start+$span) {
1018         $lines = file($file);
1019         foreach ($lines as $key => $line) {
1020           unset($value);
1021           list($key,$value) = split('=',$line);
1022           if ($value) {
1023             $data[$file][$key] = $value;
1024           }
1025         }
1026       }
1027       $i++;
1028     }
1029
1030     return $data;
1031   }
1032
1033 }
1034
1035
1036 ?>
Note: See TracBrowser for help on using the browser.