Voicemail: Add delete and move functions

Refactor some of the list handlers becuase delete and move have to act on
multiple files.  Also make it so that any played messages in INBOX
automatically move to Old.

To get the MWI to work, you have to set

pollmailboxes=yes
pollfreq=5

In voicemail.conf because we're now tampering with the files outside of the
application.

Signed-off-by: James Bottomley <JBottomley@Parallels.com>
diff --git a/include/Voicemail.class.php b/include/Voicemail.class.php
index 9b9c9b6..c1c78a5 100644
--- a/include/Voicemail.class.php
+++ b/include/Voicemail.class.php
@@ -21,6 +21,10 @@
 	private function __readbox($box) {
 		$this->box[$box] = array();
 
+		if (!$box) {
+			return;
+		}
+
 		if (!file_exists($this->path.'/'.$box)) {
 			return;
 		}
@@ -30,8 +34,11 @@
 			return;
 		}
 		while (false !== ($entry = $d->read())) {
-			if (preg_match('/(.*)\.txt$/', $entry, $m)) {
-				$this->box[$box][] = $m[1];
+			if (preg_match('/(msg.*)\.(\w+)$/', $entry, $m)) {
+				if (!isset($this->box[$box][$m[1]])) {
+					$this->box[$box][$m[1]] = array();
+				}
+				$this->box[$box][$m[1]][] = $m[2];
 			}
 		}
 		$d->close();
@@ -55,6 +62,84 @@
 		$this->__initvar();
 	}
 
+	function lock($box) {
+		if (!$box) {
+			return;
+		}
+		while (!($f = fopen($this->path.'/'.$box.'/.lock', 'x'))) {
+			sleep(1);
+		}
+		fclose($f);
+	}
+
+	function unlock($box) {
+		if (!$box) {
+			return;
+		}
+		unlink($this->path.'/'.$box.'/.lock');
+	}
+
+	function locked_move($src, $msg, $dst) {
+		$this->lock($src);
+		$this->lock($dst);
+
+		$this->__readbox($src);
+		$this->__readbox($dst);
+
+		$x = sprintf("msg%04d", $msg);
+		if ($dst) {
+			$i = count($this->box[$dst]);
+			$y = sprintf("msg%04d", $i);
+			foreach ($this->box[$src][$x] as $ext) {
+				rename($this->path.'/'.$src.'/'.$x.'.'.$ext,
+				       $this->path.'/'.$dst.'/'.$y.'.'.$ext);
+			}
+		} else {
+		error_log("box=$src, x=$x contents=".join(",",$this->box[$src][$x]));
+			foreach ($this->box[$src][$x] as $ext) {
+				unlink($this->path.'/'.$src.'/'.$x.'.'.$ext);
+			}
+		}
+
+		for ($i = $msg + 1; $i < count($this->box[$src]); $i++) {
+			$x = sprintf("msg%04d", $i);
+			$y = sprintf("msg%04d", $i - 1);
+			foreach ($this->box[$src][$x] as $ext) {
+				rename($this->path.'/'.$src.'/'.$x.'.'.$ext,
+				       $this->path.'/'.$src.'/'.$y.'.'.$ext);
+			}
+		}
+		$this->__readbox($src);
+		$this->__readbox($dst);
+		$this->unlock($dst);
+		$this->unlock($src);		
+	}
+
+	##
+	# buttons for various states
+	##
+	function button_play($box, $msg) {
+		$this->do->addSoftkey(1, 'Play', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=play');
+	}
+
+	function button_pause($box, $msg) {
+		$this->do->addSoftkey(1, 'Pause', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=pause');
+	}
+
+	function button_resume($box, $msg) {
+		$this->do->addSoftkey(1, 'Resume', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=resume');
+	}
+
+	function button_stop($box, $msg) {
+		$this->do->addSoftkey(2, 'Stop', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=stop');
+	}
+
+	function button_rest($box, $msg) {
+		$this->do->addSoftkey(3, 'Delete', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=delete');
+		$this->do->addSoftkey(4, 'Move', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=move');
+	}
+
+
 	##
 	# State diagram of voicemail play
 	##
@@ -91,31 +176,86 @@
 
 	function playing($box, $msg, $i) {
 		$this->title = 'Playing Voicemail '.$box.' Message: '.$i;
-		$this->do->addSoftkey(2, 'Stop', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=stop');
-		$this->do->addSoftkey(1, 'Pause', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=pause');
 		$this->do->setAllowDrop();
+		$this->button_pause($box, $msg);
+		$this->button_stop($box, $msg);
+		$this->button_rest($box, $msg);
 	}
 
 	function paused($box, $msg, $i) {
 		$this->title = 'Paused Voicemail '.$box.' Message: '.$i;
-		$this->do->addSoftkey(2, 'Stop', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=stop');
-		$this->do->addSoftkey(1, 'Resume', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=resume');
 		$this->do->setAllowDrop();
+		$this->button_resume($box, $msg);
+		$this->button_rest($box, $msg);
 	}
 
-	function stopped($box, $msg, $i) {
+	function stopped_override($box, $msg) {
 		$this->delActionHandler('onhook');
-		$this->message_start($box, $msg, $i);
+		if ($box == 'INBOX') {
+			# move listened new messages to old messages
+			$this->locked_move($box, $i - 1, 'Old');
+		}			
+		$this->displayObject( new AastraIPPhoneExecute());
+		$this->do->addEntry($this->url.'?action=message&box='.$box.'&msg='.$msg);
+		$this->do->setTriggerDestroyOnExit();
 	}
 
 	function message_start($box, $msg, $i) {
-		$this->do->addSoftkey(1, 'Play', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=play');
-		$this->title = 'Voicemail '.$box.' Message: '.$i;
+		$this->title = 'Message '.$i.' in mailbox '.$box;
+		$this->button_play($box, $msg);
+		$this->button_rest($box, $msg);
+	}
+
+	function delete($box, $msg, $i) {
+		$this->do->addSoftkey(1, 'Yes', $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=really_delete');
+		$this->do->addSoftkey(2, 'No', $this->url.'?action=message&box='.$box.'&msg='.$msg);
+		$this->title = 'Delete Message: '.$i.' in mailbox '.$box.'?';
+	}
+
+	function really_delete_override($box, $msg) {
+		$this->displayObject( new AastraIPPhoneExecute());
+		$this->do->addEntry($this->url.'?action=message&box='.$box.'&msg='.$msg);
+		$this->do->setTriggerDestroyOnExit();
+		preg_match('/^msg(\d*)$/', $msg, $m);
+		$this->locked_move($box, intval($m[1]), null);
+	}
+
+	function move($box, $msg, $i) {
+		$this->title = 'Move Message: '.$i.' in mailbox '.$box.'to which mailbox?';
+		$i = 1;
+		foreach($this->mapping as $k => $v) {
+			$this->do->addSoftkey($i++, $v, $this->url.'?action=message&box='.$box.'&msg='.$msg.'&state=move_to&dst='.$k);
+		}
+	}
+
+	function move_to_override($box, $msg) {
+		if (!isset($_GET['dst'])) {
+			return;
+		}
+		$this->displayObject( new AastraIPPhoneExecute());
+		$this->do->addEntry('Key:KeyPad1');
+		$this->do->addEntry($this->url.'?action=message&box='.$box.'&msg='.$msg);
+		$this->do->setTriggerDestroyOnExit();
+		preg_match('/^msg(\d*)$/', $msg, $m);
+		$this->locked_move($box, intval($m[1]), $_GET['dst']);
 	}
 
 	function message() {
 		$box = $_GET['box'];
+		if (count($this->box[$box]) == 0) {
+			$this->displayObject(new AastraIPPhoneTextScreen());
+			$this->title = 'Mailbox '.$box;
+			$this->do->setText('is empty');
+			error_log("EMPTY");
+			return;
+		}
 		$msg = $_GET['msg'];
+		preg_match('/^msg(\d*)$/', $msg, $m);
+		$i = intval($m[1]) + 1;
+		if (!isset($this->box[$box][$msg])) {
+			$i = count($this->box[$box]);
+			$msg = sprintf("msg%04d", $i - 1);
+		}
 		$ordinary='message_start';
 		if (isset($_GET['state'])) {
 			$override = $_GET['state'].'_override';
@@ -128,8 +268,6 @@
 			}
 		}
 		$this->back = $this->url.'?action=mailbox&box='.$box;
-		preg_match('/^msg(\d*)$/', $msg, $m);
-		$i = intval($m[1]) + 1;
 		$c = new ConfigFile($this->path.'/'.$box.'/'.$msg.'.txt');
 		$m = $c->section('message');
 		$this->displayObject(new AastraIPPhoneTextScreen());
diff --git a/include/VoicemailListManager.class.php b/include/VoicemailListManager.class.php
index c94d7b6..467a69f 100644
--- a/include/VoicemailListManager.class.php
+++ b/include/VoicemailListManager.class.php
@@ -26,7 +26,7 @@
 	# the 
 	function manager($box, $selecturl) {
 		$this->data = array();
-		$this->files = $this->outer->box[$box];
+		$this->files = array_keys($this->outer->box[$box]);
 		$this->path = $this->outer->path.'/'.$box;
 		sort($this->files);
 		foreach($this->files as $v) {