From 1c6f301d8faf2e6a5939e47c7a83655615bfc762 Mon Sep 17 00:00:00 2001 From: friendica Date: Wed, 5 Dec 2012 16:44:07 -0800 Subject: y'all got mail --- include/crypto.php | 6 ++- include/items.php | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/notifier.php | 126 +++++++++++++++++++++++++++++-------------------- include/text.php | 21 +++++++++ include/zot.php | 51 ++++++++++++++++++-- version.inc | 2 +- 6 files changed, 279 insertions(+), 56 deletions(-) diff --git a/include/crypto.php b/include/crypto.php index c5901f085..a646910a1 100644 --- a/include/crypto.php +++ b/include/crypto.php @@ -4,7 +4,8 @@ require_once('library/ASNValue.class.php'); require_once('library/asn1.php'); function rsa_sign($data,$key,$alg = 'sha256') { - + if(! $key) + return 'no key'; $sig = ''; openssl_sign($data,$sig,$key,$alg); return $sig; @@ -12,6 +13,9 @@ function rsa_sign($data,$key,$alg = 'sha256') { function rsa_verify($data,$sig,$key,$alg = 'sha256') { + if(! $key) + return false; + $verify = openssl_verify($data,$sig,$key,$alg); return $verify; } diff --git a/include/items.php b/include/items.php index 493a4e2f2..76e378d79 100755 --- a/include/items.php +++ b/include/items.php @@ -514,6 +514,7 @@ function get_item_elements($x) { } + function import_author_xchan($x) { $r = q("select hubloc_url from hubloc where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and (hubloc_flags & %d) limit 1", dbesc($x['guid']), @@ -672,6 +673,58 @@ function encode_item_flags($item) { return $ret; } +function encode_mail($item) { + $x = array(); + $x['type'] = 'mail'; + + logger('encode_mail: ' . print_r($item,true)); + + $x['message_id'] = $item['uri']; + $x['message_parent'] = $item['parent_uri']; + $x['created'] = $item['created']; + $x['title'] = $item['title']; + $x['body'] = $item['body']; + $x['from'] = encode_item_xchan($item['from']); + $x['to'] = encode_item_xchan($item['to']); + + return $x; +} + + + +function get_mail_elements($x) { + + $arr = array(); + + $arr['body'] = (($x['body']) ? htmlentities($x['body'],ENT_COMPAT,'UTF-8') : ''); + + $arr['created'] = datetime_convert('UTC','UTC',$x['created']); + + if($arr['created'] > datetime_convert()) + $arr['created'] = datetime_convert(); + + $arr['title'] = (($x['title']) ? htmlentities($x['title'], ENT_COMPAT,'UTF-8') : ''); + $arr['uri'] = (($x['message_id']) ? htmlentities($x['message_id'], ENT_COMPAT,'UTF-8') : ''); + $arr['parent_uri'] = (($x['message_parent']) ? htmlentities($x['message_parent'], ENT_COMPAT,'UTF-8') : ''); + + + if(import_author_xchan($x['from'])) + $arr['from_xchan'] = base64url_encode(hash('whirlpool',$x['from']['guid'] . $x['from']['guid_sig'], true)); + else + return array(); + + if(import_author_xchan($x['to'])) + $arr['to_xchan'] = base64url_encode(hash('whirlpool',$x['to']['guid'] . $x['to']['guid_sig'], true)); + else + return array(); + + + return $arr; + +} + + + function get_atom_elements($feed,$item) { require_once('library/HTMLPurifier.auto.php'); @@ -1556,6 +1609,82 @@ function tgroup_check($uid,$item) { } +function mail_store($arr) { + + if(! $arr['channel_id']) { + logger('mail_store: no uid'); + return 0; + } + + if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false)) + $arr['body'] = escape_tags($arr['body']); + + $arr['account_id'] = ((x($arr,'account_id')) ? intval($arr['account_id']) : 0); + $arr['uri'] = ((x($arr,'uri')) ? notags(trim($arr['uri'])) : random_string()); + $arr['from_xchan'] = ((x($arr,'from_xchan')) ? notags(trim($arr['from_xchan'])) : ''); + $arr['to_xchan'] = ((x($arr,'to_xchan')) ? notags(trim($arr['to_xchan'])) : ''); + $arr['created'] = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert()); + $arr['title'] = ((x($arr,'title')) ? notags(trim($arr['title'])) : ''); + $arr['parent_uri'] = ((x($arr,'parent_uri')) ? notags(trim($arr['parent_uri'])) : ''); + $arr['body'] = ((x($arr,'body')) ? trim($arr['body']) : ''); + $arr['mail_flags'] = ((x($arr,'mail_flags')) ? intval($arr['mail_flags']) : 0 ); + + + $r = q("SELECT `id` FROM mail WHERE `uri` = '%s' AND channel_id = %d LIMIT 1", + dbesc($arr['uri']), + intval($arr['channel_id']) + ); + if($r) { + logger('mail_store: duplicate item ignored. ' . print_r($arr,true)); + return 0; + } + + call_hooks('post_mail',$arr); + + if(x($arr,'cancel')) { + logger('mail_store: post cancelled by plugin.'); + return 0; + } + + dbesc_array($arr); + + logger('mail_store: ' . print_r($arr,true), LOGGER_DATA); + + $r = dbq("INSERT INTO mail (`" + . implode("`, `", array_keys($arr)) + . "`) VALUES ('" + . implode("', '", array_values($arr)) + . "')" ); + + // find the item we just created + + $r = q("SELECT `id` FROM mail WHERE `uri` = '%s' AND `channel_id` = %d ORDER BY `id` ASC ", + $arr['uri'], // already dbesc'd + intval($arr['channel_id']) + ); + + if($r) { + $current_post = $r[0]['id']; + logger('mail_store: created item ' . $current_post, LOGGER_DEBUG); + } + else { + logger('mail_store: could not locate created item'); + return 0; + } + if(count($r) > 1) { + logger('mail_store: duplicated post occurred. Removing duplicates.'); + q("DELETE FROM mail WHERE `uri` = '%s' AND `channel_id` = %d AND `id` != %d ", + $arr['uri'], + intval($arr['channel_id']), + intval($current_post) + ); + } + + call_hooks('post_mail_end',$arr); + return $current_post; +} + + diff --git a/include/notifier.php b/include/notifier.php index da3cf35a6..c95caf942 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -130,16 +130,26 @@ function notifier_run($argv, $argc){ if($cmd === 'mail') { $normal_mode = false; $mail = true; + $private = true; $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1", intval($item_id) ); if(! count($message)){ return; } - $uid = $message[0]['uid']; - $recipients[] = $message[0]['contact-id']; + xchan_mail_query($message[0]); + $uid = $message[0]['channel_id']; + $recipients[] = $message[0]['to_xchan']; $item = $message[0]; + $encoded_item = encode_mail($item); +dbg(1); + $s = q("select * from channel where channel_id = %d limit 1", + intval($item['channel_id']) + ); + if($s) + $channel = $s[0]; +dbg(0); } elseif($cmd === 'expire') { $normal_mode = false; @@ -241,66 +251,80 @@ function notifier_run($argv, $argc){ } } - logger('notifier: encoded item: ' . print_r($encoded_item,true)); + } - stringify_array_elms($recipients); - if(! $recipients) - return; - logger('notifier: recipients: ' . print_r($recipients,true)); + // Generic delivery section, we have an encoded item and recipients + // Now start the delivery process - // Now we have collected recipients (except for external mentions, FIXME) - // Let's reduce this to a set of hubs. + logger('notifier: encoded item: ' . print_r($encoded_item,true)); - $r = q("select distinct(hubloc_callback),hubloc_host,hubloc_sitekey from hubloc - where hubloc_hash in (" . implode(',',$recipients) . ") group by hubloc_callback"); - if(! $r) { - logger('notifier: no hubs'); - return; - } - $hubs = $r; - - $interval = ((get_config('system','delivery_interval') !== false) - ? intval(get_config('system','delivery_interval')) : 2 ); - - $deliveries_per_process = intval(get_config('system','delivery_batch_count')); - - if($deliveries_per_process <= 0) - $deliveries_per_process = 1; - - $deliver = array(); - - foreach($hubs as $hub) { - $hash = random_string(); - $n = zot_build_packet($channel,'notify',null,(($private) ? $hub['hubloc_sitekey'] : null),$hash); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s' )", - dbesc($hash), - intval($target_item['aid']), - intval($target_item['uid']), - dbesc($hub['hubloc_callback']), - intval(1), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($n), - dbesc(json_encode($encoded_item)) - ); - $deliver[] = $hash; + stringify_array_elms($recipients); + if(! $recipients) + return; + logger('notifier: recipients: ' . print_r($recipients,true)); - if(count($deliver) >= $deliveries_per_process) { - proc_run('php','include/deliver.php',$deliver); - $deliver = array(); - if($interval) - @time_sleep_until(microtime(true) + (float) $interval); - } + + $env_recips = null; + if($private) { + $r = q("select xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . implode(',',$recipients) . ")"); + if($r) { + $env_recips = array(); + foreach($r as $rr) + $env_recips[] = array('guid' => $rr['xchan_guid'],'guid_sig' => $rr['xchan_guid_sig']); } + } - // catch any stragglers + // Now we have collected recipients (except for external mentions, FIXME) + // Let's reduce this to a set of hubs. + + $r = q("select distinct(hubloc_callback),hubloc_host,hubloc_sitekey from hubloc + where hubloc_hash in (" . implode(',',$recipients) . ") group by hubloc_callback"); + if(! $r) { + logger('notifier: no hubs'); + return; + } + $hubs = $r; + + $interval = ((get_config('system','delivery_interval') !== false) + ? intval(get_config('system','delivery_interval')) : 2 ); + + $deliveries_per_process = intval(get_config('system','delivery_batch_count')); + + if($deliveries_per_process <= 0) + $deliveries_per_process = 1; + + $deliver = array(); + + foreach($hubs as $hub) { + $hash = random_string(); + $n = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash); + q("insert into outq ( outq_hash, outq_account, outq_channel, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s' )", + dbesc($hash), + intval($target_item['aid']), + intval($target_item['uid']), + dbesc($hub['hubloc_callback']), + intval(1), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($n), + dbesc(json_encode($encoded_item)) + ); + $deliver[] = $hash; - if(count($deliver)) { + if(count($deliver) >= $deliveries_per_process) { proc_run('php','include/deliver.php',$deliver); + $deliver = array(); + if($interval) + @time_sleep_until(microtime(true) + (float) $interval); } - } + // catch any stragglers + + if(count($deliver)) { + proc_run('php','include/deliver.php',$deliver); + } + if($normal_mode) call_hooks('notifier_normal',$target_item); diff --git a/include/text.php b/include/text.php index ee95646b7..b97b21981 100644 --- a/include/text.php +++ b/include/text.php @@ -1722,6 +1722,27 @@ function xchan_query(&$items) { } +function xchan_mail_query(&$item) { + $arr = array(); + $chans = null; + if($item) { + if($item['from_xchan'] && (! in_array($item['from_xchan'],$arr))) + $arr[] = "'" . dbesc($item['from_xchan']) . "'"; + if($item['to_xchan'] && (! in_array($item['to_xchan'],$arr))) + $arr[] = "'" . dbesc($item['to_xchan']) . "'"; + } + + if(count($arr)) { + $chans = q("select xchan.*,hubloc.* from xchan left join hubloc on hubloc_hash = xchan_hash + where xchan_hash in (" . implode(',', $arr) . ") and ( hubloc_flags & " . intval(HUBLOC_FLAGS_PRIMARY) . " )"); + } + if($chans) { + $item['from'] = find_xchan_in_array($item['from_xchan'],$chans); + $item['to'] = find_xchan_in_array($item['to_xchan'],$chans); + } +} + + function find_xchan_in_array($xchan,$arr) { if(count($arr)) { foreach($arr as $x) { diff --git a/include/zot.php b/include/zot.php index 20752a291..2d2bc92c6 100644 --- a/include/zot.php +++ b/include/zot.php @@ -666,6 +666,8 @@ function zot_import($arr) { $i['notify'] = json_decode(aes_unencapsulate($i['notify'],get_config('system','prvkey')),true); } + logger('zot_import: notify: ' . print_r($i['notify'],true)); + $i['notify']['sender']['hash'] = base64url_encode(hash('whirlpool',$i['notify']['sender']['guid'] . $i['notify']['sender']['guid_sig'], true)); $deliveries = null; @@ -673,11 +675,13 @@ function zot_import($arr) { logger('specific recipients'); $recip_arr = array(); foreach($i['notify']['recipients'] as $recip) { - $recip_arr[] = array('hash' => base64url_encode(hash('whirlpool',$recip['guid'] . $recip['guid_sig'], true))); + $recip_arr[] = base64url_encode(hash('whirlpool',$recip['guid'] . $recip['guid_sig'], true)); } + logger('recip_arr: ' . print_r($recip_arr,true)); stringify_array_elms($recip_arr); - $recips = ids_to_querystr($recip_arr,'hash'); - + logger('recip_arr: ' . print_r($recip_arr,true)); + $recips = implode(',',$recip_arr); + logger('recips: ' . $recips); $r = q("select channel_hash as hash from channel where channel_hash in ( " . $recips . " ) "); if(! $r) continue; @@ -709,6 +713,13 @@ function zot_import($arr) { } elseif($i['message']['type'] === 'mail') { + $arr = get_mail_elements($i['message']); + + logger('Mail received: ' . print_r($arr,true)); + logger('Mail recipients: ' . print_r($deliveries,true)); + + + process_mail_delivery($i['notify']['sender'],$arr,$deliveries); } } @@ -822,6 +833,7 @@ function process_delivery($sender,$arr,$deliveries,$relay) { } } + function update_imported_item($sender,$item,$uid) { // FIXME logger('update_imported_item'); @@ -857,3 +869,36 @@ function delete_imported_item($sender,$item,$uid) { } +function process_mail_delivery($sender,$arr,$deliveries) { + + + foreach($deliveries as $d) { + $r = q("select * from channel where channel_hash = '%s' limit 1", + dbesc($d['hash']) + ); + + if(! $r) + continue; + + $channel = $r[0]; + + if(! perm_is_allowed($channel['channel_id'],$sender['hash'],'post_mail')) { + logger("permission denied for mail delivery {$channel['channel_id']}"); + continue; + } + + $r = q("select id from mail where uri = '%s' and channel_id = %d limit 1", + dbesc($arr['uri']), + intval($channel['channel_id']) + ); + if($r) { + logger('duplicate mail received'); + continue; + } + else { + $arr['account_id'] = $channel['channel_account_id']; + $arr['channel_id'] = $channel['channel_id']; + $item_id = mail_store($arr); + } + } +} diff --git a/version.inc b/version.inc index fe7087514..eeab63b3f 100644 --- a/version.inc +++ b/version.inc @@ -1 +1 @@ -2012-12-04.159 +2012-12-05.160 -- cgit v1.2.3