From 2240ea1f316156f3cb4475ea23a16246c999b6f0 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 12:00:37 +0200 Subject: first start at refactoring the subscription system BROKEN This introduces a class for nicer wrapping and easier testing. Some functions were changed to provide nicer APIs (no throwing around of unescaped regexps) and to simplify things (hopefully). The refactoring isn't completed yet, so this will break the subscription system. The goal is to move as much subscription related stuff to this class as possible. Currently there is some code in lib/exe/indexer.php and maybe elsewhere (common.php?). Additionally everything should be covered by tests. A few tests are included here already. --- inc/load.php | 1 + inc/subscription.php | 724 ++++++++++++++++++++++++++------------------------- 2 files changed, 376 insertions(+), 349 deletions(-) (limited to 'inc') diff --git a/inc/load.php b/inc/load.php index b676518e7..bd6d39814 100644 --- a/inc/load.php +++ b/inc/load.php @@ -81,6 +81,7 @@ function load_autoload($name){ 'Mailer' => DOKU_INC.'inc/Mailer.class.php', 'RemoteAPI' => DOKU_INC.'inc/remote.php', 'RemoteAPICore' => DOKU_INC.'inc/RemoteAPICore.php', + 'Subscription' => DOKU_INC.'inc/subscription.php', 'DokuWiki_Action_Plugin' => DOKU_PLUGIN.'action.php', 'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php', diff --git a/inc/subscription.php b/inc/subscription.php index 1f1aedfa4..856836cd5 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -12,399 +12,425 @@ * - subscription_lock * - subscription_unlock * + * @fixme handle $conf['subscribers'] and disable actions + * * @author Adrian Lang + * @author Andreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ -/** - * Get the name of the metafile tracking subscriptions to target page or - * namespace - * - * @author Adrian Lang - * - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return string - */ -function subscription_filename($id) { - $meta_fname = '.mlist'; - if ((substr($id, -1, 1) === ':')) { - $meta_froot = getNS($id); - $meta_fname = '/' . $meta_fname; - } else { - $meta_froot = $id; +class Subscription { + + /** + * Return the subscription meta file for the given ID + * + * @author Adrian Lang + * + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return string + */ + protected function file($id) { + $meta_fname = '.mlist'; + if((substr($id, -1, 1) === ':')) { + $meta_froot = getNS($id); + $meta_fname = '/'.$meta_fname; + } else { + $meta_froot = $id; + } + return metaFN((string) $meta_froot, $meta_fname); } - return metaFN((string) $meta_froot, $meta_fname); -} -/** - * Lock subscription info for an ID - * - * @author Adrian Lang - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return string - */ -function subscription_lock_filename ($id){ - global $conf; - return $conf['lockdir'].'/_subscr_' . md5($id) . '.lock'; -} + /** + * Lock subscription info + * + * We don't use io_lock() her because we do not wait for the lock and use a larger stale time + * + * @author Adrian Lang + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return bool true, if you got a succesful lock + */ + protected function lock($id) { + global $conf; -/** - * Creates a lock file for writing subscription data - * - * @todo add lock time parameter to io_lock() and use this instead - * @param $id - * @return bool - */ -function subscription_lock($id) { - global $conf; - $lock = subscription_lock_filename($id); + $lock = $conf['lockdir'].'/_subscr_'.md5($id).'.lock'; - if (is_dir($lock) && time()-@filemtime($lock) > 60*5) { - // looks like a stale lock - remove it - @rmdir($lock); + if(is_dir($lock) && time() - @filemtime($lock) > 60 * 5) { + // looks like a stale lock - remove it + @rmdir($lock); + } + + // try creating the lock directory + if(!@mkdir($lock, $conf['dmode'])) { + return false; + } + + if($conf['dperm']) chmod($lock, $conf['dperm']); + return true; } - // try creating the lock directory - if (!@mkdir($lock,$conf['dmode'])) { - return false; + /** + * Unlock subscription info + * + * @author Adrian Lang + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return bool + */ + protected function unlock($id) { + global $conf; + $lock = $conf['lockdir'].'/_subscr_'.md5($id).'.lock'; + return @rmdir($lock); } - if($conf['dperm']) chmod($lock, $conf['dperm']); - return true; -} + /** + * Construct a regular expression for parsing a subscription definition line + * + * @author Andreas Gohr + * + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return string complete regexp including delimiters + * @throws Exception when no data is passed + */ + protected function buildregex($user = null, $style = null, $data = null) { + // always work with arrays + $user = (array) $user; + $style = (array) $style; + $data = (array) $data; -/** - * Unlock subscription info for an ID - * - * @author Adrian Lang - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return bool - */ -function subscription_unlock($id) { - $lockf = subscription_lock_filename($id); - return @rmdir($lockf); -} + // clean + $user = array_filter(array_map('trim', $user)); + $style = array_filter(array_map('trim', $style)); + $data = array_filter(array_map('trim', $data)); -/** - * Set subscription information - * - * Allows to set subscription information for permanent storage in meta files. - * Subscriptions consist of a target object, a subscribing user, a subscribe - * style and optional data. - * A subscription may be deleted by specifying an empty subscribe style. - * Only one subscription per target and user is allowed. - * The function returns false on error, otherwise true. Note that no error is - * returned if a subscription should be deleted but the user is not subscribed - * and the subscription meta file exists. - * - * @author Adrian Lang - * - * @param string $user The subscriber or unsubscriber - * @param string $page The target object (page or namespace), specified by - * id; Namespaces are identified by a trailing colon. - * @param string $style The subscribe style; DokuWiki currently implements - * “every”, “digest”, and “list”. - * @param string $data An optional data blob - * @param bool $overwrite Whether an existing subscription may be overwritten - * @return bool - */ -function subscription_set($user, $page, $style, $data = null, - $overwrite = false) { - global $lang; - if (is_null($style)) { - // Delete subscription. - $file = subscription_filename($page); - if (!@file_exists($file)) { - msg(sprintf($lang['subscr_not_subscribed'], $user, - prettyprint_id($page)), -1); - return false; - } + // user names are encoded + $user = array_map('auth_nameencode', $user); - // io_deleteFromFile does not return false if no line matched. - return io_deleteFromFile($file, - subscription_regex(array('user' => auth_nameencode($user))), - true); - } + // quote + $user = array_map('preg_quote_cb', $user); + $style = array_map('preg_quote_cb', $style); + $data = array_map('preg_quote_cb', $data); - // Delete subscription if one exists and $overwrite is true. If $overwrite - // is false, fail. - $subs = subscription_find($page, array('user' => $user)); - if (count($subs) > 0 && array_pop(array_keys($subs)) === $page) { - if (!$overwrite) { - msg(sprintf($lang['subscr_already_subscribed'], $user, - prettyprint_id($page)), -1); - return false; + // join + $user = join('|', $user); + $style = join('|', $style); + $data = join('|', $data); + + // any data at all? + if($user.$style.$data === '') throw new Exception('no data passed'); + + // replace empty values, set which ones are optional + $sopt = ''; + $dopt = ''; + if($user === '') { + $user = '\S+'; } - // Fail if deletion failed, else continue. - if (!subscription_set($user, $page, null)) { - return false; + if($style === '') { + $style = '\S+'; + $sopt = '?'; + } + if($data === '') { + $data = '\S+'; + $dopt = '?'; } - } - $file = subscription_filename($page); - $content = auth_nameencode($user) . ' ' . $style; - if (!is_null($data)) { - $content .= ' ' . $data; + // assemble + return "/^($user)(?:\\s+($style))$sopt(?:\\s+($data))$dopt$/"; } - return io_saveFile($file, $content . "\n", true); -} -/** - * Recursively search for matching subscriptions - * - * This function searches all relevant subscription files for a page or - * namespace. - * - * @author Adrian Lang - * @see function subscription_regex for $pre documentation - * - * @param string $page The target object’s (namespace or page) id - * @param array $pre A hash of predefined values - * @return array - */ -function subscription_find($page, $pre) { - // Construct list of files which may contain relevant subscriptions. - $filenames = array(':' => subscription_filename(':')); - do { - $filenames[$page] = subscription_filename($page); - $page = getNS(rtrim($page, ':')) . ':'; - } while ($page !== ':'); - - // Handle files. - $matches = array(); - foreach ($filenames as $cur_page => $filename) { - if (!@file_exists($filename)) { - continue; - } - $subscriptions = file($filename); - foreach ($subscriptions as $subscription) { - if (strpos($subscription, ' ') === false) { - // This is an old subscription file. - $subscription = trim($subscription) . " every\n"; - } + /** + * Recursively search for matching subscriptions + * + * This function searches all relevant subscription files for a page or + * namespace. + * + * @author Adrian Lang + * + * @param string $page The target object’s (namespace or page) id + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return array + */ + public function subscribers($page, $user = null, $style = null, $data = null) { + // Construct list of files which may contain relevant subscriptions. + $files = array(':' => $this->file(':')); + do { + $files[$page] = $this->file($page); + $page = getNS(rtrim($page, ':')).':'; + } while($page !== ':'); - list($user, $rest) = explode(' ', $subscription, 2); - $subscription = rawurldecode($user) . " " . $rest; + $re = $this->buildregex($user, $style, $data); - if (preg_match(subscription_regex($pre), $subscription, - $line_matches) === 0) { - continue; - } - $match = array_slice($line_matches, 1); - if (!isset($matches[$cur_page])) { - $matches[$cur_page] = array(); + // Handle files. + $result = array(); + foreach($files as $target => $file) { + if(!@file_exists($file)) continue; + + $lines = file($file); + foreach($lines as $line) { + // fix old style subscription files + if(strpos($line, ' ') === false) $line = trim($line)." every\n"; + + // check for matching entries + if(!preg_match($re, $line, $m)) continue; + + $u = rawurldecode($m[1]); // decode the user name + if(!isset($result[$target])) $result[$target] = array(); + $result[$target][$u] = array($m[2], $m[3]); // add to result } - $matches[$cur_page][] = $match; } + return array_reverse($result); } - return array_reverse($matches); -} -/** - * Get data for $INFO['subscribed'] - * - * $INFO['subscribed'] is either false if no subscription for the current page - * and user is in effect. Else it contains an array of arrays with the fields - * “target”, “style”, and optionally “data”. - * - * @author Adrian Lang - */ -function get_info_subscribed() { - global $ID; - global $conf; - if (!$conf['subscribers']) { - return false; - } + /** + * Adds a new subscription for the given page or namespace + * + * This will automatically overwrite any existent subscription for the given user on this + * *exact* page or namespace. It will *not* modify any subscription that may exist in higher namespaces. + * + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @param string $user + * @param string $style + * @param string $data + * @throws Exception when user or style is empty + * @return bool + */ + public function add($id, $user, $style, $data = '') { + // delete any existing subscription + $this->remove($id, $user); - $subs = subscription_find($ID, array('user' => $_SERVER['REMOTE_USER'])); - if (count($subs) === 0) { - return false; - } + $user = auth_nameencode(trim($user)); + $style = trim($style); + $data = trim($data); - $_ret = array(); - foreach ($subs as $target => $subs_data) { - $new = array('target' => $target, - 'style' => $subs_data[0][0]); - if (count($subs_data[0]) > 1) { - $new['data'] = $subs_data[0][1]; - } - $_ret[] = $new; + if(!$user) throw new Exception('no subscription user given'); + if(!$style) throw new Exception('no subscription style given'); + + $line = "$user $style"; + if($data) $line .= " $data"; + $line .= "\n"; + + $file = $this->file($id); + + return io_saveFile($file, $line, true); } - return $_ret; -} + /** + * Removes a subscription for the given page or namespace + * + * This removes all subscriptions matching the given criteria on the given page or + * namespace. It will *not* modify any subscriptions that may exist in higher + * namespaces. + * + * @param string $id The target object’s (namespace or page) id + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return bool + */ + public function remove($id, $user = null, $style = null, $data = null) { + $file = $this->file($id); + if(!file_exists($file)) return true; -/** - * Construct a regular expression parsing a subscription definition line - * - * @author Adrian Lang - * - * @param array $pre A hash of predefined values; “user”, “style”, and - * “data” may be set to limit the results to - * subscriptions matching these parameters. If - * “escaped” is true, these fields are inserted into the - * regular expression without escaping. - * - * @return string complete regexp including delimiters - */ -function subscription_regex($pre = array()) { - if (!isset($pre['escaped']) || $pre['escaped'] === false) { - $pre = array_map('preg_quote_cb', $pre); + $re = $this->buildregex($user, $style, $data); + return io_deleteFromFile($file, $re, true); } - foreach (array('user', 'style', 'data') as $key) { - if (!isset($pre[$key])) { - $pre[$key] = '(\S+)'; + + /** + * Get data for $INFO['subscribed'] + * + * $INFO['subscribed'] is either false if no subscription for the current page + * and user is in effect. Else it contains an array of arrays with the fields + * “target”, “style”, and optionally “data”. + * + * @param string $id Page ID, defaults to global $ID + * @param string $user User, defaults to $_SERVER['REMOTE_USER'] + * @return array + * @author Adrian Lang + */ + function user_subscription($id='', $user='') { + global $ID; + global $conf; + if(!$conf['subscribers']) return false; + + if(!$id) $id = $ID; + if(!$user) $user = $_SERVER['REMOTE_USER']; + + + $subs = $this->subscribers($id, $user); + if(!count($subs)) return false; + + $result = array(); + foreach($subs as $target => $data) { + $result[] = array( + 'target' => $target, + 'style' => $data[$user][0], + 'data' => $data[$user][1] + ); } + + return $result; } - return '/^' . $pre['user'] . '(?: ' . $pre['style'] . - '(?: ' . $pre['data'] . ')?)?$/'; -} -/** - * Return a string with the email addresses of all the - * users subscribed to a page - * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. - * - * @author Steven Danz - * @author Adrian Lang - * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) - * @return string - */ -function subscription_addresslist(&$data){ - global $conf; - /** @var auth_basic $auth */ - global $auth; + /** + * Return a string with the email addresses of all the + * users subscribed to a page + * + * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * + * @author Steven Danz + * @author Adrian Lang + * + * @todo this does NOT return a string but uses a reference to write back, either fix function or docs + * @param array $data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) + * @return string + */ + function subscription_addresslist(&$data) { + global $conf; + /** @var auth_basic $auth */ + global $auth; - $id = $data['id']; - $self = $data['self']; - $addresslist = $data['addresslist']; + $id = $data['id']; + $self = $data['self']; + $addresslist = $data['addresslist']; - if (!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if (!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!' . preg_quote_cb($_SERVER['REMOTE_USER']) . - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach ($subs as $by_targets) { - foreach ($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if ($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); - if ($level >= AUTH_READ) { - if (strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + if(!$conf['subscribers'] || $auth === null) { + return ''; + } + $pres = array('style' => 'every', 'escaped' => true); + if(!$self && isset($_SERVER['REMOTE_USER'])) { + $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). + '(?: |$))\S+)'; + } + $subs = subscription_find($id, $pres); + $emails = array(); + foreach($subs as $by_targets) { + foreach($by_targets as $sub) { + $info = $auth->getUserData($sub[0]); + if($info === false) continue; + $level = auth_aclcheck($id, $sub[0], $info['grps']); + if($level >= AUTH_READ) { + if(strcasecmp($info['mail'], $conf['notify']) != 0) { + $emails[$sub[0]] = $info['mail']; + } } } } + $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); } - $data['addresslist'] = trim($addresslist . ',' . implode(',', $emails), ','); -} -/** - * Send a digest mail - * - * Sends a digest mail showing a bunch of changes. - * - * @author Adrian Lang - * - * @param string $subscriber_mail The target mail address - * @param array $id The ID - * @param int $lastupdate Time of the last notification - */ -function subscription_send_digest($subscriber_mail, $id, $lastupdate) { - $n = 0; - do { - $rev = getRevisions($id, $n++, 1); - $rev = (count($rev) > 0) ? $rev[0] : null; - } while (!is_null($rev) && $rev > $lastupdate); - - $replaces = array('NEWPAGE' => wl($id, '', true, '&'), - 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&')); - if (!is_null($rev)) { - $subject = 'changed'; - $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $replaces['DIFF'] = $dformat->format($df); - } else { - $subject = 'newpage'; - $replaces['OLDPAGE'] = 'none'; - $replaces['DIFF'] = rawWiki($id); + /** + * Send a digest mail + * + * Sends a digest mail showing a bunch of changes. + * + * @author Adrian Lang + * + * @param string $subscriber_mail The target mail address + * @param array $id The ID + * @param int $lastupdate Time of the last notification + */ + function subscription_send_digest($subscriber_mail, $id, $lastupdate) { + $n = 0; + do { + $rev = getRevisions($id, $n++, 1); + $rev = (count($rev) > 0) ? $rev[0] : null; + } while(!is_null($rev) && $rev > $lastupdate); + + $replaces = array( + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + if(!is_null($rev)) { + $subject = 'changed'; + $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $replaces['DIFF'] = $dformat->format($df); + } else { + $subject = 'newpage'; + $replaces['OLDPAGE'] = 'none'; + $replaces['DIFF'] = rawWiki($id); + } + subscription_send( + $subscriber_mail, $replaces, $subject, $id, + 'subscr_digest' + ); } - subscription_send($subscriber_mail, $replaces, $subject, $id, - 'subscr_digest'); -} -/** - * Send a list mail - * - * Sends a list mail showing a list of changed pages. - * - * @author Adrian Lang - * - * @param string $subscriber_mail The target mail address - * @param array $ids Array of ids - * @param string $ns_id The id of the namespace - */ -function subscription_send_list($subscriber_mail, $ids, $ns_id) { - if (count($ids) === 0) return; - global $conf; - $list = ''; - foreach ($ids as $id) { - $list .= '* ' . wl($id, array(), true) . NL; + /** + * Send a list mail + * + * Sends a list mail showing a list of changed pages. + * + * @author Adrian Lang + * + * @param string $subscriber_mail The target mail address + * @param array $ids Array of ids + * @param string $ns_id The id of the namespace + */ + function subscription_send_list($subscriber_mail, $ids, $ns_id) { + if(count($ids) === 0) return; + global $conf; + $list = ''; + foreach($ids as $id) { + $list .= '* '.wl($id, array(), true).NL; + } + subscription_send( + $subscriber_mail, + array( + 'DIFF' => rtrim($list), + 'SUBSCRIBE' => wl( + $ns_id.$conf['start'], + array('do' => 'subscribe'), + true, '&' + ) + ), + 'subscribe_list', + prettyprint_id($ns_id), + 'subscr_list' + ); } - subscription_send($subscriber_mail, - array('DIFF' => rtrim($list), - 'SUBSCRIBE' => wl($ns_id . $conf['start'], - array('do' => 'subscribe'), - true, '&')), - 'subscribe_list', - prettyprint_id($ns_id), - 'subscr_list'); -} -/** - * Helper function for sending a mail - * - * @author Adrian Lang - * - * @param string $subscriber_mail The target mail address - * @param array $replaces Predefined parameters used to parse the - * template - * @param string $subject The lang id of the mail subject (without the - * prefix “mail_”) - * @param string $id The page or namespace id - * @param string $template The name of the mail template - * @return bool - */ -function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { - global $lang; - - $text = rawLocale($template); - $trep = array_merge($replaces, array('PAGE' => $id)); - - $subject = $lang['mail_' . $subject] . ' ' . $id; - $mail = new Mailer(); - $mail->bcc($subscriber_mail); - $mail->subject($subject); - $mail->setBody($text,$trep); - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id,array('do'=>'subscribe'),true,'&').'>', - false - ); - return $mail->send(); -} + /** + * Helper function for sending a mail + * + * @author Adrian Lang + * + * @param string $subscriber_mail The target mail address + * @param array $replaces Predefined parameters used to parse the + * template + * @param string $subject The lang id of the mail subject (without the + * prefix “mail_”) + * @param string $id The page or namespace id + * @param string $template The name of the mail template + * @return bool + */ + function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { + global $lang; + + $text = rawLocale($template); + $trep = array_merge($replaces, array('PAGE' => $id)); + + $subject = $lang['mail_'.$subject].' '.$id; + $mail = new Mailer(); + $mail->bcc($subscriber_mail); + $mail->subject($subject); + $mail->setBody($text, $trep); + $mail->setHeader( + 'List-Unsubscribe', + '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', + false + ); + return $mail->send(); + } + +} \ No newline at end of file -- cgit v1.2.3 From e920a0a10c3027700e61166a6f8d4ea29a9ff102 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 14:00:53 +0200 Subject: handle empty changelog in getRecentsSince() --- inc/changelog.php | 1 + 1 file changed, 1 insertion(+) (limited to 'inc') diff --git a/inc/changelog.php b/inc/changelog.php index 24583b341..7ca7c62e9 100644 --- a/inc/changelog.php +++ b/inc/changelog.php @@ -254,6 +254,7 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){ } else { $lines = @file($conf['changelog']); } + if(!$lines) return $recent; // we start searching at the end of the list $lines = array_reverse($lines); -- cgit v1.2.3 From adec979fd5453cf213b776d7dceaaaac4eb05713 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 15:07:03 +0200 Subject: more subscription refactoring BROKEN now the actual sending of bulk messages (digest, list) is reimplemented and partially tested. Still not complete --- inc/common.php | 4 +- inc/subscription.php | 191 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 149 insertions(+), 46 deletions(-) (limited to 'inc') diff --git a/inc/common.php b/inc/common.php index ac7e744d8..29940d8a6 100644 --- a/inc/common.php +++ b/inc/common.php @@ -107,9 +107,11 @@ function pageinfo() { $info['isadmin'] = false; $info['ismanager'] = false; if(isset($_SERVER['REMOTE_USER'])) { + $sub = new Subscription(); + $info['userinfo'] = $USERINFO; $info['perm'] = auth_quickaclcheck($ID); - $info['subscribed'] = get_info_subscribed(); + $info['subscribed'] = $sub->user_subscription(); $info['client'] = $_SERVER['REMOTE_USER']; if($info['perm'] == AUTH_ADMIN) { diff --git a/inc/subscription.php b/inc/subscription.php index 856836cd5..804776ced 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -253,24 +253,23 @@ class Subscription { * @return array * @author Adrian Lang */ - function user_subscription($id='', $user='') { + function user_subscription($id = '', $user = '') { global $ID; global $conf; if(!$conf['subscribers']) return false; - if(!$id) $id = $ID; + if(!$id) $id = $ID; if(!$user) $user = $_SERVER['REMOTE_USER']; - $subs = $this->subscribers($id, $user); if(!count($subs)) return false; $result = array(); - foreach($subs as $target => $data) { + foreach($subs as $target => $info) { $result[] = array( 'target' => $target, - 'style' => $data[$user][0], - 'data' => $data[$user][1] + 'style' => $info[$user][0], + 'data' => $info[$user][1] ); } @@ -278,52 +277,100 @@ class Subscription { } /** - * Return a string with the email addresses of all the - * users subscribed to a page + * Send digest and list subscriptions * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * This sends mails to all subscribers that have a subscription for namespaces above + * the given page if the needed $conf['subscribe_time'] has passed already. * - * @author Steven Danz - * @author Adrian Lang + * This function is called form lib/exe/indexer.php * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) - * @return string + * @param string $page + * @return int number of sent mails */ - function subscription_addresslist(&$data) { - global $conf; + public function send_bulk($page) { /** @var auth_basic $auth */ global $auth; + global $conf; + global $USERINFO; + $count = 0; - $id = $data['id']; - $self = $data['self']; - $addresslist = $data['addresslist']; + $subscriptions = $this->subscribers($page, null, array('digest', 'list')); - if(!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if(!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach($subs as $by_targets) { - foreach($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); - if($level >= AUTH_READ) { - if(strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + // remember current user info + $olduinfo = $USERINFO; + $olduser = $_SERVER['REMOTE_USER']; + + foreach($subscriptions as $target => $users) { + if(!$this->lock($target)) continue; + + foreach($users as $user => $info) { + list($style, $lastupdate) = $info; + + $lastupdate = (int) $lastupdate; + if($lastupdate + $conf['subscribe_time'] > time()) { + // Less than the configured time period passed since last + // update. + continue; + } + + // Work as the user to make sure ACLs apply correctly + $USERINFO = $auth->getUserData($user); + $_SERVER['REMOTE_USER'] = $user; + if($USERINFO === false) continue; + if(!$USERINFO['mail']) continue; + + if(substr($target, -1, 1) === ':') { + // subscription target is a namespace, get all changes within + $changes = getRecentsSince($lastupdate, null, getNS($target)); + } else { + // single page subscription, check ACL ourselves + if(auth_quickaclcheck($target) < AUTH_READ) continue; + $meta = p_get_metadata($target); + $changes = array($meta['last_change']); + } + + // Filter out pages only changed in small and own edits + $change_ids = array(); + foreach($changes as $rev) { + $n = 0; + while(!is_null($rev) && $rev['date'] >= $lastupdate && + ($_SERVER['REMOTE_USER'] === $rev['user'] || + $rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT)) { + $rev = getRevisions($rev['id'], $n++, 1); + $rev = (count($rev) > 0) ? $rev[0] : null; + } + + if(!is_null($rev) && $rev['date'] >= $lastupdate) { + // Some change was not a minor one and not by myself + $change_ids[] = $rev['id']; } } + + // send it + if($style === 'digest') { + foreach($change_ids as $change_id) { + $this->send_digest( + $USERINFO['mail'], $change_id, + $lastupdate + ); + $count++; + } + } elseif($style === 'list') { + $this->send_list($USERINFO['mail'], $change_ids, $target); + $count++; + } + // TODO: Handle duplicate subscriptions. + + // Update notification time. + $this->add($target, $user, $style, time()); } + $this->unlock($target); } - $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); + + // restore current user info + $USERINFO = $olduinfo; + $_SERVER['REMOTE_USER'] = $olduser; + return $count; } /** @@ -337,7 +384,7 @@ class Subscription { * @param array $id The ID * @param int $lastupdate Time of the last notification */ - function subscription_send_digest($subscriber_mail, $id, $lastupdate) { + protected function send_digest($subscriber_mail, $id, $lastupdate) { $n = 0; do { $rev = getRevisions($id, $n++, 1); @@ -360,7 +407,7 @@ class Subscription { $replaces['OLDPAGE'] = 'none'; $replaces['DIFF'] = rawWiki($id); } - subscription_send( + $this->send( $subscriber_mail, $replaces, $subject, $id, 'subscr_digest' ); @@ -377,14 +424,14 @@ class Subscription { * @param array $ids Array of ids * @param string $ns_id The id of the namespace */ - function subscription_send_list($subscriber_mail, $ids, $ns_id) { + protected function send_list($subscriber_mail, $ids, $ns_id) { if(count($ids) === 0) return; global $conf; $list = ''; foreach($ids as $id) { $list .= '* '.wl($id, array(), true).NL; } - subscription_send( + $this->send( $subscriber_mail, array( 'DIFF' => rtrim($list), @@ -414,7 +461,7 @@ class Subscription { * @param string $template The name of the mail template * @return bool */ - function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { + protected function send($subscriber_mail, $replaces, $subject, $id, $template) { global $lang; $text = rawLocale($template); @@ -433,4 +480,58 @@ class Subscription { return $mail->send(); } + + + // FIXME no refactoring below, yet + + /** + * Return a string with the email addresses of all the + * users subscribed to a page + * + * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * + * @author Steven Danz + * @author Adrian Lang + * + * @todo this does NOT return a string but uses a reference to write back, either fix function or docs + * @param array $data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) + * @return string + */ + function subscription_addresslist(&$data) { + global $conf; + /** @var auth_basic $auth */ + global $auth; + + $id = $data['id']; + $self = $data['self']; + $addresslist = $data['addresslist']; + + if(!$conf['subscribers'] || $auth === null) { + return ''; + } + $pres = array('style' => 'every', 'escaped' => true); + if(!$self && isset($_SERVER['REMOTE_USER'])) { + $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). + '(?: |$))\S+)'; + } + $subs = subscription_find($id, $pres); + $emails = array(); + foreach($subs as $by_targets) { + foreach($by_targets as $sub) { + $info = $auth->getUserData($sub[0]); + if($info === false) continue; + $level = auth_aclcheck($id, $sub[0], $info['grps']); + if($level >= AUTH_READ) { + if(strcasecmp($info['mail'], $conf['notify']) != 0) { + $emails[$sub[0]] = $info['mail']; + } + } + } + } + $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); + } + + } \ No newline at end of file -- cgit v1.2.3 From 835242b0f53a72a555ad30543a1677108ce210af Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 17:17:34 +0200 Subject: subscription system should work now again This readds the last part of the subscription system: the normal "every" subscriptions. --- inc/common.php | 2 +- inc/subscription.php | 57 ++++++++++++++++++++++------------------------------ 2 files changed, 25 insertions(+), 34 deletions(-) (limited to 'inc') diff --git a/inc/common.php b/inc/common.php index 29940d8a6..3cfeb3092 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1122,7 +1122,7 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = $data = array('id' => $id, 'addresslist' => '', 'self' => false); trigger_event( 'COMMON_NOTIFY_ADDRESSLIST', $data, - 'subscription_addresslist' + array(new Subscription(), 'notifyaddresses') ); $bcc = $data['addresslist']; if(empty($bcc)) return false; diff --git a/inc/subscription.php b/inc/subscription.php index 804776ced..9b02225f9 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -12,7 +12,7 @@ * - subscription_lock * - subscription_unlock * - * @fixme handle $conf['subscribers'] and disable actions + * @fixme handle $conf['subscribers'] and disable actions and $auth == null * * @author Adrian Lang * @author Andreas Gohr @@ -480,26 +480,23 @@ class Subscription { return $mail->send(); } - - - // FIXME no refactoring below, yet - /** - * Return a string with the email addresses of all the - * users subscribed to a page + * Default callback for COMMON_NOTIFY_ADDRESSLIST * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * Aggregates all email addresses of user who have subscribed the given page with 'every' style * * @author Steven Danz * @author Adrian Lang * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) + * @todo move the whole functionality into this class, trigger SUBSCRIPTION_NOTIFY_ADDRESSLIST instead, + * use an array for the addresses within it + * + * @param array &$data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) * @return string */ - function subscription_addresslist(&$data) { + public function notifyaddresses(&$data) { global $conf; /** @var auth_basic $auth */ global $auth; @@ -508,30 +505,24 @@ class Subscription { $self = $data['self']; $addresslist = $data['addresslist']; - if(!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if(!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach($subs as $by_targets) { - foreach($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); + $subscriptions = $this->subscribers($id, null, 'every'); + + $result = array(); + foreach($subscriptions as $target => $users) { + foreach($users as $user => $info) { + $userinfo = $auth->getUserData($user); + if($userinfo === false) continue; + if(!$userinfo['mail']) continue; + if(!$self && $user == $_SERVER['REMOTE_USER']) continue; //skip our own changes + + $level = auth_aclcheck($id, $user, $userinfo['grps']); if($level >= AUTH_READ) { - if(strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + if(strcasecmp($userinfo['mail'], $conf['notify']) != 0) { //skip user who get notified elsewhere + $result[$user] = $userinfo['mail']; } } } } - $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); + $data['addresslist'] = trim($addresslist.','.implode(',', $result), ','); } - - } \ No newline at end of file -- cgit v1.2.3 From 84c1127cc070777c8cbcf488f5422bc4b71470a8 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 17:30:01 +0200 Subject: correctly check if subscriptions are enabled --- inc/common.php | 2 +- inc/subscription.php | 26 ++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'inc') diff --git a/inc/common.php b/inc/common.php index 3cfeb3092..b4a57b154 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1117,7 +1117,7 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = $to = $conf['notify']; $bcc = ''; } elseif($who == 'subscribers') { - if(!$conf['subscribers']) return false; //subscribers enabled? + if(!actionOK('subscribe')) return false; //subscribers enabled? if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return false; //skip minors $data = array('id' => $id, 'addresslist' => '', 'self' => false); trigger_event( diff --git a/inc/subscription.php b/inc/subscription.php index 9b02225f9..742f5b1a0 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -21,6 +21,15 @@ class Subscription { + /** + * Check if subscription system is enabled + * + * @return bool + */ + public function isenabled() { + return actionOK('subscribe'); + } + /** * Return the subscription meta file for the given ID * @@ -156,6 +165,8 @@ class Subscription { * @return array */ public function subscribers($page, $user = null, $style = null, $data = null) { + if(!$this->isenabled()) return array(); + // Construct list of files which may contain relevant subscriptions. $files = array(':' => $this->file(':')); do { @@ -201,6 +212,8 @@ class Subscription { * @return bool */ public function add($id, $user, $style, $data = '') { + if(!$this->isenabled()) return false; + // delete any existing subscription $this->remove($id, $user); @@ -234,6 +247,8 @@ class Subscription { * @return bool */ public function remove($id, $user = null, $style = null, $data = null) { + if(!$this->isenabled()) return false; + $file = $this->file($id); if(!file_exists($file)) return true; @@ -254,10 +269,9 @@ class Subscription { * @author Adrian Lang */ function user_subscription($id = '', $user = '') { - global $ID; - global $conf; - if(!$conf['subscribers']) return false; + if(!$this->isenabled()) return false; + global $ID; if(!$id) $id = $ID; if(!$user) $user = $_SERVER['REMOTE_USER']; @@ -288,6 +302,8 @@ class Subscription { * @return int number of sent mails */ public function send_bulk($page) { + if(!$this->isenabled()) return 0; + /** @var auth_basic $auth */ global $auth; global $conf; @@ -497,9 +513,11 @@ class Subscription { * @return string */ public function notifyaddresses(&$data) { - global $conf; + if(!$this->isenabled()) return false; + /** @var auth_basic $auth */ global $auth; + global $conf; $id = $data['id']; $self = $data['self']; -- cgit v1.2.3 From a0519fdaeb59bd96d9071681a68c2dc1b646fc68 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 17:47:47 +0200 Subject: fixed subscription management now adding and removing subscriptions works again --- inc/actions.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'inc') diff --git a/inc/actions.php b/inc/actions.php index 62b0e1800..721492bd4 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -700,21 +700,28 @@ function act_subscription($act){ $target = $params['target']; $style = $params['style']; - $data = $params['data']; $action = $params['action']; // Perform action. - if (!subscription_set($_SERVER['REMOTE_USER'], $target, $style, $data)) { + $sub = new Subscription(); + if($action == 'unsubscribe'){ + $ok = $sub->remove($target, $_SERVER['REMOTE_USER'], $style); + }else{ + $ok = $sub->add($target, $_SERVER['REMOTE_USER'], $style); + } + + if($ok) { + msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']), + prettyprint_id($target)), 1); + act_redirect($ID, $act); + } else { throw new Exception(sprintf($lang["subscr_{$action}_error"], hsc($INFO['userinfo']['name']), prettyprint_id($target))); } - msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']), - prettyprint_id($target)), 1); - act_redirect($ID, $act); // Assure that we have valid data if act_redirect somehow fails. - $INFO['subscribed'] = get_info_subscribed(); + $INFO['subscribed'] = $sub->user_subscription(); return 'show'; } -- cgit v1.2.3 From 02308d17ed15cd633ba1fd5cab11994c42065121 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 18:01:30 +0200 Subject: initialize new subscriptions with current time We don't want to create a bunch of mails whenever a namespace is subscribed. Only changes *after* the subscription should be considered. This patch adds the timestamp to "every" style subscriptions as well, though this data is ignored. --- inc/subscription.php | 1 + 1 file changed, 1 insertion(+) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index 742f5b1a0..800329cb5 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -223,6 +223,7 @@ class Subscription { if(!$user) throw new Exception('no subscription user given'); if(!$style) throw new Exception('no subscription style given'); + if(!$data) $data = time(); //always add current time for new subscriptions $line = "$user $style"; if($data) $line .= " $data"; -- cgit v1.2.3 From f036cff4fde59f0265f6123f6faf92cb8ba8bb26 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 18:07:20 +0200 Subject: minor cleanup --- inc/subscription.php | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index 800329cb5..74f4e4d03 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -1,24 +1,11 @@ * @author Andreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ - class Subscription { /** @@ -511,10 +498,9 @@ class Subscription { * @param array &$data Containing $id (the page id), $self (whether the author * should be notified, $addresslist (current email address * list) - * @return string */ public function notifyaddresses(&$data) { - if(!$this->isenabled()) return false; + if(!$this->isenabled()) return; /** @var auth_basic $auth */ global $auth; -- cgit v1.2.3 From 2ed38036a53a489d2fcadc46ce601f8c876fca31 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 21 Sep 2012 11:53:17 +0200 Subject: consolidate more notification code in subscription class This is untested and probably broken currently --- inc/auth.php | 11 +--- inc/common.php | 45 +++------------ inc/subscription.php | 159 +++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 126 insertions(+), 89 deletions(-) (limited to 'inc') diff --git a/inc/auth.php b/inc/auth.php index cedfdee36..3fb937613 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -778,23 +778,18 @@ function register() { return false; } - // create substitutions for use in notification email - $substitutions = array( - 'NEWUSER' => $_POST['login'], - 'NEWNAME' => $_POST['fullname'], - 'NEWEMAIL' => $_POST['email'], - ); + $subscription = new Subscription(); if(!$conf['autopasswd']) { msg($lang['regsuccess2'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + $subscription->send_register($_POST['login'], $_POST['fullname'], $_POST['email']); return true; } // autogenerated password? then send him the password if(auth_sendPassword($_POST['login'], $pass)) { msg($lang['regsuccess'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + $subscription->send_register($_POST['login'], $_POST['fullname'], $_POST['email']); return true; } else { msg($lang['regmailfail'], -1); diff --git a/inc/common.php b/inc/common.php index b4a57b154..d17061a1b 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1113,9 +1113,8 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = // decide if there is something to do, eg. whom to mail if($who == 'admin') { if(empty($conf['notify'])) return false; //notify enabled? - $text = rawLocale('mailtext'); - $to = $conf['notify']; - $bcc = ''; + $tpl = 'mailtext'; + $to = $conf['notify']; } elseif($who == 'subscribers') { if(!actionOK('subscribe')) return false; //subscribers enabled? if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return false; //skip minors @@ -1124,57 +1123,29 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = 'COMMON_NOTIFY_ADDRESSLIST', $data, array(new Subscription(), 'notifyaddresses') ); - $bcc = $data['addresslist']; - if(empty($bcc)) return false; - $to = ''; - $text = rawLocale('subscr_single'); + $to = $data['addresslist']; + if(empty($to)) return false; + $tpl = 'subscr_single'; } elseif($who == 'register') { if(empty($conf['registernotify'])) return false; $text = rawLocale('registermail'); $to = $conf['registernotify']; - $bcc = ''; } else { return false; //just to be safe } - // prepare replacements (keys not set in hrep will be taken from trep) - $trep = array( - 'NEWPAGE' => wl($id, '', true, '&'), - 'PAGE' => $id, - 'SUMMARY' => $summary - ); - $trep = array_merge($trep, $replace); - $hrep = array(); - // prepare content if($who == 'register') { $subject = $lang['mail_new_user'].' '.$summary; - } elseif($rev) { - $subject = $lang['mail_changed'].' '.$id; - $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $tdiff = $dformat->format($df); - - $DIFF_INLINESTYLES = true; - $dformat = new InlineDiffFormatter(); - $hdiff = $dformat->format($df); - $hdiff = ''.$hdiff.'
'; - $DIFF_INLINESTYLES = false; } else { - $subject = $lang['mail_newpage'].' '.$id; - $trep['OLDPAGE'] = '---'; - $tdiff = rawWiki($id); - $hdiff = nl2br(hsc($tdiff)); + $subscription = new Subscription(); + return $subscription->send_diff($to, $tpl, $id, $rev, $summary); } - $trep['DIFF'] = $tdiff; - $hrep['DIFF'] = $hdiff; + // send mail $mail = new Mailer(); $mail->to($to); - $mail->bcc($bcc); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); if($who == 'subscribers') { diff --git a/inc/subscription.php b/inc/subscription.php index 74f4e4d03..4757b216c 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -377,16 +377,90 @@ class Subscription { return $count; } + /** + * Send the diff for some page change + * + * @param string $subscriber_mail The target mail address + * @param string $template Mail template, should be 'subscr_digest' or 'subscr_single' + * @param string $id Page for which the notification is + * @param int|null $rev Old revision if any + * @param string $summary Change summary if any + * @return bool true if successfully sent + */ + public function send_diff($subscriber_mail, $template, $id, $rev = null, $summary = '') { + global $DIFF_INLINESTYLES; + + // prepare replacements (keys not set in hrep will be taken from trep) + $trep = array( + 'PAGE' => $id, + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUMMARY' => $summary, + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + $hrep = array(); + + if($rev) { + $subject = 'changed'; + $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $tdiff = $dformat->format($df); + + $DIFF_INLINESTYLES = true; + $dformat = new InlineDiffFormatter(); + $hdiff = $dformat->format($df); + $hdiff = ''.$hdiff.'
'; + $DIFF_INLINESTYLES = false; + + } else { + $subject = 'newpage'; + $trep['OLDPAGE'] = '---'; + $tdiff = rawWiki($id); + $hdiff = nl2br(hsc($tdiff)); + } + + $trep['DIFF'] = $tdiff; + $hrep['DIFF'] = $hdiff; + + return $this->send( + $subscriber_mail, $subject, $id, + $template, $trep, $hrep + ); + } + + public function send_register($login, $fullname, $email) { + global $conf; + global $ID; + if(empty($conf['registernotify'])) return false; + + $trep = array( + 'NEWUSER' => $login, + 'NEWNAME' => $fullname, + 'NEWEMAIL' => $email, + ); + + return $this->send( + $conf['registernotify'], + 'new_user', + $ID, + 'registermail', + $trep + ); + } + /** * Send a digest mail * - * Sends a digest mail showing a bunch of changes. + * Sends a digest mail showing a bunch of changes of a single page. Basically the same as send_diff() + * but determines the last known revision first * * @author Adrian Lang * * @param string $subscriber_mail The target mail address * @param array $id The ID * @param int $lastupdate Time of the last notification + * @return bool */ protected function send_digest($subscriber_mail, $id, $lastupdate) { $n = 0; @@ -395,25 +469,10 @@ class Subscription { $rev = (count($rev) > 0) ? $rev[0] : null; } while(!is_null($rev) && $rev > $lastupdate); - $replaces = array( - 'NEWPAGE' => wl($id, '', true, '&'), - 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') - ); - if(!is_null($rev)) { - $subject = 'changed'; - $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $replaces['DIFF'] = $dformat->format($df); - } else { - $subject = 'newpage'; - $replaces['OLDPAGE'] = 'none'; - $replaces['DIFF'] = rawWiki($id); - } - $this->send( - $subscriber_mail, $replaces, $subject, $id, - 'subscr_digest' + return $this->send_diff( + $subscriber_mail, + 'subscr_digest', + $id, $rev ); } @@ -427,27 +486,35 @@ class Subscription { * @param string $subscriber_mail The target mail address * @param array $ids Array of ids * @param string $ns_id The id of the namespace + * @return bool */ protected function send_list($subscriber_mail, $ids, $ns_id) { if(count($ids) === 0) return; - global $conf; - $list = ''; + + $tlist = ''; + $hlist = '
    '; foreach($ids as $id) { - $list .= '* '.wl($id, array(), true).NL; + $link = wl($id, array(), true); + $tlist .= '* '.$link.NL; + $hlist .= '
  • '.hsc($id).'
  • '.NL; } - $this->send( + $hlist = '
'; + + $id = prettyprint_id($ns_id); + $trep = array( + 'DIFF' => rtrim($tlist), + 'PAGE' => $id, + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + $hrep = array( + 'DIFF' => $hlist + ); + + return $this->send( $subscriber_mail, - array( - 'DIFF' => rtrim($list), - 'SUBSCRIBE' => wl( - $ns_id.$conf['start'], - array('do' => 'subscribe'), - true, '&' - ) - ), 'subscribe_list', - prettyprint_id($ns_id), - 'subscr_list' + + 'subscr_list', $trep, $hrep ); } @@ -457,30 +524,34 @@ class Subscription { * @author Adrian Lang * * @param string $subscriber_mail The target mail address - * @param array $replaces Predefined parameters used to parse the - * template * @param string $subject The lang id of the mail subject (without the * prefix “mail_”) * @param string $id The page or namespace id * @param string $template The name of the mail template + * @param array $trep Predefined parameters used to parse the + * template (in text format) + * @param array $hrep Predefined parameters used to parse the + * template (in HTML format), null to default to $trep * @return bool */ - protected function send($subscriber_mail, $replaces, $subject, $id, $template) { + protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep = null) { global $lang; $text = rawLocale($template); - $trep = array_merge($replaces, array('PAGE' => $id)); + $trep = array_merge( + $trep, array( + + ) + ); $subject = $lang['mail_'.$subject].' '.$id; $mail = new Mailer(); $mail->bcc($subscriber_mail); $mail->subject($subject); - $mail->setBody($text, $trep); - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', - false - ); + $mail->setBody($text, $trep, $hrep); + if(isset($trep['SUBSCRIBE'])){ + $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); + } return $mail->send(); } -- cgit v1.2.3 From 10b5c32d6486ab0884deda109b1e5947f7ec7662 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 30 Nov 2012 12:35:46 +0100 Subject: fixed merge error in inc/auth.php merged the wrong change here --- inc/auth.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'inc') diff --git a/inc/auth.php b/inc/auth.php index 54d2cd50a..9c458338d 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -782,21 +782,21 @@ function register() { // create substitutions for use in notification email $substitutions = array( - 'NEWUSER' => $_POST['login'], - 'NEWNAME' => $_POST['fullname'], - 'NEWEMAIL' => $_POST['email'], + 'NEWUSER' => $login, + 'NEWNAME' => $fullname, + 'NEWEMAIL' => $email, ); if(!$conf['autopasswd']) { msg($lang['regsuccess2'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + notify('', 'register', '', $login, false, $substitutions); return true; } // autogenerated password? then send him the password if(auth_sendPassword($login, $pass)) { msg($lang['regsuccess'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + notify('', 'register', '', $login, false, $substitutions); return true; } else { msg($lang['regmailfail'], -1); -- cgit v1.2.3 From 790b77202079261b11d425e0c814608d626eea70 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 30 Nov 2012 13:09:15 +0100 Subject: moved registration notification to subscription class --- inc/auth.php | 14 +++++--------- inc/common.php | 27 ++------------------------- inc/subscription.php | 29 ++++++++++++++++------------- 3 files changed, 23 insertions(+), 47 deletions(-) (limited to 'inc') diff --git a/inc/auth.php b/inc/auth.php index 9c458338d..29a46b37e 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -780,23 +780,19 @@ function register() { return false; } - // create substitutions for use in notification email - $substitutions = array( - 'NEWUSER' => $login, - 'NEWNAME' => $fullname, - 'NEWEMAIL' => $email, - ); + // send notification about the new user + $subscription = new Subscription(); + $subscription->send_register($login, $fullname, $email); + // are we done? if(!$conf['autopasswd']) { msg($lang['regsuccess2'], 1); - notify('', 'register', '', $login, false, $substitutions); return true; } - // autogenerated password? then send him the password + // autogenerated password? then send password to user if(auth_sendPassword($login, $pass)) { msg($lang['regsuccess'], 1); - notify('', 'register', '', $login, false, $substitutions); return true; } else { msg($lang['regmailfail'], -1); diff --git a/inc/common.php b/inc/common.php index d17061a1b..20e0af389 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1126,36 +1126,13 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = $to = $data['addresslist']; if(empty($to)) return false; $tpl = 'subscr_single'; - } elseif($who == 'register') { - if(empty($conf['registernotify'])) return false; - $text = rawLocale('registermail'); - $to = $conf['registernotify']; } else { return false; //just to be safe } // prepare content - if($who == 'register') { - $subject = $lang['mail_new_user'].' '.$summary; - } else { - $subscription = new Subscription(); - return $subscription->send_diff($to, $tpl, $id, $rev, $summary); - } - - - // send mail - $mail = new Mailer(); - $mail->to($to); - $mail->subject($subject); - $mail->setBody($text, $trep, $hrep); - if($who == 'subscribers') { - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', - false - ); - } - return $mail->send(); + $subscription = new Subscription(); + return $subscription->send_diff($to, $tpl, $id, $rev, $summary); } /** diff --git a/inc/subscription.php b/inc/subscription.php index 4757b216c..bfbd95244 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -429,9 +429,18 @@ class Subscription { ); } + /** + * Send a notify mail on new registration + * + * @author Andreas Gohr + * + * @param string $login login name of the new user + * @param string $fullname full name of the new user + * @param string $email email address of the new user + * @return bool true if a mail was sent + */ public function send_register($login, $fullname, $email) { global $conf; - global $ID; if(empty($conf['registernotify'])) return false; $trep = array( @@ -443,7 +452,7 @@ class Subscription { return $this->send( $conf['registernotify'], 'new_user', - $ID, + $login, 'registermail', $trep ); @@ -486,10 +495,10 @@ class Subscription { * @param string $subscriber_mail The target mail address * @param array $ids Array of ids * @param string $ns_id The id of the namespace - * @return bool + * @return bool true if a mail was sent */ protected function send_list($subscriber_mail, $ids, $ns_id) { - if(count($ids) === 0) return; + if(count($ids) === 0) return false; $tlist = ''; $hlist = '
    '; @@ -526,7 +535,7 @@ class Subscription { * @param string $subscriber_mail The target mail address * @param string $subject The lang id of the mail subject (without the * prefix “mail_”) - * @param string $id The page or namespace id + * @param string $context The context of this mail, eg. page or namespace id * @param string $template The name of the mail template * @param array $trep Predefined parameters used to parse the * template (in text format) @@ -534,17 +543,11 @@ class Subscription { * template (in HTML format), null to default to $trep * @return bool */ - protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep = null) { + protected function send($subscriber_mail, $subject, $context, $template, $trep, $hrep = null) { global $lang; $text = rawLocale($template); - $trep = array_merge( - $trep, array( - - ) - ); - - $subject = $lang['mail_'.$subject].' '.$id; + $subject = $lang['mail_'.$subject].' '.$context; $mail = new Mailer(); $mail->bcc($subscriber_mail); $mail->subject($subject); -- cgit v1.2.3 From e13e01da48b642dcdf3efe6864f0fc2bb5094455 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 7 Dec 2012 10:35:27 +0100 Subject: added compatibility function --- inc/subscription.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index bfbd95244..df6f1af32 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -604,4 +604,19 @@ class Subscription { } $data['addresslist'] = trim($addresslist.','.implode(',', $result), ','); } +} + +/** + * Compatibility wrapper around Subscription:notifyaddresses + * + * for plugins emitting COMMON_NOTIFY_ADDRESSLIST themselves and relying on on this to + * be the default handler + * + * @param array $data event data for + * + * @deprecated 2012-12-07 + */ +function subscription_addresslist(&$data){ + $sub = new Subscription(); + $sub->notifyaddresses($data); } \ No newline at end of file -- cgit v1.2.3 From b34cf753be6c2c3fc67eac58738acc74a1c1785a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 7 Dec 2012 10:35:49 +0100 Subject: some reformatting --- inc/subscription.php | 78 ++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index df6f1af32..44248a39d 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -93,27 +93,27 @@ class Subscription { */ protected function buildregex($user = null, $style = null, $data = null) { // always work with arrays - $user = (array) $user; + $user = (array) $user; $style = (array) $style; - $data = (array) $data; + $data = (array) $data; // clean - $user = array_filter(array_map('trim', $user)); + $user = array_filter(array_map('trim', $user)); $style = array_filter(array_map('trim', $style)); - $data = array_filter(array_map('trim', $data)); + $data = array_filter(array_map('trim', $data)); // user names are encoded $user = array_map('auth_nameencode', $user); // quote - $user = array_map('preg_quote_cb', $user); + $user = array_map('preg_quote_cb', $user); $style = array_map('preg_quote_cb', $style); - $data = array_map('preg_quote_cb', $data); + $data = array_map('preg_quote_cb', $data); // join - $user = join('|', $user); + $user = join('|', $user); $style = join('|', $style); - $data = join('|', $data); + $data = join('|', $data); // any data at all? if($user.$style.$data === '') throw new Exception('no data passed'); @@ -126,7 +126,7 @@ class Subscription { } if($style === '') { $style = '\S+'; - $sopt = '?'; + $sopt = '?'; } if($data === '') { $data = '\S+'; @@ -158,7 +158,7 @@ class Subscription { $files = array(':' => $this->file(':')); do { $files[$page] = $this->file($page); - $page = getNS(rtrim($page, ':')).':'; + $page = getNS(rtrim($page, ':')).':'; } while($page !== ':'); $re = $this->buildregex($user, $style, $data); @@ -204,9 +204,9 @@ class Subscription { // delete any existing subscription $this->remove($id, $user); - $user = auth_nameencode(trim($user)); + $user = auth_nameencode(trim($user)); $style = trim($style); - $data = trim($data); + $data = trim($data); if(!$user) throw new Exception('no subscription user given'); if(!$style) throw new Exception('no subscription style given'); @@ -270,8 +270,8 @@ class Subscription { foreach($subs as $target => $info) { $result[] = array( 'target' => $target, - 'style' => $info[$user][0], - 'data' => $info[$user][1] + 'style' => $info[$user][0], + 'data' => $info[$user][1] ); } @@ -302,7 +302,7 @@ class Subscription { // remember current user info $olduinfo = $USERINFO; - $olduser = $_SERVER['REMOTE_USER']; + $olduser = $_SERVER['REMOTE_USER']; foreach($subscriptions as $target => $users) { if(!$this->lock($target)) continue; @@ -318,7 +318,7 @@ class Subscription { } // Work as the user to make sure ACLs apply correctly - $USERINFO = $auth->getUserData($user); + $USERINFO = $auth->getUserData($user); $_SERVER['REMOTE_USER'] = $user; if($USERINFO === false) continue; if(!$USERINFO['mail']) continue; @@ -329,7 +329,7 @@ class Subscription { } else { // single page subscription, check ACL ourselves if(auth_quickaclcheck($target) < AUTH_READ) continue; - $meta = p_get_metadata($target); + $meta = p_get_metadata($target); $changes = array($meta['last_change']); } @@ -372,7 +372,7 @@ class Subscription { } // restore current user info - $USERINFO = $olduinfo; + $USERINFO = $olduinfo; $_SERVER['REMOTE_USER'] = $olduser; return $count; } @@ -392,32 +392,32 @@ class Subscription { // prepare replacements (keys not set in hrep will be taken from trep) $trep = array( - 'PAGE' => $id, - 'NEWPAGE' => wl($id, '', true, '&'), - 'SUMMARY' => $summary, + 'PAGE' => $id, + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUMMARY' => $summary, 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') ); $hrep = array(); if($rev) { - $subject = 'changed'; + $subject = 'changed'; $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $tdiff = $dformat->format($df); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $tdiff = $dformat->format($df); $DIFF_INLINESTYLES = true; - $dformat = new InlineDiffFormatter(); - $hdiff = $dformat->format($df); - $hdiff = ''.$hdiff.'
    '; + $dformat = new InlineDiffFormatter(); + $hdiff = $dformat->format($df); + $hdiff = ''.$hdiff.'
    '; $DIFF_INLINESTYLES = false; } else { - $subject = 'newpage'; + $subject = 'newpage'; $trep['OLDPAGE'] = '---'; - $tdiff = rawWiki($id); - $hdiff = nl2br(hsc($tdiff)); + $tdiff = rawWiki($id); + $hdiff = nl2br(hsc($tdiff)); } $trep['DIFF'] = $tdiff; @@ -444,8 +444,8 @@ class Subscription { if(empty($conf['registernotify'])) return false; $trep = array( - 'NEWUSER' => $login, - 'NEWNAME' => $fullname, + 'NEWUSER' => $login, + 'NEWNAME' => $fullname, 'NEWEMAIL' => $email, ); @@ -548,11 +548,11 @@ class Subscription { $text = rawLocale($template); $subject = $lang['mail_'.$subject].' '.$context; - $mail = new Mailer(); + $mail = new Mailer(); $mail->bcc($subscriber_mail); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); - if(isset($trep['SUBSCRIBE'])){ + if(isset($trep['SUBSCRIBE'])) { $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); } return $mail->send(); @@ -580,8 +580,8 @@ class Subscription { global $auth; global $conf; - $id = $data['id']; - $self = $data['self']; + $id = $data['id']; + $self = $data['self']; $addresslist = $data['addresslist']; $subscriptions = $this->subscribers($id, null, 'every'); @@ -616,7 +616,7 @@ class Subscription { * * @deprecated 2012-12-07 */ -function subscription_addresslist(&$data){ +function subscription_addresslist(&$data) { $sub = new Subscription(); $sub->notifyaddresses($data); } \ No newline at end of file -- cgit v1.2.3 From 7eaa7703a43b9f22f12be04e8580a3f2515fb146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=97=A5=E5=90=91=E5=B0=8F=E9=83=8E?= Date: Wed, 9 Jan 2013 20:30:03 +0100 Subject: Traditional Chinese language update --- inc/lang/zh-tw/adminplugins.txt | 2 +- inc/lang/zh-tw/backlinks.txt | 2 +- inc/lang/zh-tw/diff.txt | 2 +- inc/lang/zh-tw/edit.txt | 2 +- inc/lang/zh-tw/editrev.txt | 2 +- inc/lang/zh-tw/index.txt | 2 +- inc/lang/zh-tw/install.html | 6 +-- inc/lang/zh-tw/lang.php | 101 ++++++++++++++++++++------------------- inc/lang/zh-tw/locked.txt | 2 +- inc/lang/zh-tw/login.txt | 3 +- inc/lang/zh-tw/mailtext.txt | 2 +- inc/lang/zh-tw/norev.txt | 2 +- inc/lang/zh-tw/preview.txt | 2 +- inc/lang/zh-tw/pwconfirm.txt | 8 ++-- inc/lang/zh-tw/read.txt | 2 +- inc/lang/zh-tw/register.txt | 3 +- inc/lang/zh-tw/registermail.txt | 4 +- inc/lang/zh-tw/resendpwd.txt | 2 +- inc/lang/zh-tw/revisions.txt | 2 +- inc/lang/zh-tw/stopwords.txt | 10 ++-- inc/lang/zh-tw/subscr_digest.txt | 6 +-- inc/lang/zh-tw/subscr_form.txt | 2 +- inc/lang/zh-tw/subscr_list.txt | 6 +-- inc/lang/zh-tw/subscr_single.txt | 6 +-- inc/lang/zh-tw/updateprofile.txt | 2 +- inc/lang/zh-tw/uploadmail.txt | 4 +- 26 files changed, 93 insertions(+), 94 deletions(-) (limited to 'inc') diff --git a/inc/lang/zh-tw/adminplugins.txt b/inc/lang/zh-tw/adminplugins.txt index fb1999269..6d21ac2cd 100644 --- a/inc/lang/zh-tw/adminplugins.txt +++ b/inc/lang/zh-tw/adminplugins.txt @@ -1 +1 @@ -===== 外加插件 ===== \ No newline at end of file +===== 附加元件 ===== \ No newline at end of file diff --git a/inc/lang/zh-tw/backlinks.txt b/inc/lang/zh-tw/backlinks.txt index 5b36728e7..6a8bf8896 100644 --- a/inc/lang/zh-tw/backlinks.txt +++ b/inc/lang/zh-tw/backlinks.txt @@ -1,4 +1,4 @@ ====== 反向連結 ====== -這裡是引用、連結到目前頁面的頁面清單。 +這是引用、連結到目前頁面的頁面清單。 diff --git a/inc/lang/zh-tw/diff.txt b/inc/lang/zh-tw/diff.txt index 17fad7ba0..e2c05001f 100644 --- a/inc/lang/zh-tw/diff.txt +++ b/inc/lang/zh-tw/diff.txt @@ -1,3 +1,3 @@ ====== 差異處 ====== -這裏顯示二個版本的差異處。 \ No newline at end of file +這裏顯示兩個版本的差異處。 \ No newline at end of file diff --git a/inc/lang/zh-tw/edit.txt b/inc/lang/zh-tw/edit.txt index bbe5bb8ed..f6b74794f 100644 --- a/inc/lang/zh-tw/edit.txt +++ b/inc/lang/zh-tw/edit.txt @@ -1 +1 @@ -編輯本頁並按下''儲存''即可。可在[[wiki:syntax|維基語法]]找到語法說明。請只在能讓本文品質「**更好**」時才編輯。如果只是要測試,請使用 [[playground:playground|遊樂場]]。 +編輯本頁後,請按下「儲存」按鈕。若要參看語法說明,請到[[wiki:syntax|語法]]頁。請只在能讓本文品質**更好**時才編輯。如果只是要測試,請移玉步至 [[playground:playground|遊樂場]]。 \ No newline at end of file diff --git a/inc/lang/zh-tw/editrev.txt b/inc/lang/zh-tw/editrev.txt index 96f9a7c6a..98a800ab1 100644 --- a/inc/lang/zh-tw/editrev.txt +++ b/inc/lang/zh-tw/editrev.txt @@ -1,2 +1,2 @@ -**您目前載入的是本份文件的舊版!** 您如果存檔,這些資料就會被存成另一份。 +**您目前載入的是本份文件的舊版!** 您如果存檔,這些舊版資料就會變成最新版本。 ---- diff --git a/inc/lang/zh-tw/index.txt b/inc/lang/zh-tw/index.txt index bba277041..1b89e0c5d 100644 --- a/inc/lang/zh-tw/index.txt +++ b/inc/lang/zh-tw/index.txt @@ -1,3 +1,3 @@ ====== 站台地圖 ====== -這個站台地圖列出了所有允許的頁面,依 [[doku>namespaces|分類空間]] 排序。 \ No newline at end of file +這個站台地圖列出了所有允許的頁面,依 [[doku>namespaces|分類名稱]] 排序。 \ No newline at end of file diff --git a/inc/lang/zh-tw/install.html b/inc/lang/zh-tw/install.html index 2a8b1aac3..9a0d1dcd9 100644 --- a/inc/lang/zh-tw/install.html +++ b/inc/lang/zh-tw/install.html @@ -1,8 +1,8 @@

    本頁面旨在幫助您完成第一次安装和設定 Dokuwiki。關於安裝工具的更多訊息請參閱 官方文檔頁面

    -

    DokuWiki 使用普通檔案儲存維基頁面以及與頁面相關的訊息(例如:圖像,搜尋索引,修訂記錄等)。為了正常運作,DokuWiki 必須 擁有針對那些路徑和檔案的寫入權限。本安裝工具無法設定目錄權限,這通常要透過命令行、FTP 或您主機上的控制台(如cPanel)進行。

    +

    DokuWiki 使用普通檔案來儲存 wiki 頁面,以及與頁面相關的訊息(例如:圖像、搜尋索引、修訂記錄等)。為了正常運作,DokuWiki 必須 擁有針對那些路徑和檔案的寫入權限。本安裝工具無法設定目錄權限,這通常要透過命令行、FTP 或您主機上的控制台(如cPanel)進行。

    -

    本安裝工具將設定您的 DokuWiki 用於 ACL 的設定檔,它能讓管理員登入並使用「管理」功能來安裝插件、管理用户、管理訪問權限和其他設定設定。它並不是 DokuWiki 正常運作所必須,但安裝之後將更方便管理。

    +

    本安裝工具將設定您的 DokuWiki 用於 ACL 的設定檔,它能讓管理員登入並使用「管理」功能來安裝附加元件、管理使用者、管理訪問權限和其他設定設定。它並不是 DokuWiki 正常運作所必須,但安裝之後將更方便管理。

    -

    有經驗的用戶或有特殊需求的用戶請參閱更詳細的 安裝指南 +

    有經驗的或有特殊需求的使用者,請參閱更詳細的 安裝指南設定

    \ No newline at end of file diff --git a/inc/lang/zh-tw/lang.php b/inc/lang/zh-tw/lang.php index 9f380acb5..ddb35617e 100644 --- a/inc/lang/zh-tw/lang.php +++ b/inc/lang/zh-tw/lang.php @@ -11,6 +11,7 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -19,7 +20,7 @@ $lang['doublequoteclosing'] = '”'; $lang['singlequoteopening'] = '‘'; $lang['singlequoteclosing'] = '’'; $lang['apostrophe'] = '’'; -$lang['btn_edit'] = '編修本頁'; +$lang['btn_edit'] = '編輯本頁'; $lang['btn_source'] = '顯示原始碼'; $lang['btn_show'] = '顯示頁面'; $lang['btn_create'] = '建立此頁'; @@ -34,7 +35,7 @@ $lang['btn_recent'] = '最近更新'; $lang['btn_upload'] = '上傳'; $lang['btn_cancel'] = '取消'; $lang['btn_index'] = '站台地圖'; -$lang['btn_secedit'] = '改這段'; +$lang['btn_secedit'] = '編輯此段'; $lang['btn_login'] = '登入'; $lang['btn_logout'] = '登出'; $lang['btn_admin'] = '管理選單'; @@ -61,40 +62,40 @@ $lang['newpass'] = '新密碼'; $lang['oldpass'] = '目前密碼'; $lang['passchk'] = '確認密碼'; $lang['remember'] = '記住帳號密碼'; -$lang['fullname'] = '真實姓名'; +$lang['fullname'] = '姓名'; $lang['email'] = '電郵'; $lang['profile'] = '使用者個人資料'; $lang['badlogin'] = '很抱歉,您的使用者名稱或密碼可能有錯誤。'; $lang['minoredit'] = '小修改'; $lang['draftdate'] = '草稿已自動存檔於'; -$lang['nosecedit'] = '頁面在這之間已被修改,過時的區段資料已載入全頁取代。'; +$lang['nosecedit'] = '在您編輯期間,其他使用者修改過本頁面。區段資料已逾時,因此系統載入了全頁,以取代之。'; $lang['regmissing'] = '很抱歉,所有欄位都要填寫。'; -$lang['reguexists'] = '很抱歉,本帳號已被註冊。'; -$lang['regsuccess'] = '使用者已建立,密碼已寄發至該 email。'; -$lang['regsuccess2'] = '使用者已建立。'; +$lang['reguexists'] = '很抱歉,有人已使用了這個帳號。'; +$lang['regsuccess'] = '使用者帳號已建立,密碼已寄發至該電郵。'; +$lang['regsuccess2'] = '使用者帳號已建立。'; $lang['regmailfail'] = '寄出密碼信似乎發生錯誤,請跟管理員聯絡!'; -$lang['regbadmail'] = '您輸入的 email 似乎不對,如果您認為是正確的,請與管理員聯絡。'; +$lang['regbadmail'] = '您輸入的電郵似乎不對,如果您認為是正確的,請與管理員聯絡。'; $lang['regbadpass'] = '兩次輸入的密碼不一致,請再試一次。'; $lang['regpwmail'] = '您的 DokuWiki 帳號密碼'; $lang['reghere'] = '您還沒有帳號嗎?註冊一個吧。'; -$lang['profna'] = '本維基不開放修改個人資料。'; -$lang['profnochange'] = '未做任何變更。'; +$lang['profna'] = '在本 wiki 上,不能修改個人資料。'; +$lang['profnochange'] = '並未作任何變更。'; $lang['profnoempty'] = '帳號或電郵地址不可空白!'; -$lang['profchanged'] = '個人資料已成功更新。'; +$lang['profchanged'] = '個人資料已更新。'; $lang['pwdforget'] = '忘記密碼了?索取新密碼!'; -$lang['resendna'] = '本維基不開放重寄密碼。'; +$lang['resendna'] = '本 wiki 並不支援重寄密碼。'; $lang['resendpwd'] = '設定新密碼供'; $lang['resendpwdmissing'] = '抱歉,您必須填寫所有欄位。'; $lang['resendpwdnouser'] = '抱歉,資料庫內找不到這個使用者。'; $lang['resendpwdbadauth'] = '抱歉,認證碼無效。請確認您使用了完整的確認連結。'; $lang['resendpwdconfirm'] = '確認連結已通過郵件發送給您了。'; $lang['resendpwdsuccess'] = '您的新密碼已寄出。'; -$lang['license'] = '若未特別註明,此維基上的內容都是採用以下授權方式:'; +$lang['license'] = '若無特別註明,本 wiki 上的內容都是採用以下授權方式:'; $lang['licenseok'] = '注意:編輯此頁面表示您已同意以下的授權方式:'; $lang['searchmedia'] = '搜尋檔名:'; $lang['searchmedia_in'] = '在 %s 裏搜尋'; $lang['txt_upload'] = '請選擇要上傳的檔案'; -$lang['txt_filename'] = '請輸入要存在維基內的檔案名稱 (非必要)'; +$lang['txt_filename'] = '請輸入要上傳至本 wiki 的檔案名稱 (非必要)'; $lang['txt_overwrt'] = '是否要覆蓋原有檔案'; $lang['maxuploadsize'] = '每個上傳檔案不可大於 %s 。'; $lang['lockedby'] = '目前已被下列人員鎖定'; @@ -135,7 +136,7 @@ $lang['js']['media_diff'] = '檢視差異:'; $lang['js']['media_diff_both'] = '並排'; $lang['js']['media_diff_opacity'] = '重疊'; $lang['js']['media_diff_portions'] = '滑動'; -$lang['js']['media_select'] = '選擇檔案…'; +$lang['js']['media_select'] = '選擇檔案……'; $lang['js']['media_upload_btn'] = '上傳'; $lang['js']['media_done_btn'] = '完成'; $lang['js']['media_drop'] = '拖拉檔案到此上傳'; @@ -145,27 +146,27 @@ $lang['rssfailed'] = '擷取 RSS 饋送檔時發生錯誤:'; $lang['nothingfound'] = '沒找到任何結果。'; $lang['mediaselect'] = '媒體檔案'; $lang['fileupload'] = '上傳媒體檔案'; -$lang['uploadsucc'] = '上傳成功'; -$lang['uploadfail'] = '上傳失敗。似乎是權限錯誤?'; +$lang['uploadsucc'] = '已上傳'; +$lang['uploadfail'] = '無法上傳。是否因權限錯誤?'; $lang['uploadwrong'] = '拒絕上傳。這個副檔名被禁止了!'; $lang['uploadexist'] = '檔案已存在,未處理。'; $lang['uploadbadcontent'] = '上傳檔案的內容不符合 %s 檔的副檔名。'; -$lang['uploadspam'] = '這次的上傳被垃圾訊息黑名單阻檔了。'; -$lang['uploadxss'] = '這次的上傳因可能的惡意的內容而被阻檔。'; -$lang['uploadsize'] = '上傳的檔案太大了 (最大:%s)'; +$lang['uploadspam'] = '是次上傳被垃圾訊息黑名單阻檔了。'; +$lang['uploadxss'] = '因可能含有惡意內容,是次上傳已被阻檔。'; +$lang['uploadsize'] = '上傳的檔案太大了 (最大為:%s)'; $lang['deletesucc'] = '檔案 "%s" 已刪除。'; $lang['deletefail'] = '檔案 "%s" 無法刪除,請檢查權限定。'; -$lang['mediainuse'] = '檔案 "%s" 未刪除,因為它正被使用。'; -$lang['namespaces'] = '分類空間'; +$lang['mediainuse'] = '檔案 "%s" 仍在使用,並未刪除。'; +$lang['namespaces'] = '分類名稱'; $lang['mediafiles'] = '可用的檔案有'; $lang['accessdenied'] = '您不可以檢視此頁面。'; $lang['mediausage'] = '使用以下的語法來連結此檔案:'; $lang['mediaview'] = '檢視原始檔案'; $lang['mediaroot'] = 'root'; -$lang['mediaupload'] = '上傳檔案至目前的分類空間。要建立子分類空間,將其名稱加在「上傳並重命名為」檔案名的前面,並用英文冒號隔開。'; +$lang['mediaupload'] = '上傳檔案至目前分類名稱之下。要建立子分類名稱,請將其名稱加在「上傳並重命名為」檔案名的前面,並用英文冒號隔開。'; $lang['mediaextchange'] = '檔案類型已由 .%s 變更為 .%s !'; $lang['reference'] = '引用到本頁的,合計有'; -$lang['ref_inuse'] = '此檔案無法刪除,因為它正被以下頁面使用:'; +$lang['ref_inuse'] = '此檔案無法刪除,因以下頁面正在使用它:'; $lang['ref_hidden'] = '一些參考內容位於您沒有讀取權限的頁面中'; $lang['hits'] = '個符合'; $lang['quickhits'] = '符合的頁面名稱'; @@ -175,12 +176,12 @@ $lang['yours'] = '您的版本'; $lang['diff'] = '顯示與目前版本的差異'; $lang['diff2'] = '顯示選擇版本間的差異'; $lang['difflink'] = '連向這個比對檢視'; -$lang['diff_type'] = '檢視差異:'; +$lang['diff_type'] = '檢視差異:'; $lang['diff_inline'] = '行內'; $lang['diff_side'] = '並排'; $lang['line'] = '行'; $lang['breadcrumb'] = '足跡'; -$lang['youarehere'] = '您在這裡'; +$lang['youarehere'] = '您在這裏'; $lang['lastmod'] = '上一次變更'; $lang['by'] = '由'; $lang['deleted'] = '移除'; @@ -188,17 +189,17 @@ $lang['created'] = '建立'; $lang['restored'] = '恢復為舊版'; $lang['external_edit'] = '外部編輯'; $lang['summary'] = '編輯摘要'; -$lang['noflash'] = '顯示此內容需要 Adobe Flash Plugin'; +$lang['noflash'] = '顯示此內容需要 Adobe Flash 附加元件。'; $lang['download'] = '下載程式碼片段'; $lang['tools'] = '工具'; -$lang['user_tools'] = '用戶工具'; +$lang['user_tools'] = '使用者工具'; $lang['site_tools'] = '網站工具'; $lang['page_tools'] = '頁面工具'; $lang['skip_to_content'] = '跳至內容'; $lang['sidebar'] = '側欄'; $lang['mail_newpage'] = '增加的頁面:'; $lang['mail_changed'] = '變更的頁面:'; -$lang['mail_subscribe_list'] = '分類空間中更動的頁面:'; +$lang['mail_subscribe_list'] = '分類名稱中變更的頁面:'; $lang['mail_new_user'] = '新使用者:'; $lang['mail_upload'] = '已上傳檔案:'; $lang['changes_type'] = '檢視最近更新類型'; @@ -229,10 +230,10 @@ $lang['qb_media'] = '加入圖片或檔案'; $lang['qb_sig'] = '插入簽名'; $lang['qb_smileys'] = '表情符號'; $lang['qb_chars'] = '特殊字元'; -$lang['upperns'] = '前往父分類空間'; +$lang['upperns'] = '前往父分類名稱'; $lang['admin_register'] = '新增使用者'; $lang['metaedit'] = '編輯後設資料'; -$lang['metasaveerr'] = '後設資料寫入失敗'; +$lang['metasaveerr'] = '後設資料無法寫入'; $lang['metasaveok'] = '後設資料已儲存'; $lang['img_backto'] = '回上一頁'; $lang['img_title'] = '標題'; @@ -253,9 +254,9 @@ $lang['subscr_subscribe_error'] = '將 %s 加入至 %s 的訂閱列表時發生 $lang['subscr_subscribe_noaddress'] = '沒有與您登入相關的地址,無法將您加入訂閱列表'; $lang['subscr_unsubscribe_success'] = '已將 %s 移除自 %s 的訂閱列表'; $lang['subscr_unsubscribe_error'] = '將 %s 移除自 %s 的訂閱列表時發生錯誤'; -$lang['subscr_already_subscribed'] = '%s 已經被 %s 訂閱了'; -$lang['subscr_not_subscribed'] = '%s 尚未被 %s 訂閱'; -$lang['subscr_m_not_subscribed'] = '您尚未訂閱目前的頁面或分類空間。'; +$lang['subscr_already_subscribed'] = '%s 已經獲 %s 訂閱了'; +$lang['subscr_not_subscribed'] = '%s 尚未獲 %s 訂閱'; +$lang['subscr_m_not_subscribed'] = '您尚未訂閱目前的頁面或分類名稱。'; $lang['subscr_m_new_header'] = '加入訂閱'; $lang['subscr_m_current_header'] = '目前訂閱'; $lang['subscr_m_unsubscribe'] = '取消訂閱'; @@ -264,34 +265,34 @@ $lang['subscr_m_receive'] = '接收'; $lang['subscr_style_every'] = '每次更改都發送信件'; $lang['subscr_style_digest'] = '對每個頁面發送更改的摘要信件 (每 %.2f 天)'; $lang['subscr_style_list'] = '自上次發信以來更改的頁面的列表 (每 %.2f 天)'; -$lang['authmodfailed'] = '帳號認證的設定不正確,請通知該維基管理員。'; -$lang['authtempfail'] = '帳號認證目前暫不提供,若本狀況持續發生的話,請通知該維基管理員。'; +$lang['authmodfailed'] = '帳號認證的設定不正確,請通知該本 wiki 管理員。'; +$lang['authtempfail'] = '帳號認證目前暫不提供。若本狀況持續,請通知本 wiki 管理員。'; $lang['authpwdexpire'] = '您的密碼將在 %d 天內到期,請馬上更換新密碼。'; $lang['i_chooselang'] = '選擇您的語系'; $lang['i_installer'] = 'DokuWiki 安裝工具'; -$lang['i_wikiname'] = '維基名稱'; +$lang['i_wikiname'] = '本 wiki 的名稱'; $lang['i_enableacl'] = '啟用 ACL (建議)'; -$lang['i_superuser'] = '超級用戶'; +$lang['i_superuser'] = '超級使用者'; $lang['i_problems'] = '安裝程式發現如下的問題。您必須修正它們才能繼續。'; $lang['i_modified'] = '出於安全考量,本腳本只能用於安裝全新且未修改的 Dokuwiki。 您可以重新解壓下載的封包或查閱完整的Dokuwiki 安裝指南'; $lang['i_funcna'] = 'PHP 函數 %s 無法使用。也許您的主機供應者基於某些理由停用了它?'; $lang['i_phpver'] = '您的 PHP 版本 %s 比需要的版本 %s 還低。您必須更新您的PHP。'; -$lang['i_permfail'] = '%s 無法被 DokuWiki 寫入。您必須修正該目錄的權限!'; +$lang['i_permfail'] = '%s 無法經由 DokuWiki 寫入。您必須修正該目錄的權限!'; $lang['i_confexists'] = '%s 已經存在'; $lang['i_writeerr'] = '無法建立 %s。您必須檢查目錄/檔案的權限並手動建立該檔案。'; -$lang['i_badhash'] = '無法辨識或被變更的 dokuwiki.php (hash=%s)'; -$lang['i_badval'] = '%s - 非法或空白的值'; -$lang['i_success'] = '設定已成功完成。您現在可以刪除 install.php 檔案。繼續到 -您的新 DokuWiki.'; -$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; +$lang['i_badhash'] = '無法辨識或已遭修改的 dokuwiki.php (hash=%s)'; +$lang['i_badval'] = '%s —— 非法或空白的值'; +$lang['i_success'] = '設定已完成。您現在可以刪除 install.php 檔案。繼續到 +您的新 DokuWiki.'; +$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; $lang['i_policy'] = '初步的 ACL 政策'; -$lang['i_pol0'] = '開放的維基 (任何人可讀取、寫入、上傳)'; -$lang['i_pol1'] = '公開的維基 (任何人可讀取,註冊使用者可寫入與上傳)'; -$lang['i_pol2'] = '封閉的維基 (只有註冊使用者可讀取、寫入、上傳)'; +$lang['i_pol0'] = '開放的 wiki (任何人可讀取、寫入、上傳)'; +$lang['i_pol1'] = '公開的 wiki (任何人可讀取,註冊使用者可寫入與上傳)'; +$lang['i_pol2'] = '封閉的 wiki (只有註冊使用者可讀取、寫入、上傳)'; $lang['i_retry'] = '重試'; $lang['i_license'] = '請選擇您想要的內容發布許可協議:'; -$lang['recent_global'] = '您正在閱讀分類空間: %s 中的變更。您亦可觀看整個維基的最近更新。'; +$lang['recent_global'] = '您正在閱讀分類名稱: %s 中的變更。您亦可觀看本 wiki 所有的最近更新。'; $lang['years'] = '%d 年前'; $lang['months'] = '%d 個月前'; $lang['weeks'] = '%d 週前'; @@ -299,7 +300,7 @@ $lang['days'] = '%d 天前'; $lang['hours'] = '%d 個小時前'; $lang['minutes'] = '%d 分鐘前'; $lang['seconds'] = '%s 秒鐘前'; -$lang['wordblock'] = '您的更改沒有被儲存,因为它包含被阻擋的文字 (垃圾訊息)。'; +$lang['wordblock'] = '無法儲存您的更改,因為它含有受阻擋的文字 (垃圾訊息)。'; $lang['media_uploadtab'] = '上傳'; $lang['media_searchtab'] = '搜尋'; $lang['media_file'] = '檔案'; @@ -310,7 +311,7 @@ $lang['media_list_thumbs'] = '縮圖'; $lang['media_list_rows'] = '列表'; $lang['media_sort_name'] = '名稱'; $lang['media_sort_date'] = '日期'; -$lang['media_namespaces'] = '選擇分類空間'; +$lang['media_namespaces'] = '選擇分類名稱'; $lang['media_files'] = '在 %s 中的檔案'; $lang['media_upload'] = '上傳至 %s'; $lang['media_search'] = '在 %s 中搜尋'; diff --git a/inc/lang/zh-tw/locked.txt b/inc/lang/zh-tw/locked.txt index e13fdc890..819e59e2f 100644 --- a/inc/lang/zh-tw/locked.txt +++ b/inc/lang/zh-tw/locked.txt @@ -1,3 +1,3 @@ ====== 頁面鎖定 ====== -本頁目前正由其他使用者編修中,您必須等他完成編輯或等鎖定時間過去。 +其他使用者正在編輯本頁,您必須等他完成編輯或等鎖定時間過去。 diff --git a/inc/lang/zh-tw/login.txt b/inc/lang/zh-tw/login.txt index 058cc5712..b82f08a20 100644 --- a/inc/lang/zh-tw/login.txt +++ b/inc/lang/zh-tw/login.txt @@ -1,5 +1,4 @@ ====== 登入 ====== -您尚未登入,請輸入您的使用者名稱和密碼。 另外,瀏覽器需要打開 cookies 設定以進行登入。 - +您尚未登入,請輸入您的使用者名稱和密碼。 另外,瀏覽器需要啟用 cookies 以登入本 wiki。 diff --git a/inc/lang/zh-tw/mailtext.txt b/inc/lang/zh-tw/mailtext.txt index 3b6ece377..2a402c2fb 100644 --- a/inc/lang/zh-tw/mailtext.txt +++ b/inc/lang/zh-tw/mailtext.txt @@ -2,7 +2,7 @@ 日期 : @DATE@ 瀏覽器 : @BROWSER@ -IP位址 : @IPADDRESS@ +IP 位址 : @IPADDRESS@ 主機名稱 : @HOSTNAME@ 舊版本 : @OLDPAGE@ 新版本 : @NEWPAGE@ diff --git a/inc/lang/zh-tw/norev.txt b/inc/lang/zh-tw/norev.txt index bd1c7a623..2a32ba6a8 100644 --- a/inc/lang/zh-tw/norev.txt +++ b/inc/lang/zh-tw/norev.txt @@ -1,3 +1,3 @@ ====== 無此版本 ====== -該版本的文件不存在。請用 「舊版」按鈕檢視該文件所有舊版本清單。 \ No newline at end of file +該版本的文件不存在。請用「舊版」按鈕檢視該文件所有舊版本清單。 \ No newline at end of file diff --git a/inc/lang/zh-tw/preview.txt b/inc/lang/zh-tw/preview.txt index c68f94819..95d4b10e1 100644 --- a/inc/lang/zh-tw/preview.txt +++ b/inc/lang/zh-tw/preview.txt @@ -1,4 +1,4 @@ ====== 預覽 ====== -以下是預覽該文件的狀態。請記住:**它還沒被儲存喔**! +以下是該文件的預覽。請記住:**您還未儲存它**! diff --git a/inc/lang/zh-tw/pwconfirm.txt b/inc/lang/zh-tw/pwconfirm.txt index 994367980..fb8a5cb82 100644 --- a/inc/lang/zh-tw/pwconfirm.txt +++ b/inc/lang/zh-tw/pwconfirm.txt @@ -1,13 +1,13 @@ @FULLNAME@ 您好! -有人為您在 @DOKUWIKIURL@ 註冊的使用者 @TITLE@ 請求新密碼 +感謝您在 @TITLE@ ( @DOKUWIKIURL@ ) 註冊了使用者帳號。我們收到請求,希望能允許此帳號使用新密碼。 -如果您沒有請求新密碼,請忽略這封郵件。 +如果您沒有發送此請求,請忽略這封郵件。 -要確認使用新密碼,請拜訪以下的連結。 +若您真的要使用新密碼,請拜訪以下的連結。 @CONFIRM@ -- 本信件由以下 DokuWiki 站台產生: -@DOKUWIKIURL@ +@DOKUWIKIURL@ \ No newline at end of file diff --git a/inc/lang/zh-tw/read.txt b/inc/lang/zh-tw/read.txt index a8305611f..4a472cd0d 100644 --- a/inc/lang/zh-tw/read.txt +++ b/inc/lang/zh-tw/read.txt @@ -1 +1 @@ -本頁是唯讀的,您可以看到原始碼,但不能更動它。您如果覺得這是誤判,請詢問管理員。 \ No newline at end of file +本頁是唯讀的,您可以看到原始碼,但不能更動它。您如果覺得它不應被鎖上,請詢問管理員。 \ No newline at end of file diff --git a/inc/lang/zh-tw/register.txt b/inc/lang/zh-tw/register.txt index 0da401ccd..3ff68dee3 100644 --- a/inc/lang/zh-tw/register.txt +++ b/inc/lang/zh-tw/register.txt @@ -1,4 +1,3 @@ ====== 註冊新使用者 ====== -填寫以下資料以註冊維基帳號,請確定您提供的是**合法的 email 地址**-如果這裡沒要求您填寫密碼,您的新密碼會自動產生並寄送到該地址。登錄名稱必須是合法的[[doku>pagename|頁面名稱]]。 - +若要註冊本 wiki 的帳號,請填寫下列資料。請確定您提供的是**合法的電郵地址**。如果您不必填寫密碼,系統就會為您自動產生登入密碼,並寄送到該電郵地址。登錄名稱須符合正確[[doku>pagename|頁面名稱]]之條件。 diff --git a/inc/lang/zh-tw/registermail.txt b/inc/lang/zh-tw/registermail.txt index 489e3f9d3..fb4951d60 100644 --- a/inc/lang/zh-tw/registermail.txt +++ b/inc/lang/zh-tw/registermail.txt @@ -2,11 +2,11 @@ 帳號 : @NEWUSER@ 姓名 : @NEWNAME@ -E-mail : @NEWEMAIL@ +電郵 : @NEWEMAIL@ 日期 : @DATE@ 瀏覽器 : @BROWSER@ -IP位址 : @IPADDRESS@ +IP 位址 : @IPADDRESS@ 主機名稱 : @HOSTNAME@ -- diff --git a/inc/lang/zh-tw/resendpwd.txt b/inc/lang/zh-tw/resendpwd.txt index 3dbfad750..46078a348 100644 --- a/inc/lang/zh-tw/resendpwd.txt +++ b/inc/lang/zh-tw/resendpwd.txt @@ -1,3 +1,3 @@ ====== 寄送新密碼 ====== -請在以下欄位輸入您的帳號,新密碼將會寄送到您註冊時填寫的 email 地址。 +請在以下欄位輸入您的帳號,新密碼將會寄送到您註冊時填寫的電郵地址。 \ No newline at end of file diff --git a/inc/lang/zh-tw/revisions.txt b/inc/lang/zh-tw/revisions.txt index 479705b95..4818839ac 100644 --- a/inc/lang/zh-tw/revisions.txt +++ b/inc/lang/zh-tw/revisions.txt @@ -1,3 +1,3 @@ ====== 舊版 ====== -以下是該文件的舊版本。如要恢復成某個舊版次,就點下它,然後按「編修本頁」,並存檔起來就可以了。 +以下是該文件的舊版本。如要恢復成某個舊版次,就點下它,然後按「編輯本頁」,並存檔起來就可以了。 diff --git a/inc/lang/zh-tw/stopwords.txt b/inc/lang/zh-tw/stopwords.txt index 55b67ed16..e549250bd 100644 --- a/inc/lang/zh-tw/stopwords.txt +++ b/inc/lang/zh-tw/stopwords.txt @@ -1,9 +1,9 @@ -# 這檔是製作索引檔(index)時不要列入的關鍵字,格式為每字(詞)就使用一行。 -# 在修改時,請注意要用 UNIX 格式的換行符號(newline)處理,而非 DOS 的 CR-LR 喔 -# (如果在 MS Windows 環境使用的話,可使用 vim win32版 或 UltraEdit或其他類似編輯器修改) +# 本清單列出製作索引檔 (index) 時不要列入的關鍵字,格式為每字 (詞) 佔一行。 +# 在修改本清單時,請注意要用 UNIX 格式的換行符號 (newline) 處理,而非 DOS 的 CR-LR 。 +# (如果在 MS Windows 環境使用的話,可使用 vim win32 版、 UltraEdit 或其他類似編輯器修改。) # -# 還有,不必把小於 3 個字元(英數字元)都包括進來。 -# 目前本清單的內容是以 http://www.ranks.nl/stopwords/ 為基礎而發展的。 +# 還有,不必把小於 3 個字元 (英數字元) 都包括進來。 +# 目前本清單的內容是以 http://www.ranks.nl/stopwords/ 為基礎,發展而成的。 about are and diff --git a/inc/lang/zh-tw/subscr_digest.txt b/inc/lang/zh-tw/subscr_digest.txt index a0f2be73e..a17a0551d 100644 --- a/inc/lang/zh-tw/subscr_digest.txt +++ b/inc/lang/zh-tw/subscr_digest.txt @@ -1,6 +1,6 @@ 您好! -維基 @TITLE@ 的頁面 @PAGE@ 已更改。 +本 wiki ( @TITLE@ ) 的頁面 @PAGE@ 已更改。 更改內容如下: -------------------------------------------------------- @@ -10,9 +10,9 @@ 舊版本:@OLDPAGE@ 新版本:@NEWPAGE@ -要取消頁面提醒,請登入維基 @DOKUWIKIURL@ +要取消頁面提醒,請登入本 wiki @DOKUWIKIURL@ 然後拜訪 @SUBSCRIBE@ -並取消訂閱頁面或分類空間的更改。 +並取消訂閱頁面或分類名稱的更改。 -- 本信件由以下 DokuWiki 站台產生: diff --git a/inc/lang/zh-tw/subscr_form.txt b/inc/lang/zh-tw/subscr_form.txt index 394d4cbad..ba3f16113 100644 --- a/inc/lang/zh-tw/subscr_form.txt +++ b/inc/lang/zh-tw/subscr_form.txt @@ -1,3 +1,3 @@ ====== 訂閱管理 ====== -這個頁面允許您管理在目前頁面和分類空間的訂閱。 \ No newline at end of file +在此頁裏,您可以管理在目前頁面及分類名稱之訂閱。 \ No newline at end of file diff --git a/inc/lang/zh-tw/subscr_list.txt b/inc/lang/zh-tw/subscr_list.txt index 078eae63e..ea82dd35d 100644 --- a/inc/lang/zh-tw/subscr_list.txt +++ b/inc/lang/zh-tw/subscr_list.txt @@ -1,15 +1,15 @@ 您好! -維基 @TITLE@ 的 @PAGE@ 分類空間的頁面已更改。 +本 wiki ( @TITLE@ ) 的 @PAGE@ 分類名稱頁面已更改。 更改內容如下: -------------------------------------------------------- @DIFF@ -------------------------------------------------------- -要取消頁面提醒,請登入維基 @DOKUWIKIURL@ +要取消頁面提醒,請登入本 wiki @DOKUWIKIURL@ 然後拜訪 @SUBSCRIBE@ -並取消訂閱頁面或分類空間的更改。 +並取消訂閱頁面或分類名稱的更改。 -- 本信件由以下 DokuWiki 站台產生: diff --git a/inc/lang/zh-tw/subscr_single.txt b/inc/lang/zh-tw/subscr_single.txt index 5128140d0..14d87bb73 100644 --- a/inc/lang/zh-tw/subscr_single.txt +++ b/inc/lang/zh-tw/subscr_single.txt @@ -1,6 +1,6 @@ 您好! -維基 @TITLE@ 的頁面 @PAGE@ 已更改。 +本 wiki ( @TITLE@ ) 的頁面 @PAGE@ 已更改。 更改內容如下: -------------------------------------------------------- @@ -13,9 +13,9 @@ 舊版本 : @OLDPAGE@ 新版本 : @NEWPAGE@ -要取消頁面提醒,請登入維基 @DOKUWIKIURL@ +要取消頁面提醒,請登入本 wiki @DOKUWIKIURL@ 然後拜訪 @NEWPAGE@ -並取消訂閱頁面或分類空間的更改。 +並取消訂閱頁面或分類名稱的更改。 -- 本信件由以下 DokuWiki 站台產生: diff --git a/inc/lang/zh-tw/updateprofile.txt b/inc/lang/zh-tw/updateprofile.txt index 47f2ae1c4..a7a2ad803 100644 --- a/inc/lang/zh-tw/updateprofile.txt +++ b/inc/lang/zh-tw/updateprofile.txt @@ -1,3 +1,3 @@ ====== 更新個人資料 ====== -您只需變更想更新的欄位就好,帳號名稱不能變更。 \ No newline at end of file +您只需修改想更新的欄位就好,帳號名稱不能變更。 \ No newline at end of file diff --git a/inc/lang/zh-tw/uploadmail.txt b/inc/lang/zh-tw/uploadmail.txt index b4c1311ba..87bac7c9a 100644 --- a/inc/lang/zh-tw/uploadmail.txt +++ b/inc/lang/zh-tw/uploadmail.txt @@ -3,7 +3,7 @@ 檔名 : @MEDIA@ 日期 : @DATE@ 瀏覽器 : @BROWSER@ -IP位址 : @IPADDRESS@ +IP 位址 : @IPADDRESS@ 主機名稱 : @HOSTNAME@ 大小 : @SIZE@ MIME類型 : @MIME@ @@ -11,4 +11,4 @@ MIME類型 : @MIME@ -- 本信件由以下 DokuWiki 站台產生: -@DOKUWIKIURL@ +@DOKUWIKIURL@ \ No newline at end of file -- cgit v1.2.3 From ffb060ea6b02211074dfc314f8651936065b3f7f Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 9 Jan 2013 21:09:42 +0100 Subject: show filesize of local file links in tooltip --- inc/parser/xhtml.php | 1 + 1 file changed, 1 insertion(+) (limited to 'inc') diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 68b92ca43..71f3aa4bf 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -803,6 +803,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); $link['class'] .= ' mediafile mf_'.$class; $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),true); + $link['title'] .= ' (' . filesize_h(filesize(mediaFN($src))).')'; } if($hash) $link['url'] .= '#'.$hash; -- cgit v1.2.3 From c647387e09a52c1a67a72b8923ca4de06f8555cf Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Wed, 9 Jan 2013 22:26:22 +0100 Subject: Check search limit depth with an inequality Otherwise, when we check for equality, the test fails if the search start beneath the max depth. Eg: if I have the page ns1:ns2:mypage in my wiki, and launch the xmlrpc query getPagelist("ns1", "depth => 1"), without this patch, it retrieves mypage --- inc/search.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'inc') diff --git a/inc/search.php b/inc/search.php index 1cecfd5ec..e18777063 100644 --- a/inc/search.php +++ b/inc/search.php @@ -247,11 +247,16 @@ function search_pagename(&$data,$base,$file,$type,$lvl,$opts){ * @author Andreas Gohr */ function search_allpages(&$data,$base,$file,$type,$lvl,$opts){ + if(isset($opts['depth'])){ + $parts = explode('/',ltrim($file,'/')); + if(($type == 'd' && count($parts) > $opts['depth']) + || ($type != 'd' && count($parts) > $opts['depth'] + 1)){ + return false; // depth reached + } + } + //we do nothing with directories if($type == 'd'){ - if(!$opts['depth']) return true; // recurse forever - $parts = explode('/',ltrim($file,'/')); - if(count($parts) == $opts['depth']) return false; // depth reached return true; } -- cgit v1.2.3 From 8451f4ad87cd104e80eb42532adebd7b2882e62e Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Thu, 10 Jan 2013 22:55:43 +0100 Subject: If depth option is set to 0, we should recurse forever At least if we want to be consistent with search_universal --- inc/search.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/search.php b/inc/search.php index e18777063..53bd240e8 100644 --- a/inc/search.php +++ b/inc/search.php @@ -247,7 +247,7 @@ function search_pagename(&$data,$base,$file,$type,$lvl,$opts){ * @author Andreas Gohr */ function search_allpages(&$data,$base,$file,$type,$lvl,$opts){ - if(isset($opts['depth'])){ + if(isset($opts['depth']) && $opts['depth']){ $parts = explode('/',ltrim($file,'/')); if(($type == 'd' && count($parts) > $opts['depth']) || ($type != 'd' && count($parts) > $opts['depth'] + 1)){ -- cgit v1.2.3 From f8591821bac23569788706524f8d6b14bd73775c Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Thu, 10 Jan 2013 08:02:26 +0100 Subject: Don't remove page version from result if uneeded It may happen when the page has few versions --- inc/RemoteAPICore.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index c04a14f5c..fef0b81dd 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -654,7 +654,9 @@ class RemoteAPICore { if(count($revisions)>0 && $first==0) { array_unshift($revisions, ''); // include current revision - array_pop($revisions); // remove extra log entry + if ( count($revisions) > $conf['recent'] ){ + array_pop($revisions); // remove extra log entry + } } if(count($revisions) > $conf['recent']) { -- cgit v1.2.3 From 187b13eb2e4f044659ad056a038b7aed65033579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Prat?= Date: Fri, 18 Jan 2013 10:07:50 +0100 Subject: Catalan language update --- inc/lang/ca/lang.php | 129 +++++++++++++++++++++++++++++++++++------- inc/lang/ca/mailwrap.html | 13 +++++ inc/lang/ca/resetpwd.txt | 3 + inc/lang/ca/subscr_digest.txt | 21 +++++++ inc/lang/ca/subscr_form.txt | 3 + inc/lang/ca/subscr_list.txt | 21 +++++++ 6 files changed, 171 insertions(+), 19 deletions(-) create mode 100644 inc/lang/ca/mailwrap.html create mode 100644 inc/lang/ca/resetpwd.txt create mode 100644 inc/lang/ca/subscr_digest.txt create mode 100644 inc/lang/ca/subscr_form.txt create mode 100644 inc/lang/ca/subscr_list.txt (limited to 'inc') diff --git a/inc/lang/ca/lang.php b/inc/lang/ca/lang.php index 0fd88ec39..cb2b64686 100644 --- a/inc/lang/ca/lang.php +++ b/inc/lang/ca/lang.php @@ -5,6 +5,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Carles Bellver * @author Carles Bellver + * @author daniel@6temes.cat */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -27,7 +28,7 @@ $lang['btn_revs'] = 'Revisions anteriors'; $lang['btn_recent'] = 'Canvis recents'; $lang['btn_upload'] = 'Penja'; $lang['btn_cancel'] = 'Cancel·la'; -$lang['btn_index'] = 'Índex'; +$lang['btn_index'] = 'Mapa del lloc'; $lang['btn_secedit'] = 'Edita'; $lang['btn_login'] = 'Entra'; $lang['btn_logout'] = 'Surt'; @@ -38,14 +39,15 @@ $lang['btn_back'] = 'Enrere'; $lang['btn_backlink'] = 'Què hi enllaça'; $lang['btn_backtomedia'] = 'Torna a la selecció de fitxers'; $lang['btn_subscribe'] = 'Subscripció a canvis d\'aquesta pàgina'; -$lang['btn_unsubscribe'] = 'Cancel·la subscripció a pàgina'; $lang['btn_profile'] = 'Actualització del perfil'; $lang['btn_reset'] = 'Reinicia'; +$lang['btn_resendpwd'] = 'Estableix una nova contrasenya'; $lang['btn_draft'] = 'Edita esborrany'; $lang['btn_recover'] = 'Recupera esborrany'; $lang['btn_draftdel'] = 'Suprimeix esborrany'; $lang['btn_revert'] = 'Restaura'; $lang['btn_register'] = 'Registra\'m'; +$lang['btn_apply'] = 'Aplica'; $lang['loggedinas'] = 'Heu entrat com'; $lang['user'] = 'Nom d\'usuari'; $lang['pass'] = 'Contrasenya'; @@ -75,6 +77,7 @@ $lang['profnoempty'] = 'No es pot deixar en blanc el nom o l\'adreça $lang['profchanged'] = 'El perfil d\'usuari s\'ha actualitzat correctament.'; $lang['pwdforget'] = 'Heu oblidat la contrasenya? Podeu obtenir-ne una de nova.'; $lang['resendna'] = 'Aquest wiki no permet tornar a enviar la contrasenya.'; +$lang['resendpwd'] = 'Estableix una nova contrasenya per'; $lang['resendpwdmissing'] = 'Heu d\'emplenar tots els camps.'; $lang['resendpwdnouser'] = 'No s\'ha pogut trobar aquest usuari a la base de dades.'; $lang['resendpwdbadauth'] = 'Aquest codi d\'autenticació no és vàlid. Assegureu-vos d\'utilitzar l\'enllaç de confirmació complet.'; @@ -87,10 +90,52 @@ $lang['searchmedia_in'] = 'Cerca en: %s'; $lang['txt_upload'] = 'Trieu el fitxer que voleu penjar'; $lang['txt_filename'] = 'Introduïu el nom wiki (opcional)'; $lang['txt_overwrt'] = 'Sobreescriu el fitxer actual'; +$lang['maxuploadsize'] = 'Puja com a màxim %s per arxiu.'; $lang['lockedby'] = 'Actualment blocat per:'; $lang['lockexpire'] = 'Venciment del blocatge:'; -$lang['js']['willexpire'] = 'El blocatge per a editar aquesta pàgina venç d\'aquí a un minut.\nUtilitzeu la visualització prèvia per reiniciar el rellotge i evitar conflictes.'; -$lang['js']['notsavedyet'] = "Heu fet canvis que es perdran si no els deseu.\nVoleu continuar?"; +$lang['js']['willexpire'] = 'El blocatge per a editar aquesta pàgina venç d\'aquí a un minut.\nUtilitzeu la visualització prèvia per reiniciar el rellotge i evitar conflictes.'; +$lang['js']['notsavedyet'] = 'Heu fet canvis que es perdran si no els deseu. +Voleu continuar?'; +$lang['js']['searchmedia'] = 'Cerca fitxers'; +$lang['js']['keepopen'] = 'Manté la finestra oberta'; +$lang['js']['hidedetails'] = 'Oculta detalls'; +$lang['js']['mediatitle'] = 'Propietats de l\'enllaç'; +$lang['js']['mediadisplay'] = 'Tipus d\'enllaç'; +$lang['js']['mediaalign'] = 'Alineació'; +$lang['js']['mediasize'] = 'Mida de la imatge'; +$lang['js']['mediatarget'] = 'Destí de l\'enllaç'; +$lang['js']['mediaclose'] = 'Tanca'; +$lang['js']['mediainsert'] = 'Inserta'; +$lang['js']['mediadisplayimg'] = 'Mostra la imatge'; +$lang['js']['mediadisplaylnk'] = 'Mostra només l\'enllaç'; +$lang['js']['mediasmall'] = 'Versió petita'; +$lang['js']['mediamedium'] = 'Versió mitjana'; +$lang['js']['medialarge'] = 'Versió gran'; +$lang['js']['mediaoriginal'] = 'Versió original'; +$lang['js']['medialnk'] = 'Enllaç a la pàgina de detalls'; +$lang['js']['mediadirect'] = 'Enllaç directe a l\'original'; +$lang['js']['medianolnk'] = 'No hi ha enllaç'; +$lang['js']['medianolink'] = 'No enllacis la imatge'; +$lang['js']['medialeft'] = 'Alinea la imatge a l\'esquerra.'; +$lang['js']['mediaright'] = 'Alinea la imatge a la dreta.'; +$lang['js']['mediacenter'] = 'Alinea la imatge al mig.'; +$lang['js']['medianoalign'] = 'No facis servir alineació.'; +$lang['js']['nosmblinks'] = 'Els enllaços amb recursos compartits de Windows només funcionen amb el Microsoft Internet Explorer. +Si voleu podeu copiar i enganxar l\'enllaç.'; +$lang['js']['linkwiz'] = 'Auxiliar d\'enllaços'; +$lang['js']['linkto'] = 'Enllaça a:'; +$lang['js']['del_confirm'] = 'Suprimiu aquesta entrada?'; +$lang['js']['restore_confirm'] = 'Vols realment restaurar aquesta versió?'; +$lang['js']['media_diff'] = 'Veure les diferències:'; +$lang['js']['media_diff_both'] = 'Un al costat de l\'altre'; +$lang['js']['media_diff_opacity'] = 'Resalta'; +$lang['js']['media_diff_portions'] = 'Llisca'; +$lang['js']['media_select'] = 'Escull els arxius'; +$lang['js']['media_upload_btn'] = 'Pujar'; +$lang['js']['media_done_btn'] = 'Fet'; +$lang['js']['media_drop'] = 'Arrossega aquí els arxius a pujar'; +$lang['js']['media_cancel'] = 'esborra'; +$lang['js']['media_overwrt'] = 'Sobreescriu els arxius existents'; $lang['rssfailed'] = 'S\'ha produït un error en recollir aquesta alimentació: '; $lang['nothingfound'] = 'No s\'ha trobat res.'; $lang['mediaselect'] = 'Selecció de fitxers'; @@ -108,14 +153,7 @@ $lang['deletefail'] = 'No s\'ha pogut suprimir el fitxer "%s". Compro $lang['mediainuse'] = 'No s\'ha pogut suprimir el fitxer "%s". Encara s\'està utilitzant.'; $lang['namespaces'] = 'Espais'; $lang['mediafiles'] = 'Fitxers disponibles en'; -$lang['js']['searchmedia'] = 'Cerca fitxers'; -$lang['js']['keepopen'] = 'Manté la finestra oberta'; -$lang['js']['hidedetails'] = 'Oculta detalls'; -$lang['js']['nosmblinks'] = 'Els enllaços amb recursos compartits de Windows només funcionen amb el Microsoft Internet Explorer. -Si voleu podeu copiar i enganxar l\'enllaç.'; -$lang['js']['linkwiz'] = 'Auxiliar d\'enllaços'; -$lang['js']['linkto'] = 'Enllaça a:'; -$lang['js']['del_confirm'] = 'Suprimiu aquesta entrada?'; +$lang['accessdenied'] = 'No teniu permís per a veure aquesta pàgina.'; $lang['mediausage'] = 'Utilitzeu la sintaxi següent per referir-vos a aquest enllaç:'; $lang['mediaview'] = 'Mostra el fitxer original'; $lang['mediaroot'] = 'arrel'; @@ -131,6 +169,10 @@ $lang['current'] = 'actual'; $lang['yours'] = 'La vostra versió'; $lang['diff'] = 'Mostra diferències amb la versió actual'; $lang['diff2'] = 'Mostra diferències entre les revisions seleccionades'; +$lang['difflink'] = 'Enllaç a la visualització de la comparació'; +$lang['diff_type'] = 'Veieu les diferències:'; +$lang['diff_inline'] = 'En línia'; +$lang['diff_side'] = 'Un al costat de l\'altre'; $lang['line'] = 'Línia'; $lang['breadcrumb'] = 'Camí'; $lang['youarehere'] = 'Sou aquí'; @@ -143,10 +185,20 @@ $lang['external_edit'] = 'edició externa'; $lang['summary'] = 'Resum d\'edició'; $lang['noflash'] = 'Per a visualitzar aquest contingut necessiteu el connector d\'Adobe Flash.'; $lang['download'] = 'Baixa el fragment'; +$lang['tools'] = 'Eines'; +$lang['user_tools'] = 'Eines de l\'usuari'; +$lang['site_tools'] = 'Eines del lloc'; +$lang['page_tools'] = 'Eines de la pàgina'; +$lang['skip_to_content'] = 'salta al contingut'; +$lang['sidebar'] = 'Barra lateral'; $lang['mail_newpage'] = 'pàgina afegida:'; $lang['mail_changed'] = 'pàgina modificada:'; $lang['mail_new_user'] = 'nou usuari:'; $lang['mail_upload'] = 'fitxer penjat:'; +$lang['changes_type'] = 'Veure els canvis de'; +$lang['pages_changes'] = 'Pàgines'; +$lang['media_changes'] = 'Arxius gràfics'; +$lang['both_changes'] = 'Pàgines i arxius gràfics'; $lang['qb_bold'] = 'Negreta'; $lang['qb_italic'] = 'Cursiva'; $lang['qb_underl'] = 'Subratllat'; @@ -187,13 +239,27 @@ $lang['img_copyr'] = 'Copyright'; $lang['img_format'] = 'Format'; $lang['img_camera'] = 'Càmera'; $lang['img_keywords'] = 'Paraules clau'; -$lang['subscribe_success'] = 'S\'ha afegit %s a la llista de subscripcions de %s'; -$lang['subscribe_error'] = 'S\'ha produït un error en afegir %s a la llista de subscripcions de %s'; -$lang['subscribe_noaddress'] = 'No hi ha cap adreça de correu associada al vostre nom d\'usuari. No se us ha pogut afegir a la llista de subscripcions.'; -$lang['unsubscribe_success'] = '%s ha estat suprimit de la llista de subscripcions de %s'; -$lang['unsubscribe_error'] = 'S\'ha produït un error en suprimir %s de la llista de subscripcions de %s'; +$lang['img_width'] = 'Ample'; +$lang['img_height'] = 'Alçada'; +$lang['subscr_subscribe_success'] = 'S\'ha afegit %s a la llista de subscripcions per %s'; +$lang['subscr_subscribe_error'] = 'Hi ha hagut un error a l\'afegir %s a la llista per %s'; +$lang['subscr_subscribe_noaddress'] = 'No hi ha cap adreça associada pel vostre nom d\'usuari, no podeu ser afegit a la llista de subscripcions'; +$lang['subscr_unsubscribe_success'] = 'S\'ha esborrat %s de la llista de subscripcions per %s'; +$lang['subscr_unsubscribe_error'] = 'Hi ha hagut un error a l\'esborrar %s de la llista de subscripcions per %s'; +$lang['subscr_already_subscribed'] = '%s ja està subscrit a %s'; +$lang['subscr_not_subscribed'] = '%s no està subscrit a %s'; +$lang['subscr_m_not_subscribed'] = 'En aquests moments no esteu subscrit a l\'actual pàgina o espai'; +$lang['subscr_m_new_header'] = 'Afegeix subcripció'; +$lang['subscr_m_current_header'] = 'Subscripcions actuals'; +$lang['subscr_m_unsubscribe'] = 'Donar-se de baixa'; +$lang['subscr_m_subscribe'] = 'Donar-se d\'alta'; +$lang['subscr_m_receive'] = 'Rebre'; +$lang['subscr_style_every'] = 'Envia\'m un correu electrònic per a cada canvi'; +$lang['subscr_style_digest'] = 'Envia\'m un correu electrònic amb un resum dels canvis per a cada pàgina (cada %.2f dies)'; +$lang['subscr_style_list'] = 'llistat de pàgines canviades des de l\'últim correu electrònic (cada %.2f dies)'; $lang['authmodfailed'] = 'La configuració de l\'autenticació d\'usuaris és errònia. Informeu els administradors del wiki.'; $lang['authtempfail'] = 'L\'autenticació d\'usuaris no està disponible temporalment. Si aquesta situació persisteix, si us plau informeu els administradors del wiki.'; +$lang['authpwdexpire'] = 'La vostra contrasenya caducarà en %d dies, l\'hauríeu de canviar aviat.'; $lang['i_chooselang'] = 'Trieu l\'idioma'; $lang['i_installer'] = 'Instal·lador de DokuWiki'; $lang['i_wikiname'] = 'Nom del wiki'; @@ -208,13 +274,14 @@ $lang['i_confexists'] = '%s ja existeix'; $lang['i_writeerr'] = 'No es pot crear %s. Comproveu els permisos del directori i/o del fitxer i creeu el fitxer manualment.'; $lang['i_badhash'] = 'dokuwiki.php no reconegut o modificat (hash=%s)'; $lang['i_badval'] = '%s - valor il·legal o buit'; -$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; -$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; +$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; +$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; $lang['i_policy'] = 'Política ACL inicial'; $lang['i_pol0'] = 'Wiki obert (tothom pot llegir, escriure i penjar fitxers)'; $lang['i_pol1'] = 'Wiki públic (tothom pot llegir, els usuaris registrats poden escriure i penjar fitxers)'; $lang['i_pol2'] = 'Wiki tancat (només els usuaris registrats poden llegir, escriure i penjar fitxers)'; $lang['i_retry'] = 'Reintenta'; +$lang['i_license'] = 'Escolliu el tipus de llicència que voleu fer servir per al vostre contingut:'; $lang['recent_global'] = 'Esteu veient els canvis recents de l\'espai %s. També podeu veure els canvis recents de tot el wiki.'; $lang['years'] = 'fa %d anys'; $lang['months'] = 'fa %d mesos'; @@ -223,3 +290,27 @@ $lang['days'] = 'fa %d dies'; $lang['hours'] = 'fa %d hores'; $lang['minutes'] = 'fa %d minuts'; $lang['seconds'] = 'fa %d segons'; +$lang['wordblock'] = 'El vostre canvi no s\'ha guardat perquè conté text blocat (spam)'; +$lang['media_uploadtab'] = 'Puja'; +$lang['media_searchtab'] = 'Busca'; +$lang['media_file'] = 'Fitxer'; +$lang['media_viewtab'] = 'Mostra'; +$lang['media_edittab'] = 'Edita'; +$lang['media_historytab'] = 'Històric'; +$lang['media_list_thumbs'] = 'Miniatura'; +$lang['media_list_rows'] = 'Files'; +$lang['media_sort_name'] = 'Nom'; +$lang['media_sort_date'] = 'Data'; +$lang['media_namespaces'] = 'Escolliu l\'espai'; +$lang['media_files'] = 'Arxius a %s'; +$lang['media_upload'] = 'Puja a %s'; +$lang['media_search'] = 'Busca a %s'; +$lang['media_view'] = '%s'; +$lang['media_viewold'] = '%s a %s'; +$lang['media_edit'] = 'Edita %s'; +$lang['media_history'] = 'Històric de %s'; +$lang['media_meta_edited'] = 'metadata editada'; +$lang['media_perm_read'] = 'No teniu permisos suficients per a llegir arxius.'; +$lang['media_perm_upload'] = 'No teniu permisos suficients per a pujar arxius'; +$lang['media_update'] = 'Puja la nova versió'; +$lang['media_restore'] = 'Restaura aquesta versió'; diff --git a/inc/lang/ca/mailwrap.html b/inc/lang/ca/mailwrap.html new file mode 100644 index 000000000..ed3bb6e9d --- /dev/null +++ b/inc/lang/ca/mailwrap.html @@ -0,0 +1,13 @@ + + +@TITLE@ + + + + +@HTMLBODY@ + +

    +Aquest correu electrònic ha estat generat per DokuWiki a @DOKUWIKIURL@. + + \ No newline at end of file diff --git a/inc/lang/ca/resetpwd.txt b/inc/lang/ca/resetpwd.txt new file mode 100644 index 000000000..565f1d5b0 --- /dev/null +++ b/inc/lang/ca/resetpwd.txt @@ -0,0 +1,3 @@ +===== Establiu una nova contrasenya ===== + +Introdueixi una nova contrasenya pel seu compte a aquest wiki. \ No newline at end of file diff --git a/inc/lang/ca/subscr_digest.txt b/inc/lang/ca/subscr_digest.txt new file mode 100644 index 000000000..2b95f97a5 --- /dev/null +++ b/inc/lang/ca/subscr_digest.txt @@ -0,0 +1,21 @@ +Hola! + +La pàgina @PAGE@ al wiki @TITLE@ ha canviat. +A continuació podeu veure els canvis: + +-------------------------------------------------------- +@DIFF@ +-------------------------------------------------------- + +Versió anterior: @OLDPAGE@ +Nova versió: @NEWPAGE@ + +Si voleu cancel·lar les notificacions per a la pàgina, accediu al wiki a +@DOKUWIKIURL@, visiteu +@SUBSCRIBE@ +i doneu-vos de baixa dels canvis de la pàgina o de l'espai. + + +-- +Aquest mail ha estat generat per DokuWiki a +@DOKUWIKIURL@ \ No newline at end of file diff --git a/inc/lang/ca/subscr_form.txt b/inc/lang/ca/subscr_form.txt new file mode 100644 index 000000000..d3679454f --- /dev/null +++ b/inc/lang/ca/subscr_form.txt @@ -0,0 +1,3 @@ +===== Gestió de les Subscripcions ===== + +Aquesta pàgina podeu gestiona les vostres subscripcions per a les pàgines i els espais actuals. \ No newline at end of file diff --git a/inc/lang/ca/subscr_list.txt b/inc/lang/ca/subscr_list.txt new file mode 100644 index 000000000..56bcad545 --- /dev/null +++ b/inc/lang/ca/subscr_list.txt @@ -0,0 +1,21 @@ +Hola! + +Alguna(es) pàgina(es) de l'espai @PAGE@ al wiki @TITLE@ han canviat. +A continuació podeu veure els canvis: + +-------------------------------------------------------- +@DIFF@ +-------------------------------------------------------- + +Versió anterior: @OLDPAGE@ +Nova versió: @NEWPAGE@ + +Si voleu cancel·lar les notificacions per a la pàgina, accediu al wiki a +@DOKUWIKIURL@, visiteu +@SUBSCRIBE@ +i doneu-vos de baixa dels canvis de la pàgina o de l'espai. + + +-- +Aquest mail ha estat generat per DokuWiki a +@DOKUWIKIURL@ \ No newline at end of file -- cgit v1.2.3 From e6c4a8221e93692572a1e78b9319a94b5ba07a0c Mon Sep 17 00:00:00 2001 From: Erdem Date: Fri, 18 Jan 2013 10:08:48 +0100 Subject: Turkish language update --- inc/lang/tr/lang.php | 55 +++++++++++++++++++++++++++++++++++++++++++++--- inc/lang/tr/resetpwd.txt | 3 +++ 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 inc/lang/tr/resetpwd.txt (limited to 'inc') diff --git a/inc/lang/tr/lang.php b/inc/lang/tr/lang.php index a8d8c5ac9..5430905b1 100644 --- a/inc/lang/tr/lang.php +++ b/inc/lang/tr/lang.php @@ -8,6 +8,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -43,11 +44,14 @@ $lang['btn_backtomedia'] = 'Çokluortam dosyası seçimine dön'; $lang['btn_subscribe'] = 'Sayfa Değişikliklerini Bildir'; $lang['btn_profile'] = 'Kullanıcı Bilgilerini Güncelle'; $lang['btn_reset'] = 'Sıfırla'; +$lang['btn_resendpwd'] = 'Yeni şifre belirle'; $lang['btn_draft'] = 'Taslağı düzenle'; $lang['btn_recover'] = 'Taslağı geri yükle'; $lang['btn_draftdel'] = 'Taslağı sil'; $lang['btn_revert'] = 'Geri Yükle'; $lang['btn_register'] = 'Kayıt ol'; +$lang['btn_apply'] = 'Uygula'; +$lang['btn_media'] = 'Çokluortam Yöneticisi'; $lang['loggedinas'] = 'Giriş ismi'; $lang['user'] = 'Kullanıcı ismi'; $lang['pass'] = 'Parola'; @@ -77,6 +81,7 @@ $lang['profnoempty'] = 'Boş isim veya e-posta adresine izin verilmiyo $lang['profchanged'] = 'Kullanıcı bilgileri başarıyla değiştirildi.'; $lang['pwdforget'] = 'Parolanızı mı unuttunuz? Yeni bir parola alın'; $lang['resendna'] = 'Bu wiki parolayı tekrar göndermeyi desteklememektedir.'; +$lang['resendpwd'] = 'İçin yeni şifre belirle'; $lang['resendpwdmissing'] = 'Üzgünüz, tüm alanları doldurmalısınız.'; $lang['resendpwdnouser'] = 'Üzgünüz, veritabanımızda bu kullanıcıyı bulamadık.'; $lang['resendpwdbadauth'] = 'Üzgünüz, bu doğrulama kodu doğru değil. Doğrulama linkini tam olarak kullandığınıza emin olun.'; @@ -91,7 +96,7 @@ $lang['txt_filename'] = 'Dosya adı (zorunlu değil)'; $lang['txt_overwrt'] = 'Mevcut dosyanın üstüne yaz'; $lang['lockedby'] = 'Şu an şunun tarafından kilitli:'; $lang['lockexpire'] = 'Kilitin açılma tarihi:'; -$lang['js']['willexpire'] = 'Bu sayfayı değiştirme kilidinin süresi yaklaşık bir dakika içinde geçecek.\nÇakışmaları önlemek için önizleme tuşunu kullanarak kilit sayacını sıfırla.'; +$lang['js']['willexpire'] = 'Bu sayfayı değiştirme kilidinin süresi yaklaşık bir dakika içinde geçecek.\nÇakışmaları önlemek için önizleme tuşunu kullanarak kilit sayacını sıfırla.'; $lang['js']['notsavedyet'] = 'Kaydedilmemiş değişiklikler kaybolacak. Devam etmek istiyor musunuz?'; $lang['js']['searchmedia'] = 'Dosyalar için Ara'; @@ -122,6 +127,14 @@ $lang['js']['nosmblinks'] = 'Windows paylaşımı sadece Microsoft Internet $lang['js']['linkwiz'] = 'Bağlantı sihirbazı'; $lang['js']['linkto'] = 'Bağlantı:'; $lang['js']['del_confirm'] = 'Bu girişi sil?'; +$lang['js']['restore_confirm'] = 'Bu sürüme geri dönmek istediğinizden emin misiniz?'; +$lang['js']['media_diff'] = 'Farkları gör:'; +$lang['js']['media_select'] = 'Dosyalar seç...'; +$lang['js']['media_upload_btn'] = 'Yükle'; +$lang['js']['media_done_btn'] = 'Bitti'; +$lang['js']['media_drop'] = 'Yüklemek istediğiniz dosyaları buraya bırakın'; +$lang['js']['media_cancel'] = 'kaldır'; +$lang['js']['media_overwrt'] = 'Var olan dosyaların üzerine yaz'; $lang['rssfailed'] = 'Bu beslemeyi çekerken hata oluştu: '; $lang['nothingfound'] = 'Hiçbir şey yok.'; $lang['mediaselect'] = 'Çokluortam dosyası seçimi'; @@ -172,6 +185,9 @@ $lang['mail_newpage'] = 'sayfa eklenme:'; $lang['mail_changed'] = 'sayfa değiştirilme:'; $lang['mail_new_user'] = 'yeni kullanıcı'; $lang['mail_upload'] = 'dosya yüklendi:'; +$lang['pages_changes'] = 'Sayfalar'; +$lang['media_changes'] = 'Çokluortam dosyaları'; +$lang['both_changes'] = 'Sayfalar ve çoklu ortam dosyaları'; $lang['qb_bold'] = 'Kalın Yazı'; $lang['qb_italic'] = 'Eğik Yazı'; $lang['qb_underl'] = 'Altı Çizgili Yazı'; @@ -209,8 +225,14 @@ $lang['img_copyr'] = 'Telif Hakkı'; $lang['img_format'] = 'Biçim'; $lang['img_camera'] = 'Fotoğraf Makinası'; $lang['img_keywords'] = 'Anahtar Sözcükler'; +$lang['img_width'] = 'Genişlik'; +$lang['img_height'] = 'Yükseklik'; +$lang['img_manager'] = 'Ortam oynatıcısında göster'; +$lang['subscr_m_subscribe'] = 'Kayıt ol'; +$lang['subscr_m_receive'] = 'Al'; $lang['authmodfailed'] = 'Yanlış kullanıcı onaylama ayarı. Lütfen Wiki yöneticisine bildiriniz.'; $lang['authtempfail'] = 'Kullanıcı doğrulama geçici olarak yapılamıyor. Eğer bu durum devam ederse lütfen Wiki yöneticine haber veriniz.'; +$lang['authpwdexpire'] = 'Şifreniz %d gün sonra geçersiz hale gelecek, yakın bir zamanda değiştirmelisiniz.'; $lang['i_chooselang'] = 'Dili seçiniz'; $lang['i_installer'] = 'Dokuwiki Kurulum Sihirbazı'; $lang['i_wikiname'] = 'Wiki Adı'; @@ -225,11 +247,38 @@ $lang['i_confexists'] = '%s zaten var'; $lang['i_writeerr'] = '%s oluşturulamadı. Dosya/Klasör izin ayarlarını gözden geçirip dosyayı elle oluşturmalısınız.'; $lang['i_badhash'] = 'dokuwiki.php tanınamadı ya da değiştirilmiş (hash=%s)'; $lang['i_badval'] = '%s - Yanlış veya boş değer'; -$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; -$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; +$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; +$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; $lang['i_policy'] = 'İlk ACL ayarı'; $lang['i_pol0'] = 'Tamamen Açık Wiki (herkes okuyabilir, yazabilir ve dosya yükleyebilir)'; $lang['i_pol1'] = 'Açık Wiki (herkes okuyabilir, ancak sadece üye olanlar yazabilir ve dosya yükleyebilir)'; $lang['i_pol2'] = 'Kapalı Wiki (sadece üye olanlar okuyabilir, yazabilir ve dosya yükleyebilir)'; $lang['i_retry'] = 'Tekrar Dene'; +$lang['i_license'] = 'Lütfen içeriği hangi lisans altında yayınlamak istediğniizi belirtin:'; $lang['recent_global'] = '%s namespace\'i içerisinde yapılan değişiklikleri görüntülemektesiniz. Wiki\'deki tüm değişiklikleri de bu adresten görebilirsiniz. '; +$lang['years'] = '%d yıl önce'; +$lang['months'] = '%d ay önce'; +$lang['weeks'] = '%d hafta önce'; +$lang['days'] = '%d gün önce'; +$lang['hours'] = '%d saat önce'; +$lang['minutes'] = '%d dakika önce'; +$lang['seconds'] = '%d saniye önce'; +$lang['wordblock'] = 'Değişikliğiniz kaydedilmedi çünkü istenmeyen mesaj içeriyor (spam).'; +$lang['media_uploadtab'] = 'Karşıya yükle'; +$lang['media_searchtab'] = 'Ara'; +$lang['media_file'] = 'Dosya'; +$lang['media_viewtab'] = 'Görünüm'; +$lang['media_edittab'] = 'Düzenle'; +$lang['media_historytab'] = 'Geçmiş'; +$lang['media_list_thumbs'] = 'Küçük resimler'; +$lang['media_list_rows'] = 'Satırlar'; +$lang['media_sort_name'] = 'İsim'; +$lang['media_sort_date'] = 'Tarih'; +$lang['media_files'] = '%s deki dosyalar'; +$lang['media_upload'] = '%s dizinine yükle'; +$lang['media_search'] = '%s dizininde ara'; +$lang['media_view'] = '%s'; +$lang['media_edit'] = 'Düzenle %s'; +$lang['media_history'] = 'Geçmiş %s'; +$lang['media_perm_upload'] = 'Üzgünüm, karşıya dosya yükleme yetkiniz yok.'; +$lang['media_restore'] = 'Bu sürümü eski haline getir'; diff --git a/inc/lang/tr/resetpwd.txt b/inc/lang/tr/resetpwd.txt new file mode 100644 index 000000000..1ed758693 --- /dev/null +++ b/inc/lang/tr/resetpwd.txt @@ -0,0 +1,3 @@ + ====== Yeni şifre belirle ====== + +Lütfen bu wiki hesabınız için yeni bir şifre belirleyin. \ No newline at end of file -- cgit v1.2.3 From 16c665d9fa1d3d1c5d82866a942ba8cb6db3a4ee Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:41:26 +0100 Subject: removed data parameter in subscription_handle_post() now the data parameter, which really is a timestamp is only handled internally of the subscription class --- inc/actions.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/actions.php b/inc/actions.php index 911edf936..4083b0454 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -784,8 +784,7 @@ function subscription_handle_post(&$params) { $style = null; } - $data = in_array($style, array('list', 'digest')) ? time() : null; - $params = compact('target', 'style', 'data', 'action'); + $params = compact('target', 'style', 'action'); } //Setup VIM: ex: et ts=2 : -- cgit v1.2.3 From cfbb9916556595cd8987f6c79771883dde656185 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:47:21 +0100 Subject: removed unused vars --- inc/common.php | 3 --- 1 file changed, 3 deletions(-) (limited to 'inc') diff --git a/inc/common.php b/inc/common.php index 20e0af389..bc49e76b2 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1105,10 +1105,7 @@ function saveOldRevision($id) { * @author Andreas Gohr */ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = array()) { - global $lang; global $conf; - global $INFO; - global $DIFF_INLINESTYLES; // decide if there is something to do, eg. whom to mail if($who == 'admin') { -- cgit v1.2.3 From edf986ad6271abac1f00055d3de4a9857cae1553 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:49:41 +0100 Subject: comment adjusted --- inc/subscription.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index 44248a39d..92c1e8579 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -381,7 +381,7 @@ class Subscription { * Send the diff for some page change * * @param string $subscriber_mail The target mail address - * @param string $template Mail template, should be 'subscr_digest' or 'subscr_single' + * @param string $template Mail template ('subscr_digest', 'subscr_single', 'mailtext', ...) * @param string $id Page for which the notification is * @param int|null $rev Old revision if any * @param string $summary Change summary if any -- cgit v1.2.3 From 004e7e6efb2e8da1d76f3959667ca0dbf8b0aaf6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:52:26 +0100 Subject: simplified subscription->add() code a bit --- inc/subscription.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index 92c1e8579..e888ee27f 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -204,20 +204,16 @@ class Subscription { // delete any existing subscription $this->remove($id, $user); - $user = auth_nameencode(trim($user)); + $user = auth_nameencode(trim($user)); $style = trim($style); - $data = trim($data); + $data = trim($data); if(!$user) throw new Exception('no subscription user given'); if(!$style) throw new Exception('no subscription style given'); if(!$data) $data = time(); //always add current time for new subscriptions - $line = "$user $style"; - if($data) $line .= " $data"; - $line .= "\n"; - + $line = "$user $style $data\n"; $file = $this->file($id); - return io_saveFile($file, $line, true); } -- cgit v1.2.3 From 8b87bc02a80bd1436f031d46f2d1e167b815323a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 11:01:04 +0100 Subject: fixed lists in HTML mails --- inc/subscription.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index e888ee27f..fc26e42e8 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -503,7 +503,7 @@ class Subscription { $tlist .= '* '.$link.NL; $hlist .= '
  • '.hsc($id).'
  • '.NL; } - $hlist = '
'; + $hlist .= ''; $id = prettyprint_id($ns_id); $trep = array( -- cgit v1.2.3 From 903e04c3aaaad8e237d8e50434aed40692672a43 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 11:07:46 +0100 Subject: correctly escape diffs in HTML mails --- inc/subscription.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index fc26e42e8..e4cabffed 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -398,17 +398,22 @@ class Subscription { if($rev) { $subject = 'changed'; $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); + + $old_content = rawWiki($id, $rev); + $new_content = rawWiki($id); + + $df = new Diff(explode("\n", $old_content), + explode("\n", $new_content)); $dformat = new UnifiedDiffFormatter(); $tdiff = $dformat->format($df); $DIFF_INLINESTYLES = true; + $df = new Diff(explode("\n", hsc($old_content)), + explode("\n", hsc($new_content))); $dformat = new InlineDiffFormatter(); $hdiff = $dformat->format($df); $hdiff = ''.$hdiff.'
'; $DIFF_INLINESTYLES = false; - } else { $subject = 'newpage'; $trep['OLDPAGE'] = '---'; -- cgit v1.2.3 From 29c964eb1ccaac4204b31ac7409bd91e93e9ed0c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 11:16:53 +0100 Subject: readded mailfromnobody to subscription sending this was lost because the subscription branch, branched before this change in master --- inc/subscription.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index e4cabffed..dfb3533fd 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -546,6 +546,7 @@ class Subscription { */ protected function send($subscriber_mail, $subject, $context, $template, $trep, $hrep = null) { global $lang; + global $conf; $text = rawLocale($template); $subject = $lang['mail_'.$subject].' '.$context; @@ -553,6 +554,7 @@ class Subscription { $mail->bcc($subscriber_mail); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); + $mail->from($conf['mailfromnobody']); if(isset($trep['SUBSCRIBE'])) { $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); } -- cgit v1.2.3 From 77e5adb1a4bff9e9dd43f7c10beaa235c6eb5398 Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Sat, 19 Jan 2013 12:18:36 +0100 Subject: wiki.getAttachments returns 'perms' according to documentation --- inc/RemoteAPICore.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'inc') diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index c04a14f5c..72af65329 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -344,6 +344,8 @@ class RemoteAPICore { for($i=0; $i<$len; $i++) { unset($data[$i]['meta']); + $data[$i]['perms'] = $data[$i]['perm']; + unset($data[$i]['perm']); $data[$i]['lastModified'] = $this->api->toDate($data[$i]['mtime']); } return $data; -- cgit v1.2.3 From 5eb9e8678ddc58a01929a9f340a01048836b47d3 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 19 Jan 2013 16:59:39 +0100 Subject: Indexer: Added page and meta value rename functions With these functions that search index can be updated after page moves or mass metadata updates without the need to reindex the whole page/wiki. These functions will be used by the new pagemove plugin. --- inc/indexer.php | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) (limited to 'inc') diff --git a/inc/indexer.php b/inc/indexer.php index 7a62345bf..70eac035b 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -338,6 +338,106 @@ class Doku_Indexer { return true; } + /** + * Rename a page in the search index without changing the indexed content + * + * @param string $oldpage The old page name + * @param string $newpage The new page name + * @return string|bool If the page was successfully renamed, can be a message in the case of an error + */ + public function renamePage($oldpage, $newpage) { + if (!$this->lock()) return 'locked'; + + $pages = $this->getPages(); + + $id = array_search($oldpage, $pages); + if ($id === false) { + $this->unlock(); + return 'page is not in index'; + } + + $new_id = array_search($newpage, $pages); + if ($new_id !== false) { + $this->unlock(); + // make sure the page is not in the index anymore + $this->deletePage($newpage); + if (!$this->lock()) return 'locked'; + + $pages[$new_id] = 'deleted:'.time().rand(0, 9999); + } + + $pages[$id] = $newpage; + + // update index + if (!$this->saveIndex('page', '', $pages)) { + $this->unlock(); + return false; + } + + // reset the pid cache + $this->pidCache = array(); + + $this->unlock(); + return true; + } + + /** + * Renames a meta value in the index. This doesn't change the meta value in the pages, it assumes that all pages + * will be updated. + * + * @param string $key The metadata key of which a value shall be changed + * @param string $oldvalue The old value that shall be renamed + * @param string $newvalue The new value to which the old value shall be renamed, can exist (then values will be merged) + * @return bool|string If renaming the value has been successful, false or error message on error. + */ + public function renameMetaValue($key, $oldvalue, $newvalue) { + if (!$this->lock()) return 'locked'; + + // change the relation references index + $metavalues = $this->getIndex($key, '_w'); + $oldid = array_search($oldvalue, $metavalues); + if ($oldid !== false) { + $newid = array_search($newvalue, $metavalues); + if ($newid !== false) { + // free memory + unset ($metavalues); + + // okay, now we have two entries for the same value. we need to merge them. + $indexline = $this->getIndexKey($key, '_i', $oldid); + if ($indexline != '') { + $newindexline = $this->getIndexKey($key, '_i', $newid); + $pagekeys = $this->getIndex($key, '_p'); + $parts = explode(':', $indexline); + foreach ($parts as $part) { + list($id, $count) = explode('*', $part); + $newindexline = $this->updateTuple($newindexline, $id, $count); + + $keyline = explode(':', $pagekeys[$id]); + // remove old meta value + $keyline = array_diff($keyline, array($oldid)); + // add new meta value when not already present + if (!in_array($newid, $keyline)) { + array_push($keyline, $newid); + } + $pagekeys[$id] = implode(':', $keyline); + } + $this->saveIndex($key, '_p', $pagekeys); + unset($pagekeys); + $this->saveIndexKey($key, '_i', $oldid, ''); + $this->saveIndexKey($key, '_i', $newid, $newindexline); + } + } else { + $metavalues[$oldid] = $newvalue; + if (!$this->saveIndex($key, '_w', $metavalues)) { + $this->unlock(); + return false; + } + } + } + + $this->unlock(); + return true; + } /** * Remove a page from the index * -- cgit v1.2.3 From 804f11b20e4a4f72cc45900e46f074fbd39b4649 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 19 Jan 2013 17:06:34 +0100 Subject: Correct PHPDoc comment of DokuWiki_Plugin::locale_xhtml() --- inc/plugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/plugin.php b/inc/plugin.php index e4bba989d..153e89407 100644 --- a/inc/plugin.php +++ b/inc/plugin.php @@ -81,8 +81,8 @@ class DokuWiki_Plugin { * retrieve a language dependent file and pass to xhtml renderer for display * plugin equivalent of p_locale_xhtml() * - * @param $id id of language dependent wiki page - * @return string parsed contents of the wiki page in xhtml format + * @param string $id id of language dependent wiki page + * @return string parsed contents of the wiki page in xhtml format */ function locale_xhtml($id) { return p_cached_output($this->localFN($id)); -- cgit v1.2.3 From 45c1b04dfbc6014555d58bc561e6c277a2c2dc79 Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Mon, 21 Jan 2013 09:46:12 +0100 Subject: Increment DOKU_API_VERSION Because wiki.getAttachments now returns 'perms' instead of 'perm' --- inc/RemoteAPICore.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index 72af65329..07e6aa090 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -3,7 +3,7 @@ /** * Increased whenever the API is changed */ -define('DOKU_API_VERSION', 7); +define('DOKU_API_VERSION', 8); class RemoteAPICore { -- cgit v1.2.3 From f99ea547962bcbfb89921395f8aa82be59699303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 23 Jan 2013 13:45:47 +0200 Subject: fixes from bee9f377bc547c99fe99b4e38199cb92cf668554 commit notes --- inc/Tar.class.php | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'inc') diff --git a/inc/Tar.class.php b/inc/Tar.class.php index 59e14c705..20f397395 100644 --- a/inc/Tar.class.php +++ b/inc/Tar.class.php @@ -17,7 +17,7 @@ * * $tar = new Tar(); * $tar->open('myfile.tgz'); - * $tar->extract(/tmp); + * $tar->extract('/tmp'); * * To create a new TAR archive directly on the filesystem (low memory requirements), create() it, * add*() files and close() it: @@ -81,7 +81,7 @@ class Tar { $this->fh = @fopen($this->file, 'rb'); } - if(!$this->fh) throw(new TarIOException('Could not open file for reading: '.$this->file)); + if(!$this->fh) throw new TarIOException('Could not open file for reading: '.$this->file); $this->closed = false; } @@ -107,9 +107,9 @@ class Tar { * Reopen the file with open() again if you want to do additional operations */ public function contents() { - if($this->closed || !$this->file) throw(new TarIOException('Can not read from a closed archive')); + if($this->closed || !$this->file) throw new TarIOException('Can not read from a closed archive'); - $result = Array(); + $result = array(); while($read = $this->readbytes(512)) { $header = $this->parseHeader($read); if(!is_array($header)) continue; @@ -148,7 +148,7 @@ class Tar { * @return array */ function extract($outdir, $strip = '', $exclude = '', $include = '') { - if($this->closed || !$this->file) throw(new TarIOException('Can not read from a closed archive')); + if($this->closed || !$this->file) throw new TarIOException('Can not read from a closed archive'); $outdir = rtrim($outdir, '/'); io_mkdir_p($outdir); @@ -207,7 +207,7 @@ class Tar { // is this a file? if(!$header['typeflag']) { $fp = fopen($output, "wb"); - if(!$fp) throw(new TarIOException('Could not open file for writing: '.$output)); + if(!$fp) throw new TarIOException('Could not open file for writing: '.$output); $size = floor($header['size'] / 512); for($i = 0; $i < $size; $i++) { @@ -260,7 +260,7 @@ class Tar { $this->fh = @fopen($this->file, 'wb'); } - if(!$this->fh) throw(new TarIOException('Could not open file for writing: '.$this->file)); + if(!$this->fh) throw new TarIOException('Could not open file for writing: '.$this->file); } $this->writeaccess = false; $this->closed = false; @@ -275,13 +275,13 @@ class Tar { * @throws TarIOException */ public function addFile($file, $name = '') { - if($this->closed) throw(new TarIOException('Archive has been closed, files can no longer be added')); + if($this->closed) throw new TarIOException('Archive has been closed, files can no longer be added'); if(!$name) $name = $file; $name = $this->cleanPath($name); $fp = fopen($file, 'rb'); - if(!$fp) throw(new TarIOException('Could not open file for reading: '.$file)); + if(!$fp) throw new TarIOException('Could not open file for reading: '.$file); // create file header and copy all stat info from the original file clearstatcache(false, $file); @@ -314,7 +314,7 @@ class Tar { * @throws TarIOException */ public function addData($name, $data, $uid = 0, $gid = 0, $perm = 0666, $mtime = 0) { - if($this->closed) throw(new TarIOException('Archive has been closed, files can no longer be added')); + if($this->closed) throw new TarIOException('Archive has been closed, files can no longer be added'); $name = $this->cleanPath($name); $len = strlen($data); @@ -401,7 +401,7 @@ class Tar { if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->filetype($file); if(!file_put_contents($file, $this->getArchive($comptype, $complevel))) { - throw(new TarIOException('Could not write to file: '.$file)); + throw new TarIOException('Could not write to file: '.$file); } } @@ -439,14 +439,14 @@ class Tar { } else { $written = @fwrite($this->fh, $data); } - if($written === false) throw(new TarIOException('Failed to write to archive stream')); + if($written === false) throw new TarIOException('Failed to write to archive stream'); return $written; } /** * Skip forward in the open file pointer * - * This is basically a wrapper around seek() (and a workarounf for bzip2) + * This is basically a wrapper around seek() (and a workaround for bzip2) * * @param int $bytes seek to this position */ @@ -494,11 +494,11 @@ class Tar { } // values are needed in octal - $uid = sprintf("%6s ", DecOct($uid)); - $gid = sprintf("%6s ", DecOct($gid)); - $perm = sprintf("%6s ", DecOct($perm)); - $size = sprintf("%11s ", DecOct($size)); - $mtime = sprintf("%11s", DecOct($mtime)); + $uid = sprintf("%6s ", decoct($uid)); + $gid = sprintf("%6s ", decoct($gid)); + $perm = sprintf("%6s ", decoct($perm)); + $size = sprintf("%11s ", decoct($size)); + $mtime = sprintf("%11s", decoct($mtime)); $data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime); $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $typeflag, '', 'ustar', '', '', '', '', '', $prefix, ""); @@ -511,7 +511,7 @@ class Tar { $this->writebytes($data_first); - $chks = pack("a8", sprintf("%6s ", DecOct($chks))); + $chks = pack("a8", sprintf("%6s ", decoct($chks))); $this->writebytes($chks.$data_last); } @@ -598,11 +598,11 @@ class Tar { */ protected function compressioncheck($comptype) { if($comptype === Tar::COMPRESS_GZIP && !function_exists('gzopen')) { - throw(new TarIllegalCompressionException('No gzip support available')); + throw new TarIllegalCompressionException('No gzip support available'); } if($comptype === Tar::COMPRESS_BZIP && !function_exists('bzopen')) { - throw(new TarIllegalCompressionException('No bzip2 support available')); + throw new TarIllegalCompressionException('No bzip2 support available'); } } @@ -631,4 +631,4 @@ class TarIOException extends Exception { } class TarIllegalCompressionException extends Exception { -} \ No newline at end of file +} -- cgit v1.2.3 From f2cb3ec76dec3fe2b40f25765ef842223c7132fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 23 Jan 2013 13:55:25 +0200 Subject: handle bzip1 as well in fact .tbz is tar.bz (bzip1) and .tbz2 is what tar.bz2 is used commonly. --- inc/Tar.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/Tar.class.php b/inc/Tar.class.php index 59e14c705..86fe65abb 100644 --- a/inc/Tar.class.php +++ b/inc/Tar.class.php @@ -618,7 +618,7 @@ class Tar { $file = strtolower($file); if(substr($file, -3) == '.gz' || substr($file, -4) == '.tgz') { $comptype = Tar::COMPRESS_GZIP; - } elseif(substr($file, -4) == '.bz2' || substr($file, -4) == '.tbz') { + } elseif(substr($file, -4) == '.bz2' || substr($file, -3) == '.bz' || substr($file, -4) == '.tbz' || substr($file, -5) == ".tbz2") { $comptype = Tar::COMPRESS_BZIP; } else { $comptype = Tar::COMPRESS_NONE; @@ -631,4 +631,4 @@ class TarIOException extends Exception { } class TarIllegalCompressionException extends Exception { -} \ No newline at end of file +} -- cgit v1.2.3 From 7afccd0aab62eed3797273e5241b7729bab1fb3f Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 23 Jan 2013 16:16:18 +0100 Subject: Revert "handle bzip1 as well" This reverts commit f2cb3ec76dec3fe2b40f25765ef842223c7132fe. Turns out I was too fast merging this. I can't get PHP's bzip handler to handle a bzip1 compressed file. --- inc/Tar.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/Tar.class.php b/inc/Tar.class.php index 20d892e68..20f397395 100644 --- a/inc/Tar.class.php +++ b/inc/Tar.class.php @@ -618,7 +618,7 @@ class Tar { $file = strtolower($file); if(substr($file, -3) == '.gz' || substr($file, -4) == '.tgz') { $comptype = Tar::COMPRESS_GZIP; - } elseif(substr($file, -4) == '.bz2' || substr($file, -3) == '.bz' || substr($file, -4) == '.tbz' || substr($file, -5) == ".tbz2") { + } elseif(substr($file, -4) == '.bz2' || substr($file, -4) == '.tbz') { $comptype = Tar::COMPRESS_BZIP; } else { $comptype = Tar::COMPRESS_NONE; -- cgit v1.2.3 From 182ac905691e45146536796b39ef9f1420fb79b5 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 24 Jan 2013 15:17:01 +0100 Subject: fix custom editor loading Custom editors can also be loaded when not a section is given. For example this happens on a preview click where the page is already separated into pre, suf and text. --- inc/html.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/html.php b/inc/html.php index f4e6af663..5c1c75cf6 100644 --- a/inc/html.php +++ b/inc/html.php @@ -1390,8 +1390,7 @@ function html_edit(){ $data = array('form' => $form, 'wr' => $wr, 'media_manager' => true, - 'target' => ($INPUT->has('target') && $wr && - $RANGE !== '') ? $INPUT->str('target') : 'section', + 'target' => ($INPUT->has('target') && $wr) ? $INPUT->str('target') : 'section', 'intro_locale' => $include); if ($data['target'] !== 'section') { -- cgit v1.2.3 From 368571d88a6155195d8d285c5facd569e8a5b385 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 25 Jan 2013 10:58:01 +0100 Subject: added missing context for list mails --- inc/subscription.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index dfb3533fd..6d62e4ced 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -523,7 +523,7 @@ class Subscription { return $this->send( $subscriber_mail, 'subscribe_list', - + $ns_id, 'subscr_list', $trep, $hrep ); } -- cgit v1.2.3 From 6cd7e49ba5bd41e3345b5cc4418f1e71476b3991 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 25 Jan 2013 10:58:15 +0100 Subject: only use mailfromnobody for bulk mails --- inc/subscription.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index 6d62e4ced..62cfd1509 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -554,7 +554,9 @@ class Subscription { $mail->bcc($subscriber_mail); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); - $mail->from($conf['mailfromnobody']); + if(in_array($template, array('subscr_list', 'subscr_digest'))){ + $mail->from($conf['mailfromnobody']); + } if(isset($trep['SUBSCRIBE'])) { $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); } -- cgit v1.2.3 From c38b7fab9eeb9456aaf5fe8e4481c3b8569e5644 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 26 Jan 2013 11:17:01 +0100 Subject: link directly to subscription management in mails This was updated in the english translation a while ago, but was still missing in some translations --- inc/lang/ar/subscr_single.txt | 2 +- inc/lang/bg/subscr_single.txt | 2 +- inc/lang/da/subscr_single.txt | 2 +- inc/lang/de-informal/subscr_single.txt | 2 +- inc/lang/de/subscr_single.txt | 2 +- inc/lang/en/subscr_single.txt | 2 +- inc/lang/eo/subscr_single.txt | 2 +- inc/lang/he/subscr_single.txt | 2 +- inc/lang/ia/subscr_single.txt | 2 +- inc/lang/it/subscr_single.txt | 2 +- inc/lang/ko/subscr_single.txt | 2 +- inc/lang/la/subscr_digest.txt | 2 +- inc/lang/la/subscr_single.txt | 2 +- inc/lang/no/subscr_digest.txt | 2 +- inc/lang/no/subscr_list.txt | 2 +- inc/lang/no/subscr_single.txt | 2 +- inc/lang/pt/subscr_single.txt | 2 +- inc/lang/sq/subscr_single.txt | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) (limited to 'inc') diff --git a/inc/lang/ar/subscr_single.txt b/inc/lang/ar/subscr_single.txt index 5c62aeaeb..611688415 100644 --- a/inc/lang/ar/subscr_single.txt +++ b/inc/lang/ar/subscr_single.txt @@ -15,7 +15,7 @@ لإلغاء إشعارات الصفحة,لُج الويكي في @DOKUWIKIURL@ ثم زُر -@NEWPAGE@ +@SUBSCRIBE@ وألغ الاشتراك من تغييرات الصفحة و/أو النطاق. -- diff --git a/inc/lang/bg/subscr_single.txt b/inc/lang/bg/subscr_single.txt index 7b26f8e96..a74a21fb8 100644 --- a/inc/lang/bg/subscr_single.txt +++ b/inc/lang/bg/subscr_single.txt @@ -14,7 +14,7 @@ Нова версия: @NEWPAGE@ Ако желаете да прекратите уведомяването за страницата трябва да се впишете на адрес @DOKUWIKIURL@, да посетите -@NEWPAGE@ +@SUBSCRIBE@ и да прекратите абонамента за промени по страницата или именното пространство. -- diff --git a/inc/lang/da/subscr_single.txt b/inc/lang/da/subscr_single.txt index 64b14588c..cdc554513 100644 --- a/inc/lang/da/subscr_single.txt +++ b/inc/lang/da/subscr_single.txt @@ -15,7 +15,7 @@ Ny Revision: @NEWPAGE@ For at slå side notifikationer fra, skal du logge ind på @DOKUWIKIURL@ og besøge -@NEWPAGE@ +@SUBSCRIBE@ og slå abonnoment for side / navnerum ændringer fra. -- diff --git a/inc/lang/de-informal/subscr_single.txt b/inc/lang/de-informal/subscr_single.txt index 3c557bc17..6e3f58b9f 100644 --- a/inc/lang/de-informal/subscr_single.txt +++ b/inc/lang/de-informal/subscr_single.txt @@ -15,7 +15,7 @@ Neue Revision: @NEWPAGE@ Um das Abonnement für diese Seite aufzulösen, melde dich im Wiki an @DOKUWIKIURL@, besuche dann -@NEWPAGE@ +@SUBSCRIBE@ und klicke auf den Link 'Aboverwaltung'. -- diff --git a/inc/lang/de/subscr_single.txt b/inc/lang/de/subscr_single.txt index f3e1cd393..da9914e50 100644 --- a/inc/lang/de/subscr_single.txt +++ b/inc/lang/de/subscr_single.txt @@ -15,7 +15,7 @@ Neue Revision: @NEWPAGE@ Um das Abonnement für diese Seite aufzulösen, melden Sie sich im Wiki an @DOKUWIKIURL@, besuchen dann -@NEWPAGE@ +@SUBSCRIBE@ und klicken auf die Taste 'Aboverwaltung'. -- diff --git a/inc/lang/en/subscr_single.txt b/inc/lang/en/subscr_single.txt index 673c4c32a..0bc310e04 100644 --- a/inc/lang/en/subscr_single.txt +++ b/inc/lang/en/subscr_single.txt @@ -15,7 +15,7 @@ New Revision: @NEWPAGE@ To cancel the page notifications, log into the wiki at @DOKUWIKIURL@ then visit -@NEWPAGE@ +@SUBSCRIBE@ and unsubscribe page and/or namespace changes. -- diff --git a/inc/lang/eo/subscr_single.txt b/inc/lang/eo/subscr_single.txt index 431fd0251..e4847e8ab 100644 --- a/inc/lang/eo/subscr_single.txt +++ b/inc/lang/eo/subscr_single.txt @@ -15,7 +15,7 @@ Nova versio: @NEWPAGE@ Por nuligi la paĝinformojn, ensalutu la vikion ĉe @DOKUWIKIURL@, poste iru al -@NEWPAGE@ +@SUBSCRIBE@ kaj malabonu la paĝajn kaj/aŭ nomspacajn ŝanĝojn. -- diff --git a/inc/lang/he/subscr_single.txt b/inc/lang/he/subscr_single.txt index 123b186c8..78b551e2f 100644 --- a/inc/lang/he/subscr_single.txt +++ b/inc/lang/he/subscr_single.txt @@ -14,7 +14,7 @@ לביטול התרעות בנוגע לעמוד, יש להיכנס לאתר הוויקי בכתובת @DOKUWIKIURL@ ואז לבקר בדף -@NEWPAGE@ +@SUBSCRIBE@ ולבטל את המינוי לקבלת שינויים בדף ו/או במרחב השם. -- diff --git a/inc/lang/ia/subscr_single.txt b/inc/lang/ia/subscr_single.txt index 3d6ef7103..445df197c 100644 --- a/inc/lang/ia/subscr_single.txt +++ b/inc/lang/ia/subscr_single.txt @@ -15,7 +15,7 @@ Version nove: @NEWPAGE@ Pro cancellar le notificationes de paginas, aperi un session al wiki a @DOKUWIKIURL@ postea visita -@NEWPAGE@ +@SUBSCRIBE@ e cancella tu subscription al modificationes in paginas e/o spatios de nomines. -- diff --git a/inc/lang/it/subscr_single.txt b/inc/lang/it/subscr_single.txt index 8cde8ea0f..a8649a4ef 100644 --- a/inc/lang/it/subscr_single.txt +++ b/inc/lang/it/subscr_single.txt @@ -15,7 +15,7 @@ Nuova revisione: @NEWPAGE@ Per non ricevere più queste notifiche, collegati al wiki all'indirizzo @DOKUWIKIURL@ e poi visita -@NEWPAGE@ +@SUBSCRIBE@ e rimuovi la sottoscrizione alle modifiche della pagina o categoria. diff --git a/inc/lang/ko/subscr_single.txt b/inc/lang/ko/subscr_single.txt index 6bd1885e6..2679db393 100644 --- a/inc/lang/ko/subscr_single.txt +++ b/inc/lang/ko/subscr_single.txt @@ -14,7 +14,7 @@ 새 버전 : @NEWPAGE@ 이 문서의 알림을 취소하려면, @DOKUWIKIURL@에 로그인한 뒤 -@NEWPAGE@ 문서를 방문하여 문서나 이름공간의 구독을 취소하세요. +@SUBSCRIBE@ 문서를 방문하여 문서나 이름공간의 구독을 취소하세요. -- @DOKUWIKIURL@의 DokuWiki가 자동으로 만들어낸 메일입니다. \ No newline at end of file diff --git a/inc/lang/la/subscr_digest.txt b/inc/lang/la/subscr_digest.txt index 629213359..32d378a7e 100644 --- a/inc/lang/la/subscr_digest.txt +++ b/inc/lang/la/subscr_digest.txt @@ -12,7 +12,7 @@ Noua recensio: @NEWPAGE@ Ut paginae adnotationes deleas, in uicem ineas in @DOKUWIKIURL@, deinde uideas -@NEWPAGE@ +@SUBSCRIBE@ et paginarum generum optiones mutes. -- diff --git a/inc/lang/la/subscr_single.txt b/inc/lang/la/subscr_single.txt index 7839791ea..14285014c 100644 --- a/inc/lang/la/subscr_single.txt +++ b/inc/lang/la/subscr_single.txt @@ -15,7 +15,7 @@ Noua recensio: @NEWPAGE@ Ut paginae adnotationes deleas, in uicem ineas in @DOKUWIKIURL@, deinde uideas -@NEWPAGE@ +@SUBSCRIBE@ et paginarum et\aut generum optiones mutasa. -- diff --git a/inc/lang/no/subscr_digest.txt b/inc/lang/no/subscr_digest.txt index 6afd0cc5c..670d39d32 100644 --- a/inc/lang/no/subscr_digest.txt +++ b/inc/lang/no/subscr_digest.txt @@ -12,7 +12,7 @@ Ny versjon: @NEWPAGE@ For å avslutte varslingen, logg inn på @DOKUWIKIURL@ og gå til -@NEWPAGE@ +@SUBSCRIBE@ og avslutt abonnementet på endringer av siden eller i navnerommet. -- diff --git a/inc/lang/no/subscr_list.txt b/inc/lang/no/subscr_list.txt index 72cd307cb..860d88d2a 100644 --- a/inc/lang/no/subscr_list.txt +++ b/inc/lang/no/subscr_list.txt @@ -9,7 +9,7 @@ Her er endringene: For å avslutte varslinga, logg inn på @DOKUWIKIURL@ og gå til -@NEWPAGE@ +@SUBSCRIBE@ og avslutt abonnementet på endringer av sida eller i navnerommet. -- diff --git a/inc/lang/no/subscr_single.txt b/inc/lang/no/subscr_single.txt index 25296da58..b26b3a879 100644 --- a/inc/lang/no/subscr_single.txt +++ b/inc/lang/no/subscr_single.txt @@ -15,7 +15,7 @@ Ny versjon: @NEWPAGE@ For å avslutte varslingen, logg inn på @DOKUWIKIURL@, gå til -@NEWPAGE@ +@SUBSCRIBE@ og avslutt abonnementet på endringer av siden eller i navnerommet. -- diff --git a/inc/lang/pt/subscr_single.txt b/inc/lang/pt/subscr_single.txt index 1187b5911..469c6bfb1 100644 --- a/inc/lang/pt/subscr_single.txt +++ b/inc/lang/pt/subscr_single.txt @@ -15,7 +15,7 @@ Revisão Nova: @NEWPAGE@ Para cancelar as notificações de página, inicie sessão no wiki em @DOKUWIKIURL@, visite -@NEWPAGE@ +@SUBSCRIBE@ e des-subscreva às alterações de página e/ou espaço de nome. -- diff --git a/inc/lang/sq/subscr_single.txt b/inc/lang/sq/subscr_single.txt index 90520be4f..df28ee176 100644 --- a/inc/lang/sq/subscr_single.txt +++ b/inc/lang/sq/subscr_single.txt @@ -15,7 +15,7 @@ Rishikimi i ri: @NEWPAGE@ Për të fshirë lajmërimet e faqes, hyni në wiki tek @DOKUWIKIURL@ dhe pastaj vizitoni -@NEWPAGE@ +@SUBSCRIBE@ dhe fshini ndryshimet e faqes dhe/ose hapësirës së emrit. -- -- cgit v1.2.3 From af73bba62fb11d7872a8b108b156d451302695bd Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 26 Jan 2013 11:17:59 +0100 Subject: Clarified the behavior of the Doku_Indexer::renamePage method --- inc/indexer.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/indexer.php b/inc/indexer.php index 70eac035b..37ca92055 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -339,7 +339,9 @@ class Doku_Indexer { } /** - * Rename a page in the search index without changing the indexed content + * Rename a page in the search index without changing the indexed content. This function doesn't check if the + * old or new name exists in the filesystem. It returns an error if the old page isn't in the page list of the + * indexer and it deletes all previously indexed content of the new page. * * @param string $oldpage The old page name * @param string $newpage The new page name -- cgit v1.2.3 From 25adeb91ff207452ebd6275707b8a0cc3121db6c Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 26 Jan 2013 11:18:52 +0100 Subject: Indexer: added internal deletePageNoLock method The new deletePageNoLock method is used by renamePage and avoids that the index needs to be unlocked and locked again for deleting the page. --- inc/indexer.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'inc') diff --git a/inc/indexer.php b/inc/indexer.php index 37ca92055..c08e438bf 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -360,10 +360,8 @@ class Doku_Indexer { $new_id = array_search($newpage, $pages); if ($new_id !== false) { - $this->unlock(); // make sure the page is not in the index anymore - $this->deletePage($newpage); - if (!$this->lock()) return 'locked'; + $this->deletePageNoLock($newpage); $pages[$new_id] = 'deleted:'.time().rand(0, 9999); } @@ -440,6 +438,7 @@ class Doku_Indexer { $this->unlock(); return true; } + /** * Remove a page from the index * @@ -453,10 +452,26 @@ class Doku_Indexer { if (!$this->lock()) return "locked"; + $result = $this->deletePageNoLock($page); + + $this->unlock(); + + return $result; + } + + /** + * Remove a page from the index without locking the index, only use this function if the index is already locked + * + * Erases entries in all known indexes. + * + * @param string $page a page name + * @return boolean the function completed successfully + * @author Tom N Harris + */ + protected function deletePageNoLock($page) { // load known documents $pid = $this->getPIDNoLock($page); if ($pid === false) { - $this->unlock(); return false; } @@ -482,7 +497,6 @@ class Doku_Indexer { } // Save the reverse index if (!$this->saveIndexKey('pageword', '', $pid, "")) { - $this->unlock(); return false; } @@ -499,7 +513,6 @@ class Doku_Indexer { $this->saveIndexKey($metaname.'_p', '', $pid, ''); } - $this->unlock(); return true; } -- cgit v1.2.3 From bc27f3e28790e9a25e9428ed275624578b3e9a2d Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 26 Jan 2013 11:22:52 +0100 Subject: Indexer: abort page rename if deletion of new id fails --- inc/indexer.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'inc') diff --git a/inc/indexer.php b/inc/indexer.php index c08e438bf..e518907d7 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -361,7 +361,9 @@ class Doku_Indexer { $new_id = array_search($newpage, $pages); if ($new_id !== false) { // make sure the page is not in the index anymore - $this->deletePageNoLock($newpage); + if ($this->deletePageNoLock($newpage) !== true) { + return false; + } $pages[$new_id] = 'deleted:'.time().rand(0, 9999); } -- cgit v1.2.3 From 529b04166c604b1d086cbfeac1bd676227d04872 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 26 Jan 2013 12:59:15 +0100 Subject: added mediawiki password method FS#2559 This should make migrating from MediaWiki a bit easier. --- inc/PassHash.class.php | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'inc') diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php index 13be479cc..6918a04b4 100644 --- a/inc/PassHash.class.php +++ b/inc/PassHash.class.php @@ -4,7 +4,7 @@ * * This class implements various mechanisms used to hash passwords * - * @author Andreas Gohr + * @author Andreas Gohr * @license LGPL2 */ class PassHash { @@ -58,6 +58,9 @@ class PassHash { } elseif(substr($hash, 0, 6) == '{SMD5}') { $method = 'lsmd5'; $salt = substr(base64_decode(substr($hash, 6)), 16); + } elseif(preg_match('/^:B:(.+?):.{32}$/', $hash, $m)) { + $method = 'mediawiki'; + $salt = $m[1]; } elseif($len == 32) { $method = 'md5'; } elseif($len == 40) { @@ -104,7 +107,7 @@ class PassHash { * applied. * * @param string &$salt The salt, pass null if you want one generated - * @param int $len The length of the salt + * @param int $len The length of the salt */ public function init_salt(&$salt, $len = 32) { if(is_null($salt)) $salt = $this->gen_salt($len); @@ -263,7 +266,7 @@ class PassHash { * * This method was used by old MySQL systems * - * @link http://www.php.net/mysql + * @link http://www.php.net/mysql * @author * @param string $clear The clear text to hash * @return string Hashed password @@ -327,9 +330,9 @@ class PassHash { * an exception. * * @link http://www.openwall.com/phpass/ - * @param string $clear The clear text to hash - * @param string $salt The salt to use, null for random - * @param string $magic The hash identifier (P or H) + * @param string $clear The clear text to hash + * @param string $salt The salt to use, null for random + * @param string $magic The hash identifier (P or H) * @param int $compute The iteration count for new passwords * @throws Exception * @return string Hashed password @@ -430,8 +433,8 @@ class PassHash { * will break. When no salt is given, the iteration count can be set * through the $compute variable. * - * @param string $clear The clear text to hash - * @param string $salt The salt to use, null for random + * @param string $clear The clear text to hash + * @param string $salt The salt to use, null for random * @param int $compute The iteration count (between 4 and 31) * @throws Exception * @return string Hashed password @@ -450,4 +453,19 @@ class PassHash { return crypt($clear, $salt); } + /** + * Password hashing method 'mediawiki' + * + * Uses salted MD5, this is referred to as Method B in MediaWiki docs. Unsalted md5 + * method 'A' is not supported. + * + * @link http://www.mediawiki.org/wiki/Manual_talk:User_table#user_password_column + * @param string $clear The clear text to hash + * @param string $salt The salt to use, null for random + * @return string Hashed password + */ + public function hash_mediawiki($clear, $salt = null) { + $this->init_salt($salt, 8); + return ':B:'.$salt.':'.md5($salt.'-'.md5($clear)); + } } -- cgit v1.2.3 From 925ad1487c71b97ed6cdb2e339a8d84abd199fef Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 26 Jan 2013 13:37:56 +0100 Subject: allow varying salt length in password hasher --- inc/PassHash.class.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'inc') diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php index 6918a04b4..15ea8cbcf 100644 --- a/inc/PassHash.class.php +++ b/inc/PassHash.class.php @@ -104,14 +104,18 @@ class PassHash { * Initialize the passed variable with a salt if needed. * * If $salt is not null, the value is kept, but the lenght restriction is - * applied. + * applied (unless, $cut is false). * * @param string &$salt The salt, pass null if you want one generated * @param int $len The length of the salt + * @param bool $cut Apply length restriction to existing salt? */ - public function init_salt(&$salt, $len = 32) { - if(is_null($salt)) $salt = $this->gen_salt($len); - if(strlen($salt) > $len) $salt = substr($salt, 0, $len); + public function init_salt(&$salt, $len = 32, $cut = true) { + if(is_null($salt)) { + $salt = $this->gen_salt($len); + $cut = true; // for new hashes we alway apply length restriction + } + if(strlen($salt) > $len && $cut) $salt = substr($salt, 0, $len); } // Password hashing methods follow below @@ -465,7 +469,7 @@ class PassHash { * @return string Hashed password */ public function hash_mediawiki($clear, $salt = null) { - $this->init_salt($salt, 8); + $this->init_salt($salt, 8, false); return ':B:'.$salt.':'.md5($salt.'-'.md5($clear)); } } -- cgit v1.2.3 From dfbe4adfd080433f91409f028935b9f9879fceca Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 26 Jan 2013 13:38:20 +0100 Subject: added SHA512 hashing method FS#2663 --- inc/PassHash.class.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'inc') diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php index 15ea8cbcf..080fb4778 100644 --- a/inc/PassHash.class.php +++ b/inc/PassHash.class.php @@ -61,6 +61,9 @@ class PassHash { } elseif(preg_match('/^:B:(.+?):.{32}$/', $hash, $m)) { $method = 'mediawiki'; $salt = $m[1]; + } elseif(preg_match('/^\$6\$(.+?)\$/', $hash, $m)) { + $method = 'sha512'; + $salt = $m[1]; } elseif($len == 32) { $method = 'md5'; } elseif($len == 40) { @@ -457,6 +460,25 @@ class PassHash { return crypt($clear, $salt); } + /** + * Password hashing method SHA512 + * + * This is only supported on PHP 5.3.2 or higher and will throw an exception if + * the needed crypt support is not available + * + * @param string $clear The clear text to hash + * @param string $salt The salt to use, null for random + * @return string Hashed password + * @throws Exception + */ + public function hash_sha512($clear, $salt = null) { + if(!defined('CRYPT_SHA512') || CRYPT_SHA512 != 1) { + throw new Exception('This PHP installation has no SHA512 support'); + } + $this->init_salt($salt, 8, false); + return crypt($clear, '$6$'.$salt.'$'); + } + /** * Password hashing method 'mediawiki' * -- cgit v1.2.3 From 10eac6731852014bcef1a0d16c59a4f6f77d8e31 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 26 Jan 2013 15:09:43 +0100 Subject: Add threading headers to change notification mails as proposed in PR #120 --- inc/subscription.php | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/subscription.php b/inc/subscription.php index 62cfd1509..31e3e08e1 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -424,9 +424,14 @@ class Subscription { $trep['DIFF'] = $tdiff; $hrep['DIFF'] = $hdiff; + $headers = array('Message-Id' => $this->getMessageID($id)); + if ($rev) { + $headers['In-Reply-To'] = $this->getMessageID($id, $rev); + } + return $this->send( $subscriber_mail, $subject, $id, - $template, $trep, $hrep + $template, $trep, $hrep, $headers ); } @@ -542,9 +547,10 @@ class Subscription { * template (in text format) * @param array $hrep Predefined parameters used to parse the * template (in HTML format), null to default to $trep + * @param array $headers Additional mail headers in the form 'name' => 'value' * @return bool */ - protected function send($subscriber_mail, $subject, $context, $template, $trep, $hrep = null) { + protected function send($subscriber_mail, $subject, $context, $template, $trep, $hrep = null, $headers = array()) { global $lang; global $conf; @@ -560,9 +566,36 @@ class Subscription { if(isset($trep['SUBSCRIBE'])) { $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); } + + foreach ($headers as $header => $value) { + $mail->setHeader($header, $value); + } + return $mail->send(); } + /** + * Get a valid message id for a certain $id and revision (or the current revision) + * @param string $id The id of the page (or media file) the message id should be for + * @param string $rev The revision of the page, set to the current revision of the page $id if not set + * @return string + */ + protected function getMessageID($id, $rev = NULL) { + static $listid = null; + if (is_null($listid)) { + $server = parse_url(DOKU_URL, PHP_URL_HOST); + $listid = join('.', array_reverse(explode('/', DOKU_BASE))).$server; + $listid = urlencode($listid); + $listid = strtolower(trim($listid, '.')); + } + + if (is_null($rev)) { + $rev = @filemtime(wikiFN($id)); + } + + return "<$id?rev=$rev@$listid>"; + } + /** * Default callback for COMMON_NOTIFY_ADDRESSLIST * -- cgit v1.2.3 From b5460ee2c820d95f75fd47d2f8bcbe5dddc21e7e Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sat, 26 Jan 2013 15:10:52 +0100 Subject: Implement media subscriptions in the new subscription class --- inc/media.php | 23 ++--------------------- inc/subscription.php | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 21 deletions(-) (limited to 'inc') diff --git a/inc/media.php b/inc/media.php index 6335bf210..572b1177c 100644 --- a/inc/media.php +++ b/inc/media.php @@ -535,32 +535,13 @@ function media_contentcheck($file,$mime){ * Send a notify mail on uploads * * @author Andreas Gohr - * @fixme this should embed thumbnails of images in HTML version */ function media_notify($id,$file,$mime,$old_rev=false){ - global $lang; global $conf; - global $INFO; if(empty($conf['notify'])) return; //notify enabled? - $text = rawLocale('uploadmail'); - $trep = array( - 'MIME' => $mime, - 'MEDIA' => ml($id,'',true,'&',true), - 'SIZE' => filesize_h(filesize($file)), - ); - - if ($old_rev && $conf['mediarevisions']) { - $trep['OLD'] = ml($id, "rev=$old_rev", true, '&', true); - } else { - $trep['OLD'] = '---'; - } - - $mail = new Mailer(); - $mail->to($conf['notify']); - $mail->subject($lang['mail_upload'].' '.$id); - $mail->setBody($text,$trep); - return $mail->send(); + $subscription = new Subscription(); + return $subscription->send_media_diff($conf['notify'], 'uploadmail', $id, $old_rev, ''); } /** diff --git a/inc/subscription.php b/inc/subscription.php index 31e3e08e1..2989de032 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -435,6 +435,43 @@ class Subscription { ); } + /** + * Send the diff for some media change + * + * @fixme this should embed thumbnails of images in HTML version + * @param string $subscriber_mail The target mail address + * @param string $template Mail template ('uploadmail', ...) + * @param string $id Media file for which the notification is + * @param int|bool $rev Old revision if any + * @return bool true if successfully sent + */ + public function send_media_diff($subscriber_mail, $template, $id, $rev = false) { + global $conf; + + $file = mediaFN($id); + list($mime, $ext) = mimetype($id); + + $trep = array( + 'MIME' => $mime, + 'MEDIA' => ml($id,'',true,'&',true), + 'SIZE' => filesize_h(filesize($file)), + ); + + if ($rev && $conf['mediarevisions']) { + $trep['OLD'] = ml($id, "rev=$rev", true, '&', true); + } else { + $trep['OLD'] = '---'; + } + + $headers = array('Message-Id' => $this->getMessageID($id, @filemtime($file))); + if ($rev) { + $headers['In-Reply-To'] = $this->getMessageID($id, $rev); + } + + $this->send($subscriber_mail, 'upload', $id, $template, $trep, null, $headers); + + } + /** * Send a notify mail on new registration * -- cgit v1.2.3