aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Daemon/Deliver.php34
-rw-r--r--Zotlabs/Daemon/Notifier.php10
-rw-r--r--Zotlabs/Lib/ActivityStreams.php16
-rw-r--r--Zotlabs/Lib/LDSignatures.php11
-rw-r--r--Zotlabs/Lib/NativeWikiPage.php9
-rw-r--r--Zotlabs/Module/Admin/Site.php2
-rw-r--r--Zotlabs/Module/Channel.php2
-rw-r--r--Zotlabs/Module/Connedit.php4
-rw-r--r--Zotlabs/Module/Photos.php6
-rw-r--r--Zotlabs/Module/Pubsites.php3
-rw-r--r--Zotlabs/Module/Pubstream.php4
-rw-r--r--Zotlabs/Module/Wiki.php3
-rw-r--r--Zotlabs/Module/Xrd.php1
-rw-r--r--Zotlabs/Web/HTTPSig.php66
-rw-r--r--Zotlabs/Web/Router.php19
-rw-r--r--Zotlabs/Widget/Common_friends.php19
-rw-r--r--Zotlabs/Widget/Wiki_pages.php7
17 files changed, 167 insertions, 49 deletions
diff --git a/Zotlabs/Daemon/Deliver.php b/Zotlabs/Daemon/Deliver.php
index 7c1ff717f..394a7bf3e 100644
--- a/Zotlabs/Daemon/Deliver.php
+++ b/Zotlabs/Daemon/Deliver.php
@@ -53,29 +53,25 @@ class Deliver {
remove_queue_item($r[0]['outq_hash']);
if($dresult && is_array($dresult)) {
- if(array_key_exists('iv',$dresult)) {
- $dresult = json_decode(crypto_unencapsulate($dresult,get_config('system','prvkey')),true);
- }
- if(! $dresult) {
- logger('dreport decryption failure');
- }
- else {
- foreach($dresult as $xx) {
- if(is_array($xx) && array_key_exists('message_id',$xx)) {
- if(delivery_report_is_storable($xx)) {
- q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
- dbesc($xx['message_id']),
- dbesc($xx['location']),
- dbesc($xx['recipient']),
- dbesc($xx['status']),
- dbesc(datetime_convert($xx['date'])),
- dbesc($xx['sender'])
- );
- }
+
+ // delivery reports for local deliveries do not require encryption
+
+ foreach($dresult as $xx) {
+ if(is_array($xx) && array_key_exists('message_id',$xx)) {
+ if(delivery_report_is_storable($xx)) {
+ q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
+ dbesc($xx['message_id']),
+ dbesc($xx['location']),
+ dbesc($xx['recipient']),
+ dbesc($xx['status']),
+ dbesc(datetime_convert($xx['date'])),
+ dbesc($xx['sender'])
+ );
}
}
}
}
+
q("delete from dreport where dreport_queue = '%s'",
dbesc($argv[$x])
);
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index 0e8c99572..5f8490b06 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -59,6 +59,8 @@ require_once('include/bbcode.php');
*
* ZOT
* permission_create abook_id
+ * permission_accept abook_id
+ * permission_reject abook_id
* permission_update abook_id
* refresh_all channel_id
* purge_all channel_id
@@ -159,7 +161,7 @@ class Notifier {
$packet_type = 'keychange';
$normal_mode = false;
}
- elseif($cmd == 'permission_update' || $cmd == 'permission_create') {
+ elseif(in_array($cmd, [ 'permission_update', 'permission_reject', 'permission_accept', 'permission_create' ])) {
// Get the (single) recipient
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
intval($item_id)
@@ -171,8 +173,12 @@ class Notifier {
if($channel) {
$perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
- if($cmd == 'permission_create')
+ if($cmd === 'permission_create')
call_hooks('permissions_create',$perm_update);
+ elseif($cmd === 'permission_accept')
+ call_hooks('permissions_accept',$perm_update);
+ elseif($cmd === 'permission_reject')
+ call_hooks('permissions_reject',$perm_update);
else
call_hooks('permissions_update',$perm_update);
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php
index d9735881a..379e78a59 100644
--- a/Zotlabs/Lib/ActivityStreams.php
+++ b/Zotlabs/Lib/ActivityStreams.php
@@ -58,7 +58,7 @@ class ActivityStreams {
$this->saved_recips = $arr;
}
- function collect_recips($base = '',$namespace = 'https://www.w3.org/ns/activitystreams') {
+ function collect_recips($base = '',$namespace = '') {
$x = [];
$fields = [ 'to','cc','bto','bcc','audience'];
foreach($fields as $f) {
@@ -75,7 +75,7 @@ class ActivityStreams {
return $x;
}
- function expand($arr,$base = '',$namespace = 'https://www.w3.org/ns/activitystreams') {
+ function expand($arr,$base = '',$namespace = '') {
$ret = [];
// right now use a hardwired recursion depth of 5
@@ -103,8 +103,12 @@ class ActivityStreams {
function get_namespace($base,$namespace) {
+ if(! $namespace)
+ return '';
+
$key = null;
+
foreach( [ $this->data, $base ] as $b ) {
if(! $b)
continue;
@@ -135,7 +139,7 @@ class ActivityStreams {
}
- function get_property_obj($property,$base = '',$namespace = 'https://www.w3.org/ns/activitystreams') {
+ function get_property_obj($property,$base = '',$namespace = '' ) {
$prefix = $this->get_namespace($base,$namespace);
if($prefix === null)
return null;
@@ -152,13 +156,13 @@ class ActivityStreams {
}
$x = z_fetch_url($url,true,$redirects,
- ['headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"']]);
+ ['headers' => [ 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json' ]]);
if($x['success'])
return json_decode($x['body'],true);
return null;
}
- function get_compound_property($property,$base = '',$namespace = 'https://www.w3.org/ns/activitystreams') {
+ function get_compound_property($property,$base = '',$namespace = '') {
$x = $this->get_property_obj($property,$base,$namespace);
if($this->is_url($x)) {
$x = $this->fetch_property($x);
@@ -173,7 +177,7 @@ class ActivityStreams {
return false;
}
- function get_primary_type($base = '',$namespace = 'https://www.w3.org/ns/activitystreams') {
+ function get_primary_type($base = '',$namespace = '') {
if(! $base)
$base = $this->data;
$x = $this->get_property_obj('type',$base,$namespace);
diff --git a/Zotlabs/Lib/LDSignatures.php b/Zotlabs/Lib/LDSignatures.php
index fa2758044..d500799c0 100644
--- a/Zotlabs/Lib/LDSignatures.php
+++ b/Zotlabs/Lib/LDSignatures.php
@@ -12,7 +12,10 @@ class LDSignatures {
$ohash = self::hash(self::signable_options($data['signature']));
$dhash = self::hash(self::signable_data($data));
- return rsa_verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
+ $x = rsa_verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
+ logger('LD-verify: ' . intval($x));
+
+ return $x;
}
static function dopplesign(&$data,$channel) {
@@ -35,7 +38,9 @@ class LDSignatures {
$options['signatureValue'] = base64_encode(rsa_sign($ohash . $dhash,$channel['channel_prvkey']));
$signed = array_merge([
- '@context' => [ 'https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1' ],
+ '@context' => [
+ ACTIVITYSTREAMS_JSONLD_REV,
+ 'https://w3id.org/security/v1' ],
],$options);
return $signed;
@@ -82,6 +87,8 @@ class LDSignatures {
if(! is_object($data))
return '';
+ jsonld_set_document_loader('jsonld_document_loader');
+
return jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
}
diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php
index 4b637781e..209a5ef3c 100644
--- a/Zotlabs/Lib/NativeWikiPage.php
+++ b/Zotlabs/Lib/NativeWikiPage.php
@@ -21,7 +21,7 @@ class NativeWikiPage {
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
- $sql_extra order by created asc",
+ $sql_extra order by title asc",
dbesc($resource_id),
intval($channel_id)
);
@@ -74,6 +74,7 @@ class NativeWikiPage {
$arr['uid'] = $channel_id;
$arr['author_xchan'] = $observer_hash;
$arr['mimetype'] = $mimetype;
+ $arr['title'] = $name;
$arr['resource_type'] = 'nwikipage';
$arr['resource_id'] = $resource_id;
$arr['allow_cid'] = $w['wiki']['allow_cid'];
@@ -139,8 +140,14 @@ class NativeWikiPage {
if($ic) {
foreach($ic as $c) {
set_iconfig($c['item_id'],'nwikipage','pagetitle',$pageNewName);
+ $ids[] = $c['item_id'];
}
+ $str_ids = implode(',', $ids);
+ q("update item set title = '%s' where id in ($str_ids)",
+ dbesc($pageNewName)
+ );
+
$page = [
'rawName' => $pageNewName,
'htmlName' => escape_tags($pageNewName),
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 4c5b82e78..4946e3433 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -206,7 +206,7 @@ class Site {
// directory server should not be set or settable unless we are a directory client
if($dirmode == DIRECTORY_MODE_NORMAL) {
- $x = q("select site_url from site where site_flags in (%d,%d) and site_realm = '%s'",
+ $x = q("select site_url from site where site_flags in (%d,%d) and site_realm = '%s' and site_dead = 0",
intval(DIRECTORY_MODE_SECONDARY),
intval(DIRECTORY_MODE_PRIMARY),
dbesc($realm)
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index 4ffc9ffc6..8550c69cd 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -123,7 +123,7 @@ class Channel extends \Zotlabs\Web\Controller {
//$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']);
- $o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
+ // $o .= common_friends_visitor_widget(\App::$profile['profile_uid']);
if($channel && $is_owner) {
$channel_acl = array(
diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php
index 0f18b432d..23c5282e3 100644
--- a/Zotlabs/Module/Connedit.php
+++ b/Zotlabs/Module/Connedit.php
@@ -248,6 +248,10 @@ class Connedit extends \Zotlabs\Web\Controller {
notice( t('Failed to update connection record.') . EOL);
if(! intval(\App::$poi['abook_self'])) {
+ if($new_friend) {
+ \Zotlabs\Daemon\Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
+ }
+
\Zotlabs\Daemon\Master::Summon( [
'Notifier',
(($new_friend) ? 'permission_create' : 'permission_update'),
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
index bb7079a6a..f86801fcc 100644
--- a/Zotlabs/Module/Photos.php
+++ b/Zotlabs/Module/Photos.php
@@ -1041,7 +1041,7 @@ class Photos extends \Zotlabs\Web\Controller {
$likebuttons = '';
- if($can_post || $can_comment) {
+ if($observer && ($can_post || $can_comment)) {
$likebuttons = [
'id' => $link_item['id'],
'likethis' => t("I like this \x28toggle\x29"),
@@ -1053,7 +1053,7 @@ class Photos extends \Zotlabs\Web\Controller {
$comments = '';
if(! count($r)) {
- if($can_post || $can_comment) {
+ if($observer && ($can_post || $can_comment)) {
$commentbox = replace_macros($cmnt_tpl,array(
'$return_path' => '',
'$mode' => 'photos',
@@ -1172,7 +1172,7 @@ class Photos extends \Zotlabs\Web\Controller {
}
- if($can_post || $can_comment) {
+ if($observer && ($can_post || $can_comment)) {
$commentbox = replace_macros($cmnt_tpl,array(
'$return_path' => '',
'$jsreload' => $return_url,
diff --git a/Zotlabs/Module/Pubsites.php b/Zotlabs/Module/Pubsites.php
index d87967189..ef02cf099 100644
--- a/Zotlabs/Module/Pubsites.php
+++ b/Zotlabs/Module/Pubsites.php
@@ -36,7 +36,8 @@ class Pubsites extends \Zotlabs\Web\Controller {
$o .= '</tr>';
if($j['sites']) {
foreach($j['sites'] as $jj) {
- if(! \Zotlabs\Lib\System::compatible_project($jj['project']))
+ $projectname = explode(' ',$jj['project']);
+ if(! \Zotlabs\Lib\System::compatible_project($projectname[0]))
continue;
if(strpos($jj['version'],' ')) {
$x = explode(' ', $jj['version']);
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
index ef818845c..72d5f80fa 100644
--- a/Zotlabs/Module/Pubstream.php
+++ b/Zotlabs/Module/Pubstream.php
@@ -28,6 +28,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
if(! $update) {
+ nav_set_selected(t('Public Stream'));
+
$_SESSION['static_loadtime'] = datetime_convert();
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
@@ -108,7 +110,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$simple_update = '';
if($static && $simple_update)
- $simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
+ $simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
//logger('update: ' . $update . ' load: ' . $load);
diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php
index 2668229ee..fe2bfbdfb 100644
--- a/Zotlabs/Module/Wiki.php
+++ b/Zotlabs/Module/Wiki.php
@@ -216,7 +216,8 @@ class Wiki extends \Zotlabs\Web\Controller {
'$deny_cid' => $x['deny_cid'],
'$deny_gid' => $x['deny_gid'],
'$typelock' => array('typelock', t('Lock content type'), '', '', array(t('No'), t('Yes'))),
- '$notify' => array('postVisible', t('Create a status post for this wiki'), '', '', array(t('No'), t('Yes')))
+ '$notify' => array('postVisible', t('Create a status post for this wiki'), '', '', array(t('No'), t('Yes'))),
+ '$edit_wiki_name' => t('Edit Wiki Name')
));
return $o;
diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php
index 60a8f58fa..959e31cbe 100644
--- a/Zotlabs/Module/Xrd.php
+++ b/Zotlabs/Module/Xrd.php
@@ -50,6 +50,7 @@ class Xrd extends \Zotlabs\Web\Controller {
'$accturi' => $resource,
'$subject' => $subject,
'$aliases' => $aliases,
+ '$channel_url' => z_root() . '/channel/' . $r[0]['channel_address'],
'$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'],
'$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'],
'$atom' => z_root() . '/ofeed/' . $r[0]['channel_address'],
diff --git a/Zotlabs/Web/HTTPSig.php b/Zotlabs/Web/HTTPSig.php
index 6526fa7c8..701c29be5 100644
--- a/Zotlabs/Web/HTTPSig.php
+++ b/Zotlabs/Web/HTTPSig.php
@@ -20,7 +20,7 @@ class HTTPSig {
return $digest;
}
- // See draft-cavage-http-signatures-07
+ // See draft-cavage-http-signatures-08
static function verify($data,$key = '') {
@@ -48,7 +48,7 @@ class HTTPSig {
else {
$headers = [];
$headers['(request-target)'] =
- $_SERVER['REQUEST_METHOD'] . ' ' .
+ strtolower($_SERVER['REQUEST_METHOD']) . ' ' .
$_SERVER['REQUEST_URI'];
foreach($_SERVER as $k => $v) {
if(strpos($k,'HTTP_') === 0) {
@@ -67,8 +67,12 @@ class HTTPSig {
$sig_block = self::parse_sigheader($headers['authorization']);
}
- if(! $sig_block)
+ if(! $sig_block) {
+ logger('no signature provided.');
return $result;
+ }
+
+ logger('sig_block: ' . print_r($sig_block,true), LOGGER_DATA);
$result['header_signed'] = true;
@@ -110,6 +114,8 @@ class HTTPSig {
$x = rsa_verify($signed_data,$sig_block['signature'],$key,$algorithm);
+ logger('verified: ' . $x, LOGGER_DEBUG);
+
if($x === false)
return $result;
@@ -130,6 +136,8 @@ class HTTPSig {
}
}
+ logger('Content_Valid: ' . $result['content_valid']);
+
return $result;
}
@@ -167,7 +175,8 @@ class HTTPSig {
- static function create_sig($request,$head,$prvkey,$keyid = 'Key',$send_headers = false,$auth = false,$alg = 'sha256') {
+ static function create_sig($request,$head,$prvkey,$keyid = 'Key',$send_headers = false,$auth = false,$alg = 'sha256',
+ $crypt_key = null, $crypt_algo = 'aes256ctr') {
$return_headers = [];
@@ -178,15 +187,21 @@ class HTTPSig {
$algorithm = 'rsa-sha512';
}
- $x = self::sign($request,$head,$prvkey,$alg);
+ $x = self::sign($request,$head,$prvkey,$alg);
- if($auth) {
- $sighead = 'Authorization: Signature keyId="' . $keyid . '",algorithm="' . $algorithm
+ $headerval = keyId="' . $keyid . '",algorithm="' . $algorithm
. '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
+
+ if($crypt_key) {
+ $x = crypto_encapsulate($headerval,$crypt_key,$crypt_alg);
+ $headerval = 'iv="' . $x['iv'] . '",key="' . $x['key'] . '",alg="' . $x['alg'] . '",data="' . $x['data'];
+ }
+
+ if($auth) {
+ $sighead = 'Authorization: Signature ' . $headerval;
}
else {
- $sighead = 'Signature: keyId="' . $keyid . '",algorithm="' . $algorithm
- . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
+ $sighead = 'Signature: ' . $headerval;
}
if($head) {
@@ -241,8 +256,15 @@ class HTTPSig {
}
static function parse_sigheader($header) {
+
$ret = [];
$matches = [];
+
+ // if the header is encrypted, decrypt with (default) site private key and continue
+
+ if(preg_match('/iv="(.*?)"/ism',$header,$matches))
+ $header = self::decrypt_sigheader($header);
+
if(preg_match('/keyId="(.*?)"/ism',$header,$matches))
$ret['keyId'] = $matches[1];
if(preg_match('/algorithm="(.*?)"/ism',$header,$matches))
@@ -259,6 +281,32 @@ class HTTPSig {
}
+ static function decrypt_sigheader($header,$prvkey = null) {
+
+ $iv = $key = $alg = $data = null;
+
+ if(! $prvkey) {
+ $prvkey = get_config('system','prvkey');
+ }
+
+ $matches = [];
+
+ if(preg_match('/iv="(.*?)"/ism',$header,$matches))
+ $iv = $matches[1];
+ if(preg_match('/key="(.*?)"/ism',$header,$matches))
+ $key = $matches[1];
+ if(preg_match('/alg="(.*?)"/ism',$header,$matches))
+ $alg = $matches[1];
+ if(preg_match('/data="(.*?)"/ism',$header,$matches))
+ $data = $matches[1];
+
+ if($iv && $key && $alg && $data) {
+ return crypto_unencapsulate([ 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data ] , $prvkey);
+ }
+ return '';
+
+ }
+
}
diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php
index 710aa2844..b0193652b 100644
--- a/Zotlabs/Web/Router.php
+++ b/Zotlabs/Web/Router.php
@@ -178,6 +178,25 @@ class Router {
*/
if(\App::$module_loaded) {
+ if (( \App::$module === 'channel' ) && argc() > 1) {
+ \App::$channel_links = [
+ [
+ 'rel' => 'lrdd',
+ 'type' => 'application/xrd+xml',
+ 'url' => z_root() . '/xrd?f=&uri=acct%3A' . argv(1) . '%40' . \App::get_hostname()
+ ],
+ [
+ 'rel' => 'jrd',
+ 'type' => 'application/jrd+json',
+ 'url' => z_root() . '/.well-known/webfinger?f=&resource=acct%3A' . argv(1) . '%40' . \App::get_hostname()
+ ],
+ ];
+ $x = [ 'channel_address' => argv(1), 'channel_links' => \App::$channel_links ];
+ call_hooks('channel_links', $x );
+ \App::$channel_links = $x['channel_links'];
+ header('Link: ' . \App::get_channel_links());
+ }
+
\App::$page['page_title'] = \App::$module;
$placeholder = '';
diff --git a/Zotlabs/Widget/Common_friends.php b/Zotlabs/Widget/Common_friends.php
new file mode 100644
index 000000000..a67b9312c
--- /dev/null
+++ b/Zotlabs/Widget/Common_friends.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Zotlabs\Widget;
+
+require_once('include/contact_widgets.php');
+
+class Common_friends {
+
+ function widget($arr) {
+
+ if((! \App::$profile['profile_uid'])
+ || (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_contacts'))) {
+ return '';
+ }
+
+ return common_friends_visitor_widget(\App::$profile['profile_uid']);
+
+ }
+}
diff --git a/Zotlabs/Widget/Wiki_pages.php b/Zotlabs/Widget/Wiki_pages.php
index f98081da0..ac44b8d88 100644
--- a/Zotlabs/Widget/Wiki_pages.php
+++ b/Zotlabs/Widget/Wiki_pages.php
@@ -53,9 +53,12 @@ class Wiki_pages {
'$addnew' => t('Add new page'),
'$typelock' => $typelock,
'$lockedtype' => $w['mimeType'],
- '$mimetype' => mimetype_select(0,$w['mimeType'], [ 'text/markdown','text/bbcode', 'text/plain' ]),
+ '$mimetype' => mimetype_select(0,$w['mimeType'],
+ [ 'text/markdown' => t('Markdown'), 'text/bbcode' => t('BBcode'), 'text/plain' => t('Text') ]),
'$pageName' => array('pageName', t('Page name')),
- '$refresh' => $arr['refresh']
+ '$refresh' => $arr['refresh'],
+ '$options' => t('Options'),
+ '$submit' => t('Submit')
));
}
}