Example #1
0
function crepair_post(&$a)
{
    if (!local_user()) {
        return;
    }
    $cid = $a->argc > 1 ? intval($a->argv[1]) : 0;
    if ($cid) {
        $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($cid), intval(local_user()));
    }
    if (!count($r)) {
        return;
    }
    $contact = $r[0];
    $nick = x($_POST, 'nick') ? $_POST['nick'] : '';
    $url = x($_POST, 'url') ? $_POST['url'] : '';
    $request = x($_POST, 'request') ? $_POST['request'] : '';
    $confirm = x($_POST, 'confirm') ? $_POST['confirm'] : '';
    $notify = x($_POST, 'notify') ? $_POST['notify'] : '';
    $poll = x($_POST, 'poll') ? $_POST['poll'] : '';
    $attag = x($_POST, 'attag') ? $_POST['attag'] : '';
    $photo = x($_POST, 'photo') ? $_POST['photo'] : '';
    $r = q("UPDATE `contact` SET `nick` = '%s', `url` = '%s', `request` = '%s', `confirm` = '%s', `notify` = '%s', `poll` = '%s', `attag` = '%s' \n\t\tWHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($nick), dbesc($url), dbesc($request), dbesc($confirm), dbesc($notify), dbesc($poll), dbesc($attag), intval($contact['id']), local_user());
    if ($photo) {
        logger('mod-crepair: updating photo from ' . $photo);
        require_once "Photo.php";
        $photos = import_profile_photo($photo, local_user(), $contact['id']);
        $x = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d LIMIT 1\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact['id']));
    }
    if ($r) {
        info(t('Contact settings applied.') . EOL);
    } else {
        notice(t('Contact update failed.') . EOL);
    }
    return;
}
Example #2
0
File: zot.php Project: Mauru/red
/**
 * @function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED)
 *   Takes an associative array of a fetched discovery packet and updates
 *   all internal data structures which need to be updated as a result.
 * 
 * @param array $arr => json_decoded discovery packet
 * @param int $ud_flags
 *    Determines whether to create a directory update record if any changes occur, default is UPDATE_FLAGS_UPDATED
 *    $ud_flags = UPDATE_FLAGS_FORCED indicates a forced refresh where we unconditionally create a directory update record
 *      this typically occurs once a month for each channel as part of a scheduled ping to notify the directory
 *      that the channel still exists
 * @param array $ud_arr
 *    If set [typically by update_directory_entry()] indicates a specific update table row and more particularly 
 *    contains a particular address (ud_addr) which needs to be updated in that table.
 *
 * @returns array =>  'success' (boolean true or false)
 *                    'message' (optional error string only if success is false)
 */
function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null)
{
    call_hooks('import_xchan', $arr);
    $ret = array('success' => false);
    $dirmode = intval(get_config('system', 'directory_mode'));
    $changed = false;
    $what = '';
    if (!(is_array($arr) && array_key_exists('success', $arr) && $arr['success'])) {
        logger('import_xchan: invalid data packet: ' . print_r($arr, true));
        $ret['message'] = t('Invalid data packet');
        return $ret;
    }
    if (!($arr['guid'] && $arr['guid_sig'])) {
        logger('import_xchan: no identity information provided. ' . print_r($arr, true));
        return $ret;
    }
    $xchan_hash = make_xchan_hash($arr['guid'], $arr['guid_sig']);
    $import_photos = false;
    if (!rsa_verify($arr['guid'], base64url_decode($arr['guid_sig']), $arr['key'])) {
        logger('import_xchan: Unable to verify channel signature for ' . $arr['address']);
        $ret['message'] = t('Unable to verify channel signature');
        return $ret;
    }
    logger('import_xchan: ' . $xchan_hash, LOGGER_DEBUG);
    $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($xchan_hash));
    if (!array_key_exists('connect_url', $arr)) {
        $arr['connect_url'] = '';
    }
    if (strpos($arr['address'], '/') !== false) {
        $arr['address'] = substr($arr['address'], 0, strpos($arr['address'], '/'));
    }
    if ($r) {
        if ($r[0]['xchan_photo_date'] != $arr['photo_updated']) {
            $import_photos = true;
        }
        // if we import an entry from a site that's not ours and either or both of us is off the grid - hide the entry.
        // TODO: check if we're the same directory realm, which would mean we are allowed to see it
        $dirmode = get_config('system', 'directory_mode');
        if (($arr['site']['directory_mode'] === 'standalone' || $dirmode & DIRECTORY_MODE_STANDALONE) && $arr['site']['url'] != z_root()) {
            $arr['searchable'] = false;
        }
        $hidden = 1 - intval($arr['searchable']);
        // Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1
        if (($r[0]['xchan_flags'] & XCHAN_FLAGS_HIDDEN) != $hidden) {
            $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_HIDDEN;
        } else {
            $new_flags = $r[0]['xchan_flags'];
        }
        $adult = $r[0]['xchan_flags'] & XCHAN_FLAGS_SELFCENSORED ? true : false;
        $adult_changed = intval($adult) != intval($arr['adult_content']) ? true : false;
        if ($adult_changed) {
            $new_flags = $new_flags ^ XCHAN_FLAGS_SELFCENSORED;
        }
        $deleted = $r[0]['xchan_flags'] & XCHAN_FLAGS_DELETED ? true : false;
        $deleted_changed = intval($deleted) != intval($arr['deleted']) ? true : false;
        if ($deleted_changed) {
            $new_flags = $new_flags ^ XCHAN_FLAGS_DELETED;
        }
        if ($r[0]['xchan_name_date'] != $arr['name_updated'] || $r[0]['xchan_connurl'] != $arr['connections_url'] || $r[0]['xchan_flags'] != $new_flags || $r[0]['xchan_addr'] != $arr['address'] || $r[0]['xchan_follow'] != $arr['follow_url'] || $r[0]['xchan_connpage'] != $arr['connect_url'] || $r[0]['xchan_url'] != $arr['url']) {
            $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s', \n\t\t\t\txchan_connpage = '%s', xchan_flags = %d,\n\t\t\t\txchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s' limit 1", dbesc($arr['name']), dbesc($arr['name_updated']), dbesc($arr['connections_url']), dbesc($arr['follow_url']), dbesc($arr['connect_url']), intval($new_flags), dbesc($arr['address']), dbesc($arr['url']), dbesc($xchan_hash));
            logger('import_xchan: existing: ' . print_r($r[0], true), LOGGER_DATA);
            logger('import_xchan: new: ' . print_r($arr, true), LOGGER_DATA);
            $what .= 'xchan ';
            $changed = true;
        }
    } else {
        $import_photos = true;
        if (($arr['site']['directory_mode'] === 'standalone' || $dirmode & DIRECTORY_MODE_STANDALONE) && $arr['site']['url'] != z_root()) {
            $arr['searchable'] = false;
        }
        $hidden = 1 - intval($arr['searchable']);
        if ($hidden) {
            $new_flags = XCHAN_FLAGS_HIDDEN;
        } else {
            $new_flags = 0;
        }
        if ($arr['adult_content']) {
            $new_flags |= XCHAN_FLAGS_SELFCENSORED;
        }
        if (array_key_exists('deleted', $arr) && $arr['deleted']) {
            $new_flags |= XCHAN_FLAGS_DELETED;
        }
        $x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype,\n\t\t\t\txchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags)\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d) ", dbesc($xchan_hash), dbesc($arr['guid']), dbesc($arr['guid_sig']), dbesc($arr['key']), dbesc($arr['photo_mimetype']), dbesc($arr['photo']), dbesc($arr['address']), dbesc($arr['url']), dbesc($arr['connections_url']), dbesc($arr['follow_url']), dbesc($arr['connect_url']), dbesc($arr['name']), dbesc('zot'), dbesc($arr['photo_updated']), dbesc($arr['name_updated']), intval($new_flags));
        $what .= 'new_xchan';
        $changed = true;
    }
    if ($import_photos) {
        require_once 'include/photo/photo_driver.php';
        // see if this is a channel clone that's hosted locally - which we treat different from other xchans/connections
        $local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1", dbesc($xchan_hash));
        if ($local) {
            $ph = z_fetch_url($arr['photo'], true);
            if ($ph['success']) {
                import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']);
                // reset the names in case they got messed up when we had a bug in this function
                $photos = array(z_root() . '/photo/profile/l/' . $local[0]['channel_id'], z_root() . '/photo/profile/m/' . $local[0]['channel_id'], z_root() . '/photo/profile/s/' . $local[0]['channel_id'], $arr['photo_mimetype'], false);
            }
        } else {
            $photos = import_profile_photo($arr['photo'], $xchan_hash);
        }
        if ($photos) {
            if ($photos[4]) {
                // importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
                // This often happens when somebody joins the matrix with a bad cert.
                $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\t\twhere xchan_hash = '%s' limit 1", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($xchan_hash));
            } else {
                $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\t\twhere xchan_hash = '%s' limit 1", dbesc(datetime_convert('UTC', 'UTC', $arr['photo_updated'])), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($xchan_hash));
            }
            $what .= 'photo ';
            $changed = true;
        }
    }
    // what we are missing for true hub independence is for any changes in the primary hub to
    // get reflected not only in the hublocs, but also to update the URLs and addr in the appropriate xchan
    if ($arr['locations']) {
        $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'", dbesc($xchan_hash));
        // See if a primary is specified
        $has_primary = false;
        foreach ($arr['locations'] as $location) {
            if ($location['primary']) {
                $has_primary = true;
                break;
            }
        }
        foreach ($arr['locations'] as $location) {
            if (!rsa_verify($location['url'], base64url_decode($location['url_sig']), $arr['key'])) {
                logger('import_xchan: Unable to verify site signature for ' . $location['url']);
                $ret['message'] .= sprintf(t('Unable to verify site signature for %s'), $location['url']) . EOL;
                continue;
            }
            // Ensure that they have one primary hub
            if (!$has_primary) {
                $location['primary'] = true;
            }
            for ($x = 0; $x < count($xisting); $x++) {
                if ($xisting[$x]['hubloc_url'] === $location['url'] && $xisting[$x]['hubloc_sitekey'] === $location['sitekey']) {
                    $xisting[$x]['updated'] = true;
                }
            }
            if (!$location['sitekey']) {
                logger('import_xchan: empty hubloc sitekey. ' . print_r($location, true));
                continue;
            }
            // Catch some malformed entries from the past which still exist
            if (strpos($location['address'], '/') !== false) {
                $location['address'] = substr($location['address'], 0, strpos($location['address'], '/'));
            }
            // match as many fields as possible in case anything at all changed.
            $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ", dbesc($xchan_hash), dbesc($arr['guid']), dbesc($arr['guid_sig']), dbesc($location['url']), dbesc($location['url_sig']), dbesc($location['host']), dbesc($location['address']), dbesc($location['callback']), dbesc($location['sitekey']));
            if ($r) {
                logger('import_xchan: hub exists: ' . $location['url']);
                // update connection timestamp if this is the site we're talking to
                if ($location['url'] == $arr['site']['url']) {
                    q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d limit 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($r[0]['hubloc_id']));
                }
                if ($r[0]['hubloc_status'] & HUBLOC_OFFLINE) {
                    q("update hubloc set hubloc_status = (hubloc_status ^ %d) where hubloc_id = %d limit 1", intval(HUBLOC_OFFLINE), intval($r[0]['hubloc_id']));
                    if ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) {
                        q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_id = %d limit 1", intval(HUBLOC_FLAGS_ORPHANCHECK), intval($r[0]['hubloc_id']));
                    }
                    q("update xchan set xchan_flags = (xchan_flags ^ %d) where (xchan_flags & %d) and xchan_hash = '%s' limit 1", intval(XCHAN_FLAGS_ORPHAN), intval(XCHAN_FLAGS_ORPHAN), dbesc($xchan_hash));
                }
                // Remove pure duplicates
                if (count($r) > 1) {
                    for ($h = 1; $h < count($r); $h++) {
                        q("delete from hubloc where hubloc_id = %d limit 1", intval($r[$h]['hubloc_id']));
                    }
                }
                if ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY && !$location['primary'] || !($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) && $location['primary']) {
                    $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1", intval(HUBLOC_FLAGS_PRIMARY), dbesc(datetime_convert()), intval($r[0]['hubloc_id']));
                    $what = 'primary_hub ';
                    $changed = true;
                }
                if ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED && !$location['deleted'] || !($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED) && $location['deleted']) {
                    $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1", intval(HUBLOC_FLAGS_DELETED), dbesc(datetime_convert()), intval($r[0]['hubloc_id']));
                    $what = 'delete_hub ';
                    $changed = true;
                }
                continue;
            }
            // new hub claiming to be primary. Make it so.
            if (intval($location['primary'])) {
                $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_hash = '%s' and (hubloc_flags & %d )", intval(HUBLOC_FLAGS_PRIMARY), dbesc(datetime_convert()), dbesc($xchan_hash), intval(HUBLOC_FLAGS_PRIMARY));
            }
            logger('import_xchan: new hub: ' . $location['url']);
            $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_flags, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_updated, hubloc_connected)\n\t\t\t\t\tvalues ( '%s','%s','%s','%s', '%s', %d ,'%s','%s','%s','%s','%s','%s','%s')", dbesc($arr['guid']), dbesc($arr['guid_sig']), dbesc($xchan_hash), dbesc($location['address']), dbesc('zot'), intval(intval($location['primary']) ? HUBLOC_FLAGS_PRIMARY : 0), dbesc($location['url']), dbesc($location['url_sig']), dbesc($location['host']), dbesc($location['callback']), dbesc($location['sitekey']), dbesc(datetime_convert()), dbesc(datetime_convert()));
            $what .= 'newhub ';
            $changed = true;
        }
        // get rid of any hubs we have for this channel which weren't reported.
        // This was needed at one time to resolve complicated cross-site inconsistencies, but can cause sync conflict.
        // currently disabled.
        //		if($xisting) {
        //			foreach($xisting as $x) {
        //				if(! array_key_exists('updated',$x)) {
        //					logger('import_xchan: removing unreferenced hub location ' . $x['hubloc_url']);
        //					$r = q("delete from hubloc where hubloc_id = %d limit 1",
        //						intval($x['hubloc_id'])
        //					);
        //					$what .= 'removed_hub';
        //					$changed = true;
        //				}
        //			}
        //		}
    }
    // Which entries in the update table are we interested in updating?
    $address = $ud_arr && $ud_arr['ud_addr'] ? $ud_arr['ud_addr'] : $arr['address'];
    // Are we a directory server of some kind?
    $other_realm = false;
    $realm = get_directory_realm();
    if (array_key_exists('site', $arr) && array_key_exists('realm', $arr['site']) && strpos($arr['site']['realm'], $realm) === false) {
        $other_realm = true;
    }
    if ($dirmode != DIRECTORY_MODE_NORMAL) {
        // We're some kind of directory server. However we can only add directory information
        // if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by
        // including the parent realm in the name. e.g. 'RED_GLOBAL:foo' would allow an entry to
        // be in directories for the local realm (foo) and also the RED_GLOBAL realm.
        if (array_key_exists('profile', $arr) && is_array($arr['profile']) && !$other_realm) {
            $profile_changed = import_directory_profile($xchan_hash, $arr['profile'], $address, $ud_flags, 1);
            if ($profile_changed) {
                $what .= 'profile ';
                $changed = true;
            }
        } else {
            logger('import_xchan: profile not available - hiding');
            // they may have made it private
            $r = q("delete from xprof where xprof_hash = '%s' limit 1", dbesc($xchan_hash));
            $r = q("delete from xtag where xtag_hash = '%s' limit 1", dbesc($xchan_hash));
        }
    }
    if (array_key_exists('site', $arr) && is_array($arr['site'])) {
        $profile_changed = import_site($arr['site'], $arr['key']);
        if ($profile_changed) {
            $what .= 'site ';
            $changed = true;
        }
    }
    if ($changed || $ud_flags == UPDATE_FLAGS_FORCED) {
        $guid = random_string() . '@' . get_app()->get_hostname();
        update_modtime($xchan_hash, $guid, $address, $ud_flags);
        logger('import_xchan: changed: ' . $what, LOGGER_DEBUG);
    } elseif (!$ud_flags) {
        // nothing changed but we still need to update the updates record
        q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d) ", intval(UPDATE_FLAGS_UPDATED), dbesc($address), intval(UPDATE_FLAGS_UPDATED));
    }
    if (!x($ret, 'message')) {
        $ret['success'] = true;
        $ret['hash'] = $xchan_hash;
    }
    logger('import_xchan: result: ' . print_r($ret, true), LOGGER_DATA);
    return $ret;
}
Example #3
0
function import_author_unknown($x)
{
    if (!$x['url']) {
        return false;
    }
    $r = q("select xchan_hash from xchan where xchan_network = 'unknown' and xchan_url = '%s' limit 1", dbesc($x['url']));
    if ($r) {
        logger('import_author_unknown: in cache', LOGGER_DEBUG);
        return $r[0]['xchan_hash'];
    }
    $name = trim($x['name']);
    $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network )\n\t\tvalues ( '%s', '%s', '%s', '%s', '%s' )", dbesc($x['url']), dbesc($x['url']), dbesc($x['url']), dbesc($name ? $name : t('(Unknown)')), dbesc('unknown'));
    if ($r && $x['photo']) {
        $photos = import_profile_photo($x['photo']['src'], $x['url']);
        if ($photos) {
            /** @bug $arr is undefined in this SQL query */
            $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_url = '%s' and xchan_network = 'unknown'", dbesc(datetime_convert('UTC', 'UTC', $arr['photo_updated'])), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($x['url']));
            if ($r) {
                return $x['url'];
            }
        }
    }
    return false;
}
Example #4
0
File: apps.php Project: Mauru/red
function app_update($arr)
{
    $darray = array();
    $ret = array('success' => false);
    $darray['app_url'] = x($arr, 'url') ? $arr['url'] : '';
    $darray['app_channel'] = x($arr, 'uid') ? $arr['uid'] : 0;
    $darray['app_id'] = x($arr, 'guid') ? $arr['guid'] : 0;
    if (!$darray['app_url'] || !$darray['app_channel'] || !$darray['app_id']) {
        return $ret;
    }
    if ($arr['photo'] && !strstr($arr['photo'], z_root())) {
        $x = import_profile_photo($arr['photo'], get_observer_hash(), true);
        $arr['photo'] = $x[1];
    }
    $darray['app_sig'] = x($arr, 'sig') ? $arr['sig'] : '';
    $darray['app_author'] = x($arr, 'author') ? $arr['author'] : get_observer_hash();
    $darray['app_name'] = x($arr, 'name') ? escape_tags($arr['name']) : t('Unknown');
    $darray['app_desc'] = x($arr, 'desc') ? escape_tags($arr['desc']) : '';
    $darray['app_photo'] = x($arr, 'photo') ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80);
    $darray['app_version'] = x($arr, 'version') ? escape_tags($arr['version']) : '';
    $darray['app_addr'] = x($arr, 'addr') ? escape_tags($arr['addr']) : '';
    $darray['app_price'] = x($arr, 'price') ? escape_tags($arr['price']) : '';
    $darray['app_page'] = x($arr, 'page') ? escape_tags($arr['page']) : '';
    $darray['app_requires'] = x($arr, 'requires') ? escape_tags($arr['requires']) : '';
    $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s' where app_id = '%s' and app_channel = %d limit 1", dbesc($darray['app_sig']), dbesc($darray['app_author']), dbesc($darray['app_name']), dbesc($darray['app_desc']), dbesc($darray['app_url']), dbesc($darray['app_photo']), dbesc($darray['app_version']), dbesc($darray['app_addr']), dbesc($darray['app_price']), dbesc($darray['app_page']), dbesc($darray['app_requires']), dbesc($darray['app_id']), intval($darray['app_channel']));
    if ($r) {
        $ret['success'] = true;
        $ret['app_id'] = $darray['app_id'];
    }
    return $ret;
}
Example #5
0
function new_follower($importer, $contact, $datarray, $item, $sharing = false)
{
    $url = notags(trim($datarray['author-link']));
    $name = notags(trim($datarray['author-name']));
    $photo = notags(trim($datarray['author-avatar']));
    if (is_object($item)) {
        $rawtag = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
        if ($rawtag && $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data']) {
            $nick = $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'];
        }
    } else {
        $nick = $item;
    }
    if (is_array($contact)) {
        if ($contact['network'] == NETWORK_OSTATUS && $contact['rel'] == CONTACT_IS_SHARING || $sharing && $contact['rel'] == CONTACT_IS_FOLLOWER) {
            $r = q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($contact['id']), intval($importer['uid']));
        }
        // send email notification to owner?
    } else {
        // create contact record
        $r = q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,\n\t\t\t`blocked`, `readonly`, `pending`, `writable`)\n\t\t\tVALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, 1)", intval($importer['uid']), dbesc(datetime_convert()), dbesc($url), dbesc(normalise_link($url)), dbesc($name), dbesc($nick), dbesc($photo), dbesc($sharing ? NETWORK_ZOT : NETWORK_OSTATUS), intval($sharing ? CONTACT_IS_SHARING : CONTACT_IS_FOLLOWER));
        $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 LIMIT 1", intval($importer['uid']), dbesc($url));
        if (count($r)) {
            $contact_record = $r[0];
            $photos = import_profile_photo($photo, $importer["uid"], $contact_record["id"]);
            q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($contact_record["id"]));
        }
        $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer['uid']));
        $a = get_app();
        if (count($r) and !in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE))) {
            // create notification
            $hash = random_string();
            if (is_array($contact_record)) {
                $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `hash`, `datetime`)\n\t\t\t\t\tVALUES ( %d, %d, 0, 0, '%s', '%s' )", intval($importer['uid']), intval($contact_record['id']), dbesc($hash), dbesc(datetime_convert()));
            }
            if (intval($r[0]['def_gid'])) {
                require_once 'include/group.php';
                group_add_member($r[0]['uid'], '', $contact_record['id'], $r[0]['def_gid']);
            }
            if ($r[0]['notify-flags'] & NOTIFY_INTRO && in_array($r[0]['page-flags'], array(PAGE_NORMAL))) {
                notification(array('type' => NOTIFY_INTRO, 'notify_flags' => $r[0]['notify-flags'], 'language' => $r[0]['language'], 'to_name' => $r[0]['username'], 'to_email' => $r[0]['email'], 'uid' => $r[0]['uid'], 'link' => $a->get_baseurl() . '/notifications/intro', 'source_name' => strlen(stripslashes($contact_record['name'])) ? stripslashes($contact_record['name']) : t('[Name Withheld]'), 'source_link' => $contact_record['url'], 'source_photo' => $contact_record['photo'], 'verb' => $sharing ? ACTIVITY_FRIEND : ACTIVITY_FOLLOW, 'otype' => 'intro'));
            }
        } elseif (count($r) and in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE))) {
            $r = q("UPDATE `contact` SET `pending` = 0 WHERE `uid` = %d AND `url` = '%s' AND `pending` LIMIT 1", intval($importer['uid']), dbesc($url));
        }
    }
}
Example #6
0
/**
 * @brief Takes an associative array of a fetched discovery packet and updates
 *   all internal data structures which need to be updated as a result.
 *
 * @param array $arr => json_decoded discovery packet
 * @param int $ud_flags
 *    Determines whether to create a directory update record if any changes occur, default is UPDATE_FLAGS_UPDATED
 *    $ud_flags = UPDATE_FLAGS_FORCED indicates a forced refresh where we unconditionally create a directory update record
 *      this typically occurs once a month for each channel as part of a scheduled ping to notify the directory
 *      that the channel still exists
 * @param array $ud_arr
 *    If set [typically by update_directory_entry()] indicates a specific update table row and more particularly
 *    contains a particular address (ud_addr) which needs to be updated in that table.
 *
 * @return associative array
 *   * \e boolean \b success boolean true or false
 *   * \e string \b message (optional) error string only if success is false
 */
function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null)
{
    call_hooks('import_xchan', $arr);
    $ret = array('success' => false);
    $dirmode = intval(get_config('system', 'directory_mode'));
    $changed = false;
    $what = '';
    if (!(is_array($arr) && array_key_exists('success', $arr) && $arr['success'])) {
        logger('import_xchan: invalid data packet: ' . print_r($arr, true));
        $ret['message'] = t('Invalid data packet');
        return $ret;
    }
    if (!($arr['guid'] && $arr['guid_sig'])) {
        logger('import_xchan: no identity information provided. ' . print_r($arr, true));
        return $ret;
    }
    $xchan_hash = make_xchan_hash($arr['guid'], $arr['guid_sig']);
    $arr['hash'] = $xchan_hash;
    $import_photos = false;
    if (!rsa_verify($arr['guid'], base64url_decode($arr['guid_sig']), $arr['key'])) {
        logger('import_xchan: Unable to verify channel signature for ' . $arr['address']);
        $ret['message'] = t('Unable to verify channel signature');
        return $ret;
    }
    logger('import_xchan: ' . $xchan_hash, LOGGER_DEBUG);
    $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($xchan_hash));
    if (!array_key_exists('connect_url', $arr)) {
        $arr['connect_url'] = '';
    }
    if (strpos($arr['address'], '/') !== false) {
        $arr['address'] = substr($arr['address'], 0, strpos($arr['address'], '/'));
    }
    if ($r) {
        if ($r[0]['xchan_photo_date'] != $arr['photo_updated']) {
            $import_photos = true;
        }
        // if we import an entry from a site that's not ours and either or both of us is off the grid - hide the entry.
        /** @TODO: check if we're the same directory realm, which would mean we are allowed to see it */
        $dirmode = get_config('system', 'directory_mode');
        if (($arr['site']['directory_mode'] === 'standalone' || $dirmode & DIRECTORY_MODE_STANDALONE) && $arr['site']['url'] != z_root()) {
            $arr['searchable'] = false;
        }
        $hidden = 1 - intval($arr['searchable']);
        // Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1
        if (($r[0]['xchan_flags'] & XCHAN_FLAGS_HIDDEN) != $hidden) {
            $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_HIDDEN;
        } else {
            $new_flags = $r[0]['xchan_flags'];
        }
        $adult = $r[0]['xchan_flags'] & XCHAN_FLAGS_SELFCENSORED ? true : false;
        $adult_changed = intval($adult) != intval($arr['adult_content']) ? true : false;
        if ($adult_changed) {
            $new_flags = $new_flags ^ XCHAN_FLAGS_SELFCENSORED;
        }
        $deleted = $r[0]['xchan_flags'] & XCHAN_FLAGS_DELETED ? true : false;
        $deleted_changed = intval($deleted) != intval($arr['deleted']) ? true : false;
        if ($deleted_changed) {
            $new_flags = $new_flags ^ XCHAN_FLAGS_DELETED;
        }
        $public_forum = $r[0]['xchan_flags'] & XCHAN_FLAGS_PUBFORUM ? true : false;
        $pubforum_changed = intval($public_forum) != intval($arr['public_forum']) ? true : false;
        if ($pubforum_changed) {
            $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_PUBFORUM;
        }
        if ($r[0]['xchan_name_date'] != $arr['name_updated'] || $r[0]['xchan_connurl'] != $arr['connections_url'] || $r[0]['xchan_flags'] != $new_flags || $r[0]['xchan_addr'] != $arr['address'] || $r[0]['xchan_follow'] != $arr['follow_url'] || $r[0]['xchan_connpage'] != $arr['connect_url'] || $r[0]['xchan_url'] != $arr['url']) {
            $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s',\n\t\t\t\txchan_connpage = '%s', xchan_flags = %d,\n\t\t\t\txchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s'", dbesc($arr['name'] ? $arr['name'] : '-'), dbesc($arr['name_updated']), dbesc($arr['connections_url']), dbesc($arr['follow_url']), dbesc($arr['connect_url']), intval($new_flags), dbesc($arr['address']), dbesc($arr['url']), dbesc($xchan_hash));
            logger('import_xchan: existing: ' . print_r($r[0], true), LOGGER_DATA);
            logger('import_xchan: new: ' . print_r($arr, true), LOGGER_DATA);
            $what .= 'xchan ';
            $changed = true;
        }
    } else {
        $import_photos = true;
        if (($arr['site']['directory_mode'] === 'standalone' || $dirmode & DIRECTORY_MODE_STANDALONE) && $arr['site']['url'] != z_root()) {
            $arr['searchable'] = false;
        }
        $hidden = 1 - intval($arr['searchable']);
        if ($hidden) {
            $new_flags = XCHAN_FLAGS_HIDDEN;
        } else {
            $new_flags = 0;
        }
        if ($arr['adult_content']) {
            $new_flags |= XCHAN_FLAGS_SELFCENSORED;
        }
        if (array_key_exists('deleted', $arr) && $arr['deleted']) {
            $new_flags |= XCHAN_FLAGS_DELETED;
        }
        $x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype,\n\t\t\t\txchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags)\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d) ", dbesc($xchan_hash), dbesc($arr['guid']), dbesc($arr['guid_sig']), dbesc($arr['key']), dbesc($arr['photo_mimetype']), dbesc($arr['photo']), dbesc($arr['address']), dbesc($arr['url']), dbesc($arr['connections_url']), dbesc($arr['follow_url']), dbesc($arr['connect_url']), dbesc($arr['name'] ? $arr['name'] : '-'), dbesc('zot'), dbescdate($arr['photo_updated']), dbescdate($arr['name_updated']), intval($new_flags));
        $what .= 'new_xchan';
        $changed = true;
    }
    if ($import_photos) {
        require_once 'include/photo/photo_driver.php';
        // see if this is a channel clone that's hosted locally - which we treat different from other xchans/connections
        $local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1", dbesc($xchan_hash));
        if ($local) {
            $ph = z_fetch_url($arr['photo'], true);
            if ($ph['success']) {
                import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']);
                // reset the names in case they got messed up when we had a bug in this function
                $photos = array(z_root() . '/photo/profile/l/' . $local[0]['channel_id'], z_root() . '/photo/profile/m/' . $local[0]['channel_id'], z_root() . '/photo/profile/s/' . $local[0]['channel_id'], $arr['photo_mimetype'], false);
            }
        } else {
            $photos = import_profile_photo($arr['photo'], $xchan_hash);
        }
        if ($photos) {
            if ($photos[4]) {
                // importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
                // This often happens when somebody joins the matrix with a bad cert.
                $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\t\twhere xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($xchan_hash));
            } else {
                $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\t\twhere xchan_hash = '%s'", dbescdate(datetime_convert('UTC', 'UTC', $arr['photo_updated'])), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($xchan_hash));
            }
            $what .= 'photo ';
            $changed = true;
        }
    }
    // what we are missing for true hub independence is for any changes in the primary hub to
    // get reflected not only in the hublocs, but also to update the URLs and addr in the appropriate xchan
    $s = sync_locations($arr, $arr);
    if ($s) {
        if ($s['change_message']) {
            $what .= $s['change_message'];
        }
        if ($s['changed']) {
            $changed = $s['changed'];
        }
        if ($s['message']) {
            $ret['message'] .= $s['message'];
        }
    }
    // Which entries in the update table are we interested in updating?
    $address = $ud_arr && $ud_arr['ud_addr'] ? $ud_arr['ud_addr'] : $arr['address'];
    // Are we a directory server of some kind?
    $other_realm = false;
    $realm = get_directory_realm();
    if (array_key_exists('site', $arr) && array_key_exists('realm', $arr['site']) && strpos($arr['site']['realm'], $realm) === false) {
        $other_realm = true;
    }
    if ($dirmode != DIRECTORY_MODE_NORMAL) {
        // We're some kind of directory server. However we can only add directory information
        // if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by
        // including the parent realm in the name. e.g. 'RED_GLOBAL:foo' would allow an entry to
        // be in directories for the local realm (foo) and also the RED_GLOBAL realm.
        if (array_key_exists('profile', $arr) && is_array($arr['profile']) && !$other_realm) {
            $profile_changed = import_directory_profile($xchan_hash, $arr['profile'], $address, $ud_flags, 1);
            if ($profile_changed) {
                $what .= 'profile ';
                $changed = true;
            }
        } else {
            logger('import_xchan: profile not available - hiding');
            // they may have made it private
            $r = q("delete from xprof where xprof_hash = '%s'", dbesc($xchan_hash));
            $r = q("delete from xtag where xtag_hash = '%s' and xtag_flags = 0", dbesc($xchan_hash));
        }
    }
    if (array_key_exists('site', $arr) && is_array($arr['site'])) {
        $profile_changed = import_site($arr['site'], $arr['key']);
        if ($profile_changed) {
            $what .= 'site ';
            $changed = true;
        }
    }
    if ($changed || $ud_flags == UPDATE_FLAGS_FORCED) {
        $guid = random_string() . '@' . get_app()->get_hostname();
        update_modtime($xchan_hash, $guid, $address, $ud_flags);
        logger('import_xchan: changed: ' . $what, LOGGER_DEBUG);
    } elseif (!$ud_flags) {
        // nothing changed but we still need to update the updates record
        q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ", intval(UPDATE_FLAGS_UPDATED), dbesc($address), intval(UPDATE_FLAGS_UPDATED));
    }
    if (!x($ret, 'message')) {
        $ret['success'] = true;
        $ret['hash'] = $xchan_hash;
    }
    logger('import_xchan: result: ' . print_r($ret, true), LOGGER_DATA);
    return $ret;
}
Example #7
0
function pumpio_get_contact($uid, $contact)
{
    $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($contact->url)));
    if (count($r) == 0) {
        q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')", dbesc(normalise_link($contact->url)), dbesc($contact->displayName), dbesc($contact->preferredUsername), dbesc($contact->image->url));
    } else {
        q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'", dbesc($contact->displayName), dbesc($contact->preferredUsername), dbesc($contact->image->url), dbesc(normalise_link($contact->url)));
    }
    if (DB_UPDATE_VERSION >= "1177") {
        q("UPDATE `unique_contacts` SET `location` = '%s', `about` = '%s' WHERE url = '%s'", dbesc($contact->location->displayName), dbesc($contact->summary), dbesc(normalise_link($contact->url)));
    }
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1", intval($uid), dbesc($contact->url));
    if (!count($r)) {
        // create contact record
        q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,\n\t\t\t\t\t`name`, `nick`, `photo`, `network`, `rel`, `priority`,\n\t\t\t\t\t`writable`, `blocked`, `readonly`, `pending` )\n\t\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ", intval($uid), dbesc(datetime_convert()), dbesc($contact->url), dbesc(normalise_link($contact->url)), dbesc(str_replace("acct:", "", $contact->id)), dbesc(''), dbesc($contact->id), dbesc('pump.io ' . $contact->id), dbesc($contact->displayName), dbesc($contact->preferredUsername), dbesc($contact->image->url), dbesc(NETWORK_PUMPIO), intval(CONTACT_IS_FRIEND), intval(1), intval(1));
        $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($contact->url), intval($uid));
        if (!count($r)) {
            return false;
        }
        $contact_id = $r[0]['id'];
        $g = q("select def_gid from user where uid = %d limit 1", intval($uid));
        if ($g && intval($g[0]['def_gid'])) {
            require_once 'include/group.php';
            group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
        }
        require_once "Photo.php";
        $photos = import_profile_photo($contact->image->url, $uid, $contact_id);
        q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t`avatar-date` = '%s'\n\t\t\t\tWHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
        if (DB_UPDATE_VERSION >= "1177") {
            q("UPDATE `contact` SET `location` = '%s',\n\t\t\t\t\t\t`about` = '%s'\n\t\t\t\t\tWHERE `id` = %d", dbesc($contact->location->displayName), dbesc($contact->summary), intval($contact_id));
        }
    } else {
        // update profile photos once every two weeks as we have no notification of when they change.
        //$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -14 days')) ? true : false);
        $update_photo = $r[0]['avatar-date'] < datetime_convert('', '', 'now -12 hours');
        // check that we have all the photos, this has been known to fail on occasion
        if (!$r[0]['photo'] || !$r[0]['thumb'] || !$r[0]['micro'] || $update_photo) {
            require_once "Photo.php";
            $photos = import_profile_photo($contact->image->url, $uid, $r[0]['id']);
            q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t\t`name` = '%s',\n\t\t\t\t\t`nick` = '%s'\n\t\t\t\t\tWHERE `id` = %d\n\t\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($contact->displayName), dbesc($contact->preferredUsername), intval($r[0]['id']));
            if (DB_UPDATE_VERSION >= "1177") {
                q("UPDATE `contact` SET `location` = '%s',\n\t\t\t\t\t\t\t`about` = '%s'\n\t\t\t\t\t\tWHERE `id` = %d", dbesc($contact->location->displayName), dbesc($contact->summary), intval($r[0]['id']));
            }
        }
    }
    return $r[0]["id"];
}
Example #8
0
function ostatus_fetchauthor($xpath, $context, $importer, &$contact)
{
    $author = array();
    $author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
    $author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
    // Preserve the value
    $authorlink = $author["author-link"];
    $alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
    if (is_object($alternate)) {
        foreach ($alternate as $attributes) {
            if ($attributes->name == "href") {
                $author["author-link"] = $attributes->textContent;
            }
        }
    }
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'", intval($importer["uid"]), dbesc(normalise_link($author["author-link"])), dbesc(normalise_link($authorlink)), dbesc(NETWORK_STATUSNET));
    if ($r) {
        $contact = $r[0];
        $author["contact-id"] = $r[0]["id"];
    } else {
        $author["contact-id"] = $contact["id"];
    }
    $avatarlist = array();
    $avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
    foreach ($avatars as $avatar) {
        $href = "";
        $width = 0;
        foreach ($avatar->attributes as $attributes) {
            if ($attributes->name == "href") {
                $href = $attributes->textContent;
            }
            if ($attributes->name == "width") {
                $width = $attributes->textContent;
            }
        }
        if ($width > 0 and $href != "") {
            $avatarlist[$width] = $href;
        }
    }
    if (count($avatarlist) > 0) {
        krsort($avatarlist);
        $author["author-avatar"] = current($avatarlist);
    }
    $displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
    if ($displayname != "") {
        $author["author-name"] = $displayname;
    }
    $author["owner-name"] = $author["author-name"];
    $author["owner-link"] = $author["author-link"];
    $author["owner-avatar"] = $author["author-avatar"];
    if ($r) {
        // Update contact data
        $update_contact = $r[0]['name-date'] < datetime_convert('', '', 'now -12 hours');
        if ($update_contact) {
            logger("Update contact data for contact " . $contact["id"], LOGGER_DEBUG);
            $value = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
            if ($value != "") {
                $contact["name"] = $value;
            }
            $value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
            if ($value != "") {
                $contact["nick"] = $value;
            }
            $value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
            if ($value != "") {
                $contact["about"] = $value;
            }
            $value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
            if ($value != "") {
                $contact["location"] = $value;
            }
            q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d", dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]), dbesc(datetime_convert()), intval($contact["id"]));
            poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"], "", "", "", datetime_convert(), 2, $contact["id"], $contact["uid"]);
        }
        $update_photo = $r[0]['avatar-date'] < datetime_convert('', '', 'now -12 hours');
        if ($update_photo and isset($author["author-avatar"])) {
            logger("Update profile picture for contact " . $contact["id"], LOGGER_DEBUG);
            $photos = import_profile_photo($author["author-avatar"], $importer["uid"], $contact["id"]);
            q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), intval($contact["id"]));
        }
    }
    return $author;
}
Example #9
0
function poller_run($argv, $argc)
{
    cli_startup();
    $a = get_app();
    $maxsysload = intval(get_config('system', 'maxloadavg'));
    if ($maxsysload < 1) {
        $maxsysload = 50;
    }
    if (function_exists('sys_getloadavg')) {
        $load = sys_getloadavg();
        if (intval($load[0]) > $maxsysload) {
            logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
            return;
        }
    }
    $interval = intval(get_config('system', 'poll_interval'));
    if (!$interval) {
        $interval = get_config('system', 'delivery_interval') === false ? 3 : intval(get_config('system', 'delivery_interval'));
    }
    // Check for a lockfile.  If it exists, but is over an hour old, it's stale.  Ignore it.
    $lockfile = 'store/[data]/poller';
    if (file_exists($lockfile) && filemtime($lockfile) > time() - 3600 && !get_config('system', 'override_poll_lockfile')) {
        logger("poller: Already running");
        return;
    }
    // Create a lockfile.  Needs two vars, but $x doesn't need to contain anything.
    file_put_contents($lockfile, $x);
    logger('poller: start');
    // run queue delivery process in the background
    proc_run('php', "include/queue.php");
    // maintenance for mod sharedwithme - check for updated items and remove them
    require_once 'include/sharedwithme.php';
    apply_updates();
    // expire any expired mail
    q("delete from mail where expires != '%s' and expires < %s ", dbesc(NULL_DATE), db_utcnow());
    // expire any expired items
    $r = q("select id from item where expires != '%s' and expires < %s \n\t\tand ( item_restrict & %d ) = 0 ", dbesc(NULL_DATE), db_utcnow(), intval(ITEM_DELETED));
    if ($r) {
        require_once 'include/items.php';
        foreach ($r as $rr) {
            drop_item($rr['id'], false);
        }
    }
    // Ensure that every channel pings a directory server once a month. This way we can discover
    // channels and sites that quietly vanished and prevent the directory from accumulating stale
    // or dead entries.
    $r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s", db_utcnow(), db_quoteinterval('30 DAY'));
    if ($r) {
        foreach ($r as $rr) {
            proc_run('php', 'include/directory.php', $rr['channel_id'], 'force');
            if ($interval) {
                @time_sleep_until(microtime(true) + (double) $interval);
            }
        }
    }
    // publish any applicable items that were set to be published in the future
    // (time travel posts). Restrict to items that have come of age in the last
    // couple of days to limit the query to something reasonable.
    $r = q("select id from item where ( item_restrict & %d ) > 0 and created <= %s  and created > '%s' ", intval(ITEM_DELAYED_PUBLISH), db_utcnow(), dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days')));
    if ($r) {
        foreach ($r as $rr) {
            $x = q("update item set item_restrict = ( item_restrict & ~%d ) where id = %d", intval(ITEM_DELAYED_PUBLISH), intval($rr['id']));
            if ($x) {
                proc_run('php', 'include/notifier.php', 'wall-new', $rr['id']);
            }
        }
    }
    $abandon_days = intval(get_config('system', 'account_abandon_days'));
    if ($abandon_days < 1) {
        $abandon_days = 0;
    }
    // once daily run birthday_updates and then expire in background
    // FIXME: add birthday updates, both locally and for xprof for use
    // by directory servers
    $d1 = intval(get_config('system', 'last_expire_day'));
    $d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd'));
    // Allow somebody to staggger daily activities if they have more than one site on their server,
    // or if it happens at an inconvenient (busy) hour.
    $h1 = intval(get_config('system', 'cron_hour'));
    $h2 = intval(datetime_convert('UTC', 'UTC', 'now', 'G'));
    $dirmode = get_config('system', 'directory_mode');
    /**
     * Cron Daily
     *
     * Actions in the following block are executed once per day, not on every poller run
     *
     */
    if ($d2 != $d1 && $h1 == $h2) {
        require_once 'include/dir_fns.php';
        check_upstream_directory();
        call_hooks('cron_daily', datetime_convert());
        $d3 = intval(datetime_convert('UTC', 'UTC', 'now', 'N'));
        if ($d3 == 7) {
            /**
             * Cron Weekly
             * 
             * Actions in the following block are executed once per day only on Sunday (once per week).
             *
             */
            call_hooks('cron_weekly', datetime_convert());
            z_check_cert();
            require_once 'include/hubloc.php';
            prune_hub_reinstalls();
            require_once 'include/Contact.php';
            mark_orphan_hubsxchans();
            // get rid of really old poco records
            q("delete from xlink where xlink_updated < %s - INTERVAL %s and xlink_static = 0 ", db_utcnow(), db_quoteinterval('14 DAY'));
            $dirmode = intval(get_config('system', 'directory_mode'));
            if ($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
                logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())), true));
            }
            /**
             * End Cron Weekly
             */
        }
        update_birthdays();
        //update statistics in config
        require_once 'include/statistics_fns.php';
        update_channels_total_stat();
        update_channels_active_halfyear_stat();
        update_channels_active_monthly_stat();
        update_local_posts_stat();
        // expire any read notifications over a month old
        q("delete from notify where seen = 1 and date < %s - INTERVAL %s", db_utcnow(), db_quoteinterval('30 DAY'));
        // expire any expired accounts
        downgrade_accounts();
        // If this is a directory server, request a sync with an upstream
        // directory at least once a day, up to once every poll interval.
        // Pull remote changes and push local changes.
        // potential issue: how do we keep from creating an endless update loop?
        if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
            require_once 'include/dir_fns.php';
            sync_directories($dirmode);
        }
        set_config('system', 'last_expire_day', $d2);
        proc_run('php', 'include/expire.php');
        proc_run('php', 'include/cli_suggest.php');
        require_once 'include/hubloc.php';
        remove_obsolete_hublocs();
        /**
         * End Cron Daily
         */
    }
    // update any photos which didn't get imported properly
    // This should be rare
    $r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = '' \n\t\tand xchan_photo_date < %s - INTERVAL %s", db_utcnow(), db_quoteinterval('1 DAY'));
    if ($r) {
        require_once 'include/photo/photo_driver.php';
        foreach ($r as $rr) {
            $photos = import_profile_photo($rr['xchan_photo_l'], $rr['xchan_hash']);
            $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\twhere xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($rr['xchan_hash']));
        }
    }
    // pull in some public posts
    if (!get_config('system', 'disable_discover_tab')) {
        proc_run('php', 'include/externals.php');
    }
    $manual_id = 0;
    $generation = 0;
    $force = false;
    $restart = false;
    if ($argc > 1 && $argv[1] == 'force') {
        $force = true;
    }
    if ($argc > 1 && $argv[1] == 'restart') {
        $restart = true;
        $generation = intval($argv[2]);
        if (!$generation) {
            killme();
        }
    }
    if ($argc > 1 && intval($argv[1])) {
        $manual_id = intval($argv[1]);
        $force = true;
    }
    $sql_extra = $manual_id ? " AND abook_id = " . intval($manual_id) . " " : "";
    reload_plugins();
    $d = datetime_convert();
    // TODO check to see if there are any cronhooks before wasting a process
    if (!$restart) {
        proc_run('php', 'include/cronhooks.php');
    }
    // Only poll from those with suitable relationships
    $abandon_sql = $abandon_days ? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days) . ' DAY')) : '';
    $randfunc = db_getfunc('RAND');
    $contacts = q("SELECT abook_id, abook_flags, abook_updated, abook_connected, abook_closeness, abook_xchan, abook_channel, xchan_network\n\t\tFROM abook LEFT JOIN xchan on abook_xchan = xchan_hash LEFT JOIN account on abook_account = account_id\n\t\t{$sql_extra} \n\t\tAND (( abook_flags & %d ) > 0 OR  ( abook_flags = %d )) \n\t\tAND (( account_flags = %d ) OR ( account_flags = %d )) {$abandon_sql} ORDER BY {$randfunc}", intval(ABOOK_FLAG_HIDDEN | ABOOK_FLAG_PENDING | ABOOK_FLAG_UNCONNECTED | ABOOK_FLAG_FEED), intval(0), intval(ACCOUNT_OK), intval(ACCOUNT_UNVERIFIED));
    if ($contacts) {
        foreach ($contacts as $contact) {
            if ($contact['abook_flags'] & ABOOK_FLAG_SELF) {
                continue;
            }
            $update = false;
            $t = $contact['abook_updated'];
            $c = $contact['abook_connected'];
            if ($contact['abook_flags'] & ABOOK_FLAG_FEED) {
                $min = service_class_fetch($contact['abook_channel'], 'minimum_feedcheck_minutes');
                if (!$min) {
                    $min = intval(get_config('system', 'minimum_feedcheck_minutes'));
                }
                if (!$min) {
                    $min = 60;
                }
                $x = datetime_convert('UTC', 'UTC', "now - {$min} minutes");
                if ($c < $x) {
                    proc_run('php', 'include/onepoll.php', $contact['abook_id']);
                    if ($interval) {
                        @time_sleep_until(microtime(true) + (double) $interval);
                    }
                }
                continue;
            }
            if ($contact['xchan_network'] !== 'zot') {
                continue;
            }
            if ($c == $t) {
                if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 day")) {
                    $update = true;
                }
            } else {
                // if we've never connected with them, start the mark for death countdown from now
                if ($c == NULL_DATE) {
                    $r = q("update abook set abook_connected = '%s'  where abook_id = %d", dbesc(datetime_convert()), intval($contact['abook_id']));
                    $c = datetime_convert();
                    $update = true;
                }
                // He's dead, Jim
                if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 30 day")) > 0) {
                    $r = q("update abook set abook_flags = (abook_flags | %d) where abook_id = %d", intval(ABOOK_FLAG_ARCHIVED), intval($contact['abook_id']));
                    $update = false;
                    continue;
                }
                if ($contact['abook_flags'] & ABOOK_FLAG_ARCHIVED) {
                    $update = false;
                    continue;
                }
                // might be dead, so maybe don't poll quite so often
                // recently deceased, so keep up the regular schedule for 3 days
                if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 3 day")) > 0 && strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 1 day")) > 0) {
                    $update = true;
                }
                // After that back off and put them on a morphine drip
                if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 2 day")) > 0) {
                    $update = true;
                }
            }
            if ($contact['abook_flags'] & (ABOOK_FLAG_PENDING | ABOOK_FLAG_ARCHIVED | ABOOK_FLAG_IGNORED)) {
                continue;
            }
            if (!$update && !$force) {
                continue;
            }
            proc_run('php', 'include/onepoll.php', $contact['abook_id']);
            if ($interval) {
                @time_sleep_until(microtime(true) + (double) $interval);
            }
        }
    }
    if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
        $r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last = '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ", intval(UPDATE_FLAGS_UPDATED), dbesc(NULL_DATE), db_utcnow(), db_quoteinterval('7 DAY'));
        if ($r) {
            foreach ($r as $rr) {
                // If they didn't respond when we attempted before, back off to once a day
                // After 7 days we won't bother anymore
                if ($rr['ud_last'] != NULL_DATE) {
                    if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day')) {
                        continue;
                    }
                }
                proc_run('php', 'include/onedirsync.php', $rr['ud_id']);
                if ($interval) {
                    @time_sleep_until(microtime(true) + (double) $interval);
                }
            }
        }
    }
    set_config('system', 'lastpoll', datetime_convert());
    //All done - clear the lockfile
    @unlink($lockfile);
    return;
}
Example #10
0
/**
 * @param int $uid
 * @param object $contact
 */
function fb_get_friends_sync_parsecontact($uid, $contact)
{
    $contact->link = 'http://facebook.com/profile.php?id=' . $contact->id;
    // If its a page then set the first name from the username
    if (!$contact->first_name and $contact->username) {
        $contact->first_name = $contact->username;
    }
    // check if we already have a contact
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1", intval($uid), dbesc($contact->link));
    if (count($r)) {
        // check that we have all the photos, this has been known to fail on occasion
        if (!$r[0]['photo'] || !$r[0]['thumb'] || !$r[0]['micro']) {
            require_once "Photo.php";
            $photos = import_profile_photo('https://graph.facebook.com/' . $contact->id . '/picture', $uid, $r[0]['id']);
            q("UPDATE `contact` SET `photo` = '%s',\n                                        `thumb` = '%s',\n                                        `micro` = '%s',\n                                        `name-date` = '%s',\n                                        `uri-date` = '%s',\n                                        `avatar-date` = '%s'\n                                        WHERE `id` = %d LIMIT 1\n                                ", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($r[0]['id']));
        }
        return;
    } else {
        // create contact record
        q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,\n                                `name`, `nick`, `photo`, `network`, `rel`, `priority`,\n                                `writable`, `blocked`, `readonly`, `pending` )\n                                VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ", intval($uid), dbesc(datetime_convert()), dbesc($contact->link), dbesc(normalise_link($contact->link)), dbesc(''), dbesc(''), dbesc($contact->id), dbesc('facebook ' . $contact->id), dbesc($contact->name), dbesc($contact->nickname ? $contact->nickname : strtolower($contact->first_name)), dbesc('https://graph.facebook.com/' . $contact->id . '/picture'), dbesc(NETWORK_FACEBOOK), intval(CONTACT_IS_FRIEND), intval(1), intval(1));
    }
    $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($contact->link), intval($uid));
    if (!count($r)) {
        return;
    }
    $contact_id = $r[0]['id'];
    $g = q("select def_gid from user where uid = %d limit 1", intval($uid));
    if ($g && intval($g[0]['def_gid'])) {
        require_once 'include/group.php';
        group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
    }
    require_once "Photo.php";
    $photos = import_profile_photo($r[0]['photo'], $uid, $contact_id);
    q("UPDATE `contact` SET `photo` = '%s',\n                        `thumb` = '%s',\n                        `micro` = '%s',\n                        `name-date` = '%s',\n                        `uri-date` = '%s',\n                        `avatar-date` = '%s'\n                        WHERE `id` = %d LIMIT 1\n                ", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
}
Example #11
0
function xchan_store($arr)
{
    logger('xchan_store: ' . print_r($arr, true));
    if (!$arr['hash']) {
        $arr['hash'] = $arr['guid'];
    }
    if (!$arr['hash']) {
        return false;
    }
    $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($arr['hash']));
    if ($r) {
        return true;
    }
    if (!$arr['network']) {
        $arr['network'] = 'unknown';
    }
    if (!$arr['name']) {
        $arr['name'] = 'unknown';
    }
    if (!$arr['url']) {
        $arr['url'] = z_root();
    }
    if (!$arr['photo']) {
        $arr['photo'] = z_root() . '/' . get_default_profile_photo();
    }
    $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_instance_url, xchan_flags, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s',%d,'%s') ", dbesc($arr['hash']), dbesc($arr['guid']), dbesc($arr['guid_sig']), dbesc($arr['pubkey']), dbesc($arr['address']), dbesc($arr['url']), dbesc($arr['connurl']), dbesc($arr['follow']), dbesc($arr['connpage']), dbesc($arr['name']), dbesc($arr['network']), dbesc($arr['instance_url']), intval($arr['flags']), dbesc(datetime_convert()));
    if (!$r) {
        return $r;
    }
    $photos = import_profile_photo($arr['photo'], $arr['hash']);
    $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($arr['hash']));
    return $r;
}
Example #12
0
function follow_init(&$a)
{
    if (!local_user()) {
        notice(t('Permission denied.') . EOL);
        goaway($_SESSION['return_url']);
        // NOTREACHED
    }
    $url = $orig_url = notags(trim($_REQUEST['url']));
    // remove ajax junk, e.g. Twitter
    $url = str_replace('/#!/', '/', $url);
    if (!allowed_url($url)) {
        notice(t('Disallowed profile URL.') . EOL);
        goaway($_SESSION['return_url']);
        // NOTREACHED
    }
    if (!$url) {
        notice(t('Connect URL missing.') . EOL);
        goaway($_SESSION['return_url']);
        // NOTREACHED
    }
    $ret = probe_url($url);
    if ($ret['network'] === NETWORK_DFRN) {
        if (strlen($a->path)) {
            $myaddr = bin2hex($a->get_baseurl() . '/profile/' . $a->user['nickname']);
        } else {
            $myaddr = bin2hex($a->user['nickname'] . '@' . $a->get_hostname());
        }
        goaway($ret['request'] . "&addr={$myaddr}");
        // NOTREACHED
    } else {
        if (get_config('system', 'dfrn_only')) {
            notice(t('This site is not configured to allow communications with other networks.') . EOL);
            notice(t('No compatible communication protocols or feeds were discovered.') . EOL);
            goaway($_SESSION['return_url']);
        }
    }
    // do we have enough information?
    if (!(x($ret, 'name') && x($ret, 'poll') && (x($ret, 'url') || x($ret, 'addr')))) {
        notice(t('The profile address specified does not provide adequate information.') . EOL);
        if (!x($ret, 'poll')) {
            notice(t('No compatible communication protocols or feeds were discovered.') . EOL);
        }
        if (!x($ret, 'name')) {
            notice(t('An author or name was not found.') . EOL);
        }
        if (!x($ret, 'url')) {
            notice(t('No browser URL could be matched to this address.') . EOL);
        }
        if (strpos($url, '@') !== false) {
            notice('Unable to match @-style Identity Address with a known protocol or email contact');
        }
        goaway($_SESSION['return_url']);
    }
    if ($ret['network'] === NETWORK_OSTATUS && get_config('system', 'ostatus_disabled')) {
        notice(t('The profile address specified belongs to a network which has been disabled on this site.') . EOL);
        $ret['notify'] = '';
    }
    if (!$ret['notify']) {
        notice(t('Limited profile. This person will be unable to receive direct/personal notifications from you.') . EOL);
    }
    $writeable = $ret['network'] === NETWORK_OSTATUS && $ret['notify'] ? 1 : 0;
    $hidden = $ret['network'] === NETWORK_MAIL ? 1 : 0;
    if ($ret['network'] === NETWORK_MAIL) {
        $writeable = 1;
    }
    if ($ret['network'] === NETWORK_DIASPORA) {
        $writeable = 1;
    }
    // check if we already have a contact
    // the poll url is more reliable than the profile url, as we may have
    // indirect links or webfinger links
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` = '%s' LIMIT 1", intval(local_user()), dbesc($ret['poll']));
    if (count($r)) {
        // update contact
        if ($r[0]['rel'] == CONTACT_IS_FOLLOWER || $network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING) {
            q("UPDATE `contact` SET `rel` = %d , `readonly` = 0 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(CONTACT_IS_FRIEND), intval($r[0]['id']), intval(local_user()));
        }
    } else {
        $new_relation = $ret['network'] === NETWORK_MAIL ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING;
        if ($ret['network'] === NETWORK_DIASPORA) {
            $new_relation = CONTACT_IS_FOLLOWER;
        }
        // create contact record
        $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `name`, `nick`, `photo`, `network`, `pubkey`, `rel`, `priority`,\n\t\t\t`writable`, `hidden`, `blocked`, `readonly`, `pending` )\n\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, 0, 0, 0 ) ", intval(local_user()), dbesc(datetime_convert()), dbesc($ret['url']), dbesc(normalise_link($ret['url'])), dbesc($ret['addr']), dbesc($ret['alias']), dbesc($ret['batch']), dbesc($ret['notify']), dbesc($ret['poll']), dbesc($ret['poco']), dbesc($ret['name']), dbesc($ret['nick']), dbesc($ret['photo']), dbesc($ret['network']), dbesc($ret['pubkey']), intval($new_relation), intval($ret['priority']), intval($writeable), intval($hidden));
    }
    $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($ret['url']), intval(local_user()));
    if (!count($r)) {
        notice(t('Unable to retrieve contact information.') . EOL);
        goaway($_SESSION['return_url']);
        // NOTREACHED
    }
    $contact = $r[0];
    $contact_id = $r[0]['id'];
    require_once "Photo.php";
    $photos = import_profile_photo($ret['photo'], local_user(), $contact_id);
    $r = q("UPDATE `contact` SET `photo` = '%s', \n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s', \n\t\t\t`name-date` = '%s', \n\t\t\t`uri-date` = '%s', \n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d LIMIT 1\n\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
    // pull feed and consume it, which should subscribe to the hub.
    proc_run('php', "include/poller.php", "{$contact_id}");
    // create a follow slap
    $tpl = get_markup_template('follow_slap.tpl');
    $slap = replace_macros($tpl, array('$name' => $a->user['username'], '$profile_page' => $a->get_baseurl() . '/profile/' . $a->user['nickname'], '$photo' => $a->contact['photo'], '$thumb' => $a->contact['thumb'], '$published' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME), '$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . random_string(), '$title' => '', '$type' => 'text', '$content' => t('following'), '$nick' => $a->user['nickname'], '$verb' => ACTIVITY_FOLLOW, '$ostat_follow' => ''));
    $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid` \n\t\t\tWHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", intval(local_user()));
    if (count($r)) {
        if ($contact['network'] == NETWORK_OSTATUS && strlen($contact['notify'])) {
            require_once 'include/salmon.php';
            slapper($r[0], $contact['notify'], $slap);
        }
        if ($contact['network'] == NETWORK_DIASPORA) {
            require_once 'include/diaspora.php';
            $ret = diaspora_share($a->user, $contact);
            logger('mod_follow: diaspora_share returns: ' . $ret);
        }
    }
    if (strstr($_SESSION['return_url'], 'contacts')) {
        goaway($a->get_baseurl() . '/contacts/' . $contact_id);
    }
    goaway($_SESSION['return_url']);
    // NOTREACHED
}
Example #13
0
File: poller.php Project: Mauru/red
function poller_run($argv, $argc)
{
    cli_startup();
    $a = get_app();
    $maxsysload = intval(get_config('system', 'maxloadavg'));
    if ($maxsysload < 1) {
        $maxsysload = 50;
    }
    if (function_exists('sys_getloadavg')) {
        $load = sys_getloadavg();
        if (intval($load[0]) > $maxsysload) {
            logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
            return;
        }
    }
    $interval = intval(get_config('system', 'poll_interval'));
    if (!$interval) {
        $interval = get_config('system', 'delivery_interval') === false ? 3 : intval(get_config('system', 'delivery_interval'));
    }
    logger('poller: start');
    // run queue delivery process in the background
    proc_run('php', "include/queue.php");
    // expire any expired mail
    q("delete from mail where expires != '%s' and expires < UTC_TIMESTAMP() ", dbesc(NULL_DATE));
    // expire any expired items
    $r = q("select id from item where expires != '%s' and expires < UTC_TIMESTAMP() \n\t\tand not ( item_restrict & %d ) ", dbesc(NULL_DATE), intval(ITEM_DELETED));
    if ($r) {
        require_once 'include/items.php';
        foreach ($r as $rr) {
            drop_item($rr['id'], false);
        }
    }
    // Ensure that every channel pings a directory server once a month. This way we can discover
    // channels and sites that quietly vanished and prevent the directory from accumulating stale
    // or dead entries.
    $r = q("select channel_id from channel where channel_dirdate < UTC_TIMESTAMP() - INTERVAL 30 DAY");
    if ($r) {
        foreach ($r as $rr) {
            proc_run('php', 'include/directory.php', $rr['channel_id'], 'force');
            if ($interval) {
                @time_sleep_until(microtime(true) + (double) $interval);
            }
        }
    }
    // publish any applicable items that were set to be published in the future
    // (time travel posts)
    $r = q("select id from item where ( item_restrict & %d ) and created <= UTC_TIMESTAMP() ", intval(ITEM_DELAYED_PUBLISH));
    if ($r) {
        foreach ($r as $rr) {
            $x = q("update item set item_restrict = ( item_restrict ^ %d ) where id = %d limit 1", intval(ITEM_DELAYED_PUBLISH), intval($rr['id']));
            if ($x) {
                proc_run('php', 'include/notifier.php', 'wall-new', $rr['id']);
            }
        }
    }
    $abandon_days = intval(get_config('system', 'account_abandon_days'));
    if ($abandon_days < 1) {
        $abandon_days = 0;
    }
    // once daily run birthday_updates and then expire in background
    // FIXME: add birthday updates, both locally and for xprof for use
    // by directory servers
    $d1 = intval(get_config('system', 'last_expire_day'));
    $d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd'));
    // Allow somebody to staggger daily activities if they have more than one site on their server,
    // or if it happens at an inconvenient (busy) hour.
    $h1 = intval(get_config('system', 'cron_hour'));
    $h2 = intval(datetime_convert('UTC', 'UTC', 'now', 'G'));
    $dirmode = get_config('system', 'directory_mode');
    /**
     * Cron Daily
     *
     * Actions in the following block are executed once per day, not on every poller run
     *
     */
    if ($d2 != $d1 && $h1 == $h2) {
        require_once 'include/dir_fns.php';
        check_upstream_directory();
        call_hooks('cron_daily', datetime_convert());
        $d3 = intval(datetime_convert('UTC', 'UTC', 'now', 'N'));
        if ($d3 == 7) {
            /**
             * Cron Weekly
             * 
             * Actions in the following block are executed once per day only on Sunday (once per week).
             *
             */
            call_hooks('cron_weekly', datetime_convert());
            require_once 'include/hubloc.php';
            prune_hub_reinstalls();
            require_once 'include/Contact.php';
            mark_orphan_hubsxchans();
            /**
             * End Cron Weekly
             */
        }
        update_birthdays();
        // expire any read notifications over a month old
        q("delete from notify where seen = 1 and date < UTC_TIMESTAMP() - INTERVAL 30 DAY");
        // expire any expired accounts
        downgrade_accounts();
        // If this is a directory server, request a sync with an upstream
        // directory at least once a day, up to once every poll interval.
        // Pull remote changes and push local changes.
        // potential issue: how do we keep from creating an endless update loop?
        if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
            require_once 'include/dir_fns.php';
            sync_directories($dirmode);
        }
        set_config('system', 'last_expire_day', $d2);
        proc_run('php', 'include/expire.php');
        proc_run('php', 'include/cli_suggest.php');
        /**
         * End Cron Daily
         */
    }
    // update any photos which didn't get imported properly
    // This should be rare
    $r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = '' \n\t\tand xchan_photo_date < UTC_TIMESTAMP() - INTERVAL 1 DAY");
    if ($r) {
        require_once 'include/photo/photo_driver.php';
        foreach ($r as $rr) {
            $photos = import_profile_photo($rr['xchan_photo_l'], $rr['xchan_hash']);
            $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\twhere xchan_hash = '%s' limit 1", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($rr['xchan_hash']));
        }
    }
    // pull in some public posts
    if (!get_config('system', 'disable_discover_tab')) {
        proc_run('php', 'include/externals.php');
    }
    $manual_id = 0;
    $generation = 0;
    $force = false;
    $restart = false;
    if ($argc > 1 && $argv[1] == 'force') {
        $force = true;
    }
    if ($argc > 1 && $argv[1] == 'restart') {
        $restart = true;
        $generation = intval($argv[2]);
        if (!$generation) {
            killme();
        }
    }
    if ($argc > 1 && intval($argv[1])) {
        $manual_id = intval($argv[1]);
        $force = true;
    }
    $sql_extra = $manual_id ? " AND abook_id = {$manual_id} " : "";
    reload_plugins();
    $d = datetime_convert();
    //TODO check to see if there are any cronhooks before wasting a process
    if (!$restart) {
        proc_run('php', 'include/cronhooks.php');
    }
    // Only poll from those with suitable relationships
    $abandon_sql = $abandon_days ? sprintf(" AND account_lastlog > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days)) : '';
    $contacts = q("SELECT abook_id, abook_flags, abook_updated, abook_connected, abook_closeness, abook_channel\n\t\tFROM abook LEFT JOIN account on abook_account = account_id where 1\n\t\t{$sql_extra} \n\t\tAND (( abook_flags & %d ) OR  ( abook_flags = %d )) \n\t\tAND (( account_flags = %d ) OR ( account_flags = %d )) {$abandon_sql} ORDER BY RAND()", intval(ABOOK_FLAG_HIDDEN | ABOOK_FLAG_PENDING | ABOOK_FLAG_UNCONNECTED | ABOOK_FLAG_FEED), intval(0), intval(ACCOUNT_OK), intval(ACCOUNT_UNVERIFIED));
    if ($contacts) {
        foreach ($contacts as $contact) {
            $update = false;
            $t = $contact['abook_updated'];
            $c = $contact['abook_connected'];
            if ($contact['abook_flags'] & ABOOK_FLAG_FEED) {
                $min = service_class_fetch($contact['abook_channel'], 'minimum_feedcheck_minutes');
                if (!$min) {
                    $min = intval(get_config('system', 'minimum_feedcheck_minutes'));
                }
                if (!$min) {
                    $min = 60;
                }
                $x = datetime_convert('UTC', 'UTC', "now - {$min} minutes");
                if ($c < $x) {
                    proc_run('php', 'include/onepoll.php', $contact['abook_id']);
                    if ($interval) {
                        @time_sleep_until(microtime(true) + (double) $interval);
                    }
                }
                continue;
            }
            if ($c == $t) {
                if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 day")) {
                    $update = true;
                }
            } else {
                // if we've never connected with them, start the mark for death countdown from now
                if ($c == NULL_DATE) {
                    $r = q("update abook set abook_connected = '%s'  where abook_id = %d limit 1", dbesc(datetime_convert()), intval($contact['abook_id']));
                    $c = datetime_convert();
                    $update = true;
                }
                // He's dead, Jim
                if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 30 day")) > 0) {
                    $r = q("update abook set abook_flags = (abook_flags | %d) where abook_id = %d limit 1", intval(ABOOK_FLAG_ARCHIVED), intval($contact['abook_id']));
                    $update = false;
                    continue;
                }
                if ($contact['abook_flags'] & ABOOK_FLAG_ARCHIVED) {
                    $update = false;
                    continue;
                }
                // might be dead, so maybe don't poll quite so often
                // recently deceased, so keep up the regular schedule for 3 days
                if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 3 day")) > 0 && strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 1 day")) > 0) {
                    $update = true;
                }
                // After that back off and put them on a morphine drip
                if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 2 day")) > 0) {
                    $update = true;
                }
            }
            if (!$update && !$force) {
                continue;
            }
            proc_run('php', 'include/onepoll.php', $contact['abook_id']);
            if ($interval) {
                @time_sleep_until(microtime(true) + (double) $interval);
            }
        }
    }
    if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
        $r = q("select distinct ud_addr, updates.* from updates where not ( ud_flags & %d ) and ud_addr != '' and ( ud_last = '%s' OR ud_last > UTC_TIMESTAMP() - INTERVAL 7 DAY ) group by ud_addr ", intval(UPDATE_FLAGS_UPDATED), dbesc(NULL_DATE));
        if ($r) {
            foreach ($r as $rr) {
                // If they didn't respond when we attempted before, back off to once a day
                // After 7 days we won't bother anymore
                if ($rr['ud_last'] != NULL_DATE) {
                    if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day')) {
                        continue;
                    }
                }
                proc_run('php', 'include/onedirsync.php', $rr['ud_id']);
                if ($interval) {
                    @time_sleep_until(microtime(true) + (double) $interval);
                }
            }
        }
    }
    return;
}
Example #14
0
function _contact_update_profile($contact_id)
{
    $r = q("SELECT `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
    if (!$r) {
        return;
    }
    $data = probe_url($r[0]["url"]);
    // "Feed" is mostly a sign of communication problems
    if ($data["network"] == NETWORK_FEED and $data["network"] != $r[0]["network"]) {
        return;
    }
    $updatefields = array("name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm", "poco", "network", "alias", "pubkey");
    $update = array();
    foreach ($updatefields as $field) {
        if (isset($data[$field]) and $data[$field] != "") {
            $update[$field] = $data[$field];
        }
    }
    $update["nurl"] = normalise_link($data["url"]);
    $query = "";
    if (isset($data["priority"]) and $data["priority"] != 0) {
        $query = "`priority` = " . intval($data["priority"]);
    }
    foreach ($update as $key => $value) {
        if ($query != "") {
            $query .= ", ";
        }
        $query .= "`" . $key . "` = '" . dbesc($value) . "'";
    }
    if ($query == "") {
        return;
    }
    $r = q("UPDATE `contact` SET {$query} WHERE `id` = %d AND `uid` = %d", intval($contact_id), intval(local_user()));
    $photos = import_profile_photo($data['photo'], local_user(), $contact_id);
    $r = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
}
Example #15
0
function thing_init(&$a)
{
    if (!local_channel()) {
        return;
    }
    $account_id = $a->get_account();
    $channel = $a->get_channel();
    $term_hash = $_REQUEST['term_hash'] ? $_REQUEST['term_hash'] : '';
    $name = escape_tags($_REQUEST['term']);
    $verb = escape_tags($_REQUEST['verb']);
    $activity = intval($_REQUEST['activity']);
    $profile_guid = escape_tags($_REQUEST['profile_assign']);
    $url = $_REQUEST['link'];
    $photo = $_REQUEST['img'];
    $hash = random_string();
    $verbs = obj_verbs();
    /**
     * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants" 
     * We use the first person form when creating an activity, but the third person for use in activities
     * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually
     * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module.
     */
    $translated_verb = $verbs[$verb][1];
    /*
     * The site administrator can do things that normals cannot.
     * This is restricted because it will likely cause
     * an activitystreams protocol violation and the activity might
     * choke in some other network and result in unnecessary 
     * support requests. It isn't because we're trying to be heavy-handed
     * about what you can and can't do. 
     */
    if (!$translated_verb) {
        if (is_site_admin()) {
            $translated_verb = $verb;
        }
    }
    /*
     * Things, objects: We do not provide definite (a, an) or indefinite (the) articles or singular/plural designators
     * That needs to be specified in your thing. e.g. Mike has "a carrot", Greg wants "balls", Bob likes "the Boston Red Sox".  
     */
    /*
     * Future work on this module might produce more complex activities with targets, e.g. Phillip likes Karen's moustache
     * and to describe other non-thing objects like channels, such as Karl wants Susan - where Susan represents a channel profile.
     */
    if (!$name || !$translated_verb) {
        return;
    }
    if ($term_hash) {
        $t = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", intval(TERM_OBJ_THING), dbesc($term_hash));
        if (!$t) {
            notice(t('Item not found.') . EOL);
            return;
        }
        $orig_record = $t[0];
        if ($photo != $orig_record['imgurl']) {
            $arr = import_profile_photo($photo, get_observer_hash(), true);
            $local_photo = $arr[0];
            $local_photo_type = $arr[3];
        } else {
            $local_photo = $orig_record['imgurl'];
        }
        $r = q("update term  set term = '%s', url = '%s', imgurl = '%s' where term_hash = '%s' and uid = %d", dbesc($name), dbesc($url ? $url : z_root() . '/thing/' . $term_hash), dbesc($local_photo), dbesc($term_hash), intval(local_channel()));
        info(t('Thing updated') . EOL);
        return;
    }
    $sql = $profile_guid ? " and profile_guid = '" . dbesc($profile_guid) . "' " : " and is_default = 1 ";
    $p = q("select profile_guid, is_default from profile where uid = %d {$sql} limit 1", intval(local_channel()));
    if ($p) {
        $profile = $p[0];
    } else {
        return;
    }
    $local_photo = null;
    if ($photo) {
        $arr = import_profile_photo($photo, get_observer_hash(), true);
        $local_photo = $arr[0];
        $local_photo_type = $arr[3];
    }
    $r = q("select * from term where uid = %d and otype = %d and type = %d and term = '%s' limit 1", intval(local_channel()), intval(TERM_OBJ_THING), intval(TERM_THING), dbesc($name));
    if (!$r) {
        $r = q("insert into term ( aid, uid, oid, otype, type, term, url, imgurl, term_hash )\n\t\t\tvalues( %d, %d, %d, %d, %d, '%s', '%s', '%s', '%s' ) ", intval($account_id), intval(local_channel()), 0, intval(TERM_OBJ_THING), intval(TERM_THING), dbesc($name), dbesc($url ? $url : z_root() . '/thing/' . $hash), dbesc($photo ? $local_photo : ''), dbesc($hash));
        $r = q("select * from term where uid = %d and otype = %d and type = %d and term = '%s' limit 1", intval(local_channel()), intval(TERM_OBJ_THING), intval(TERM_THING), dbesc($name));
    }
    $term = $r[0];
    $r = q("insert into obj ( obj_page, obj_verb, obj_type, obj_channel, obj_obj) values ('%s','%s', %d, %d, '%s') ", dbesc($profile['profile_guid']), dbesc($verb), intval(TERM_OBJ_THING), intval(local_channel()), dbesc($term['term_hash']));
    if (!$r) {
        notice(t('Object store: failed'));
        return;
    }
    info(t('Thing added'));
    if ($activity) {
        $arr = array();
        $links = array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => $term['url']));
        if ($local_photo) {
            $links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo);
        }
        $objtype = ACTIVITY_OBJ_THING;
        $obj = json_encode(array('type' => $objtype, 'id' => $term['url'], 'link' => $links, 'title' => $term['term'], 'content' => $term['term']));
        $bodyverb = str_replace('OBJ: ', '', t('OBJ: %1$s %2$s %3$s'));
        $arr['owner_xchan'] = $channel['channel_hash'];
        $arr['author_xchan'] = $channel['channel_hash'];
        $arr['item_flags'] = ITEM_ORIGIN | ITEM_WALL | ITEM_THREAD_TOP;
        $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]';
        $plink = '[zrl=' . $term['url'] . ']' . $term['term'] . '[/zrl]';
        $arr['body'] = sprintf($bodyverb, $ulink, $translated_verb, $plink);
        if ($local_photo) {
            $arr['body'] .= "\n\n[zmg]" . $local_photo . "[/zmg]";
        }
        $arr['verb'] = $verb;
        $arr['obj_type'] = $objtype;
        $arr['object'] = $obj;
        if (!$profile['is_default']) {
            $arr['item_private'] = true;
            $str = '';
            $r = q("select abook_xchan from abook where abook_channel = %d and abook_profile = '%s'", intval(local_channel()), dbesc($profile_guid));
            if ($r) {
                $arr['allow_cid'] = '';
                foreach ($r as $rr) {
                    $arr['allow_cid'] .= '<' . $rr['abook_xchan'] . '>';
                }
            } else {
                $arr['allow_cid'] = '<' . get_observer_hash() . '>';
            }
        }
        $ret = post_activity_item($arr);
    }
}
Example #16
0
function diaspora_profile($importer, $xml, $msg)
{
    $a = get_app();
    $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    if ($diaspora_handle != $msg['author']) {
        logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
        return 202;
    }
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $diaspora_handle);
    if (!$contact) {
        return;
    }
    if ($contact['blocked']) {
        logger('diaspora_post: Ignoring this author.');
        return 202;
    }
    $name = unxmlify($xml->first_name) . (strlen($xml->last_name) ? ' ' . unxmlify($xml->last_name) : '');
    $image_url = unxmlify($xml->image_url);
    $birthday = unxmlify($xml->birthday);
    $handle_parts = explode("@", $diaspora_handle);
    if ($name === '') {
        $name = $handle_parts[0];
    }
    if (preg_match("|^https?://|", $image_url) === 0) {
        $image_url = "http://" . $handle_parts[1] . $image_url;
    }
    require_once 'include/photo/photo_driver.php';
    $images = import_profile_photo($image_url, $contact['xchan_hash']);
    // Generic birthday. We don't know the timezone. The year is irrelevant.
    $birthday = str_replace('1000', '1901', $birthday);
    $birthday = datetime_convert('UTC', 'UTC', $birthday, 'Y-m-d');
    // this is to prevent multiple birthday notifications in a single year
    // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
    if (substr($birthday, 5) === substr($contact['bd'], 5)) {
        $birthday = $contact['bd'];
    }
    $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' ", dbesc($name), dbesc(datetime_convert()), dbesc($images[0]), dbesc($images[1]), dbesc($images[2]), dbesc($images[3]), dbesc(datetime_convert()), intval($contact['xchan_hash']));
    return;
}
Example #17
0
function twitter_fetch_contact($uid, $contact, $create_user)
{
    require_once "include/Photo.php";
    if ($contact->id_str == "") {
        return -1;
    }
    $avatar = str_replace("_normal.", ".", $contact->profile_image_url_https);
    $info = get_photo_info($avatar);
    if (!$info) {
        $avatar = $contact->profile_image_url_https;
    }
    // Check if the unique contact is existing
    // To-Do: only update once a while
    $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link("https://twitter.com/" . $contact->screen_name)));
    if (count($r) == 0) {
        q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')", dbesc(normalise_link("https://twitter.com/" . $contact->screen_name)), dbesc($contact->name), dbesc($contact->screen_name), dbesc($avatar));
    } else {
        q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'", dbesc($contact->name), dbesc($contact->screen_name), dbesc($avatar), dbesc(normalise_link("https://twitter.com/" . $contact->screen_name)));
    }
    if (DB_UPDATE_VERSION >= "1177") {
        q("UPDATE `unique_contacts` SET `location` = '%s', `about` = '%s' WHERE url = '%s'", dbesc($contact->location), dbesc($contact->description), dbesc(normalise_link("https://twitter.com/" . $contact->screen_name)));
    }
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1", intval($uid), dbesc("twitter::" . $contact->id_str));
    if (!count($r) and !$create_user) {
        return 0;
    }
    if (count($r) and ($r[0]["readonly"] or $r[0]["blocked"])) {
        logger("twitter_fetch_contact: Contact '" . $r[0]["nick"] . "' is blocked or readonly.", LOGGER_DEBUG);
        return -1;
    }
    if (!count($r)) {
        // create contact record
        q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,\n\t\t\t\t\t`name`, `nick`, `photo`, `network`, `rel`, `priority`,\n\t\t\t\t\t`writable`, `blocked`, `readonly`, `pending` )\n\t\t\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0) ", intval($uid), dbesc(datetime_convert()), dbesc("https://twitter.com/" . $contact->screen_name), dbesc(normalise_link("https://twitter.com/" . $contact->screen_name)), dbesc($contact->screen_name . "@twitter.com"), dbesc("twitter::" . $contact->id_str), dbesc(''), dbesc("twitter::" . $contact->id_str), dbesc($contact->name), dbesc($contact->screen_name), dbesc($avatar), dbesc(NETWORK_TWITTER), intval(CONTACT_IS_FRIEND), intval(1), intval(1));
        $r = q("SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1", dbesc("twitter::" . $contact->id_str), intval($uid));
        if (!count($r)) {
            return false;
        }
        $contact_id = $r[0]['id'];
        $g = q("SELECT def_gid FROM user WHERE uid = %d LIMIT 1", intval($uid));
        if ($g && intval($g[0]['def_gid'])) {
            require_once 'include/group.php';
            group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
        }
        require_once "Photo.php";
        $photos = import_profile_photo($avatar, $uid, $contact_id);
        q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t`avatar-date` = '%s'\n\t\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
        if (DB_UPDATE_VERSION >= "1177") {
            q("UPDATE `contact` SET `location` = '%s',\n\t\t\t\t\t\t`about` = '%s'\n\t\t\t\t\tWHERE `id` = %d", dbesc($contact->location), dbesc($contact->description), intval($contact_id));
        }
    } else {
        // update profile photos once every two weeks as we have no notification of when they change.
        //$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -2 days')) ? true : false);
        $update_photo = $r[0]['avatar-date'] < datetime_convert('', '', 'now -12 hours');
        // check that we have all the photos, this has been known to fail on occasion
        if (!$r[0]['photo'] || !$r[0]['thumb'] || !$r[0]['micro'] || $update_photo) {
            logger("twitter_fetch_contact: Updating contact " . $contact->screen_name, LOGGER_DEBUG);
            require_once "Photo.php";
            $photos = import_profile_photo($avatar, $uid, $r[0]['id']);
            q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t\t\t`url` = '%s',\n\t\t\t\t\t\t`nurl` = '%s',\n\t\t\t\t\t\t`addr` = '%s',\n\t\t\t\t\t\t`name` = '%s',\n\t\t\t\t\t\t`nick` = '%s'\n\t\t\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc("https://twitter.com/" . $contact->screen_name), dbesc(normalise_link("https://twitter.com/" . $contact->screen_name)), dbesc($contact->screen_name . "@twitter.com"), dbesc($contact->name), dbesc($contact->screen_name), intval($r[0]['id']));
            if (DB_UPDATE_VERSION >= "1177") {
                q("UPDATE `contact` SET `location` = '%s',\n\t\t\t\t\t\t\t`about` = '%s'\n\t\t\t\t\t\tWHERE `id` = %d", dbesc($contact->location), dbesc($contact->description), intval($r[0]['id']));
            }
        }
    }
    return $r[0]["id"];
}
Example #18
0
function diaspora_profile($importer, $xml)
{
    $a = get_app();
    $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    $contact = diaspora_get_contact_by_handle($importer['uid'], $diaspora_handle);
    if (!$contact) {
        return;
    }
    if ($contact['blocked']) {
        logger('diaspora_post: Ignoring this author.');
        return 202;
    }
    $name = unxmlify($xml->first_name) . (strlen($xml->last_name) ? ' ' . unxmlify($xml->last_name) : '');
    $image_url = unxmlify($xml->image_url);
    $birthday = unxmlify($xml->birthday);
    $r = q("SELECT DISTINCT ( `resource-id` ) FROM `photo` WHERE  `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' ", intval($importer['uid']), intval($contact['id']));
    $oldphotos = count($r) ? $r : null;
    require_once 'include/Photo.php';
    $images = import_profile_photo($image_url, $importer['uid'], $contact['id']);
    // Generic birthday. We don't know the timezone. The year is irrelevant.
    $birthday = str_replace('1000', '1901', $birthday);
    $birthday = datetime_convert('UTC', 'UTC', $birthday, 'Y-m-d');
    // this is to prevent multiple birthday notifications in a single year
    // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
    if (substr($birthday, 5) === substr($contact['bd'], 5)) {
        $birthday = $contact['bd'];
    }
    $r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' , `bd` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($name), dbesc(datetime_convert()), dbesc($images[0]), dbesc($images[1]), dbesc($images[2]), dbesc(datetime_convert()), dbesc($birthday), intval($contact['id']), intval($importer['uid']));
    if ($r) {
        if ($oldphotos) {
            foreach ($oldphotos as $ph) {
                q("DELETE FROM `photo` WHERE `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' AND `resource-id` = '%s' ", intval($importer['uid']), intval($contact['id']), dbesc($ph['resource-id']));
            }
        }
    }
    return;
}
Example #19
0
function openid_content(&$a)
{
    $noid = get_config('system', 'disable_openid');
    if ($noid) {
        goaway(z_root());
    }
    logger('mod_openid ' . print_r($_REQUEST, true), LOGGER_DATA);
    if (x($_REQUEST, 'openid_mode')) {
        $openid = new LightOpenID(z_root());
        if ($openid->validate()) {
            logger('openid: validate');
            $authid = normalise_openid($_REQUEST['openid_identity']);
            if (!strlen($authid)) {
                logger(t('OpenID protocol error. No ID returned.') . EOL);
                goaway(z_root());
            }
            $x = match_openid($authid);
            if ($x) {
                $r = q("select * from channel where channel_id = %d limit 1", intval($x));
                if ($r) {
                    $y = q("select * from account where account_id = %d limit 1", intval($r[0]['channel_account_id']));
                    if ($y) {
                        foreach ($y as $record) {
                            if ($record['account_flags'] == ACCOUNT_OK || $record['account_flags'] == ACCOUNT_UNVERIFIED) {
                                logger('mod_openid: openid success for ' . $x[0]['channel_name']);
                                $_SESSION['uid'] = $r[0]['channel_id'];
                                $_SESSION['account_id'] = $r[0]['channel_account_id'];
                                $_SESSION['authenticated'] = true;
                                authenticate_success($record, true, true, true, true);
                                goaway(z_root());
                            }
                        }
                    }
                }
            }
            // Successful OpenID login - but we can't match it to an existing account.
            // See if they've got an xchan
            $r = q("select * from xconfig left join xchan on xchan_hash = xconfig.xchan where cat = 'system' and k = 'openid' and v = '%s' limit 1", dbesc($authid));
            if ($r) {
                $_SESSION['authenticated'] = 1;
                $_SESSION['visitor_id'] = $r[0]['xchan_hash'];
                $_SESSION['my_url'] = $r[0]['xchan_url'];
                $_SESSION['my_address'] = $r[0]['xchan_addr'];
                $arr = array('xchan' => $r[0], 'session' => $_SESSION);
                call_hooks('magic_auth_openid_success', $arr);
                $a->set_observer($r[0]);
                require_once 'include/security.php';
                $a->set_groups(init_groups_visitor($_SESSION['visitor_id']));
                info(sprintf(t('Welcome %s. Remote authentication successful.'), $r[0]['xchan_name']));
                logger('mod_openid: remote auth success from ' . $r[0]['xchan_addr']);
                if ($_SESSION['return_url']) {
                    goaway($_SESSION['return_url']);
                }
                goaway(z_root());
            }
            // no xchan...
            // create one.
            // We should probably probe the openid url and figure out if they have any kind of social presence we might be able to
            // scrape some identifying info from.
            $name = $authid;
            $url = trim($_REQUEST['openid_identity'], '/');
            if (strpos($url, 'http') === false) {
                $url = 'https://' . $url;
            }
            $pphoto = z_root() . '/' . get_default_profile_photo();
            $parsed = @parse_url($url);
            if ($parsed) {
                $host = $parsed['host'];
            }
            $attr = $openid->getAttributes();
            if (is_array($attr) && count($attr)) {
                foreach ($attr as $k => $v) {
                    if ($k === 'namePerson/friendly') {
                        $nick = notags(trim($v));
                    }
                    if ($k === 'namePerson/first') {
                        $first = notags(trim($v));
                    }
                    if ($k === 'namePerson') {
                        $name = notags(trim($v));
                    }
                    if ($k === 'contact/email') {
                        $addr = notags(trim($v));
                    }
                    if ($k === 'media/image/aspect11') {
                        $photosq = trim($v);
                    }
                    if ($k === 'media/image/default') {
                        $photo_other = trim($v);
                    }
                }
            }
            if (!$nick) {
                if ($first) {
                    $nick = $first;
                } else {
                    $nick = $name;
                }
            }
            require_once 'library/urlify/URLify.php';
            $x = strtolower(URLify::transliterate($nick));
            if ($nick & $host) {
                $addr = $nick . '@' . $host;
            }
            $network = 'unknown';
            if ($photosq) {
                $pphoto = $photosq;
            } elseif ($photo_other) {
                $pphoto = $photo_other;
            }
            $mimetype = guess_image_type($pphoto);
            $x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype,\n                xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, \n\t\t\t\txchan_name_date, xchan_flags)\n                values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d) ", dbesc($url), dbesc(''), dbesc(''), dbesc(''), dbesc($mimetype), dbesc($pphoto), dbesc($addr), dbesc($url), dbesc(''), dbesc(''), dbesc(''), dbesc($name), dbesc($network), dbesc(datetime_convert()), dbesc(datetime_convert()), intval(XCHAN_FLAGS_HIDDEN));
            if ($x) {
                $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($url));
                if ($r) {
                    $photos = import_profile_photo($pphoto, $url);
                    if ($photos) {
                        $z = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', \n\t\t\t\t\t\t\txchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($url));
                    }
                    set_xconfig($url, 'system', 'openid', $authid);
                    $_SESSION['authenticated'] = 1;
                    $_SESSION['visitor_id'] = $r[0]['xchan_hash'];
                    $_SESSION['my_url'] = $r[0]['xchan_url'];
                    $_SESSION['my_address'] = $r[0]['xchan_addr'];
                    $arr = array('xchan' => $r[0], 'session' => $_SESSION);
                    call_hooks('magic_auth_openid_success', $arr);
                    $a->set_observer($r[0]);
                    info(sprintf(t('Welcome %s. Remote authentication successful.'), $r[0]['xchan_name']));
                    logger('mod_openid: remote auth success from ' . $r[0]['xchan_addr']);
                    if ($_SESSION['return_url']) {
                        goaway($_SESSION['return_url']);
                    }
                    goaway(z_root());
                }
            }
        }
    }
    notice(t('Login failed.') . EOL);
    goaway(z_root());
    // NOTREACHED
}
Example #20
0
function get_contact($url, $uid = 0)
{
    require_once "include/Scrape.php";
    $data = array();
    $contactid = 0;
    // is it an address in the format user@server.tld?
    if (!strstr($url, "http") or strstr($url, "@")) {
        $data = probe_url($url);
        $url = $data["url"];
        if ($url == "") {
            return 0;
        }
    }
    $contact = q("SELECT `id`, `avatar-date` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d", dbesc(normalise_link($url)), intval($uid));
    if (!$contact) {
        $contact = q("SELECT `id`, `avatar-date` FROM `contact` WHERE `alias` IN ('%s', '%s') AND `uid` = %d", dbesc($url), dbesc(normalise_link($url)), intval($uid));
    }
    if ($contact) {
        $contactid = $contact[0]["id"];
        // Update the contact every 7 days
        $update_photo = $contact[0]['avatar-date'] < datetime_convert('', '', 'now -7 days');
        //$update_photo = ($contact[0]['avatar-date'] < datetime_convert('','','now -12 hours'));
        if (!$update_photo) {
            return $contactid;
        }
    }
    if (!count($data)) {
        $data = probe_url($url);
    }
    // Does this address belongs to a valid network?
    if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) {
        return 0;
    }
    // tempory programming. Can be deleted after 2015-02-07
    if ($data["alias"] == "" and normalise_link($data["url"]) != normalise_link($url)) {
        $data["alias"] = normalise_link($url);
    }
    if ($contactid == 0) {
        q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,\n\t\t\t\t\t`name`, `nick`, `photo`, `network`, `pubkey`, `rel`, `priority`,\n\t\t\t\t\t`batch`, `request`, `confirm`, `poco`,\n\t\t\t\t\t`writable`, `blocked`, `readonly`, `pending`)\n\t\t\t\t\tVALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', 1, 0, 0, 0)", intval($uid), dbesc(datetime_convert()), dbesc($data["url"]), dbesc(normalise_link($data["url"])), dbesc($data["addr"]), dbesc($data["alias"]), dbesc($data["notify"]), dbesc($data["poll"]), dbesc($data["name"]), dbesc($data["nick"]), dbesc($data["photo"]), dbesc($data["network"]), dbesc($data["pubkey"]), intval(CONTACT_IS_SHARING), intval($data["priority"]), dbesc($data["batch"]), dbesc($data["request"]), dbesc($data["confirm"]), dbesc($data["poco"]));
        $contact = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d", dbesc(normalise_link($data["url"])), intval($uid));
        if (!$contact) {
            return 0;
        }
        $contactid = $contact[0]["id"];
    }
    require_once "Photo.php";
    $photos = import_profile_photo($data["photo"], $uid, $contactid);
    q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s',\n\t\t`addr` = '%s', `alias` = '%s', `name` = '%s', `nick` = '%s',\n\t\t`name-date` = '%s', `uri-date` = '%s', `avatar-date` = '%s' WHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($data["addr"]), dbesc($data["alias"]), dbesc($data["name"]), dbesc($data["nick"]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contactid));
    return $contactid;
}
Example #21
0
function import_post(&$a)
{
    $account_id = get_account_id();
    if (!$account_id) {
        return;
    }
    $max_identities = account_service_class_fetch($account_id, 'total_identities');
    $max_friends = account_service_class_fetch($account_id, 'total_channels');
    $max_feeds = account_service_class_fetch($account_id, 'total_feeds');
    if ($max_identities !== false) {
        $r = q("select channel_id from channel where channel_account_id = %d", intval($account_id));
        if ($r && count($r) > $max_identities) {
            notice(sprintf(t('Your service plan only allows %d channels.'), $max_identities) . EOL);
            return;
        }
    }
    $data = null;
    $seize = x($_REQUEST, 'make_primary') ? intval($_REQUEST['make_primary']) : 0;
    $import_posts = x($_REQUEST, 'import_posts') ? intval($_REQUEST['import_posts']) : 0;
    $src = $_FILES['filename']['tmp_name'];
    $filename = basename($_FILES['filename']['name']);
    $filesize = intval($_FILES['filename']['size']);
    $filetype = $_FILES['filename']['type'];
    if ($src) {
        // This is OS specific and could also fail if your tmpdir isn't very large
        // mostly used for Diaspora which exports gzipped files.
        if (strpos($filename, '.gz')) {
            @rename($src, $src . '.gz');
            @system('gunzip ' . escapeshellarg($src . '.gz'));
        }
        if ($filesize) {
            $data = @file_get_contents($src);
        }
        unlink($src);
    }
    if (!$src) {
        $old_address = x($_REQUEST, 'old_address') ? $_REQUEST['old_address'] : '';
        if (!$old_address) {
            logger('mod_import: nothing to import.');
            notice(t('Nothing to import.') . EOL);
            return;
        }
        $email = x($_REQUEST, 'email') ? $_REQUEST['email'] : '';
        $password = x($_REQUEST, 'password') ? $_REQUEST['password'] : '';
        $channelname = substr($old_address, 0, strpos($old_address, '@'));
        $servername = substr($old_address, strpos($old_address, '@') + 1);
        $scheme = 'https://';
        $api_path = '/api/red/channel/export/basic?f=&channel=' . $channelname;
        if ($import_posts) {
            $api_path .= '&posts=1';
        }
        $binary = false;
        $redirects = 0;
        $opts = array('http_auth' => $email . ':' . $password);
        $url = $scheme . $servername . $api_path;
        $ret = z_fetch_url($url, $binary, $redirects, $opts);
        if (!$ret['success']) {
            $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
        }
        if ($ret['success']) {
            $data = $ret['body'];
        } else {
            notice(t('Unable to download data from old server') . EOL);
        }
    }
    if (!$data) {
        logger('mod_import: empty file.');
        notice(t('Imported file is empty.') . EOL);
        return;
    }
    $data = json_decode($data, true);
    //	logger('import: data: ' . print_r($data,true));
    //	print_r($data);
    if (array_key_exists('user', $data) && array_key_exists('version', $data)) {
        require_once 'include/Import/import_diaspora.php';
        import_diaspora($data);
        return;
    }
    if (array_key_exists('compatibility', $data) && array_key_exists('database', $data['compatibility'])) {
        $v1 = substr($data['compatibility']['database'], -4);
        $v2 = substr(DB_UPDATE_VERSION, -4);
        if ($data['compatibility']['project'] !== PLATFORM_NAME) {
            notice(t('The data provided is not compatible with this project.'));
            return;
        }
    }
    if ($v2 > $v1) {
        $t = sprintf(t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1);
        notice($t);
    }
    // import channel
    $channel = $data['channel'];
    $r = q("select * from channel where (channel_guid = '%s' or channel_hash = '%s' or channel_address = '%s' ) limit 1", dbesc($channel['channel_guid']), dbesc($channel['channel_hash']), dbesc($channel['channel_address']));
    // We should probably also verify the hash
    if ($r) {
        if ($r[0]['channel_guid'] === $channel['channel_guid'] || $r[0]['channel_hash'] === $channel['channel_hash']) {
            logger('mod_import: duplicate channel. ', print_r($channel, true));
            notice(t('Cannot create a duplicate channel identifier on this system. Import failed.') . EOL);
            return;
        } else {
            // try at most ten times to generate a unique address.
            $x = 0;
            $found_unique = false;
            do {
                $tmp = $channel['channel_address'] . mt_rand(1000, 9999);
                $r = q("select * from channel where channel_address = '%s' limit 1", dbesc($tmp));
                if (!$r) {
                    $channel['channel_address'] = $tmp;
                    $found_unique = true;
                    break;
                }
                $x++;
            } while ($x < 10);
            if (!$found_unique) {
                logger('mod_import: duplicate channel. randomisation failed.', print_r($channel, true));
                notice(t('Unable to create a unique channel address. Import failed.') . EOL);
                return;
            }
        }
    }
    unset($channel['channel_id']);
    $channel['channel_account_id'] = get_account_id();
    $channel['channel_primary'] = $seize ? 1 : 0;
    dbesc_array($channel);
    $r = dbq("INSERT INTO channel (`" . implode("`, `", array_keys($channel)) . "`) VALUES ('" . implode("', '", array_values($channel)) . "')");
    if (!$r) {
        logger('mod_import: channel clone failed. ', print_r($channel, true));
        notice(t('Channel clone failed. Import failed.') . EOL);
        return;
    }
    $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", intval(get_account_id()), $channel['channel_guid']);
    if (!$r) {
        logger('mod_import: channel not found. ', print_r($channel, true));
        notice(t('Cloned channel not found. Import failed.') . EOL);
        return;
    }
    // reset
    $channel = $r[0];
    set_default_login_identity(get_account_id(), $channel['channel_id'], false);
    if ($data['photo']) {
        require_once 'include/photo/photo_driver.php';
        import_channel_photo(base64url_decode($data['photo']['data']), $data['photo']['type'], get_account_id(), $channel['channel_id']);
    }
    $profiles = $data['profile'];
    if ($profiles) {
        foreach ($profiles as $profile) {
            unset($profile['id']);
            $profile['aid'] = get_account_id();
            $profile['uid'] = $channel['channel_id'];
            // we are going to reset all profile photos to the original
            // somebody will have to fix this later and put all the applicable photos into the export
            $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id'];
            $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id'];
            dbesc_array($profile);
            $r = dbq("INSERT INTO profile (`" . implode("`, `", array_keys($profile)) . "`) VALUES ('" . implode("', '", array_values($profile)) . "')");
        }
    }
    $hublocs = $data['hubloc'];
    if ($hublocs) {
        foreach ($hublocs as $hubloc) {
            $arr = array('guid' => $hubloc['hubloc_guid'], 'guid_sig' => $hubloc['guid_sig'], 'url' => $hubloc['hubloc_url'], 'url_sig' => $hubloc['hubloc_url_sig']);
            if ($hubloc['hubloc_hash'] === $channel['channel_hash'] && $hubloc['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY && $seize) {
                $hubloc['hubloc_flags'] = $hubloc['hubloc_flags'] ^ HUBLOC_FLAGS_PRIMARY;
            }
            if (!zot_gethub($arr)) {
                unset($hubloc['hubloc_id']);
                dbesc_array($hubloc);
                $r = dbq("INSERT INTO hubloc (`" . implode("`, `", array_keys($hubloc)) . "`) VALUES ('" . implode("', '", array_values($hubloc)) . "')");
            }
        }
    }
    // create new hubloc for the new channel at this site
    $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_flags, \n\t\thubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey )\n\t\tvalues ( '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )", dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_hash']), dbesc($channel['channel_address'] . '@' . get_app()->get_hostname()), dbesc('zot'), intval($seize ? HUBLOC_FLAGS_PRIMARY : 0), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $channel['channel_prvkey']))), dbesc(get_app()->get_hostname()), dbesc(z_root() . '/post'), dbesc(get_config('system', 'pubkey')));
    // reset the original primary hubloc if it is being seized
    if ($seize) {
        $r = q("update hubloc set hubloc_flags = (hubloc_flags & ~%d) where (hubloc_flags & %d)>0 and hubloc_hash = '%s' and hubloc_url != '%s' ", intval(HUBLOC_FLAGS_PRIMARY), intval(HUBLOC_FLAGS_PRIMARY), dbesc($channel['channel_hash']), dbesc(z_root()));
    }
    // import xchans and contact photos
    if ($seize) {
        // replace any existing xchan we may have on this site if we're seizing control
        $r = q("delete from xchan where xchan_hash = '%s'", dbesc($channel['channel_hash']));
        $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", dbesc($channel['channel_hash']), dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_pubkey']), dbesc($a->get_baseurl() . "/photo/profile/l/" . $channel['channel_id']), dbesc($a->get_baseurl() . "/photo/profile/m/" . $channel['channel_id']), dbesc($a->get_baseurl() . "/photo/profile/s/" . $channel['channel_id']), dbesc($channel['channel_address'] . '@' . get_app()->get_hostname()), dbesc(z_root() . '/channel/' . $channel['channel_address']), dbesc(z_root() . '/follow?f=&url=%s'), dbesc(z_root() . '/poco/' . $channel['channel_address']), dbesc($channel['channel_name']), dbesc('zot'), dbesc(datetime_convert()), dbesc(datetime_convert()));
    }
    $xchans = $data['xchan'];
    if ($xchans) {
        foreach ($xchans as $xchan) {
            $r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", dbesc($xchan['xchan_hash']));
            if ($r) {
                continue;
            }
            dbesc_array($xchan);
            $r = dbq("INSERT INTO xchan (`" . implode("`, `", array_keys($xchan)) . "`) VALUES ('" . implode("', '", array_values($xchan)) . "')");
            require_once 'include/photo/photo_driver.php';
            $photos = import_profile_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']);
            if ($photos[4]) {
                $photodate = NULL_DATE;
            } else {
                $photodate = $xchan['xchan_photo_date'];
            }
            $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s'\n\t\t\t\twhere xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($photodate), dbesc($xchan['xchan_hash']));
        }
    }
    // FIXME - ensure we have an xchan if somebody is trying to pull a fast one
    $friends = 0;
    $feeds = 0;
    // import contacts
    $abooks = $data['abook'];
    if ($abooks) {
        foreach ($abooks as $abook) {
            if ($max_friends !== false && $friends > $max_friends) {
                continue;
            }
            if ($max_feeds !== false && $abook['abook_flags'] & ABOOK_FLAG_FEED && $feeds > $max_feeds) {
                continue;
            }
            unset($abook['abook_id']);
            $abook['abook_account'] = get_account_id();
            $abook['abook_channel'] = $channel['channel_id'];
            dbesc_array($abook);
            $r = dbq("INSERT INTO abook (`" . implode("`, `", array_keys($abook)) . "`) VALUES ('" . implode("', '", array_values($abook)) . "')");
            $friends++;
            if ($abook['abook_flags'] & ABOOK_FLAG_FEED) {
                $feeds++;
            }
        }
    }
    $configs = $data['config'];
    if ($configs) {
        foreach ($configs as $config) {
            unset($config['id']);
            $config['uid'] = $channel['channel_id'];
            dbesc_array($config);
            $r = dbq("INSERT INTO pconfig (`" . implode("`, `", array_keys($config)) . "`) VALUES ('" . implode("', '", array_values($config)) . "')");
        }
    }
    $groups = $data['group'];
    if ($groups) {
        $saved = array();
        foreach ($groups as $group) {
            $saved[$group['hash']] = array('old' => $group['id']);
            unset($group['id']);
            $group['uid'] = $channel['channel_id'];
            dbesc_array($group);
            $r = dbq("INSERT INTO groups (`" . implode("`, `", array_keys($group)) . "`) VALUES ('" . implode("', '", array_values($group)) . "')");
        }
        $r = q("select * from `groups` where uid = %d", intval($channel['channel_id']));
        if ($r) {
            foreach ($r as $rr) {
                $saved[$rr['hash']]['new'] = $rr['id'];
            }
        }
    }
    $group_members = $data['group_member'];
    if ($group_members) {
        foreach ($group_members as $group_member) {
            unset($group_member['id']);
            $group_member['uid'] = $channel['channel_id'];
            foreach ($saved as $x) {
                if ($x['old'] == $group_member['gid']) {
                    $group_member['gid'] = $x['new'];
                }
            }
            dbesc_array($group_member);
            $r = dbq("INSERT INTO group_member (`" . implode("`, `", array_keys($group_member)) . "`) VALUES ('" . implode("', '", array_values($group_member)) . "')");
        }
    }
    $saved_notification_flags = notifications_off($channel['channel_id']);
    if ($import_posts && array_key_exists('item', $data) && $data['item']) {
        foreach ($data['item'] as $i) {
            $item = get_item_elements($i);
            $r = q("select id, edited from item where mid = '%s' and uid = %d limit 1", dbesc($item['mid']), intval($channel['channel_id']));
            if ($r) {
                if ($item['edited'] > $r[0]['edited']) {
                    $item['id'] = $r[0]['id'];
                    $item['uid'] = $channel['channel_id'];
                    item_store_update($item);
                    continue;
                }
            } else {
                $item['aid'] = $channel['channel_account_id'];
                $item['uid'] = $channel['channel_id'];
                $item_result = item_store($item);
            }
        }
    }
    notifications_on($channel['channel_id'], $saved_notification_flags);
    if (array_key_exists('item_id', $data) && $data['item_id']) {
        foreach ($data['item_id'] as $i) {
            $r = q("select id from item where mid = '%s' and uid = %d limit 1", dbesc($i['mid']), intval($channel['channel_id']));
            if (!$r) {
                continue;
            }
            $z = q("select * from item_id where service = '%s' and sid = '%s' and iid = %d and uid = %d limit 1", dbesc($i['service']), dbesc($i['sid']), intval($r[0]['id']), intval($channel['channel_id']));
            if (!$z) {
                q("insert into item_id (iid,uid,sid,service) values(%d,%d,'%s','%s')", intval($r[0]['id']), intval($channel['channel_id']), dbesc($i['sid']), dbesc($i['service']));
            }
        }
    }
    // FIXME - ensure we have a self entry if somebody is trying to pull a fast one
    // send out refresh requests
    // notify old server that it may no longer be primary.
    proc_run('php', 'include/notifier.php', 'location', $channel['channel_id']);
    // This will indirectly perform a refresh_all *and* update the directory
    proc_run('php', 'include/directory.php', $channel['channel_id']);
    notice(t('Import completed.') . EOL);
    change_channel($channel['channel_id']);
    goaway(z_root() . '/network');
}
Example #22
0
function discover_by_webbie($webbie)
{
    require_once 'library/HTML5/Parser.php';
    $webbie = strtolower($webbie);
    $x = webfinger_rfc7033($webbie);
    if ($x && array_key_exists('links', $x) && $x['links']) {
        foreach ($x['links'] as $link) {
            if (array_key_exists('rel', $link) && $link['rel'] == 'http://purl.org/zot/protocol') {
                logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG);
                $z = z_fetch_url($link['href']);
                if ($z['success']) {
                    $j = json_decode($z['body'], true);
                    $i = import_xchan($j);
                    return true;
                }
            }
        }
    }
    $result = array();
    $network = null;
    $diaspora = false;
    $diaspora_base = '';
    $diaspora_guid = '';
    $diaspora_key = '';
    $dfrn = false;
    $x = old_webfinger($webbie);
    if ($x) {
        logger('old_webfinger: ' . print_r($x, true));
        foreach ($x as $link) {
            if ($link['@attributes']['rel'] === NAMESPACE_DFRN) {
                $dfrn = unamp($link['@attributes']['href']);
            }
            if ($link['@attributes']['rel'] === 'salmon') {
                $notify = unamp($link['@attributes']['href']);
            }
            if ($link['@attributes']['rel'] === NAMESPACE_FEED) {
                $poll = unamp($link['@attributes']['href']);
            }
            if ($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') {
                $hcard = unamp($link['@attributes']['href']);
            }
            if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') {
                $profile = unamp($link['@attributes']['href']);
            }
            if ($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0') {
                $poco = unamp($link['@attributes']['href']);
            }
            if ($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') {
                $diaspora_base = unamp($link['@attributes']['href']);
                $diaspora = true;
            }
            if ($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') {
                $diaspora_guid = unamp($link['@attributes']['href']);
                $diaspora = true;
            }
            if ($link['@attributes']['rel'] === 'diaspora-public-key') {
                $diaspora_key = base64_decode(unamp($link['@attributes']['href']));
                if (strstr($diaspora_key, 'RSA ')) {
                    $pubkey = rsatopem($diaspora_key);
                } else {
                    $pubkey = $diaspora_key;
                }
                $diaspora = true;
            }
        }
        if ($diaspora && $diaspora_base && $diaspora_guid) {
            $guid = $diaspora_guid;
            $diaspora_base = trim($diaspora_base, '/');
            $notify = $diaspora_base . '/receive';
            if (strpos($webbie, '@')) {
                $addr = str_replace('acct:', '', $webbie);
                $hostname = substr($webbie, strpos($webbie, '@') + 1);
            }
            $network = 'diaspora';
            // until we get a dfrn layer, we'll use diaspora protocols for Friendica,
            // but give it a different network so we can go back and fix these when we get proper support.
            // It really should be just 'friendica' but we also want to distinguish
            // between Friendica sites that we can use D* protocols with and those we can't.
            // Some Friendica sites will have Diaspora disabled.
            if ($dfrn) {
                $network = 'friendica-over-diaspora';
            }
            if ($hcard) {
                $vcard = scrape_vcard($hcard);
                $vcard['nick'] = substr($webbie, 0, strpos($webbie, '@'));
            }
            $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($webbie));
            if (!$r) {
                $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_instance_url, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", dbesc($addr), dbesc($guid), dbesc($pubkey), dbesc($addr), dbesc($profile), dbesc($vcard['fn']), dbesc($network), dbesc(z_root()), dbescdate(datetime_convert()));
            }
            $r = q("select * from hubloc where hubloc_hash = '%s' limit 1", dbesc($webbie));
            if (!$r) {
                $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_flags ) values ('%s','%s','%s','%s','%s','%s','%s','%s', %d)", dbesc($guid), dbesc($addr), dbesc($addr), dbesc($network), dbesc(trim($diaspora_base, '/')), dbesc($hostname), dbesc($notify), dbescdate(datetime_convert()), intval(HUBLOC_FLAGS_PRIMARY));
            }
            $photos = import_profile_photo($vcard['photo'], $addr);
            $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbescdate(datetime_convert('UTC', 'UTC', $arr['photo_updated'])), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($addr));
            return true;
        }
        return false;
        /*
        	$vcard['fn'] = notags($vcard['fn']);
        	$vcard['nick'] = str_replace(' ','',notags($vcard['nick']));
        	$result['name'] = $vcard['fn'];
        	$result['nick'] = $vcard['nick'];
        	$result['guid'] = $guid;
        	$result['url'] = $profile;
        	$result['hostname'] = $hostname;
        	$result['addr'] = $addr;
        	$result['batch'] = $batch;
        	$result['notify'] = $notify;
        	$result['poll'] = $poll;
        	$result['request'] = $request;
        	$result['confirm'] = $confirm;
        	$result['poco'] = $poco;
        	$result['photo'] = $vcard['photo'];
        	$result['priority'] = $priority;
        	$result['network'] = $network;
        	$result['alias'] = $alias;
        	$result['pubkey'] = $pubkey;
        	logger('probe_url: ' . print_r($result,true), LOGGER_DEBUG);
        	return $result;
        */
        /* Sample Diaspora result.
        
        Array
        (
        	[name] => Mike Macgirvin
        	[nick] => macgirvin
        	[guid] => a9174a618f8d269a
        	[url] => https://joindiaspora.com/u/macgirvin
        	[hostname] => joindiaspora.com
        	[addr] => macgirvin@joindiaspora.com
        	[batch] => 
        	[notify] => https://joindiaspora.com/receive
        	[poll] => https://joindiaspora.com/public/macgirvin.atom
        	[request] => 
        	[confirm] => 
        	[poco] => 
        	[photo] => https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_fec4e6eef13ae5e56207.jpg
        	[priority] => 
        	[network] => diaspora
        	[alias] => 
        	[pubkey] => -----BEGIN PUBLIC KEY-----
        MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtihtyIuRDWkDpCA+I1UaQ
        jI4S7k625+A7EEJm+pL2ZVSJxeCKiFeEgHBQENjLMNNm8l8F6blxgQqE6ZJ9Spa7f
        tlaXYTRCrfxKzh02L3hR7sNA+JS/nXJaUAIo+IwpIEspmcIRbD9GB7Wv/rr+M28uH
        31EeYyDz8QL6InU/bJmnCdFvmEMBQxJOw1ih9tQp7UNJAbUMCje0WYFzBz7sfcaHL
        OyYcCOqOCBLdGucUoJzTQ9iDBVzB8j1r1JkIHoEb2moUoKUp+tkCylNfd/3IVELF9
        7w1Qjmit3m50OrJk2DQOXvCW9KQxaQNdpRPSwhvemIt98zXSeyZ1q/YjjOwG0DWDq
        AF8aLj3/oQaZndTPy/6tMiZogKaijoxj8xFLuPYDTw5VpKquriVC0z8oxyRbv4t9v
        8JZZ9BXqzmayvY3xZGGp8NulrfjW+me2bKh0/df1aHaBwpZdDTXQ6kqAiS2FfsuPN
        vg57fhfHbL1yJ4oDbNNNeI0kJTGchXqerr8C20khU/cQ2Xt31VyEZtnTB665Ceugv
        kp3t2qd8UpAVKl430S5Quqx2ymfUIdxdW08CEjnoRNEL3aOWOXfbf4gSVaXmPCR4i
        LSIeXnd14lQYK/uxW/8cTFjcmddsKxeXysoQxbSa9VdDK+KkpZdgYXYrTTofXs6v+
        4afAEhRaaY+MCAwEAAQ==
        -----END PUBLIC KEY-----
        
        )
        */
    }
}
Example #23
0
function dfrn_confirm_post(&$a, $handsfree = null)
{
    if (is_array($handsfree)) {
        /**
         * We were called directly from dfrn_request due to automatic friend acceptance.
         * Any $_POST parameters we may require are supplied in the $handsfree array.
         *
         */
        $node = $handsfree['node'];
        $a->interactive = false;
        // notice() becomes a no-op since nobody is there to see it
    } else {
        if ($a->argc > 1) {
            $node = $a->argv[1];
        }
    }
    /**
     *
     * Main entry point. Scenario 1. Our user received a friend request notification (perhaps
     * from another site) and clicked 'Approve'.
     * $POST['source_url'] is not set. If it is, it indicates Scenario 2.
     *
     * We may also have been called directly from dfrn_request ($handsfree != null) due to
     * this being a page type which supports automatic friend acceptance. That is also Scenario 1
     * since we are operating on behalf of our registered user to approve a friendship.
     *
     */
    if (!x($_POST, 'source_url')) {
        $uid = is_array($handsfree) ? $handsfree['uid'] : local_user();
        if (!$uid) {
            notice(t('Permission denied.') . EOL);
            return;
        }
        $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid));
        if (!$user) {
            notice(t('Profile not found.') . EOL);
            return;
        }
        // These data elements may come from either the friend request notification form or $handsfree array.
        if (is_array($handsfree)) {
            logger('Confirm in handsfree mode');
            $dfrn_id = $handsfree['dfrn_id'];
            $intro_id = $handsfree['intro_id'];
            $duplex = $handsfree['duplex'];
            $hidden = array_key_exists('hidden', $handsfree) ? intval($handsfree['hidden']) : 0;
            $activity = array_key_exists('activity', $handsfree) ? intval($handsfree['activity']) : 0;
        } else {
            $dfrn_id = x($_POST, 'dfrn_id') ? notags(trim($_POST['dfrn_id'])) : "";
            $intro_id = x($_POST, 'intro_id') ? intval($_POST['intro_id']) : 0;
            $duplex = x($_POST, 'duplex') ? intval($_POST['duplex']) : 0;
            $cid = x($_POST, 'contact_id') ? intval($_POST['contact_id']) : 0;
            $hidden = x($_POST, 'hidden') ? intval($_POST['hidden']) : 0;
            $activity = x($_POST, 'activity') ? intval($_POST['activity']) : 0;
        }
        /**
         *
         * Ensure that dfrn_id has precedence when we go to find the contact record.
         * We only want to search based on contact id if there is no dfrn_id,
         * e.g. for OStatus network followers.
         *
         */
        if (strlen($dfrn_id)) {
            $cid = 0;
        }
        logger('Confirming request for dfrn_id (issued) ' . $dfrn_id);
        if ($cid) {
            logger('Confirming follower with contact_id: ' . $cid);
        }
        /**
         *
         * The other person will have been issued an ID when they first requested friendship.
         * Locate their record. At this time, their record will have both pending and blocked set to 1.
         * There won't be any dfrn_id if this is a network follower, so use the contact_id instead.
         *
         */
        $r = q("SELECT * FROM `contact` WHERE ( ( `issued-id` != '' AND `issued-id` = '%s' ) OR ( `id` = %d AND `id` != 0 ) ) AND `uid` = %d AND `duplex` = 0 LIMIT 1", dbesc($dfrn_id), intval($cid), intval($uid));
        if (!count($r)) {
            logger('Contact not found in DB.');
            notice(t('Contact not found.') . EOL);
            notice(t('This may occasionally happen if contact was requested by both persons and it has already been approved.') . EOL);
            return;
        }
        $contact = $r[0];
        $contact_id = $contact['id'];
        $relation = $contact['rel'];
        $site_pubkey = $contact['site-pubkey'];
        $dfrn_confirm = $contact['confirm'];
        $aes_allow = $contact['aes_allow'];
        $network = strlen($contact['issued-id']) ? NETWORK_DFRN : NETWORK_OSTATUS;
        if ($contact['network']) {
            $network = $contact['network'];
        }
        if ($network === NETWORK_DFRN) {
            /**
             *
             * Generate a key pair for all further communications with this person.
             * We have a keypair for every contact, and a site key for unknown people.
             * This provides a means to carry on relationships with other people if
             * any single key is compromised. It is a robust key. We're much more
             * worried about key leakage than anybody cracking it.
             *
             */
            require_once 'include/crypto.php';
            $res = new_keypair(4096);
            $private_key = $res['prvkey'];
            $public_key = $res['pubkey'];
            // Save the private key. Send them the public key.
            $r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($private_key), intval($contact_id), intval($uid));
            $params = array();
            /**
             *
             * Per the DFRN protocol, we will verify both ends by encrypting the dfrn_id with our
             * site private key (person on the other end can decrypt it with our site public key).
             * Then encrypt our profile URL with the other person's site public key. They can decrypt
             * it with their site private key. If the decryption on the other end fails for either
             * item, it indicates tampering or key failure on at least one site and we will not be
             * able to provide a secure communication pathway.
             *
             * If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3
             * or later) then we encrypt the personal public key we send them using AES-256-CBC and a
             * random key which is encrypted with their site public key.
             *
             */
            $src_aes_key = random_string();
            $result = '';
            openssl_private_encrypt($dfrn_id, $result, $user[0]['prvkey']);
            $params['dfrn_id'] = bin2hex($result);
            $params['public_key'] = $public_key;
            $my_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
            openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
            $params['source_url'] = bin2hex($params['source_url']);
            if ($aes_allow && function_exists('openssl_encrypt')) {
                openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
                $params['aes_key'] = bin2hex($params['aes_key']);
                $params['public_key'] = bin2hex(openssl_encrypt($public_key, 'AES-256-CBC', $src_aes_key));
            }
            $params['dfrn_version'] = DFRN_PROTOCOL_VERSION;
            if ($duplex == 1) {
                $params['duplex'] = 1;
            }
            if ($user[0]['page-flags'] == PAGE_COMMUNITY) {
                $params['page'] = 1;
            }
            if ($user[0]['page-flags'] == PAGE_PRVGROUP) {
                $params['page'] = 2;
            }
            logger('Confirm: posting data to ' . $dfrn_confirm . ': ' . print_r($params, true), LOGGER_DATA);
            /**
             *
             * POST all this stuff to the other site.
             * Temporarily raise the network timeout to 120 seconds because the default 60
             * doesn't always give the other side quite enough time to decrypt everything.
             *
             */
            $a->config['system']['curl_timeout'] = 120;
            $res = post_url($dfrn_confirm, $params);
            logger(' Confirm: received data: ' . $res, LOGGER_DATA);
            // Now figure out what they responded. Try to be robust if the remote site is
            // having difficulty and throwing up errors of some kind.
            $leading_junk = substr($res, 0, strpos($res, '<?xml'));
            $res = substr($res, strpos($res, '<?xml'));
            if (!strlen($res)) {
                // No XML at all, this exchange is messed up really bad.
                // We shouldn't proceed, because the xml parser might choke,
                // and $status is going to be zero, which indicates success.
                // We can hardly call this a success.
                notice(t('Response from remote site was not understood.') . EOL);
                return;
            }
            if (strlen($leading_junk) && get_config('system', 'debugging')) {
                // This might be more common. Mixed error text and some XML.
                // If we're configured for debugging, show the text. Proceed in either case.
                notice(t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL);
            }
            if (stristr($res, "<status") === false) {
                // wrong xml! stop here!
                notice(t('Unexpected response from remote site: ') . EOL . htmlspecialchars($res) . EOL);
                return;
            }
            $xml = parse_xml_string($res);
            $status = (int) $xml->status;
            $message = unxmlify($xml->message);
            // human readable text of what may have gone wrong.
            switch ($status) {
                case 0:
                    info(t("Confirmation completed successfully.") . EOL);
                    if (strlen($message)) {
                        notice(t('Remote site reported: ') . $message . EOL);
                    }
                    break;
                case 1:
                    // birthday paradox - generate new dfrn-id and fall through.
                    $new_dfrn_id = random_string();
                    $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($new_dfrn_id), intval($contact_id), intval($uid));
                case 2:
                    notice(t("Temporary failure. Please wait and try again.") . EOL);
                    if (strlen($message)) {
                        notice(t('Remote site reported: ') . $message . EOL);
                    }
                    break;
                case 3:
                    notice(t("Introduction failed or was revoked.") . EOL);
                    if (strlen($message)) {
                        notice(t('Remote site reported: ') . $message . EOL);
                    }
                    break;
            }
            if ($status == 0 && $intro_id) {
                // Success. Delete the notification.
                $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d", intval($intro_id), intval($uid));
            }
            if ($status != 0) {
                return;
            }
        }
        /*
         *
         * We have now established a relationship with the other site.
         * Let's make our own personal copy of their profile photo so we don't have
         * to always load it from their site.
         *
         * We will also update the contact record with the nature and scope of the relationship.
         *
         */
        require_once 'include/Photo.php';
        $photos = import_profile_photo($contact['photo'], $uid, $contact_id);
        logger('dfrn_confirm: confirm - imported photos');
        if ($network === NETWORK_DFRN) {
            $new_relation = CONTACT_IS_FOLLOWER;
            if ($relation == CONTACT_IS_SHARING || $duplex) {
                $new_relation = CONTACT_IS_FRIEND;
            }
            if ($relation == CONTACT_IS_SHARING && $duplex) {
                $duplex = 0;
            }
            $r = q("UPDATE `contact` SET\n\t\t\t\t`photo` = '%s',\n\t\t\t\t`thumb` = '%s',\n\t\t\t\t`micro` = '%s',\n\t\t\t\t`rel` = %d,\n\t\t\t\t`name-date` = '%s',\n\t\t\t\t`uri-date` = '%s',\n\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t`blocked` = 0,\n\t\t\t\t`pending` = 0,\n\t\t\t\t`duplex` = %d,\n\t\t\t\t`hidden` = %d,\n\t\t\t\t`network` = '%s' WHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($duplex), intval($hidden), dbesc(NETWORK_DFRN), intval($contact_id));
        } else {
            // $network !== NETWORK_DFRN
            $network = $contact['network'] ? $contact['network'] : NETWORK_OSTATUS;
            $notify = $contact['notify'] ? $contact['notify'] : '';
            $poll = $contact['poll'] ? $contact['poll'] : '';
            if (!$contact['notify'] || !$contact['poll']) {
                $arr = lrdd($contact['url']);
                if (count($arr)) {
                    foreach ($arr as $link) {
                        if ($link['@attributes']['rel'] === 'salmon') {
                            $notify = $link['@attributes']['href'];
                        }
                        if ($link['@attributes']['rel'] === NAMESPACE_FEED) {
                            $poll = $link['@attributes']['href'];
                        }
                    }
                }
            }
            $new_relation = $contact['rel'];
            $writable = $contact['writable'];
            if ($network === NETWORK_DIASPORA) {
                if ($duplex) {
                    $new_relation = CONTACT_IS_FRIEND;
                } else {
                    $new_relation = CONTACT_IS_FOLLOWER;
                }
                if ($new_relation != CONTACT_IS_FOLLOWER) {
                    $writable = 1;
                }
            }
            $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d", intval($intro_id), intval($uid));
            $r = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t`thumb` = '%s',\n\t\t\t\t`micro` = '%s',\n\t\t\t\t`name-date` = '%s',\n\t\t\t\t`uri-date` = '%s',\n\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t`notify` = '%s',\n\t\t\t\t`poll` = '%s',\n\t\t\t\t`blocked` = 0,\n\t\t\t\t`pending` = 0,\n\t\t\t\t`network` = '%s',\n\t\t\t\t`writable` = %d,\n\t\t\t\t`hidden` = %d,\n\t\t\t\t`rel` = %d\n\t\t\t\tWHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($notify), dbesc($poll), dbesc($network), intval($writable), intval($hidden), intval($new_relation), intval($contact_id));
        }
        if ($r === false) {
            notice(t('Unable to set contact photo.') . EOL);
        }
        // reload contact info
        $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id));
        if (count($r)) {
            $contact = $r[0];
        } else {
            $contact = null;
        }
        if (isset($new_relation) && $new_relation == CONTACT_IS_FRIEND) {
            if ($contact && $contact['network'] === NETWORK_DIASPORA) {
                require_once 'include/diaspora.php';
                $ret = diaspora_share($user[0], $r[0]);
                logger('mod_follow: diaspora_share returns: ' . $ret);
            }
            // Send a new friend post if we are allowed to...
            $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($uid));
            if (count($r) && $r[0]['hide-friends'] == 0 && $activity && !$hidden) {
                require_once 'include/items.php';
                $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid));
                if (count($self)) {
                    $arr = array();
                    $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $uid);
                    $arr['uid'] = $uid;
                    $arr['contact-id'] = $self[0]['id'];
                    $arr['wall'] = 1;
                    $arr['type'] = 'wall';
                    $arr['gravity'] = 0;
                    $arr['origin'] = 1;
                    $arr['author-name'] = $arr['owner-name'] = $self[0]['name'];
                    $arr['author-link'] = $arr['owner-link'] = $self[0]['url'];
                    $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb'];
                    $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]';
                    $APhoto = '[url=' . $self[0]['url'] . ']' . '[img]' . $self[0]['thumb'] . '[/img][/url]';
                    $B = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
                    $BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]';
                    $arr['verb'] = ACTIVITY_FRIEND;
                    $arr['object-type'] = ACTIVITY_OBJ_PERSON;
                    $arr['body'] = sprintf(t('%1$s is now friends with %2$s'), $A, $B) . "\n\n\n" . $BPhoto;
                    $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>' . '<id>' . $contact['url'] . '/' . $contact['name'] . '</id>';
                    $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact['url'] . '" />' . "\n");
                    $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact['thumb'] . '" />' . "\n");
                    $arr['object'] .= '</link></object>' . "\n";
                    $arr['last-child'] = 1;
                    $arr['allow_cid'] = $user[0]['allow_cid'];
                    $arr['allow_gid'] = $user[0]['allow_gid'];
                    $arr['deny_cid'] = $user[0]['deny_cid'];
                    $arr['deny_gid'] = $user[0]['deny_gid'];
                    $i = item_store($arr);
                    if ($i) {
                        proc_run('php', "include/notifier.php", "activity", "{$i}");
                    }
                }
            }
        }
        $g = q("select def_gid from user where uid = %d limit 1", intval($uid));
        if ($contact && $g && intval($g[0]['def_gid'])) {
            require_once 'include/group.php';
            group_add_member($uid, '', $contact['id'], $g[0]['def_gid']);
        }
        // Let's send our user to the contact editor in case they want to
        // do anything special with this new friend.
        if ($handsfree === null) {
            goaway($a->get_baseurl() . '/contacts/' . intval($contact_id));
        } else {
            return;
        }
        //NOTREACHED
    }
    /**
     *
     *
     * End of Scenario 1. [Local confirmation of remote friend request].
     *
     * Begin Scenario 2. This is the remote response to the above scenario.
     * This will take place on the site that originally initiated the friend request.
     * In the section above where the confirming party makes a POST and
     * retrieves xml status information, they are communicating with the following code.
     *
     */
    if (x($_POST, 'source_url')) {
        // We are processing an external confirmation to an introduction created by our user.
        $public_key = x($_POST, 'public_key') ? $_POST['public_key'] : '';
        $dfrn_id = x($_POST, 'dfrn_id') ? hex2bin($_POST['dfrn_id']) : '';
        $source_url = x($_POST, 'source_url') ? hex2bin($_POST['source_url']) : '';
        $aes_key = x($_POST, 'aes_key') ? $_POST['aes_key'] : '';
        $duplex = x($_POST, 'duplex') ? intval($_POST['duplex']) : 0;
        $page = x($_POST, 'page') ? intval($_POST['page']) : 0;
        $version_id = x($_POST, 'dfrn_version') ? (double) $_POST['dfrn_version'] : 2.0;
        $forum = $page == 1 ? 1 : 0;
        $prv = $page == 2 ? 1 : 0;
        logger('dfrn_confirm: requestee contacted: ' . $node);
        logger('dfrn_confirm: request: POST=' . print_r($_POST, true), LOGGER_DATA);
        // If $aes_key is set, both of these items require unpacking from the hex transport encoding.
        if (x($aes_key)) {
            $aes_key = hex2bin($aes_key);
            $public_key = hex2bin($public_key);
        }
        // Find our user's account
        $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' LIMIT 1", dbesc($node));
        if (!count($r)) {
            $message = sprintf(t('No user record found for \'%s\' '), $node);
            xml_status(3, $message);
            // failure
            // NOTREACHED
        }
        $my_prvkey = $r[0]['prvkey'];
        $local_uid = $r[0]['uid'];
        if (!strstr($my_prvkey, 'PRIVATE KEY')) {
            $message = t('Our site encryption key is apparently messed up.');
            xml_status(3, $message);
        }
        // verify everything
        $decrypted_source_url = "";
        openssl_private_decrypt($source_url, $decrypted_source_url, $my_prvkey);
        if (!strlen($decrypted_source_url)) {
            $message = t('Empty site URL was provided or URL could not be decrypted by us.');
            xml_status(3, $message);
            // NOTREACHED
        }
        $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($decrypted_source_url), intval($local_uid));
        if (!count($ret)) {
            if (strstr($decrypted_source_url, 'http:')) {
                $newurl = str_replace('http:', 'https:', $decrypted_source_url);
            } else {
                $newurl = str_replace('https:', 'http:', $decrypted_source_url);
            }
            $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($newurl), intval($local_uid));
            if (!count($ret)) {
                // this is either a bogus confirmation (?) or we deleted the original introduction.
                $message = t('Contact record was not found for you on our site.');
                xml_status(3, $message);
                return;
                // NOTREACHED
            }
        }
        $relation = $ret[0]['rel'];
        // Decrypt all this stuff we just received
        $foreign_pubkey = $ret[0]['site-pubkey'];
        $dfrn_record = $ret[0]['id'];
        if (!$foreign_pubkey) {
            $message = sprintf(t('Site public key not available in contact record for URL %s.'), $newurl);
            xml_status(3, $message);
        }
        $decrypted_dfrn_id = "";
        openssl_public_decrypt($dfrn_id, $decrypted_dfrn_id, $foreign_pubkey);
        if (strlen($aes_key)) {
            $decrypted_aes_key = "";
            openssl_private_decrypt($aes_key, $decrypted_aes_key, $my_prvkey);
            $dfrn_pubkey = openssl_decrypt($public_key, 'AES-256-CBC', $decrypted_aes_key);
        } else {
            $dfrn_pubkey = $public_key;
        }
        $r = q("SELECT * FROM `contact` WHERE `dfrn-id` = '%s' LIMIT 1", dbesc($decrypted_dfrn_id));
        if (count($r)) {
            $message = t('The ID provided by your system is a duplicate on our system. It should work if you try again.');
            xml_status(1, $message);
            // Birthday paradox - duplicate dfrn-id
            // NOTREACHED
        }
        $r = q("UPDATE `contact` SET `dfrn-id` = '%s', `pubkey` = '%s' WHERE `id` = %d", dbesc($decrypted_dfrn_id), dbesc($dfrn_pubkey), intval($dfrn_record));
        if (!count($r)) {
            $message = t('Unable to set your contact credentials on our system.');
            xml_status(3, $message);
        }
        // It's possible that the other person also requested friendship.
        // If it is a duplex relationship, ditch the issued-id if one exists.
        if ($duplex) {
            $r = q("UPDATE `contact` SET `issued-id` = '' WHERE `id` = %d", intval($dfrn_record));
        }
        // We're good but now we have to scrape the profile photo and send notifications.
        $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1", intval($dfrn_record));
        if (count($r)) {
            $photo = $r[0]['photo'];
        } else {
            $photo = $a->get_baseurl() . '/images/person-175.jpg';
        }
        require_once "include/Photo.php";
        $photos = import_profile_photo($photo, $local_uid, $dfrn_record);
        logger('dfrn_confirm: request - photos imported');
        $new_relation = CONTACT_IS_SHARING;
        if ($relation == CONTACT_IS_FOLLOWER || $duplex) {
            $new_relation = CONTACT_IS_FRIEND;
        }
        if ($relation == CONTACT_IS_FOLLOWER && $duplex) {
            $duplex = 0;
        }
        $r = q("UPDATE `contact` SET\n\t\t\t`photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`rel` = %d,\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s',\n\t\t\t`blocked` = 0,\n\t\t\t`pending` = 0,\n\t\t\t`duplex` = %d,\n\t\t\t`forum` = %d,\n\t\t\t`prv` = %d,\n\t\t\t`network` = '%s' WHERE `id` = %d\n\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($duplex), intval($forum), intval($prv), dbesc(NETWORK_DFRN), intval($dfrn_record));
        if ($r === false) {
            // indicates schema is messed up or total db failure
            $message = t('Unable to update your contact profile details on our system');
            xml_status(3, $message);
        }
        // Otherwise everything seems to have worked and we are almost done. Yay!
        // Send an email notification
        logger('dfrn_confirm: request: info updated');
        $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `contact`.`id` = %d LIMIT 1", intval($dfrn_record));
        if (count($r)) {
            $combined = $r[0];
        }
        if (count($r) && $r[0]['notify-flags'] & NOTIFY_CONFIRM) {
            $mutual = $new_relation == CONTACT_IS_FRIEND;
            notification(array('type' => NOTIFY_CONFIRM, 'notify_flags' => $r[0]['notify-flags'], 'language' => $r[0]['language'], 'to_name' => $r[0]['username'], 'to_email' => $r[0]['email'], 'uid' => $r[0]['uid'], 'link' => $a->get_baseurl() . '/contacts/' . $dfrn_record, 'source_name' => strlen(stripslashes($r[0]['name'])) ? stripslashes($r[0]['name']) : t('[Name Withheld]'), 'source_link' => $r[0]['url'], 'source_photo' => $r[0]['photo'], 'verb' => $mutual ? ACTIVITY_FRIEND : ACTIVITY_FOLLOW, 'otype' => 'intro'));
        }
        // Send a new friend post if we are allowed to...
        if ($page && intval(get_pconfig($local_uid, 'system', 'post_joingroup'))) {
            $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($local_uid));
            if (count($r) && $r[0]['hide-friends'] == 0) {
                require_once 'include/items.php';
                $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($local_uid));
                if (count($self)) {
                    $arr = array();
                    $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $local_uid);
                    $arr['uid'] = $local_uid;
                    $arr['contact-id'] = $self[0]['id'];
                    $arr['wall'] = 1;
                    $arr['type'] = 'wall';
                    $arr['gravity'] = 0;
                    $arr['origin'] = 1;
                    $arr['author-name'] = $arr['owner-name'] = $self[0]['name'];
                    $arr['author-link'] = $arr['owner-link'] = $self[0]['url'];
                    $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb'];
                    $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]';
                    $APhoto = '[url=' . $self[0]['url'] . ']' . '[img]' . $self[0]['thumb'] . '[/img][/url]';
                    $B = '[url=' . $combined['url'] . ']' . $combined['name'] . '[/url]';
                    $BPhoto = '[url=' . $combined['url'] . ']' . '[img]' . $combined['thumb'] . '[/img][/url]';
                    $arr['verb'] = ACTIVITY_JOIN;
                    $arr['object-type'] = ACTIVITY_OBJ_GROUP;
                    $arr['body'] = sprintf(t('%1$s has joined %2$s'), $A, $B) . "\n\n\n" . $BPhoto;
                    $arr['object'] = '<object><type>' . ACTIVITY_OBJ_GROUP . '</type><title>' . $combined['name'] . '</title>' . '<id>' . $combined['url'] . '/' . $combined['name'] . '</id>';
                    $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $combined['url'] . '" />' . "\n");
                    $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $combined['thumb'] . '" />' . "\n");
                    $arr['object'] .= '</link></object>' . "\n";
                    $arr['last-child'] = 1;
                    $arr['allow_cid'] = $user[0]['allow_cid'];
                    $arr['allow_gid'] = $user[0]['allow_gid'];
                    $arr['deny_cid'] = $user[0]['deny_cid'];
                    $arr['deny_gid'] = $user[0]['deny_gid'];
                    $i = item_store($arr);
                    if ($i) {
                        proc_run('php', "include/notifier.php", "activity", "{$i}");
                    }
                }
            }
        }
        xml_status(0);
        // Success
        return;
        // NOTREACHED
        ////////////////////// End of this scenario ///////////////////////////////////////////////
    }
    // somebody arrived here by mistake or they are fishing. Send them to the homepage.
    goaway(z_root());
    // NOTREACHED
}
Example #24
0
function new_contact($uid, $url, $interactive = false)
{
    $result = array('cid' => -1, 'success' => false, 'message' => '');
    $a = get_app();
    // remove ajax junk, e.g. Twitter
    $url = str_replace('/#!/', '/', $url);
    if (!allowed_url($url)) {
        $result['message'] = t('Disallowed profile URL.');
        return $result;
    }
    if (!$url) {
        $result['message'] = t('Connect URL missing.');
        return $result;
    }
    $arr = array('url' => $url, 'contact' => array());
    call_hooks('follow', $arr);
    if (x($arr['contact'], 'name')) {
        $ret = $arr['contact'];
    } else {
        $ret = probe_url($url);
    }
    if ($ret['network'] === NETWORK_DFRN) {
        if ($interactive) {
            if (strlen($a->path)) {
                $myaddr = bin2hex($a->get_baseurl() . '/profile/' . $a->user['nickname']);
            } else {
                $myaddr = bin2hex($a->user['nickname'] . '@' . $a->get_hostname());
            }
            goaway($ret['request'] . "&addr={$myaddr}");
            // NOTREACHED
        }
    } else {
        if (get_config('system', 'dfrn_only')) {
            $result['message'] = t('This site is not configured to allow communications with other networks.') . EOL;
            $result['message'] != t('No compatible communication protocols or feeds were discovered.') . EOL;
            return $result;
        }
    }
    // This extra param just confuses things, remove it
    if ($ret['network'] === NETWORK_DIASPORA) {
        $ret['url'] = str_replace('?absolute=true', '', $ret['url']);
    }
    // do we have enough information?
    if (!(x($ret, 'name') && x($ret, 'poll') && (x($ret, 'url') || x($ret, 'addr')))) {
        $result['message'] .= t('The profile address specified does not provide adequate information.') . EOL;
        if (!x($ret, 'poll')) {
            $result['message'] .= t('No compatible communication protocols or feeds were discovered.') . EOL;
        }
        if (!x($ret, 'name')) {
            $result['message'] .= t('An author or name was not found.') . EOL;
        }
        if (!x($ret, 'url')) {
            $result['message'] .= t('No browser URL could be matched to this address.') . EOL;
        }
        if (strpos($url, '@') !== false) {
            $result['message'] .= t('Unable to match @-style Identity Address with a known protocol or email contact.') . EOL;
            $result['message'] .= t('Use mailto: in front of address to force email check.') . EOL;
        }
        return $result;
    }
    if ($ret['network'] === NETWORK_OSTATUS && get_config('system', 'ostatus_disabled')) {
        $result['message'] .= t('The profile address specified belongs to a network which has been disabled on this site.') . EOL;
        $ret['notify'] = '';
    }
    if (!$ret['notify']) {
        $result['message'] .= t('Limited profile. This person will be unable to receive direct/personal notifications from you.') . EOL;
    }
    $writeable = $ret['network'] === NETWORK_OSTATUS && $ret['notify'] ? 1 : 0;
    $subhub = $ret['network'] === NETWORK_OSTATUS ? true : false;
    $hidden = $ret['network'] === NETWORK_MAIL ? 1 : 0;
    if ($ret['network'] === NETWORK_MAIL) {
        $writeable = 1;
    }
    if ($ret['network'] === NETWORK_DIASPORA) {
        $writeable = 1;
    }
    // check if we already have a contact
    // the poll url is more reliable than the profile url, as we may have
    // indirect links or webfinger links
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` IN ('%s', '%s') AND `network` = '%s' LIMIT 1", intval($uid), dbesc($ret['poll']), dbesc(normalise_link($ret['poll'])), dbesc($ret['network']));
    if (!count($r)) {
        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` = '%s' LIMIT 1", intval($uid), dbesc(normalise_link($url)), dbesc($ret['network']));
    }
    if (count($r)) {
        // update contact
        if ($r[0]['rel'] == CONTACT_IS_FOLLOWER || $network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING) {
            q("UPDATE `contact` SET `rel` = %d , `subhub` = %d, `readonly` = 0 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($subhub), intval($r[0]['id']), intval($uid));
        }
    } else {
        // check service class limits
        $r = q("select count(*) as total from contact where uid = %d and pending = 0 and self = 0", intval($uid));
        if (count($r)) {
            $total_contacts = $r[0]['total'];
        }
        if (!service_class_allows($uid, 'total_contacts', $total_contacts)) {
            $result['message'] .= upgrade_message();
            return $result;
        }
        $r = q("select count(network) as total from contact where uid = %d and network = '%s' and pending = 0 and self = 0", intval($uid), dbesc($network));
        if (count($r)) {
            $total_network = $r[0]['total'];
        }
        if (!service_class_allows($uid, 'total_contacts_' . $network, $total_network)) {
            $result['message'] .= upgrade_message();
            return $result;
        }
        $new_relation = $ret['network'] === NETWORK_MAIL ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING;
        if ($ret['network'] === NETWORK_DIASPORA) {
            $new_relation = CONTACT_IS_FOLLOWER;
        }
        // create contact record
        $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `name`, `nick`, `network`, `pubkey`, `rel`, `priority`,\n\t\t\t`writable`, `hidden`, `blocked`, `readonly`, `pending`, `subhub` )\n\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, 0, 0, 0, %d ) ", intval($uid), dbesc(datetime_convert()), dbesc($ret['url']), dbesc(normalise_link($ret['url'])), dbesc($ret['addr']), dbesc($ret['alias']), dbesc($ret['batch']), dbesc($ret['notify']), dbesc($ret['poll']), dbesc($ret['poco']), dbesc($ret['name']), dbesc($ret['nick']), dbesc($ret['network']), dbesc($ret['pubkey']), intval($new_relation), intval($ret['priority']), intval($writeable), intval($hidden), intval($subhub));
    }
    $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1", dbesc($ret['url']), dbesc($ret['network']), intval($uid));
    if (!count($r)) {
        $result['message'] .= t('Unable to retrieve contact information.') . EOL;
        return $result;
    }
    $contact = $r[0];
    $contact_id = $r[0]['id'];
    $result['cid'] = $contact_id;
    $g = q("select def_gid from user where uid = %d limit 1", intval($uid));
    if ($g && intval($g[0]['def_gid'])) {
        require_once 'include/group.php';
        group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
    }
    require_once "include/Photo.php";
    $photos = import_profile_photo($ret['photo'], $uid, $contact_id);
    $r = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
    // pull feed and consume it, which should subscribe to the hub.
    proc_run('php', "include/onepoll.php", "{$contact_id}", "force");
    // create a follow slap
    $tpl = get_markup_template('follow_slap.tpl');
    $slap = replace_macros($tpl, array('$name' => $a->user['username'], '$profile_page' => $a->get_baseurl() . '/profile/' . $a->user['nickname'], '$photo' => $a->contact['photo'], '$thumb' => $a->contact['thumb'], '$published' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME), '$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . get_guid(32), '$title' => '', '$type' => 'text', '$content' => t('following'), '$nick' => $a->user['nickname'], '$verb' => ACTIVITY_FOLLOW, '$ostat_follow' => ''));
    $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", intval($uid));
    if (count($r)) {
        if ($contact['network'] == NETWORK_OSTATUS && strlen($contact['notify'])) {
            require_once 'include/salmon.php';
            slapper($r[0], $contact['notify'], $slap);
        }
        if ($contact['network'] == NETWORK_DIASPORA) {
            require_once 'include/diaspora.php';
            $ret = diaspora_share($a->user, $contact);
            logger('mod_follow: diaspora_share returns: ' . $ret);
        }
    }
    $result['success'] = true;
    return $result;
}
Example #25
0
File: import.php Project: Mauru/red
function import_post(&$a)
{
    if (!get_account_id()) {
        return;
    }
    $data = null;
    $seize = x($_REQUEST, 'make_primary') ? intval($_REQUEST['make_primary']) : 0;
    $src = $_FILES['filename']['tmp_name'];
    $filename = basename($_FILES['filename']['name']);
    $filesize = intval($_FILES['filename']['size']);
    $filetype = $_FILES['filename']['type'];
    if ($src) {
        if ($filesize) {
            $data = @file_get_contents($src);
        }
        unlink($src);
    }
    if (!$src) {
        $old_address = x($_REQUEST, 'old_address') ? $_REQUEST['old_address'] : '';
        if (!$old_address) {
            logger('mod_import: nothing to import.');
            notice(t('Nothing to import.') . EOL);
            return;
        }
        $email = x($_REQUEST, 'email') ? $_REQUEST['email'] : '';
        $password = x($_REQUEST, 'password') ? $_REQUEST['password'] : '';
        $channelname = substr($old_address, 0, strpos($old_address, '@'));
        $servername = substr($old_address, strpos($old_address, '@') + 1);
        $scheme = 'https://';
        $api_path = '/api/red/channel/export/basic?f=&channel=' . $channelname;
        $binary = false;
        $redirects = 0;
        $opts = array('http_auth' => $email . ':' . $password);
        $url = $scheme . $servername . $api_path;
        $ret = z_fetch_url($url, $binary, $redirects, $opts);
        if (!$ret['success']) {
            $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
        }
        if ($ret['success']) {
            $data = $ret['body'];
        } else {
            notice(t('Unable to download data from old server') . EOL);
        }
    }
    if (!$data) {
        logger('mod_import: empty file.');
        notice(t('Imported file is empty.') . EOL);
        return;
    }
    $data = json_decode($data, true);
    //	logger('import: data: ' . print_r($data,true));
    //	print_r($data);
    // import channel
    $channel = $data['channel'];
    $r = q("select * from channel where (channel_guid = '%s' or channel_hash = '%s' or channel_address = '%s' ) limit 1", dbesc($channel['channel_guid']), dbesc($channel['channel_hash']), dbesc($channel['channel_address']));
    // We should probably also verify the hash
    if ($r) {
        logger('mod_import: duplicate channel. ', print_r($channel, true));
        notice(t('Cannot create a duplicate channel identifier on this system. Import failed.') . EOL);
        return;
    }
    unset($channel['channel_id']);
    $channel['channel_account_id'] = get_account_id();
    $channel['channel_primary'] = $seize ? 1 : 0;
    dbesc_array($channel);
    $r = dbq("INSERT INTO channel (`" . implode("`, `", array_keys($channel)) . "`) VALUES ('" . implode("', '", array_values($channel)) . "')");
    if (!$r) {
        logger('mod_import: channel clone failed. ', print_r($channel, true));
        notice(t('Channel clone failed. Import failed.') . EOL);
        return;
    }
    $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", intval(get_account_id()), $channel['channel_guid']);
    if (!$r) {
        logger('mod_import: channel not found. ', print_r($channel, true));
        notice(t('Cloned channel not found. Import failed.') . EOL);
        return;
    }
    // reset
    $channel = $r[0];
    set_default_login_identity(get_account_id(), $channel['channel_id'], false);
    if ($data['photo']) {
        require_once 'include/photo/photo_driver.php';
        import_channel_photo(base64url_decode($data['photo']['data']), $data['photo']['type'], get_account_id(), $channel['channel_id']);
    }
    $profiles = $data['profile'];
    if ($profiles) {
        foreach ($profiles as $profile) {
            unset($profile['id']);
            $profile['aid'] = get_account_id();
            $profile['uid'] = $channel['channel_id'];
            // we are going to reset all profile photos to the original
            // somebody will have to fix this later and put all the applicable photos into the export
            $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id'];
            $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id'];
            dbesc_array($profile);
            $r = dbq("INSERT INTO profile (`" . implode("`, `", array_keys($profile)) . "`) VALUES ('" . implode("', '", array_values($profile)) . "')");
        }
    }
    $hublocs = $data['hubloc'];
    if ($hublocs) {
        foreach ($hublocs as $hubloc) {
            $arr = array('guid' => $hubloc['hubloc_guid'], 'guid_sig' => $hubloc['guid_sig'], 'url' => $hubloc['hubloc_url'], 'url_sig' => $hubloc['hubloc_url_sig']);
            if ($hubloc['hubloc_hash'] === $channel['channel_hash'] && $hubloc['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY && $seize) {
                $hubloc['hubloc_flags'] = $hubloc['hubloc_flags'] ^ HUBLOC_FLAGS_PRIMARY;
            }
            if (!zot_gethub($arr)) {
                unset($hubloc['hubloc_id']);
                dbesc_array($hubloc);
                $r = dbq("INSERT INTO hubloc (`" . implode("`, `", array_keys($hubloc)) . "`) VALUES ('" . implode("', '", array_values($hubloc)) . "')");
            }
        }
    }
    // create new hubloc for the new channel at this site
    $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_flags, \n\t\thubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey )\n\t\tvalues ( '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )", dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_hash']), dbesc($channel['channel_address'] . '@' . get_app()->get_hostname()), dbesc('zot'), intval($seize ? HUBLOC_FLAGS_PRIMARY : 0), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $channel['channel_prvkey']))), dbesc(get_app()->get_hostname()), dbesc(z_root() . '/post'), dbesc(get_config('system', 'pubkey')));
    // reset the original primary hubloc if it is being seized
    if ($seize) {
        $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where (hubloc_flags & %d) and hubloc_hash = '%s' and hubloc_url != '%s' ", intval(HUBLOC_FLAGS_PRIMARY), intval(HUBLOC_FLAGS_PRIMARY), dbesc($channel['channel_hash']), dbesc(z_root()));
    }
    // import xchans and contact photos
    if ($seize) {
        // replace our existing xchan if we're seizing control
        $r = q("delete from xchan where xchan_hash = '%s' limit 1", dbesc($channel['channel_hash']));
        $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", dbesc($channel['channel_hash']), dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_pubkey']), dbesc($a->get_baseurl() . "/photo/profile/l/" . $channel['channel_id']), dbesc($a->get_baseurl() . "/photo/profile/m/" . $channel['channel_id']), dbesc($a->get_baseurl() . "/photo/profile/s/" . $channel['channel_id']), dbesc($channel['channel_address'] . '@' . get_app()->get_hostname()), dbesc(z_root() . '/channel/' . $channel['channel_address']), dbesc(z_root() . '/follow?f=&url=%s'), dbesc(z_root() . '/poco/' . $channel['channel_address']), dbesc($channel['channel_name']), dbesc('zot'), dbesc(datetime_convert()), dbesc(datetime_convert()));
    }
    $xchans = $data['xchan'];
    if ($xchans) {
        foreach ($xchans as $xchan) {
            $r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", dbesc($xchan['xchan_hash']));
            if ($r) {
                continue;
            }
            dbesc_array($xchan);
            $r = dbq("INSERT INTO xchan (`" . implode("`, `", array_keys($xchan)) . "`) VALUES ('" . implode("', '", array_values($xchan)) . "')");
            require_once 'include/photo/photo_driver.php';
            $photos = import_profile_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']);
            if ($photos[4]) {
                $photodate = NULL_DATE;
            } else {
                $photodate = $xchan['xchan_photo_date'];
            }
            $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s'\n\t\t\t\twhere xchan_hash = '%s' limit 1", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($photodate), dbesc($xchan_hash));
        }
    }
    // FIXME - ensure we have an xchan if somebody is trying to pull a fast one
    // import contacts
    $abooks = $data['abook'];
    if ($abooks) {
        foreach ($abooks as $abook) {
            unset($abook['abook_id']);
            $abook['abook_account'] = get_account_id();
            $abook['abook_channel'] = $channel['channel_id'];
            dbesc_array($abook);
            $r = dbq("INSERT INTO abook (`" . implode("`, `", array_keys($abook)) . "`) VALUES ('" . implode("', '", array_values($abook)) . "')");
        }
    }
    $configs = $data['config'];
    if ($configs) {
        foreach ($configs as $config) {
            unset($config['id']);
            $config['uid'] = $channel['channel_id'];
            dbesc_array($config);
            $r = dbq("INSERT INTO pconfig (`" . implode("`, `", array_keys($config)) . "`) VALUES ('" . implode("', '", array_values($config)) . "')");
        }
    }
    $groups = $data['group'];
    if ($groups) {
        $saved = array();
        foreach ($groups as $group) {
            $saved[$group['hash']] = array('old' => $group['id']);
            unset($group['id']);
            $group['uid'] = $channel['channel_id'];
            dbesc_array($group);
            $r = dbq("INSERT INTO group (`" . implode("`, `", array_keys($group)) . "`) VALUES ('" . implode("', '", array_values($group)) . "')");
        }
        $r = q("select * from `groups` where uid = %d", intval($channel['channel_id']));
        if ($r) {
            foreach ($r as $rr) {
                $saved[$rr['hash']]['new'] = $rr['id'];
            }
        }
    }
    $group_members = $data['group_member'];
    if ($groups_members) {
        foreach ($group_members as $group_member) {
            unset($group_member['id']);
            $group_member['uid'] = $channel['channel_id'];
            foreach ($saved as $x) {
                if ($x['old'] == $group_member['gid']) {
                    $group_member['gid'] = $x['new'];
                }
            }
            dbesc_array($group_member);
            $r = dbq("INSERT INTO group_member (`" . implode("`, `", array_keys($group_member)) . "`) VALUES ('" . implode("', '", array_values($group_member)) . "')");
        }
    }
    // FIXME - ensure we have a self entry if somebody is trying to pull a fast one
    if ($seize) {
        // notify old server that it is no longer primary.
    }
    // This will indirectly perform a refresh_all *and* update the directory
    proc_run('php', 'include/directory.php', $channel['channel_id']);
    // send out refresh requests
    notice(t('Import completed.') . EOL);
    change_channel($channel['channel_id']);
    goaway(z_root() . '/network');
}
Example #26
0
function diaspora_profile($importer, $xml, $msg)
{
    $a = get_app();
    $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    if ($diaspora_handle != $msg['author']) {
        logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
        return 202;
    }
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $diaspora_handle);
    if (!$contact) {
        return;
    }
    if ($contact['blocked']) {
        logger('diaspora_post: Ignoring this author.');
        return 202;
    }
    $name = unxmlify($xml->first_name) . (strlen($xml->last_name) ? ' ' . unxmlify($xml->last_name) : '');
    $image_url = unxmlify($xml->image_url);
    $birthday = unxmlify($xml->birthday);
    $handle_parts = explode("@", $diaspora_handle);
    if ($name === '') {
        $name = $handle_parts[0];
    }
    if (preg_match("|^https?://|", $image_url) === 0) {
        $image_url = "http://" . $handle_parts[1] . $image_url;
    }
    /*	$r = q("SELECT DISTINCT ( `resource-id` ) FROM `photo` WHERE  `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' ",
    		intval($importer['channel_id']),
    		intval($contact['id'])
    	);
    	$oldphotos = ((count($r)) ? $r : null);*/
    require_once 'include/Photo.php';
    $images = import_profile_photo($image_url, $importer['channel_id'], $contact['id']);
    // Generic birthday. We don't know the timezone. The year is irrelevant.
    $birthday = str_replace('1000', '1901', $birthday);
    $birthday = datetime_convert('UTC', 'UTC', $birthday, 'Y-m-d');
    // this is to prevent multiple birthday notifications in a single year
    // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
    if (substr($birthday, 5) === substr($contact['bd'], 5)) {
        $birthday = $contact['bd'];
    }
    // TODO: update name on item['author-name'] if the name changed. See consume_feed()
    // Not doing this currently because D* protocol is scheduled for revision soon.
    $r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' , `bd` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($name), dbesc(datetime_convert()), dbesc($images[0]), dbesc($images[1]), dbesc($images[2]), dbesc(datetime_convert()), dbesc($birthday), intval($contact['id']), intval($importer['channel_id']));
    /*	if($r) {
    		if($oldphotos) {
    			foreach($oldphotos as $ph) {
    				q("DELETE FROM `photo` WHERE `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' AND `resource-id` = '%s' ",
    					intval($importer['channel_id']),
    					intval($contact['id']),
    					dbesc($ph['resource-id'])
    				);
    			}
    		}
    	}	*/
    return;
}
Example #27
0
function appnet_fetchcontact($a, $uid, $contact, $me, $create_user)
{
    if (function_exists("update_gcontact")) {
        update_gcontact(array("url" => $contact["canonical_url"], "generation" => 2, "network" => NETWORK_APPNET, "photo" => $contact["avatar_image"]["url"], "name" => $contact["name"], "nick" => $contact["username"], "about" => $contact["description"]["text"], "hide" => true, "addr" => $contact["username"] . "@app.net"));
    } else {
        // Old Code
        $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($contact["canonical_url"])));
        if (count($r) == 0) {
            q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')", dbesc(normalise_link($contact["canonical_url"])), dbesc($contact["name"]), dbesc($contact["username"]), dbesc($contact["avatar_image"]["url"]));
        } else {
            q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'", dbesc($contact["name"]), dbesc($contact["username"]), dbesc($contact["avatar_image"]["url"]), dbesc(normalise_link($contact["canonical_url"])));
        }
        if (DB_UPDATE_VERSION >= "1177") {
            q("UPDATE `unique_contacts` SET `location` = '%s', `about` = '%s' WHERE url = '%s'", dbesc(""), dbesc($contact["description"]["text"]), dbesc(normalise_link($contact["canonical_url"])));
        }
    }
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1", intval($uid), dbesc("adn::" . $contact["id"]));
    if (!count($r) and !$create_user) {
        return $me["id"];
    }
    if ($contact["canonical_url"] == "") {
        return $me["id"];
    }
    if (count($r) and ($r[0]["readonly"] or $r[0]["blocked"])) {
        logger("appnet_fetchcontact: Contact '" . $r[0]["nick"] . "' is blocked or readonly.", LOGGER_DEBUG);
        return -1;
    }
    if (!count($r)) {
        if ($contact["name"] == "") {
            $contact["name"] = $contact["username"];
        }
        if ($contact["username"] == "") {
            $contact["username"] = $contact["name"];
        }
        // create contact record
        q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,\n\t\t\t\t\t`name`, `nick`, `photo`, `network`, `rel`, `priority`,\n\t\t\t\t\t`writable`, `blocked`, `readonly`, `pending` )\n\t\t\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ", intval($uid), dbesc(datetime_convert()), dbesc($contact["canonical_url"]), dbesc(normalise_link($contact["canonical_url"])), dbesc($contact["username"] . "@app.net"), dbesc("adn::" . $contact["id"]), dbesc(''), dbesc("adn::" . $contact["id"]), dbesc($contact["name"]), dbesc($contact["username"]), dbesc($contact["avatar_image"]["url"]), dbesc(NETWORK_APPNET), intval(CONTACT_IS_FRIEND), intval(1), intval(1));
        $r = q("SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1", dbesc("adn::" . $contact["id"]), intval($uid));
        if (!count($r)) {
            return false;
        }
        $contact_id = $r[0]['id'];
        $g = q("SELECT def_gid FROM user WHERE uid = %d LIMIT 1", intval($uid));
        if ($g && intval($g[0]['def_gid'])) {
            require_once 'include/group.php';
            group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
        }
        require_once "Photo.php";
        $photos = import_profile_photo($contact["avatar_image"]["url"], $uid, $contact_id);
        q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t`avatar-date` = '%s'\n\t\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
        if (DB_UPDATE_VERSION >= "1177") {
            q("UPDATE `contact` SET `location` = '%s',\n\t\t\t\t\t\t`about` = '%s'\n\t\t\t\t\tWHERE `id` = %d", dbesc(""), dbesc($contact["description"]["text"]), intval($contact_id));
        }
    } else {
        // update profile photos once every two weeks as we have no notification of when they change.
        //$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -2 days')) ? true : false);
        $update_photo = $r[0]['avatar-date'] < datetime_convert('', '', 'now -12 hours');
        // check that we have all the photos, this has been known to fail on occasion
        if (!$r[0]['photo'] || !$r[0]['thumb'] || !$r[0]['micro'] || $update_photo) {
            logger("appnet_fetchcontact: Updating contact " . $contact["username"], LOGGER_DEBUG);
            require_once "Photo.php";
            $photos = import_profile_photo($contact["avatar_image"]["url"], $uid, $r[0]['id']);
            q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t\t\t`url` = '%s',\n\t\t\t\t\t\t`nurl` = '%s',\n\t\t\t\t\t\t`addr` = '%s',\n\t\t\t\t\t\t`name` = '%s',\n\t\t\t\t\t\t`nick` = '%s'\n\t\t\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($contact["canonical_url"]), dbesc(normalise_link($contact["canonical_url"])), dbesc($contact["username"] . "@app.net"), dbesc($contact["name"]), dbesc($contact["username"]), intval($r[0]['id']));
            if (DB_UPDATE_VERSION >= "1177") {
                q("UPDATE `contact` SET `location` = '%s',\n\t\t\t\t\t\t\t`about` = '%s'\n\t\t\t\t\t\tWHERE `id` = %d", dbesc(""), dbesc($contact["description"]["text"]), intval($r[0]['id']));
            }
        }
    }
    return $r[0]["id"];
}
Example #28
0
function diaspora_profile($importer, $xml, $msg)
{
    $a = get_app();
    $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
    if ($diaspora_handle != $msg['author']) {
        logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
        return 202;
    }
    $contact = diaspora_get_contact_by_handle($importer['uid'], $diaspora_handle);
    if (!$contact) {
        return;
    }
    if ($contact['blocked']) {
        logger('diaspora_post: Ignoring this author.');
        return 202;
    }
    $name = unxmlify($xml->first_name) . (strlen($xml->last_name) ? ' ' . unxmlify($xml->last_name) : '');
    $image_url = unxmlify($xml->image_url);
    $birthday = unxmlify($xml->birthday);
    $location = diaspora2bb(unxmlify($xml->location));
    $about = diaspora2bb(unxmlify($xml->bio));
    $gender = unxmlify($xml->gender);
    $tags = unxmlify($xml->tag_string);
    $tags = explode("#", $tags);
    $keywords = array();
    foreach ($tags as $tag) {
        $tag = trim(strtolower($tag));
        if ($tag != "") {
            $keywords[] = $tag;
        }
    }
    $keywords = implode(", ", $keywords);
    $handle_parts = explode("@", $diaspora_handle);
    if ($name === '') {
        $name = $handle_parts[0];
    }
    if (preg_match("|^https?://|", $image_url) === 0) {
        $image_url = "http://" . $handle_parts[1] . $image_url;
    }
    /*	$r = q("SELECT DISTINCT ( `resource-id` ) FROM `photo` WHERE  `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' ",
    		intval($importer['uid']),
    		intval($contact['id'])
    	);
    	$oldphotos = ((count($r)) ? $r : null);*/
    require_once 'include/Photo.php';
    $images = import_profile_photo($image_url, $importer['uid'], $contact['id']);
    // Generic birthday. We don't know the timezone. The year is irrelevant.
    $birthday = str_replace('1000', '1901', $birthday);
    $birthday = datetime_convert('UTC', 'UTC', $birthday, 'Y-m-d');
    // this is to prevent multiple birthday notifications in a single year
    // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
    if (substr($birthday, 5) === substr($contact['bd'], 5)) {
        $birthday = $contact['bd'];
    }
    // TODO: update name on item['author-name'] if the name changed. See consume_feed()
    // Not doing this currently because D* protocol is scheduled for revision soon.
    $r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' , `bd` = '%s', `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($name), dbesc(datetime_convert()), dbesc($images[0]), dbesc($images[1]), dbesc($images[2]), dbesc(datetime_convert()), dbesc($birthday), dbesc($location), dbesc($about), dbesc($keywords), dbesc($gender), intval($contact['id']), intval($importer['uid']));
    if (unxmlify($xml->searchable) == "true") {
        require_once 'include/socgraph.php';
        poco_check($contact['url'], $name, NETWORK_DIASPORA, $images[0], $about, $location, $gender, $keywords, "", datetime_convert(), 2, $contact['id'], $importer['uid']);
    }
    $profileurl = "";
    $author = q("SELECT * FROM `unique_contacts` WHERE `url`='%s' LIMIT 1", dbesc(normalise_link($contact['url'])));
    if (count($author) == 0) {
        q("INSERT INTO `unique_contacts` (`url`, `name`, `avatar`, `location`, `about`) VALUES ('%s', '%s', '%s', '%s', '%s')", dbesc(normalise_link($contact['url'])), dbesc($name), dbesc($location), dbesc($about), dbesc($images[0]));
        $author = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($contact['url'])));
    } else {
        if (normalise_link($contact['url']) . $name . $location . $about != normalise_link($author[0]["url"]) . $author[0]["name"] . $author[0]["location"] . $author[0]["about"]) {
            q("UPDATE unique_contacts SET name = '%s', avatar = '%s', `location` = '%s', `about` = '%s' WHERE url = '%s'", dbesc($name), dbesc($images[0]), dbesc($location), dbesc($about), dbesc(normalise_link($contact['url'])));
        }
    }
    /*	if($r) {
    		if($oldphotos) {
    			foreach($oldphotos as $ph) {
    				q("DELETE FROM `photo` WHERE `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' AND `resource-id` = '%s' ",
    					intval($importer['uid']),
    					intval($contact['id']),
    					dbesc($ph['resource-id'])
    				);
    			}
    		}
    	}	*/
    return;
}
Example #29
0
function fbsync_fetch_contact($uid, $contact, $create_user)
{
    if ($contact->url == "") {
        return 0;
    }
    // Check if the unique contact is existing
    // To-Do: only update once a while
    $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($contact->url)));
    if (count($r) == 0) {
        q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')", dbesc(normalise_link($contact->url)), dbesc($contact->name), dbesc($contact->username), dbesc($contact->pic_square));
    } else {
        q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'", dbesc($contact->name), dbesc($contact->username), dbesc($contact->pic_square), dbesc(normalise_link($contact->url)));
    }
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1", intval($uid), dbesc("facebook::" . $contact->id));
    if (!count($r) and !$create_user) {
        return 0;
    }
    if (count($r) and ($r[0]["readonly"] or $r[0]["blocked"])) {
        logger("fbsync_fetch_contact: Contact '" . $r[0]["nick"] . "' is blocked or readonly.", LOGGER_DEBUG);
        return -1;
    }
    $avatarpicture = $contact->pic_square;
    if (!count($r)) {
        // create contact record
        q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,\n\t\t\t\t\t`name`, `nick`, `photo`, `network`, `rel`, `priority`,\n\t\t\t\t\t`writable`, `blocked`, `readonly`, `pending`)\n\t\t\t\t\tVALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0)", intval($uid), dbesc(datetime_convert()), dbesc($contact->url), dbesc(normalise_link($contact->url)), dbesc($contact->username . "@facebook.com"), dbesc("facebook::" . $contact->id), dbesc($contact->id), dbesc("facebook::" . $contact->id), dbesc($contact->name), dbesc($contact->username), dbesc($avatarpicture), dbesc(NETWORK_FACEBOOK), intval(CONTACT_IS_FRIEND), intval(1), intval(1));
        $r = q("SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1", dbesc("facebook::" . $contact->id), intval($uid));
        if (!count($r)) {
            return false;
        }
        $contact_id = $r[0]['id'];
        $g = q("SELECT def_gid FROM user WHERE uid = %d LIMIT 1", intval($uid));
        if ($g && intval($g[0]['def_gid'])) {
            require_once 'include/group.php';
            group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
        }
        require_once "Photo.php";
        $photos = import_profile_photo($avatarpicture, $uid, $contact_id);
        q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t`avatar-date` = '%s'\n\t\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
    } else {
        // update profile photos once every 12 hours as we have no notification of when they change.
        $update_photo = $r[0]['avatar-date'] < datetime_convert('', '', 'now -12 hours');
        // check that we have all the photos, this has been known to fail on occasion
        if (!$r[0]['photo'] || !$r[0]['thumb'] || !$r[0]['micro'] || $update_photo) {
            logger("fbsync_fetch_contact: Updating contact " . $contact->username, LOGGER_DEBUG);
            require_once "Photo.php";
            $photos = import_profile_photo($avatarpicture, $uid, $r[0]['id']);
            q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t\t\t`thumb` = '%s',\n\t\t\t\t\t\t`micro` = '%s',\n\t\t\t\t\t\t`name-date` = '%s',\n\t\t\t\t\t\t`uri-date` = '%s',\n\t\t\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t\t\t`url` = '%s',\n\t\t\t\t\t\t`nurl` = '%s',\n\t\t\t\t\t\t`addr` = '%s',\n\t\t\t\t\t\t`name` = '%s',\n\t\t\t\t\t\t`nick` = '%s',\n\t\t\t\t\t\t`notify` = '%s'\n\t\t\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($contact->url), dbesc(normalise_link($contact->url)), dbesc($contact->username . "@facebook.com"), dbesc($contact->name), dbesc($contact->username), dbesc($contact->id), intval($r[0]['id']));
        }
    }
    return $r[0]["id"];
}