From 1380fc452d56dd6f48ddbfa3a6b0e69edd043b04 Mon Sep 17 00:00:00 2001
From: Andreas Gohr <andi@splitbrain.org>
Date: Sat, 6 Aug 2005 23:20:00 +0200
Subject: [PATCH] changes to the page subscription feature

darcs-hash:20050806212000-7ad00-c5ab54a33289f8be0ce99443f82f0b3cf1bdbf0d.gz
---
 inc/actions.php          |  35 +++++++------
 inc/common.php           |  43 +++++++--------
 inc/io.php               | 109 ++++++++++++++++-----------------------
 inc/lang/en/lang.php     |   4 +-
 inc/pageutils.php        |   7 +--
 inc/template.php         |   8 +--
 lib/tpl/default/main.php |   2 +-
 7 files changed, 96 insertions(+), 112 deletions(-)

diff --git a/inc/actions.php b/inc/actions.php
index 5818993c9..8a3a61cb9 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -35,9 +35,9 @@ function act_dispatch(){
   if(in_array($ACT,array('login','logout')))
     $ACT = act_auth($ACT);
 
-  //check if user is asking to track a page
-  if($ACT == 'track' || $ACT == 'ignore')
-    $ACT = act_track($ACT);
+  //check if user is asking to (un)subscribe a page
+  if($ACT == 'subscribe' || $ACT == 'unsubscribe')
+    $ACT = act_subscription($ACT);
  
   //check permissions
   $ACT = act_permcheck($ACT);
@@ -106,7 +106,8 @@ function act_clean($act){
 
   if(array_search($act,array('login','logout','register','save','edit',
                              'preview','search','show','check','index','revisions',
-                             'diff','recent','backlink','admin','track','ignore',)) === false
+                             'diff','recent','backlink','admin','subscribe',
+                             'unsubscribe',)) === false
      && substr($act,0,7) != 'export_' ) {
     msg('Unknown command: '.htmlspecialchars($act),-1);
     return 'show';
@@ -273,31 +274,33 @@ function act_export($act){
 }
 
 /**
- * Handle 'track', 'ignore'
+ * Handle 'subscribe', 'unsubscribe'
  *
  * @author Steven Danz <steven-danz@kc.rr.com>
+ * @todo   localize
  */
-function act_track($act){
+function act_subscription($act){
   global $ID;
   global $INFO;
 
-  $tracking = tracking($ID, $_SERVER['REMOTE_USER']);
-  $file=wikiMN($ID);
-  if ($act=='track' && !$tracking){
+  $file=metaFN($ID,'.mlist');
+  if ($act=='subscribe' && !$INFO['subscribed']){
     if ($INFO['userinfo']['mail']){
-      if (io_appendFile($file,$_SERVER['REMOTE_USER']."\n")) {
-        msg('Added '.$INFO['userinfo']['name'].' to tracking list for '.$ID,0);
+      if (io_saveFile($file,$_SERVER['REMOTE_USER']."\n",true)) {
+        $INFO['subscribed'] = true;
+        msg('Added '.$INFO['userinfo']['name'].' to subscription list for '.$ID,1);
       } else {
-        msg('Error adding '.$INFO['userinfo']['name'].' to tracking list for '.$ID,0);
+        msg('Error adding '.$INFO['userinfo']['name'].' to subscription list for '.$ID,-1);
       }
     } else {
-      msg('There is no address associated with your login, you cannot be added to the tracking list',-1);
+      msg('There is no address associated with your login, you cannot be added to the subscription list',-1);
     }
-  } elseif ($act=='ignore' && $tracking){
+  } elseif ($act=='unsubscribe' && $INFO['subscribed']){
     if (io_deleteFromFile($file,$_SERVER['REMOTE_USER']."\n")) {
-      msg('Removed '.$INFO['userinfo']['name'].' from the tracking list for '.$ID,0);
+      $INFO['subscribed'] = false;
+      msg('Removed '.$INFO['userinfo']['name'].' from subscription list for '.$ID,1);
     } else {
-      msg('Error removing '.$INFO['userinfo']['name'].' to tracking list for '.$ID,0);
+      msg('Error removing '.$INFO['userinfo']['name'].' from subscription list for '.$ID,-1);
     }
   }
 
diff --git a/inc/common.php b/inc/common.php
index 676787e73..b0d7c4c10 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -26,12 +26,14 @@ function pageinfo(){
   global $conf;
 
   if($_SERVER['REMOTE_USER']){
-    $info['user']     = $_SERVER['REMOTE_USER'];
-    $info['userinfo'] = $USERINFO;
-    $info['perm']     = auth_quickaclcheck($ID);
+    $info['user']       = $_SERVER['REMOTE_USER'];
+    $info['userinfo']   = $USERINFO;
+    $info['perm']       = auth_quickaclcheck($ID);
+    $info['subscribed'] = is_subscribed($ID,$_SERVER['REMOTE_USER']);
   }else{
-    $info['user']     = '';
-    $info['perm']     = auth_aclcheck($ID,'',null);
+    $info['user']       = '';
+    $info['perm']       = auth_aclcheck($ID,'',null);
+    $info['subscribed'] = false;
   }
 
   $info['namespace'] = getNS($ID);
@@ -678,12 +680,6 @@ function notify($id,$rev="",$summary=""){
   global $conf;
   $hdrs ='';
 
-  $mlist = array();
-
-  $file=wikiMN($id);
-  if (file_exists($file)) {
-    $mlist = file($file);
-  }
 
   if(empty($conf['notify']) && count($mlist) == 0) return; //notify enabled?
   
@@ -713,6 +709,14 @@ function notify($id,$rev="",$summary=""){
   $text = str_replace('@DIFF@',$diff,$text);
   $subject = '['.$conf['title'].'] '.$subject;
 
+
+  // FIXME move this to its own function
+  $mlist = array();
+  $file=metaFN($id,'.mlist');
+  if (file_exists($file)) {
+    $mlist = file($file);
+  }
+
   $bcc = '';
   if(count($mlist) > 0) {
     foreach ($mlist as $who) {
@@ -924,19 +928,16 @@ function check(){
 /**
  * Let us know if a user is tracking a page
  *
- * @author Steven Danz <steven-danz@kc.rr.com>
+ * @author Andreas Gohr <andi@splitbrain.org>
  */
-function tracking($id,$uid){
-  $file=wikiMN($id);
-  if (file_exists($file)) {
+function is_subscribed($id,$uid){
+  $file=metaFN($id,'.mlist');
+  if (@file_exists($file)) {
     $mlist = file($file);
-    foreach ($mlist as $who) {
-      $who = rtrim($who);
-      if ($who==$uid) {
-        return true;
-      }
-    }
+    $pos = array_search($uid."\n",$mlist);
+    return is_int($pos);
   }
+
   return false;
 }
 
diff --git a/inc/io.php b/inc/io.php
index 922d2af02..5cf50af8f 100644
--- a/inc/io.php
+++ b/inc/io.php
@@ -50,16 +50,21 @@ function io_readFile($file){
 /**
  * Saves $content to $file.
  *
+ * If the third parameter is set to true the given content
+ * will be appended.
+ *
  * Uses gzip if extension is .gz
  *
  * @author  Andreas Gohr <andi@splitbrain.org>
  * @return bool true on success
  */
-function io_saveFile($file,$content){
+function io_saveFile($file,$content,$append=false){
+  $mode = ($append) ? 'ab' : 'wb';
+
   io_makeFileDir($file);
   io_lock($file);
   if(substr($file,-3) == '.gz'){
-    $fh = @gzopen($file,'wb9');
+    $fh = @gzopen($file,$mode.'9');
     if(!$fh){
       msg("Writing $file failed",-1);
       return false;
@@ -67,7 +72,7 @@ function io_saveFile($file,$content){
     gzwrite($fh, $content);
     gzclose($fh);
   }else{
-    $fh = @fopen($file,'wb');
+    $fh = @fopen($file,$mode);
     if(!$fh){
       msg("Writing $file failed",-1);
       return false;
@@ -80,84 +85,58 @@ function io_saveFile($file,$content){
 }
 
 /**
- * Appends $content to $file.
+ * Delete exact linematch for $badline from $file.
+ *
+ * Be sure to include the trailing newline in $badline
  *
  * Uses gzip if extension is .gz
  *
  * @author Steven Danz <steven-danz@kc.rr.com>
  * @return bool true on success
  */
-function io_appendFile($file,$content){
-  io_makeFileDir($file);
+function io_deleteFromFile($file,$badline){
+  if (!@file_exists($file)) return true;
+
   io_lock($file);
+
+  // load into array
   if(substr($file,-3) == '.gz'){
-    $fh = @gzopen($file,'ab9');
-    if(!$fh){
-      msg("Appending to $file failed",-1);
-      return false;
-    }
-    gzwrite($fh, $content);
-    gzclose($fh);
+    $lines = gzfile($file);
   }else{
-    $fh = @fopen($file,'ab');
-    if(!$fh){
-      msg("Appending to $file failed",-1);
-      return false;
-    }
-    fwrite($fh, $content);
-    fclose($fh);
+    $lines = file($file);
   }
-  io_unlock($file);
-  return true;
-}
 
-/**
- * Delete exact match for $content from $file.
- *
- * Uses gzip if extension is .gz
- *
- * @author Steven Danz <steven-danz@kc.rr.com>
- * @return bool true on success
- */
-function io_deleteFromFile($file,$remove){
-  if (@file_exists($file)) {
-    io_lock($file);
-    $content = '';
+  // remove all matching lines
+  $pos = array_search($badline,$lines); //return null or false if not found
+  while(is_int($pos)){
+    unset($lines[$pos]);
+    $pos = array_search($badline,$lines);
+  }
+
+  if(count($lines)){
+    $content = join('',$lines);
     if(substr($file,-3) == '.gz'){
-      $mlist = gzfile($file);
-    }else{
-      $mlist = file($file);
-    }
-    foreach ($mlist as $entry) {
-      if ($entry != $remove) {
-        $content = $content . $entry;
+      $fh = @gzopen($file,'wb9');
+      if(!$fh){
+        msg("Removing content from $file failed",-1);
+        return false;
       }
-    }
-
-    if (!empty($content)) {
-      if(substr($file,-3) == '.gz'){
-        $fh = @gzopen($file,'wb9');
-        if(!$fh){
-          msg("Removing content from $file failed",-1);
-          return false;
-        }
-        gzwrite($fh, $content);
-        gzclose($fh);
-      }else{
-        $fh = @fopen($file,'wb');
-        if(!$fh){
-          msg("Removing content from $file failed",-1);
-          return false;
-        }
-        fwrite($fh, $content);
-        fclose($fh);
+      gzwrite($fh, $content);
+      gzclose($fh);
+    }else{
+      $fh = @fopen($file,'wb');
+      if(!$fh){
+        msg("Removing content from $file failed",-1);
+        return false;
       }
-    } else {
-      @unlink($file);
+      fwrite($fh, $content);
+      fclose($fh);
     }
-
-    io_unlock($file);
+  }else{
+    @unlink($file);
   }
+
+  io_unlock($file);
   return true;
 }
 
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index f80c484aa..5b350b441 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -32,8 +32,8 @@ $lang['btn_update'] = 'Update';
 $lang['btn_delete'] = 'Delete';
 $lang['btn_back']   = 'Back';
 $lang['btn_backtomedia'] = 'Back to Mediafile Selection';
-$lang['btn_track']  = 'Email Changes';
-$lang['btn_ignore'] = 'End Changes Email';
+$lang['btn_subscribe']   = 'Subscribe Changes';
+$lang['btn_unsubscribe'] = 'Unsubscribe Changes';
 
 $lang['loggedinas'] = 'Logged in as';
 $lang['user']       = 'Username';
diff --git a/inc/pageutils.php b/inc/pageutils.php
index b04f6e596..1e0792b7d 100644
--- a/inc/pageutils.php
+++ b/inc/pageutils.php
@@ -4,6 +4,7 @@
  * 
  * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
  * @author     Andreas Gohr <andi@splitbrain.org>
+ * @todo       Combine similar functions like {wiki,media,meta}FN()
  */
 
 /**
@@ -131,17 +132,17 @@ function wikiFN($id,$rev=''){
 }
 
 /**
- * returns the full path to the mailist specified by ID
+ * returns the full path to the meta file specified by ID and extension
  *
  * The filename is URL encoded to protect Unicode chars
  *
  * @author Steven Danz <steven-danz@kc.rr.com>
  */
-function wikiMN($id){
+function metaFN($id,$ext){
   global $conf;
   $id = cleanID($id);
   $id = str_replace(':','/',$id);
-  $fn = $conf['metadir'].'/'.utf8_encodeFN($id).'.mlist';
+  $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext;
   return $fn;
 }
 
diff --git a/inc/template.php b/inc/template.php
index 9baf19348..34fdfb009 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -341,13 +341,13 @@ function tpl_button($type){
     case 'backtomedia':
       print html_backtomedia_button(array('ns' => $NS),'b');
       break;
-    case 'track':
+    case 'subscription':
       if($conf['useacl'] && $ACT == 'show'){
         if($_SERVER['REMOTE_USER']){
-          if(tracking($ID,$_SERVER['REMOTE_USER'])){
-            print html_btn('ignore',$ID,'',array('do' => 'ignore',));
+          if($INFO['subscribed']){
+            print html_btn('unsubscribe',$ID,'',array('do' => 'unsubscribe',));
           } else {
-            print html_btn('track',$ID,'',array('do' => 'track',));
+            print html_btn('subscribe',$ID,'',array('do' => 'subscribe',));
           }
         }
       }
diff --git a/lib/tpl/default/main.php b/lib/tpl/default/main.php
index fe1188efb..3a3a3b5aa 100644
--- a/lib/tpl/default/main.php
+++ b/lib/tpl/default/main.php
@@ -114,9 +114,9 @@
         <?php tpl_button('history')?>
       </div>
       <div class="bar-right" id="bar_bottomright">
+        <?php tpl_button('subscription')?>
         <?php tpl_button('admin')?>
         <?php tpl_button('login')?>
-        <?php tpl_button('track')?>
         <?php tpl_button('index')?>
         <?php tpl_button('top')?>&nbsp;
       </div>
-- 
GitLab