vmail.cgi 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. #!/usr/bin/perl
  2. #
  3. # Web based Voicemail for Asterisk
  4. #
  5. # Copyright (C) 2002, Linux Support Services, Inc.
  6. #
  7. # Distributed under the terms of the GNU General Public License
  8. #
  9. # Written by Mark Spencer <markster@linux-support.net>
  10. #
  11. # (icky, I know.... if you know better perl please help!)
  12. #
  13. #
  14. use CGI qw/:standard/;
  15. use Carp::Heavy;
  16. use CGI::Carp qw(fatalsToBrowser);
  17. use DBI;
  18. $context=""; # Define here your by default context (so you dont need to put voicemail@context in the login
  19. @validfolders = ( "INBOX", "Old", "Work", "Family", "Friends", "Cust1", "Cust2", "Cust3", "Cust4", "Cust5" );
  20. %formats = (
  21. "wav" => {
  22. name => "Uncompressed WAV",
  23. mime => "audio/x-wav",
  24. pref => 1
  25. },
  26. "WAV" => {
  27. name => "GSM Compressed WAV",
  28. mime => "audio/x-wav",
  29. pref => 2
  30. },
  31. "gsm" => {
  32. name => "Raw GSM Audio",
  33. mime => "audio/x-gsm",
  34. pref => 3
  35. }
  36. );
  37. $astpath = "/_asterisk";
  38. $stdcontainerstart = "<table align=center width=600><tr><td>\n";
  39. $footer = "<hr><font size=-1><a href=\"http://www.asterisk.org\">The Asterisk Open Source PBX</a> Copyright 2004, <a href=\"http://www.digium.com\">Digium, Inc.</a></a>";
  40. $stdcontainerend = "</td></tr><tr><td align=right>$footer</td></tr></table>\n";
  41. sub login_screen() {
  42. print header;
  43. my ($message) = @_;
  44. print <<_EOH;
  45. <TITLE>Asterisk Web-Voicemail</TITLE>
  46. <BODY BGCOLOR="white">
  47. $stdcontainerstart
  48. <FORM METHOD="post">
  49. <input type=hidden name="action" value="login">
  50. <table align=center>
  51. <tr><td valign=top align=center rowspan=6><img align=center src="$astpath/animlogo.gif"></td></tr>
  52. <tr><td align=center colspan=2><font size=+2>Comedian Mail Login</font></td></tr>
  53. <tr><td align=center colspan=2><font size=+1>$message</font></td></tr>
  54. <tr><td>Mailbox:</td><td><input type=text name="mailbox"></td></tr>
  55. <tr><td>Password:</td><td><input type=password name="password"></td></tr>
  56. <tr><td align=right colspan=2><input value="Login" type=submit></td></tr>
  57. <input type=hidden name="context" value="$context">
  58. </table>
  59. </FORM>
  60. $stdcontainerend
  61. </BODY>\n
  62. _EOH
  63. }
  64. sub check_login()
  65. {
  66. local ($filename, $startcat) = @_;
  67. local ($mbox, $context) = split(/\@/, param('mailbox'));
  68. local $pass = param('password');
  69. local $category = $startcat;
  70. local @fields;
  71. local $tmp;
  72. local (*VMAIL);
  73. if (!$category) {
  74. $category = "general";
  75. }
  76. if (!$context) {
  77. $context = param('context');
  78. }
  79. if (!$context) {
  80. $context = "default";
  81. }
  82. if (!$filename) {
  83. $filename = "/etc/asterisk/voicemail.conf";
  84. }
  85. # print header;
  86. # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
  87. open(VMAIL, "<$filename") || die("Bleh, no $filename");
  88. while(<VMAIL>) {
  89. chomp;
  90. if (/include\s\"([^\"]+)\"$/) {
  91. ($tmp, $category) = &check_login("/etc/asterisk/$1", $category);
  92. if (length($tmp)) {
  93. # print "Got '$tmp'\n";
  94. return ($tmp, $category);
  95. }
  96. } elsif (/\[(.*)\]/) {
  97. $category = $1;
  98. } elsif ($category eq "general") {
  99. if (/([^\s]+)\s*\=\s*(.*)/) {
  100. if ($1 eq "dbname") {
  101. $dbname = $2;
  102. } elsif ($1 eq "dbpass") {
  103. $dbpass = $2;
  104. } elsif ($1 eq "dbhost") {
  105. $dbhost = $2;
  106. } elsif ($1 eq "dbuser") {
  107. $dbuser = $2;
  108. }
  109. }
  110. if ($dbname and $dbpass and $dbhost and $dbuser) {
  111. # db variables are present. Use db for authentication.
  112. my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
  113. my $sth = $dbh->prepare(qq{select fullname,context from users where mailbox='$mbox' and password='$pass' and context='$context'});
  114. $sth->execute();
  115. if (($fullname, $category) = $sth->fetchrow_array()) {;
  116. return ($fullname ? $fullname : "Extension $mbox in $context",$category);
  117. }
  118. }
  119. } elsif (($category ne "general") && ($category ne "zonemessages")) {
  120. if (/([^\s]+)\s*\=\>?\s*(.*)/) {
  121. @fields = split(/\,\s*/, $2);
  122. # print "<p>Mailbox is $1\n";
  123. if (($mbox eq $1) && (($pass eq $fields[0]) || ("-${pass}" eq $fields[0])) && ($context eq $category)) {
  124. return ($fields[1] ? $fields[1] : "Extension $mbox in $context", $category);
  125. }
  126. }
  127. }
  128. }
  129. close(VMAIL);
  130. return ("", $category);
  131. }
  132. sub validmailbox()
  133. {
  134. local ($context, $mbox, $filename, $startcat) = @_;
  135. local $category = $startcat;
  136. local @fields;
  137. local (*VMAIL);
  138. if (!$context) {
  139. $context = param('context');
  140. }
  141. if (!$context) {
  142. $context = "default";
  143. }
  144. if (!$filename) {
  145. $filename = "/etc/asterisk/voicemail.conf";
  146. }
  147. if (!$category) {
  148. $category = "general";
  149. }
  150. open(VMAIL, "<$filename") || die("Bleh, no $filename");
  151. while(<VMAIL>) {
  152. chomp;
  153. if (/include\s\"([^\"]+)\"$/) {
  154. ($tmp, $category) = &validmailbox($mbox, $context, "/etc/asterisk/$1");
  155. if ($tmp) {
  156. return ($tmp, $category);
  157. }
  158. } elsif (/\[(.*)\]/) {
  159. $category = $1;
  160. } elsif ($category eq "general") {
  161. if (/([^\s]+)\s*\=\s*(.*)/) {
  162. if ($1 eq "dbname") {
  163. $dbname = $2;
  164. } elsif ($1 eq "dbpass") {
  165. $dbpass = $2;
  166. } elsif ($1 eq "dbhost") {
  167. $dbhost = $2;
  168. } elsif ($1 eq "dbuser") {
  169. $dbuser = $2;
  170. }
  171. }
  172. if ($dbname and $dbpass and $dbhost and $dbuser) {
  173. # db variables are present. Use db for authentication.
  174. my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
  175. my $sth = $dbh->prepare(qq{select fullname,context from users where mailbox='$mbox' and password='$pass' and context='$context'});
  176. $sth->execute();
  177. if (($fullname, $category) = $sth->fetchrow_array()) {;
  178. return ($fullname ? $fullname : "unknown", $category);
  179. }
  180. }
  181. } elsif (($category ne "general") && ($category ne "zonemessages") && ($category eq $context)) {
  182. if (/([^\s]+)\s*\=\>?\s*(.*)/) {
  183. @fields = split(/\,\s*/, $2);
  184. if (($mbox eq $1) && ($context eq $category)) {
  185. return ($fields[2] ? $fields[2] : "unknown", $category);
  186. }
  187. }
  188. }
  189. }
  190. return ("", $category);
  191. }
  192. sub mailbox_options()
  193. {
  194. local($context, $current, $filename, $category) = @_;
  195. local (*VMAIL);
  196. local $tmp2;
  197. local $tmp;
  198. if (!$filename) {
  199. $filename = "/etc/asterisk/voicemail.conf";
  200. }
  201. if (!$category) {
  202. $category = "general";
  203. }
  204. # print header;
  205. # print "Including <h2>$filename</h2> while in <h2>$category</h2>...\n";
  206. open(VMAIL, "<$filename") || die("Bleh, no voicemail.conf");
  207. while(<VMAIL>) {
  208. chomp;
  209. s/\;.*$//;
  210. if (/include\s\"([^\"]+)\"$/) {
  211. ($tmp2, $category) = &mailbox_options($context, $current, "/etc/asterisk/$1", $category);
  212. # print "Got '$tmp2'...\n";
  213. $tmp .= $tmp2;
  214. } elsif (/\[(.*)\]/) {
  215. $category = $1;
  216. } elsif ($category eq "general") {
  217. if (/([^\s]+)\s*\=\s*(.*)/) {
  218. if ($1 eq "dbname") {
  219. $dbname = $2;
  220. } elsif ($1 eq "dbpass") {
  221. $dbpass = $2;
  222. } elsif ($1 eq "dbhost") {
  223. $dbhost = $2;
  224. } elsif ($1 eq "dbuser") {
  225. $dbuser = $2;
  226. }
  227. }
  228. if ($dbname and $dbpass and $dbhost and $dbuser) {
  229. # db variables are present. Use db for authentication.
  230. my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass);
  231. my $sth = $dbh->prepare(qq{select mailbox,fullname,context from users where context='$context' order by mailbox});
  232. $sth->execute();
  233. while (($mailbox, $fullname, $category) = $sth->fetchrow_array()) {
  234. $text = $mailbox;
  235. if ($fullname) {
  236. $text .= " (".$fullname.")";
  237. }
  238. if ($mailbox eq $current) {
  239. $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
  240. } else {
  241. $tmp .= "<OPTION>$text</OPTION>\n";
  242. }
  243. }
  244. return ($tmp, $category);
  245. }
  246. } elsif (($category ne "general") && ($category ne "zonemessages")) {
  247. if (/([^\s]+)\s*\=\>?\s*(.*)/) {
  248. @fields = split(/\,\s*/, $2);
  249. $text = "$1";
  250. if ($fields[1]) {
  251. $text .= " ($fields[1])";
  252. }
  253. if ($1 eq $current) {
  254. $tmp .= "<OPTION SELECTED>$text</OPTION>\n";
  255. } else {
  256. $tmp .= "<OPTION>$text</OPTION>\n";
  257. }
  258. }
  259. }
  260. }
  261. close(VMAIL);
  262. return ($tmp, $category);
  263. }
  264. sub mailbox_list()
  265. {
  266. local ($name, $context, $current) = @_;
  267. local $tmp;
  268. local $text;
  269. local $tmp;
  270. local $opts;
  271. if (!$context) {
  272. $context = "default";
  273. }
  274. $tmp = "<SELECT name=\"$name\">\n";
  275. ($opts) = &mailbox_options($context, $current);
  276. $tmp .= $opts;
  277. $tmp .= "</SELECT>\n";
  278. }
  279. sub msgcount()
  280. {
  281. my ($context, $mailbox, $folder) = @_;
  282. my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
  283. if (opendir(DIR, $path)) {
  284. my @msgs = grep(/^msg....\.txt$/, readdir(DIR));
  285. closedir(DIR);
  286. return sprintf "%d", $#msgs + 1;
  287. }
  288. return "0";
  289. }
  290. sub msgcountstr()
  291. {
  292. my ($context, $mailbox, $folder) = @_;
  293. my $count = &msgcount($context, $mailbox, $folder);
  294. if ($count > 1) {
  295. "$count messages";
  296. } elsif ($count > 0) {
  297. "$count message";
  298. } else {
  299. "no messages";
  300. }
  301. }
  302. sub messages()
  303. {
  304. my ($context, $mailbox, $folder) = @_;
  305. my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder";
  306. if (opendir(DIR, $path)) {
  307. my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
  308. closedir(DIR);
  309. return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
  310. }
  311. return ();
  312. }
  313. sub getcookie()
  314. {
  315. my ($var) = @_;
  316. return cookie($var);
  317. }
  318. sub makecookie()
  319. {
  320. my ($format) = @_;
  321. cookie(-name => "format", -value =>["$format"], -expires=>"+1y");
  322. }
  323. sub getfields()
  324. {
  325. my ($context, $mailbox, $folder, $msg) = @_;
  326. my $fields;
  327. if (open(MSG, "</var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msg}.txt")) {
  328. while(<MSG>) {
  329. s/\#.*$//g;
  330. if (/^(\w+)\s*\=\s*(.*)$/) {
  331. $fields->{$1} = $2;
  332. }
  333. }
  334. close(MSG);
  335. $fields->{'msgid'} = $msg;
  336. } else { print "<BR>Unable to open '$msg' in '$mailbox', '$folder'\n<B>"; }
  337. $fields;
  338. }
  339. sub message_prefs()
  340. {
  341. my ($nextaction, $msgid) = @_;
  342. my $folder = param('folder');
  343. my $mbox = param('mailbox');
  344. my $context = param('context');
  345. my $passwd = param('password');
  346. my $format = param('format');
  347. if (!$format) {
  348. $format = &getcookie('format');
  349. }
  350. print header;
  351. print <<_EOH;
  352. <TITLE>Asterisk Web-Voicemail: Preferences</TITLE>
  353. <BODY BGCOLOR="white">
  354. $stdcontainerstart
  355. <FORM METHOD="post">
  356. <table width=100% align=center>
  357. <tr><td align=right colspan=3><font size=+2>Web Voicemail Preferences</font></td></tr>
  358. <tr><td align=left><font size=+1>Preferred&nbsp;Audio&nbsp;Format:</font></td><td colspan=2></td></tr>
  359. _EOH
  360. foreach $fmt (sort { $formats{$a}->{'pref'} <=> $formats{$b}->{'pref'} } keys %formats) {
  361. my $clicked = "checked" if $fmt eq $format;
  362. print "<tr><td></td><td align=left><input type=radio name=\"format\" $clicked value=\"$fmt\"></td><td width=100%>&nbsp;$formats{$fmt}->{name}</td></tr>\n";
  363. }
  364. print <<_EOH;
  365. <tr><td align=right colspan=3><input type=submit value="save settings..."></td></tr>
  366. </table>
  367. <input type=hidden name="action" value="$nextaction">
  368. <input type=hidden name="folder" value="$folder">
  369. <input type=hidden name="mailbox" value="$mbox">
  370. <input type=hidden name="context" value="$context">
  371. <input type=hidden name="password" value="$passwd">
  372. <input type=hidden name="msgid" value="$msgid">
  373. $stdcontainerend
  374. </BODY>\n
  375. _EOH
  376. }
  377. sub message_play()
  378. {
  379. my ($message, $msgid) = @_;
  380. my $folder = param('folder');
  381. my ($mbox, $context) = split(/\@/, param('mailbox'));
  382. my $passwd = param('password');
  383. my $format = param('format');
  384. my $fields;
  385. if (!$context) {
  386. $context = param('context');
  387. }
  388. if (!$context) {
  389. $context = "default";
  390. }
  391. my $folders = &folder_list('newfolder', $context, $mbox, $folder);
  392. my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
  393. if (!$format) {
  394. $format = &getcookie('format');
  395. }
  396. if (!$format) {
  397. &message_prefs("play", $msgid);
  398. } else {
  399. print header(-cookie => &makecookie($format));
  400. $fields = &getfields($context, $mbox, $folder, $msgid);
  401. if (!$fields) {
  402. print "<BR>Bah!\n";
  403. return;
  404. }
  405. my $duration = $fields->{'duration'};
  406. if ($duration) {
  407. $duration = sprintf "%d:%02d", $duration/60, $duration % 60;
  408. } else {
  409. $duration = "<i>Unknown</i>";
  410. }
  411. print <<_EOH;
  412. <TITLE>Asterisk Web-Voicemail: $folder Message $msgid</TITLE>
  413. <BODY BGCOLOR="white">
  414. $stdcontainerstart
  415. <FORM METHOD="post">
  416. <table width=100% align=center>
  417. <tr><td align=right colspan=3><font size=+1>$folder Message $msgid</font></td></tr>
  418. _EOH
  419. print <<_EOH;
  420. <tr><td align=center colspan=3>
  421. <table>
  422. <tr><td colspan=2 align=center><font size=+1>$folder <b>$msgid</b></font></td></tr>
  423. <tr><td><b>Message:</b></td><td>$msgid</td></tr>\n
  424. <tr><td><b>Mailbox:</b></td><td>$mbox\@$context</td></tr>\n
  425. <tr><td><b>Folder:</b></td><td>$folder</td></tr>\n
  426. <tr><td><b>From:</b></td><td>$fields->{callerid}</td></tr>\n
  427. <tr><td><b>Duration:</b></td><td>$duration</td></tr>\n
  428. <tr><td><b>Original Date:</b></td><td>$fields->{origdate}</td></tr>\n
  429. <tr><td><b>Original Mailbox:</b></td><td>$fields->{origmailbox}</td></tr>\n
  430. <tr><td><b>Caller Channel:</b></td><td>$fields->{callerchan}</td></tr>\n
  431. <tr><td align=center colspan=2>
  432. <input name="action" type=submit value="index">&nbsp;
  433. <input name="action" type=submit value="delete ">&nbsp;
  434. <input name="action" type=submit value="forward to -> ">&nbsp;
  435. $mailboxes&nbsp;
  436. <input name="action" type=submit value="save to ->">
  437. $folders&nbsp;
  438. <input name="action" type=submit value="play ">
  439. <input name="action" type=submit value="download">
  440. </td></tr>
  441. <tr><td colspan=2 align=center>
  442. <embed width=400 height=40 src="vmail.cgi?action=audio&folder=$folder&mailbox=$mbox&context=$context&password=$passwd&msgid=$msgid&format=$format&dontcasheme=$$.$format" autostart=yes loop=false></embed>
  443. </td></tr></table>
  444. </td></tr>
  445. </table>
  446. <input type=hidden name="folder" value="$folder">
  447. <input type=hidden name="mailbox" value="$mbox">
  448. <input type=hidden name="context" value="$context">
  449. <input type=hidden name="password" value="$passwd">
  450. <input type=hidden name="msgid" value="$msgid">
  451. $stdcontainerend
  452. </BODY>\n
  453. _EOH
  454. }
  455. }
  456. sub message_audio()
  457. {
  458. my ($forcedownload) = @_;
  459. my $folder = param('folder');
  460. my $msgid = param('msgid');
  461. my $mailbox = param('mailbox');
  462. my $context = param('context');
  463. my $format = param('format');
  464. if (!$format) {
  465. $format = &getcookie('format');
  466. }
  467. my $path = "/var/spool/asterisk/voicemail/$context/$mailbox/$folder/msg${msgid}.$format";
  468. $msgid =~ /^\d\d\d\d$/ || die("Msgid Liar ($msgid)!");
  469. grep(/^${format}$/, keys %formats) || die("Format Liar ($format)!");
  470. # Mailbox and folder are already verified
  471. if (open(AUDIO, "<$path")) {
  472. $size = -s $path;
  473. $|=1;
  474. if ($forcedownload) {
  475. print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size, -attachment => "msg${msgid}.$format");
  476. } else {
  477. print header(-type=>$formats{$format}->{'mime'}, -Content_length => $size);
  478. }
  479. while(($amt = sysread(AUDIO, $data, 4096)) > 0) {
  480. syswrite(STDOUT, $data, $amt);
  481. }
  482. close(AUDIO);
  483. } else {
  484. die("Hrm, can't seem to open $path\n");
  485. }
  486. }
  487. sub message_index()
  488. {
  489. my ($folder, $message) = @_;
  490. my ($mbox, $context) = split(/\@/, param('mailbox'));
  491. my $passwd = param('password');
  492. my $message2;
  493. my $msgcount;
  494. my $hasmsg;
  495. my $newmessages, $oldmessages;
  496. my $format = param('format');
  497. if (!$format) {
  498. $format = &getcookie('format');
  499. }
  500. if (!$context) {
  501. $context = param('context');
  502. }
  503. if (!$context) {
  504. $context = "default";
  505. }
  506. if ($folder) {
  507. $msgcount = &msgcountstr($context, $mbox, $folder);
  508. $message2 = "&nbsp;&nbsp;&nbsp;Folder '$folder' has " . &msgcountstr($context, $mbox, $folder);
  509. } else {
  510. $newmessages = &msgcount($context, $mbox, "INBOX");
  511. $oldmessages = &msgcount($context, $mbox, "Old");
  512. if (($newmessages > 0) || ($oldmessages < 1)) {
  513. $folder = "INBOX";
  514. } else {
  515. $folder = "Old";
  516. }
  517. $message2 = "You have";
  518. if ($newmessages > 0) {
  519. $message2 .= " <b>$newmessages</b> NEW";
  520. if ($oldmessages > 0) {
  521. $message2 .= "and <b>$oldmessages</b> OLD";
  522. if ($oldmessages != 1) {
  523. $message2 .= " messages.";
  524. } else {
  525. $message2 .= "message.";
  526. }
  527. } else {
  528. if ($newmessages != 1) {
  529. $message2 .= " messages.";
  530. } else {
  531. $message2 .= " message.";
  532. }
  533. }
  534. } else {
  535. if ($oldmessages > 0) {
  536. $message2 .= " <b>$oldmessages</b> OLD";
  537. if ($oldmessages != 1) {
  538. $message2 .= " messages.";
  539. } else {
  540. $message2 .= " message.";
  541. }
  542. } else {
  543. $message2 .= " <b>no</b> messages.";
  544. }
  545. }
  546. }
  547. my $folders = &folder_list('newfolder', $context, $mbox, $folder);
  548. my $cfolders = &folder_list('changefolder', $context, $mbox, $folder);
  549. my $mailboxes = &mailbox_list('forwardto', $context, $mbox);
  550. print header(-cookie => &makecookie($format));
  551. print <<_EOH;
  552. <TITLE>Asterisk Web-Voicemail: $mbox\@$context $folder</TITLE>
  553. <BODY BGCOLOR="white">
  554. $stdcontainerstart
  555. <FORM METHOD="post">
  556. <table width=100% align=center>
  557. <tr><td align=center colspan=2><font size=+2><I>$message</I></font></td></tr>
  558. <tr><td align=right colspan=2><font size=+1><b>$folder</b> Messages</font> <input type=submit name="action" value="change to ->">$cfolders</td></tr>
  559. <tr><td align=left colspan=2><font size=+1>$message2</font></td></tr>
  560. </table>
  561. <table width=100% align=center cellpadding=0 cellspacing=0>
  562. _EOH
  563. print "<tr><td>&nbsp;Msg</td><td>&nbsp;From</td><td>&nbsp;Duration</td><td>&nbsp;Date</td><td>&nbsp;</td></tr>\n";
  564. print "<tr><td><hr></td><td><hr></td><td><hr></td><td><hr></td><td></td></tr>\n";
  565. foreach $msg (&messages($context, $mbox, $folder)) {
  566. $fields = &getfields($context, $mbox, $folder, $msg);
  567. $duration = $fields->{'duration'};
  568. if ($duration) {
  569. $duration = sprintf "%d:%02d", $duration / 60, $duration % 60;
  570. } else {
  571. $duration = "<i>Unknown</i>";
  572. }
  573. $hasmsg++;
  574. print "<tr><td><input type=checkbox name=\"msgselect\" value=\"$msg\">&nbsp;<b>$msg</b></td><td>$fields->{'callerid'}</td><td>$duration</td><td>$fields->{'origdate'}</td><td><input name='play$msg' alt=\"Play message $msg\" border=0 type=image align=left src=\"$astpath/play.gif\"></td></tr>\n";
  575. }
  576. if (!$hasmsg) {
  577. print "<tr><td colspan=4 align=center><P><b><i>No messages</i></b><P></td></tr>";
  578. }
  579. print <<_EOH;
  580. </table>
  581. <table width=100% align=center>
  582. <tr><td align=right colspan=2>
  583. <input type="submit" name="action" value="refresh">&nbsp;
  584. _EOH
  585. if ($hasmsg) {
  586. print <<_EOH;
  587. <input type="submit" name="action" value="delete">&nbsp;
  588. <input type="submit" name="action" value="save to ->">
  589. $folders&nbsp;
  590. <input type="submit" name="action" value="forward to ->">
  591. $mailboxes
  592. _EOH
  593. }
  594. print <<_EOH;
  595. </td></tr>
  596. <tr><td align=right colspan=2>
  597. <input type="submit" name="action" value="preferences">
  598. <input type="submit" name="action" value="logout">
  599. </td></tr>
  600. </table>
  601. <input type=hidden name="folder" value="$folder">
  602. <input type=hidden name="mailbox" value="$mbox">
  603. <input type=hidden name="context" value="$context">
  604. <input type=hidden name="password" value="$passwd">
  605. </FORM>
  606. $stdcontainerend
  607. </BODY>\n
  608. _EOH
  609. }
  610. sub validfolder()
  611. {
  612. my ($folder) = @_;
  613. return grep(/^$folder$/, @validfolders);
  614. }
  615. sub folder_list()
  616. {
  617. my ($name, $context, $mbox, $selected) = @_;
  618. my $f;
  619. my $count;
  620. my $tmp = "<SELECT name=\"$name\">\n";
  621. foreach $f (@validfolders) {
  622. $count = &msgcount($context, $mbox, $f);
  623. if ($f eq $selected) {
  624. $tmp .= "<OPTION SELECTED>$f ($count)</OPTION>\n";
  625. } else {
  626. $tmp .= "<OPTION>$f ($count)</OPTION>\n";
  627. }
  628. }
  629. $tmp .= "</SELECT>";
  630. }
  631. sub message_rename()
  632. {
  633. my ($context, $mbox, $oldfolder, $old, $newfolder, $new) = @_;
  634. my $oldfile, $newfile;
  635. return if ($old eq $new) && ($oldfolder eq $newfolder);
  636. if ($context =~ /^(\w+)$/) {
  637. $context = $1;
  638. } else {
  639. die("Invalid Context<BR>\n");
  640. }
  641. if ($mbox =~ /^(\w+)$/) {
  642. $mbox = $1;
  643. } else {
  644. die ("Invalid mailbox<BR>\n");
  645. }
  646. if ($oldfolder =~ /^(\w+)$/) {
  647. $oldfolder = $1;
  648. } else {
  649. die("Invalid old folder<BR>\n");
  650. }
  651. if ($newfolder =~ /^(\w+)$/) {
  652. $newfolder = $1;
  653. } else {
  654. die("Invalid new folder ($newfolder)<BR>\n");
  655. }
  656. if ($old =~ /^(\d\d\d\d)$/) {
  657. $old = $1;
  658. } else {
  659. die("Invalid old Message<BR>\n");
  660. }
  661. if ($new =~ /^(\d\d\d\d)$/) {
  662. $new = $1;
  663. } else {
  664. die("Invalid old Message<BR>\n");
  665. }
  666. my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder";
  667. mkdir $path, 0770;
  668. my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
  669. opendir(DIR, $path) || die("Unable to open directory\n");
  670. my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
  671. closedir(DIR);
  672. foreach $oldfile (@files) {
  673. my $tmp = $oldfile;
  674. if ($tmp =~ /^(msg${old}.\w+)$/) {
  675. $tmp = $1;
  676. $oldfile = $path . "/$tmp";
  677. $tmp =~ s/msg${old}/msg${new}/;
  678. $newfile = "/var/spool/asterisk/voicemail/$context/$mbox/$newfolder/$tmp";
  679. # print "Renaming $oldfile to $newfile<BR>\n";
  680. rename($oldfile, $newfile);
  681. }
  682. }
  683. }
  684. sub file_copy()
  685. {
  686. my ($orig, $new) = @_;
  687. my $res;
  688. my $data;
  689. open(IN, "<$orig") || die("Unable to open '$orig'\n");
  690. open(OUT, ">$new") || DIE("Unable to open '$new'\n");
  691. while(($res = sysread(IN, $data, 4096)) > 0) {
  692. syswrite(OUT, $data, $res);
  693. }
  694. close(OUT);
  695. close(IN);
  696. }
  697. sub message_copy()
  698. {
  699. my ($context, $mbox, $newmbox, $oldfolder, $old, $new) = @_;
  700. my $oldfile, $newfile;
  701. return if ($mbox eq $newmbox);
  702. if ($mbox =~ /^(\w+)$/) {
  703. $mbox = $1;
  704. } else {
  705. die ("Invalid mailbox<BR>\n");
  706. }
  707. if ($newmbox =~ /^(\w+)$/) {
  708. $newmbox = $1;
  709. } else {
  710. die ("Invalid new mailbox<BR>\n");
  711. }
  712. if ($oldfolder =~ /^(\w+)$/) {
  713. $oldfolder = $1;
  714. } else {
  715. die("Invalid old folder<BR>\n");
  716. }
  717. if ($old =~ /^(\d\d\d\d)$/) {
  718. $old = $1;
  719. } else {
  720. die("Invalid old Message<BR>\n");
  721. }
  722. if ($new =~ /^(\d\d\d\d)$/) {
  723. $new = $1;
  724. } else {
  725. die("Invalid old Message<BR>\n");
  726. }
  727. my $path = "/var/spool/asterisk/voicemail/$context/$newmbox";
  728. mkdir $path, 0770;
  729. my $path = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX";
  730. mkdir $path, 0770;
  731. my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$oldfolder";
  732. opendir(DIR, $path) || die("Unable to open directory\n");
  733. my @files = grep /^msg${old}\.\w+$/, readdir(DIR);
  734. closedir(DIR);
  735. foreach $oldfile (@files) {
  736. my $tmp = $oldfile;
  737. if ($tmp =~ /^(msg${old}.\w+)$/) {
  738. $tmp = $1;
  739. $oldfile = $path . "/$tmp";
  740. $tmp =~ s/msg${old}/msg${new}/;
  741. $newfile = "/var/spool/asterisk/voicemail/$context/$newmbox/INBOX/$tmp";
  742. # print "Copying $oldfile to $newfile<BR>\n";
  743. &file_copy($oldfile, $newfile);
  744. }
  745. }
  746. }
  747. sub message_delete()
  748. {
  749. my ($context, $mbox, $folder, $msg) = @_;
  750. if ($mbox =~ /^(\w+)$/) {
  751. $mbox = $1;
  752. } else {
  753. die ("Invalid mailbox<BR>\n");
  754. }
  755. if ($context =~ /^(\w+)$/) {
  756. $context = $1;
  757. } else {
  758. die ("Invalid context<BR>\n");
  759. }
  760. if ($folder =~ /^(\w+)$/) {
  761. $folder = $1;
  762. } else {
  763. die("Invalid folder<BR>\n");
  764. }
  765. if ($msg =~ /^(\d\d\d\d)$/) {
  766. $msg = $1;
  767. } else {
  768. die("Invalid Message<BR>\n");
  769. }
  770. my $path = "/var/spool/asterisk/voicemail/$context/$mbox/$folder";
  771. opendir(DIR, $path) || die("Unable to open directory\n");
  772. my @files = grep /^msg${msg}\.\w+$/, readdir(DIR);
  773. closedir(DIR);
  774. foreach $oldfile (@files) {
  775. if ($oldfile =~ /^(msg${msg}.\w+)$/) {
  776. $oldfile = $path . "/$1";
  777. # print "Deleting $oldfile<BR>\n";
  778. unlink($oldfile);
  779. }
  780. }
  781. }
  782. sub message_forward()
  783. {
  784. my ($toindex, @msgs) = @_;
  785. my $folder = param('folder');
  786. my ($mbox, $context) = split(/\@/, param('mailbox'));
  787. my $newmbox = param('forwardto');
  788. my $msg;
  789. my $msgcount;
  790. if (!$context) {
  791. $context = param('context');
  792. }
  793. if (!$context) {
  794. $context = "default";
  795. }
  796. $newmbox =~ s/(\w+)(\s+.*)?$/$1/;
  797. if (!&validmailbox($context, $newmbox)) {
  798. die("Bah! Not a valid mailbox '$newmbox'\n");
  799. return "";
  800. }
  801. $msgcount = &msgcount($context, $newmbox, "INBOX");
  802. my $txt;
  803. if ($newmbox ne $mbox) {
  804. # print header;
  805. foreach $msg (@msgs) {
  806. # print "Forwarding $msg from $mbox to $newmbox<BR>\n";
  807. &message_copy($context, $mbox, $newmbox, $folder, $msg, sprintf "%04d", $msgcount);
  808. $msgcount++;
  809. }
  810. $txt = "Forwarded messages " . join(', ', @msgs) . "to $newmbox";
  811. } else {
  812. $txt = "Can't forward messages to yourself!\n";
  813. }
  814. if ($toindex) {
  815. &message_index($folder, $txt);
  816. } else {
  817. &message_play($txt, $msgs[0]);
  818. }
  819. }
  820. sub message_delete_or_move()
  821. {
  822. my ($toindex, $del, @msgs) = @_;
  823. my $txt;
  824. my $path;
  825. my $y, $x;
  826. my $folder = param('folder');
  827. my $newfolder = param('newfolder') unless $del;
  828. $newfolder =~ s/^(\w+)\s+.*$/$1/;
  829. my ($mbox, $context) = split(/\@/, param('mailbox'));
  830. if (!$context) {
  831. $context = param('context');
  832. }
  833. if (!$context) {
  834. $context = "default";
  835. }
  836. my $passwd = param('password');
  837. my $msgcount = &msgcount($context, $mbox, $folder);
  838. my $omsgcount = &msgcount($context, $mbox, $newfolder) if $newfolder;
  839. # print header;
  840. if ($newfolder ne $folder) {
  841. $y = 0;
  842. for ($x=0;$x<$msgcount;$x++) {
  843. my $msg = sprintf "%04d", $x;
  844. my $newmsg = sprintf "%04d", $y;
  845. if (grep(/^$msg$/, @msgs)) {
  846. if ($newfolder) {
  847. &message_rename($context, $mbox, $folder, $msg, $newfolder, sprintf "%04d", $omsgcount);
  848. $omsgcount++;
  849. } else {
  850. &message_delete($context, $mbox, $folder, $msg);
  851. }
  852. } else {
  853. &message_rename($context, $mbox, $folder, $msg, $folder, $newmsg);
  854. $y++;
  855. }
  856. }
  857. if ($del) {
  858. $txt = "Deleted messages " . join (', ', @msgs);
  859. } else {
  860. $txt = "Moved messages " . join (', ', @msgs) . " to $newfolder";
  861. }
  862. } else {
  863. $txt = "Can't move a message to the same folder they're in already";
  864. }
  865. # Not as many messages now
  866. $msgcount--;
  867. if ($toindex || ($msgs[0] >= $msgcount)) {
  868. &message_index($folder, $txt);
  869. } else {
  870. &message_play($txt, $msgs[0]);
  871. }
  872. }
  873. if (param()) {
  874. my $folder = param('folder');
  875. my $changefolder = param('changefolder');
  876. $changefolder =~ s/(\w+)\s+.*$/$1/;
  877. my $newfolder = param('newfolder');
  878. $newfolder =~ s/^(\w+)\s+.*$/$1/;
  879. if ($newfolder && !&validfolder($newfolder)) {
  880. print header;
  881. die("Bah! new folder '$newfolder' isn't a folder.");
  882. }
  883. $action = param('action');
  884. $msgid = param('msgid');
  885. if (!$action) {
  886. my ($tmp) = grep /^play\d\d\d\d\.x$/, param;
  887. if ($tmp =~ /^play(\d\d\d\d)/) {
  888. $msgid = $1;
  889. $action = "play";
  890. } else {
  891. print header;
  892. print "No message?<BR>\n";
  893. return;
  894. }
  895. }
  896. @msgs = param('msgselect');
  897. @msgs = ($msgid) unless @msgs;
  898. {
  899. ($mailbox) = &check_login();
  900. if (length($mailbox)) {
  901. if ($action eq 'login') {
  902. &message_index($folder, "Welcome, $mailbox");
  903. } elsif (($action eq 'refresh') || ($action eq 'index')) {
  904. &message_index($folder, "Welcome, $mailbox");
  905. } elsif ($action eq 'change to ->') {
  906. if (&validfolder($changefolder)) {
  907. $folder = $changefolder;
  908. &message_index($folder, "Welcome, $mailbox");
  909. } else {
  910. die("Bah! Not a valid change to folder '$changefolder'\n");
  911. }
  912. } elsif ($action eq 'play') {
  913. &message_play("$mailbox $folder $msgid", $msgid);
  914. } elsif ($action eq 'preferences') {
  915. &message_prefs("refresh", $msgid);
  916. } elsif ($action eq 'download') {
  917. &message_audio(1);
  918. } elsif ($action eq 'play ') {
  919. &message_audio(0);
  920. } elsif ($action eq 'audio') {
  921. &message_audio(0);
  922. } elsif ($action eq 'delete') {
  923. &message_delete_or_move(1, 1, @msgs);
  924. } elsif ($action eq 'delete ') {
  925. &message_delete_or_move(0, 1, @msgs);
  926. } elsif ($action eq 'forward to ->') {
  927. &message_forward(1, @msgs);
  928. } elsif ($action eq 'forward to -> ') {
  929. &message_forward(0, @msgs);
  930. } elsif ($action eq 'save to ->') {
  931. &message_delete_or_move(1, 0, @msgs);
  932. } elsif ($action eq 'save to -> ') {
  933. &message_delete_or_move(0, 0, @msgs);
  934. } elsif ($action eq 'logout') {
  935. &login_screen("Logged out!\n");
  936. }
  937. } else {
  938. sleep(1);
  939. &login_screen("Login Incorrect!\n");
  940. }
  941. }
  942. } else {
  943. &login_screen("\&nbsp;");
  944. }