Exemplo n.º 1
0
function directory_init(&$a)
{
    $a->set_pager_itemspage(60);
    if (x($_GET, 'ignore')) {
        q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ", intval(local_channel()), dbesc($_GET['ignore']));
    }
    $observer = get_observer_hash();
    $global_changed = false;
    $safe_changed = false;
    if (array_key_exists('global', $_REQUEST)) {
        $globaldir = intval($_REQUEST['global']);
        $global_changed = true;
    }
    if ($global_changed) {
        $_SESSION['globaldir'] = $globaldir;
        if ($observer) {
            set_xconfig($observer, 'directory', 'globaldir', $globaldir);
        }
    }
    if (array_key_exists('safe', $_REQUEST)) {
        $safemode = intval($_REQUEST['safe']);
        $safe_changed = true;
    }
    if ($safe_changed) {
        $_SESSION['safemode'] = $safemode;
        if ($observer) {
            set_xconfig($observer, 'directory', 'safe_mode', $safemode);
        }
    }
}
Exemplo n.º 2
0
 function init()
 {
     \App::set_pager_itemspage(60);
     if (x($_GET, 'ignore')) {
         q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ", intval(local_channel()), dbesc($_GET['ignore']));
         goaway(z_root() . '/directory?suggest=1');
     }
     $observer = get_observer_hash();
     $global_changed = false;
     $safe_changed = false;
     $pubforums_changed = false;
     if (array_key_exists('global', $_REQUEST)) {
         $globaldir = intval($_REQUEST['global']);
         $global_changed = true;
     }
     if ($global_changed) {
         $_SESSION['globaldir'] = $globaldir;
         if ($observer) {
             set_xconfig($observer, 'directory', 'globaldir', $globaldir);
         }
     }
     if (array_key_exists('safe', $_REQUEST)) {
         $safemode = intval($_REQUEST['safe']);
         $safe_changed = true;
     }
     if ($safe_changed) {
         $_SESSION['safemode'] = $safemode;
         if ($observer) {
             set_xconfig($observer, 'directory', 'safemode', $safemode);
         }
     }
     if (array_key_exists('pubforums', $_REQUEST)) {
         $pubforums = intval($_REQUEST['pubforums']);
         $pubforums_changed = true;
     }
     if ($pubforums_changed) {
         $_SESSION['pubforums'] = $pubforums;
         if ($observer) {
             set_xconfig($observer, 'directory', 'pubforums', $pubforums);
         }
     }
 }
Exemplo n.º 3
0
 function init()
 {
     $observer = get_observer_hash();
     if (!$observer) {
         return;
     }
     if ($observer) {
         $safe_mode = get_xconfig($observer, 'directory', 'safe_mode');
     }
     if ($safe_mode == '') {
         set_xconfig($observer, 'directory', 'safe_mode', '0');
     } elseif ($safe_mode == '0') {
         set_xconfig($observer, 'directory', 'safe_mode', '1');
     } elseif ($safe_mode == '1') {
         set_xconfig($observer, 'directory', 'safe_mode', '0');
     }
     if (isset($_GET['address'])) {
         $address = $_GET['address'];
     } else {
         $address = z_root() . '/directory';
     }
     goaway($address);
 }
Exemplo n.º 4
0
 function get()
 {
     $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, $r[0], 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);
                 \App::set_observer($r[0]);
                 require_once 'include/security.php';
                 \App::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\t                xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, \n\t\t\t\t\txchan_name_date, xchan_hidden)\n\t                values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 1) ", 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()));
             if ($x) {
                 $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($url));
                 if ($r) {
                     $photos = import_xchan_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\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);
                     \App::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
 }
Exemplo n.º 5
0
function discover_by_webbie($webbie)
{
    require_once 'library/HTML5/Parser.php';
    $result = array();
    $network = null;
    $diaspora = false;
    $gnusoc = false;
    $dfrn = false;
    $has_salmon = false;
    $salmon_key = false;
    $atom_feed = false;
    $diaspora_base = '';
    $diaspora_guid = '';
    $diaspora_key = '';
    $webbie = strtolower($webbie);
    $x = webfinger_rfc7033($webbie, true);
    if ($x && array_key_exists('links', $x) && $x['links']) {
        foreach ($x['links'] as $link) {
            if (array_key_exists('rel', $link)) {
                // If we discover zot - don't search further; grab the info and get out of
                // here.
                if ($link['rel'] === PROTOCOL_ZOT) {
                    logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG);
                    if (array_key_exists('zot', $x) && $x['zot']['success']) {
                        $i = import_xchan($x['zot']);
                    } else {
                        $z = z_fetch_url($link['href']);
                        if ($z['success']) {
                            $j = json_decode($z['body'], true);
                            $i = import_xchan($j);
                            return true;
                        }
                    }
                }
                if ($link['rel'] == NAMESPACE_DFRN) {
                    $dfrn = $link['href'];
                }
                if ($link['rel'] == 'magic-public-key') {
                    if (substr($link['href'], 0, 5) === 'data:') {
                        $salmon_key = convert_salmon_key($link['href']);
                    }
                }
                if ($link['rel'] == 'salmon') {
                    $has_salmon = true;
                    $salmon = $link['href'];
                }
                if ($link['rel'] == 'http://schemas.google.com/g/2010#updates-from') {
                    $atom_feed = $link['href'];
                }
            }
        }
    }
    logger('webfinger: ' . print_r($x, true), LOGGER_DATA, LOG_INFO);
    $arr = array('address' => $webbie, 'success' => false, 'webfinger' => $x);
    call_hooks('discover_channel_webfinger', $arr);
    if ($arr['success']) {
        return true;
    }
    $aliases = array();
    // Now let's make some decisions on what we may need
    // to obtain further info
    $probe_atom = false;
    $probe_old = false;
    $probe_hcard = false;
    $address = '';
    $location = '';
    $nickname = '';
    $fullname = '';
    $avatar = '';
    $pubkey = '';
    if (is_array($x)) {
        if (array_key_exists('address', $x)) {
            $address = $x['address'];
        }
        if (array_key_exists('location', $x)) {
            $location = $x['location'];
        }
        if (array_key_exists('nickname', $x)) {
            $nickname = $x['nickname'];
        }
    }
    if (!$x) {
        $probe_old = true;
    }
    if (!$dfrn && !$has_salmon) {
        $probe_old = true;
    }
    if ($probe_old) {
        $y = old_webfinger($webbie);
        if ($y) {
            logger('old_webfinger: ' . print_r($x, true));
            foreach ($y 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 ($link['@attributes']['rel'] == 'magic-public-key') {
                    if (substr($link['@attributes']['href'], 0, 5) === 'data:') {
                        $salmon_key = convert_salmon_key($link['@attributes']['href']);
                    }
                }
                if ($link['@attributes']['rel'] == 'salmon') {
                    $has_salmon = true;
                    $salmon = $link['@attributes']['href'];
                }
                if ($link['@attributes']['rel'] == 'http://schemas.google.com/g/2010#updates-from') {
                    $atom_feed = $link['@attributes']['href'];
                }
                if ($link['@attributes']['rel'] === 'alias') {
                    $aliases[] = $link['@attributes']['href'];
                }
                if ($link['@attributes']['rel'] === 'subject') {
                    $subject = $link['@attributes']['href'];
                }
            }
        }
    }
    if ($subject || $aliases) {
        if (strpos($webbie, '@')) {
            $rhs = substr($webbie, strpos($webbie, '@') + 1);
        } else {
            $m = parse_url($webbie);
            if ($m) {
                $rhs = $m['host'] . ($m['port'] ? ':' . $m['port'] : '');
            }
        }
        $v = array('subject' => $subject, 'aliases' => $aliases);
        $address = find_webfinger_address($v, $rhs);
        $location = find_webfinger_location($v, $rhs);
        if ($address) {
            $nickname = substr($address, 0, strpos($address, '@'));
        }
    }
    if ($salmon_key && $has_salmon && $atom_feed && !$dfrn && !$diaspora) {
        $gnusoc = true;
        $probe_atom = true;
    }
    if (!$pubkey) {
        $pubkey = $salmon_key;
    }
    if (($dfrn || $diaspora) && $hcard) {
        $probe_hcard = true;
    }
    if (!$fullname) {
        $fullname = $nickname;
    }
    if ($probe_atom) {
        $k = z_fetch_url($atom_feed);
        if ($k['success']) {
            $feed_meta = feed_meta($k['body']);
        }
        if ($feed_meta) {
            // stash any discovered pubsubhubbub hubs in case we need to follow them
            // this will save an expensive lookup later
            if ($feed_meta['hubs'] && $address) {
                set_xconfig($address, 'system', 'push_hubs', $feed_meta['hubs']);
                set_xconfig($address, 'system', 'feed_url', $atom_feed);
            }
            if ($feed_meta['author']['author_name']) {
                $fullname = $feed_meta['author']['author_name'];
            }
            if (!$avatar) {
                if ($feed_meta['author']['author_photo']) {
                    $avatar = $feed_meta['author']['author_photo'];
                }
            }
            // for GNU-social over-ride any url aliases we may have picked up in webfinger
            // The author.uri element in the feed is likely to be more accurate
            if ($gnusoc && $feed_meta['author']['author_uri']) {
                $location = $feed_meta['author']['author_uri'];
            }
        }
    } else {
        if ($probe_hcard) {
            $vcard = scrape_vcard($hcard);
            if ($vcard) {
                logger('vcard: ' . print_r($vcard, true), LOGGER_DATA);
                if ($vcard['fn']) {
                    $fullname = $vcard['fn'];
                }
                if ($vcard['photo'] && strpos($vcard['photo'], 'http') !== 0) {
                    $vcard['photo'] = $diaspora_base . '/' . $vcard['photo'];
                }
                if (!$avatar) {
                    $avatar = $vcard['photo'];
                }
            }
        }
    }
    if ($profile && !$location) {
        $location = $profile;
    }
    if ($location) {
        $m = parse_url($location);
        $base = $m['scheme'] . '://' . $m['host'];
        $host = $m['host'];
    }
    if ($diaspora && $diaspora_base && $diaspora_guid) {
        if ($dfrn) {
            $network = 'friendica-over-diaspora';
        } else {
            $network = 'diaspora';
        }
        $base = trim($diaspora_base, '/');
        $notify = $base . '/receive';
    } else {
        if ($gnusoc) {
            $network = 'gnusoc';
            $notify = $salmon;
        }
    }
    logger('network: ' . $network);
    logger('address: ' . $address);
    logger('fullname: ' . $fullname);
    logger('pubkey: ' . $pubkey);
    logger('location: ' . $location);
    // if we have everything we need, let's create the records
    if ($network && $address && $fullname && $pubkey && $location) {
        $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($address));
        if ($r) {
            $r = q("update xchan set xchan_name = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s' limit 1", dbesc($fullname), dbesc($network), dbesc(datetime_convert()), dbesc($address));
        } else {
            $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", dbesc($address), dbesc($diaspora_guid ? $diaspora_guid : $location), dbesc($pubkey), dbesc($address), dbesc($location), dbesc($fullname), dbesc($network), dbescdate(datetime_convert()));
        }
        $r = q("select * from hubloc where hubloc_hash = '%s' limit 1", dbesc($address));
        if (!$r) {
            $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_primary ) values ('%s','%s','%s','%s','%s','%s','%s','%s', 1)", dbesc($diaspora_guid ? $diaspora_guid : $location), dbesc($address), dbesc($address), dbesc($network), dbesc($base), dbesc($host), dbesc($notify), dbescdate(datetime_convert()));
        }
        $photos = import_xchan_photo($avatar, $address);
        $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()), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($address));
        return true;
    }
    return false;
}
Exemplo n.º 6
0
function pubsubhubbub_subscribe($url, $channel, $xchan, $feed, $hubmode = 'subscribe')
{
    $push_url = z_root() . '/pubsub/' . $channel['channel_address'] . '/' . $xchan['abook_id'];
    $verify = get_abconfig($channel['channel_id'], $xchan['xchan_hash'], 'pubsubhubbub', 'verify_token');
    if (!$verify) {
        $verify = set_abconfig($channel['channel_id'], $xchan['xchan_hash'], 'pubsubhubbub', 'verify_token', random_string(16));
    }
    if ($feed) {
        set_xconfig($xchan['xchan_hash'], 'system', 'feed_url', $feed);
    } else {
        $feed = get_xconfig($xchan['xchan_hash'], 'system', 'feed_url');
    }
    $params = 'hub.mode=' . $hubmode . '&hub.callback=' . urlencode($push_url) . '&hub.topic=' . urlencode($feed) . '&hub.verify=async&hub.verify_token=' . $verify;
    logger('subscribe_to_hub: ' . $hubmode . ' ' . $xchan['xchan_name'] . ' to hub ' . $url . ' endpoint: ' . $push_url . ' with verifier ' . $verify);
    $x = z_post_url($url, $params);
    logger('subscribe_to_hub: returns: ' . $x['return_code'], LOGGER_DEBUG);
    return;
}
Exemplo n.º 7
0
function set_aconfig($account_id, $family, $key, $value)
{
    return set_xconfig('a_' . $account_id, $family, $key, $value);
}
Exemplo n.º 8
0
/**
 * @brief This function provides the API endpoints, primarily called by the 
 * JavaScript functions via $.post() calls.
 *
 * @return json JSON-formatted structures with a "status" indicator for success
 * as well as other requested data
 */
function chess_post(&$a)
{
    if (argc() > 1) {
        switch (argv(1)) {
            // API: /chess/settings
            // Updates game settings for the observer
            case 'settings':
                $observer = App::get_observer();
                $settings = x($_POST, 'settings') ? $_POST['settings'] : null;
                $settings = json_decode($settings, true);
                if (!isset($settings['notify_enabled'])) {
                    json_return_and_die(array('errormsg' => 'Invalid settings', 'status' => false));
                }
                $notify_enable = intval($settings['notify_enabled']);
                set_xconfig($observer['xchan_hash'], 'chess', 'notifications', $notify_enable);
                json_return_and_die(array('status' => true));
                // API: /chess/resume
                // Resumes a game specified by "game_id" allowing further moves
            // API: /chess/resume
            // Resumes a game specified by "game_id" allowing further moves
            case 'resume':
                $observer = App::get_observer();
                $game_id = x($_POST, 'game_id') ? $_POST['game_id'] : '';
                $g = chess_get_game($game_id);
                if (!$g['status']) {
                    json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false));
                }
                // Verify that observer is a valid player
                $game = json_decode($g['game']['obj'], true);
                if (!in_array($observer['xchan_hash'], $game['players'])) {
                    json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false));
                }
                $success = chess_resume_game($g['game']);
                if (!$success) {
                    json_return_and_die(array('errormsg' => 'Error resuming game', 'status' => false));
                } else {
                    json_return_and_die(array('status' => true));
                }
                // API: /chess/end
                // Ends a game specified by "game_id" preventing further moves
            // API: /chess/end
            // Ends a game specified by "game_id" preventing further moves
            case 'end':
                $observer = App::get_observer();
                $game_id = x($_POST, 'game_id') ? $_POST['game_id'] : '';
                $g = chess_get_game($game_id);
                if (!$g['status']) {
                    json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false));
                }
                // Verify that observer is a valid player
                $game = json_decode($g['game']['obj'], true);
                if (!in_array($observer['xchan_hash'], $game['players'])) {
                    json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false));
                }
                $success = chess_end_game($g['game']);
                if (!$success) {
                    json_return_and_die(array('errormsg' => 'Error ending game', 'status' => false));
                } else {
                    json_return_and_die(array('status' => true));
                }
                // API: /chess/delete
                // Deletes a game specified by "game_id"
            // API: /chess/delete
            // Deletes a game specified by "game_id"
            case 'delete':
                if (!local_channel()) {
                    json_return_and_die(array('errormsg' => 'Must be local channel.', 'status' => false));
                }
                $channel = App::get_channel();
                $game_id = x($_POST, 'game_id') ? $_POST['game_id'] : '';
                $d = chess_delete_game($game_id, $channel);
                if (!$d['status']) {
                    json_return_and_die(array('errormsg' => 'Error deleting game', 'status' => false));
                } else {
                    json_return_and_die(array('status' => true));
                }
                // API: /chess/revert
                // Reverts a game specified by "game_id" to a previous board position
                // specified by the "mid" of the child post of the original game post
                // in the item table
                // TODO: Determine why the board position in the game item is not actually
                // being reverted
            // API: /chess/revert
            // Reverts a game specified by "game_id" to a previous board position
            // specified by the "mid" of the child post of the original game post
            // in the item table
            // TODO: Determine why the board position in the game item is not actually
            // being reverted
            case 'revert':
                $observer = App::get_observer();
                $game_id = $_POST['game_id'];
                $g = chess_get_game($game_id);
                if (!$g['status']) {
                    json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false));
                }
                // Verify that observer is a valid player
                $game = json_decode($g['game']['obj'], true);
                if (!in_array($observer['xchan_hash'], $game['players'])) {
                    json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false));
                }
                $active = $game['active'] === $observer['xchan_hash'] ? true : false;
                if (!$active) {
                    json_return_and_die(array('errormsg' => 'It is not your turn', 'status' => false));
                }
                $r = chess_revert_position($g['game'], $observer, $_POST['mid']);
                if (!$r['status']) {
                    json_return_and_die(array('errormsg' => 'Error reverting game', 'status' => false));
                }
                json_return_and_die(array('status' => true));
                // API: /chess/history
                // Retrieves all the board positions for a game in order to populate the
                // history viewer in the control panel
            // API: /chess/history
            // Retrieves all the board positions for a game in order to populate the
            // history viewer in the control panel
            case 'history':
                $observer = App::get_observer();
                $game_id = $_POST['game_id'];
                $g = chess_get_game($game_id);
                if (!$g['status']) {
                    json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false));
                }
                // Verify that observer is a valid player
                $game = json_decode($g['game']['obj'], true);
                if (!in_array($observer['xchan_hash'], $game['players'])) {
                    json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false));
                }
                $player = array_search($observer['xchan_hash'], $game['players']);
                $h = chess_get_history($g['game']);
                if (!$h['status']) {
                    json_return_and_die(array('errormsg' => 'Error retrieving game history', 'status' => false));
                }
                json_return_and_die(array('history' => $h['history'], 'status' => true));
                // API: /chess/update
                // Updates a game specified by "game_id" with a new board position specified
                // by "newPosFEN" in FEN-format
            // API: /chess/update
            // Updates a game specified by "game_id" with a new board position specified
            // by "newPosFEN" in FEN-format
            case 'update':
                $observer = App::get_observer();
                $game_id = $_POST['game_id'];
                $g = chess_get_game($game_id);
                if (!$g['status']) {
                    json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false));
                }
                // Verify that observer is a valid player
                $game = json_decode($g['game']['obj'], true);
                if (!in_array($observer['xchan_hash'], $game['players'])) {
                    json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false));
                }
                $player = array_search($observer['xchan_hash'], $game['players']);
                $active = $game['active'] === $game['players'][$player] ? true : false;
                json_return_and_die(array('position' => $game['position'], 'myturn' => $active, 'ended' => $game['ended'], 'status' => true));
                // API: /chess/move
                // Adds a new board position by creating a child post for the original
                // game item.
            // API: /chess/move
            // Adds a new board position by creating a child post for the original
            // game item.
            case 'move':
                $observer = App::get_observer();
                $game_id = $_POST['game_id'];
                $newPosFEN = $_POST['newPosFEN'];
                $g = chess_get_game($game_id);
                if (!$g['status']) {
                    notice(t('Invalid game.') . EOL);
                    json_return_and_die(array('errormsg' => 'Invalid game ID', 'status' => false));
                }
                // Verify that observer is a valid player
                $game = json_decode($g['game']['obj'], true);
                if (!in_array($observer['xchan_hash'], $game['players'])) {
                    notice(t('You are not a player in this game.') . EOL);
                    goaway('/chess');
                }
                $player = array_search($observer['xchan_hash'], $game['players']);
                $color = $game['colors'][$player];
                $active = $game['active'] === $observer['xchan_hash'] ? true : false;
                if (!$active) {
                    json_return_and_die(array('errormsg' => 'It is not your turn', 'status' => false));
                }
                if (x($game, 'ended') && intval($game['ended']) === 1) {
                    json_return_and_die(array('errormsg' => 'The game is over', 'status' => false));
                }
                $move = chess_make_move($observer, $newPosFEN, $g['game']);
                if ($move['status']) {
                    $active_xchan = $game['players'][0] === $observer['xchan_hash'] ? $game['players'][1] : $game['players'][0];
                    if (chess_set_position(chess_get_game($game_id)['game'], $newPosFEN)) {
                        chess_set_active(chess_get_game($game_id)['game'], $active_xchan);
                    }
                    json_return_and_die(array('status' => true));
                } else {
                    json_return_and_die(array('errormsg' => 'Move failed', 'status' => false));
                }
            default:
                break;
        }
    }
    if (argc() > 2) {
        switch (argv(2)) {
            // API: /chess/[channelname]/new/
            // This endpoint handles the new game form submission and creates a new
            // game between two channels specified by the standard ACL
            case 'new':
                if (!local_channel()) {
                    notice(t('You must be a local channel to create a game.') . EOL);
                    return;
                }
                // Ensure ACL specifies exactly one other channel
                $channel = App::get_channel();
                $acl = new Zotlabs\Access\AccessList($channel);
                $acl->set_from_array($_REQUEST);
                $perms = $acl->get();
                $allow_cid = expand_acl($perms['allow_cid']);
                $valid = 0;
                if (count($allow_cid) > 1) {
                    foreach ($allow_cid as $allow) {
                        if ($allow == $channel['channel_hash']) {
                            continue;
                        }
                        $valid++;
                    }
                }
                if ($valid != 1) {
                    notice(t('You must select one opponent that is not yourself.') . EOL);
                    return;
                } else {
                    info(t('Creating new game...') . EOL);
                    // Get the game owner's color choice
                    $color = '';
                    if ($_POST['color'] === 'white' || $_POST['color'] === 'black') {
                        $color = $_POST['color'];
                    } else {
                        notice(t('You must select white or black.') . EOL);
                        return;
                    }
                    $game = chess_create_game($channel, $color, $acl);
                    if ($game['status']) {
                        goaway('/chess/' . $channel['channel_address'] . '/' . $game['item']['resource_id']);
                    } else {
                        notice(t('Error creating new game.') . EOL);
                    }
                    return;
                }
            default:
                break;
        }
    }
}