function atoken_xchan($atoken) { $c = channelx_by_n($atoken['atoken_uid']); if ($c) { return ['atoken_id' => $atoken['atoken_id'], 'xchan_hash' => substr($c['channel_hash'], 0, 16) . '.' . $atoken['atoken_name'], 'xchan_name' => $atoken['atoken_name'], 'xchan_addr' => t('guest:') . $atoken['atoken_name'] . '@' . \App::get_hostname(), 'xchan_network' => 'unknown', 'xchan_url' => z_root(), 'xchan_hidden' => 1, 'xchan_photo_mimetype' => 'image/jpeg', 'xchan_photo_l' => get_default_profile_photo(300), 'xchan_photo_m' => get_default_profile_photo(80), 'xchan_photo_s' => get_default_profile_photo(48)]; } return null; }
function import_xchan_photo($photo, $xchan, $thing = false) { $flags = $thing ? PHOTO_THING : PHOTO_XCHAN; $album = $thing ? 'Things' : 'Contact Photos'; logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG); if ($thing) { $hash = photo_new_resource(); } else { $r = q("select resource_id from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1", dbesc($xchan), intval(PHOTO_XCHAN)); if ($r) { $hash = $r[0]['resource_id']; } else { $hash = photo_new_resource(); } } $photo_failure = false; $img_str = ''; if ($photo) { $filename = basename($photo); $result = z_fetch_url($photo, true); if ($result['success']) { $img_str = $result['body']; $type = guess_image_type($photo, $result['header']); $h = explode("\n", $result['header']); if ($h) { foreach ($h as $hl) { if (stristr($hl, 'content-type:')) { if (!stristr($hl, 'image/')) { $photo_failure = true; } } } } } } else { $photo_failure = true; } if (!$photo_failure) { $img = photo_factory($img_str, $type); if ($img->is_valid()) { $width = $img->getWidth(); $height = $img->getHeight(); if ($width && $height) { if ($width / $height > 1.2) { // crop out the sides $margin = $width - $height; $img->cropImage(300, $margin / 2, 0, $height, $height); } elseif ($height / $width > 1.2) { // crop out the bottom $margin = $height - $width; $img->cropImage(300, 0, 0, $width, $width); } else { $img->scaleImageSquare(300); } } else { $photo_failure = true; } $p = array('xchan' => $xchan, 'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'imgscale' => 4); $r = $img->save($p); if ($r === false) { $photo_failure = true; } $img->scaleImage(80); $p['imgscale'] = 5; $r = $img->save($p); if ($r === false) { $photo_failure = true; } $img->scaleImage(48); $p['imgscale'] = 6; $r = $img->save($p); if ($r === false) { $photo_failure = true; } $photo = z_root() . '/photo/' . $hash . '-4'; $thumb = z_root() . '/photo/' . $hash . '-5'; $micro = z_root() . '/photo/' . $hash . '-6'; } else { logger('import_xchan_photo: invalid image from ' . $photo); $photo_failure = true; } } if ($photo_failure) { $photo = z_root() . '/' . get_default_profile_photo(); $thumb = z_root() . '/' . get_default_profile_photo(80); $micro = z_root() . '/' . get_default_profile_photo(48); $type = 'image/png'; } return array($photo, $thumb, $micro, $type, $photo_failure); }
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 }
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; }
function avatar_img($email) { $avatar = array(); $a = get_app(); $avatar['size'] = 175; $avatar['email'] = $email; $avatar['url'] = ''; $avatar['success'] = false; call_hooks('avatar_lookup', $avatar); if (!$avatar['success']) { $avatar['url'] = $a->get_baseurl() . '/' . get_default_profile_photo(); } logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG); return $avatar['url']; }
function init() { $prvcachecontrol = false; $streaming = null; $channel = null; switch (argc()) { case 4: $person = argv(3); $res = argv(2); $type = argv(1); break; case 2: $photo = argv(1); break; case 1: default: killme(); // NOTREACHED } $observer_xchan = get_observer_hash(); $default = get_default_profile_photo(); if (isset($type)) { /** * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites. * */ if ($type === 'profile') { switch ($res) { case 'm': $resolution = 5; $default = get_default_profile_photo(80); break; case 's': $resolution = 6; $default = get_default_profile_photo(48); break; case 'l': default: $resolution = 4; break; } } $uid = $person; $d = ['imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '']; call_hooks('get_profile_photo', $d); $resolution = $d['imgscale']; $uid = $d['channel_id']; $default = $d['default']; $data = $d['data']; $mimetype = $d['mimetype']; if (!$data) { $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1", intval($resolution), intval($uid), intval(PHOTO_PROFILE)); if ($r) { $data = dbunescbin($r[0]['content']); $mimetype = $r[0]['mimetype']; } if (intval($r[0]['os_storage'])) { $data = file_get_contents($data); } } if (!$data) { $data = file_get_contents($default); } if (!$mimetype) { $mimetype = 'image/png'; } } else { /** * Other photos */ /* Check for a cookie to indicate display pixel density, in order to detect high-resolution displays. This procedure was derived from the "Retina Images" by Jeremey Worboys, used in accordance with the Creative Commons Attribution 3.0 Unported License. Project link: https://github.com/Retina-Images/Retina-Images License link: http://creativecommons.org/licenses/by/3.0/ */ $cookie_value = false; if (isset($_COOKIE['devicePixelRatio'])) { $cookie_value = intval($_COOKIE['devicePixelRatio']); } else { // Force revalidation of cache on next request $cache_directive = 'no-cache'; $status = 'no cookie'; } $resolution = 0; if (strpos($photo, '.') !== false) { $photo = substr($photo, 0, strpos($photo, '.')); } if (substr($photo, -2, 1) == '-') { $resolution = intval(substr($photo, -1, 1)); $photo = substr($photo, 0, -2); // If viewing on a high-res screen, attempt to serve a higher resolution image: if ($resolution == 2 && $cookie_value > 1) { $resolution = 1; } } // If using resolution 1, make sure it exists before proceeding: if ($resolution == 1) { $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution)); if (!$r) { $resolution = 2; } } $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution)); if ($r) { $allowed = $r[0]['uid'] ? perm_is_allowed($r[0]['uid'], $observer_xchan, 'view_storage') : true; $sql_extra = permissions_sql($r[0]['uid']); if (!$sql_extra) { $sql_extra = ' and true '; } // Only check permissions on normal photos. Those photos we don't check includes // profile photos, xchan photos (which are also profile photos), 'thing' photos, // and cover photos $sql_extra = " and (( photo_usage = 0 {$sql_extra} ) or photo_usage != 0 )"; $channel = channelx_by_n($r[0]['uid']); // Now we'll see if we can access the photo $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d {$sql_extra} LIMIT 1", dbesc($photo), intval($resolution)); if ($r && $allowed) { $data = dbunescbin($r[0]['content']); $mimetype = $r[0]['mimetype']; if (intval($r[0]['os_storage'])) { $streaming = $data; } } else { // Does the picture exist? It may be a remote person with no credentials, // but who should otherwise be able to view it. Show a default image to let // them know permissions was denied. It may be possible to view the image // through an authenticated profile visit. // There won't be many completely unauthorised people seeing this because // they won't have the photo link, so there's a reasonable chance that the person // might be able to obtain permission to view it. $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `imgscale` = %d LIMIT 1", dbesc($photo), intval($resolution)); if ($r) { logger('mod_photo: forbidden. ' . \App::$query_string); $observer = \App::get_observer(); logger('mod_photo: observer = ' . ($observer ? $observer['xchan_addr'] : '(not authenticated)')); $data = file_get_contents('images/nosign.png'); $mimetype = 'image/png'; $prvcachecontrol = true; } } } } if (!isset($data)) { if (isset($resolution)) { switch ($resolution) { case 4: $data = file_get_contents(get_default_profile_photo()); $mimetype = 'image/png'; break; case 5: $data = file_get_contents(get_default_profile_photo(80)); $mimetype = 'image/png'; break; case 6: $data = file_get_contents(get_default_profile_photo(48)); $mimetype = 'image/png'; break; default: killme(); // NOTREACHED break; } } } if (isset($res) && intval($res) && $res < 500) { $ph = photo_factory($data, $mimetype); if ($ph->is_valid()) { $ph->scaleImageSquare($res); $data = $ph->imageString(); $mimetype = $ph->getType(); } } // Writing in cachefile if (isset($cachefile) && $cachefile != '') { file_put_contents($cachefile, $data); } if (function_exists('header_remove')) { header_remove('Pragma'); header_remove('pragma'); } header("Content-type: " . $mimetype); if ($prvcachecontrol) { // it is a private photo that they have no permission to view. // tell the browser not to cache it, in case they authenticate // and subsequently have permission to see it header("Cache-Control: no-store, no-cache, must-revalidate"); } else { // The photo cache default is 1 day to provide a privacy trade-off, // as somebody reducing photo permissions on a photo that is already // "in the wild" won't be able to stop the photo from being viewed // for this amount amount of time once it is in the browser cache. // The privacy expectations of your site members and their perception // of privacy where it affects the entire project may be affected. // This has performance considerations but we highly recommend you // leave it alone. $cache = get_config('system', 'photo_cache_time'); if (!$cache) { $cache = 3600 * 24; } // 1 day header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT"); header("Cache-Control: max-age=" . $cache); } // If it's a file resource, stream it. if ($streaming && $channel) { if (strpos($streaming, 'store') !== false) { $istream = fopen($streaming, 'rb'); } else { $istream = fopen('store/' . $channel['channel_address'] . '/' . $streaming, 'rb'); } $ostream = fopen('php://output', 'wb'); if ($istream && $ostream) { pipe_streams($istream, $ostream); fclose($istream); fclose($ostream); } } else { echo $data; } killme(); // NOTREACHED }
function reflect_comment_store($channel, $post, $comment, $user) { // if the commenter was the channel owner, use their hubzilla xchan if ($comment['author'] === REFLECT_EXPORTUSERNAME && $comment['registered']) { $hash = $channel['xchan_hash']; } else { // we need a unique hash for the commenter. We don't know how many may have supplied // http://yahoo.com as their URL, so we'll use their avatar guid if they have one. // anonymous folks may get more than one xchan_hash if they commented more than once. $hash = $comment['registered'] && $user ? $user['avatar'] : ''; if (!$hash) { $hash = random_string() . '.unknown'; } // create an xchan for them which will also import their profile photo // they will have a network type 'unknown'. $x = array('hash' => $hash, 'guid' => $hash, 'url' => $comment['url'] ? $comment['url'] : z_root(), 'photo' => $user ? REFLECT_BASEURL . $user['avatar'] : z_root() . '/' . get_default_profile_photo(), 'name' => $comment['author']); xchan_store($x); } $arr = array(); $r = q("select * from item where mid = '%s' and uid = %d limit 1", dbesc($comment['guid']), intval($channel['channel_id'])); if ($r) { if (REFLECT_OVERWRITE) { $arr['id'] = $r[0]['id']; } else { return; } } // this is a lot like storing the post except for subtle differences, like parent_mid, flags, author_xchan, // and we don't have a comment edited field so use creation date $arr['uid'] = $channel['channel_account_id']; $arr['aid'] = $channel['channel_id']; $arr['mid'] = $comment['guid']; $arr['parent_mid'] = $post['mid']; $arr['created'] = $comment['created']; $arr['edited'] = $comment['created']; $arr['author_xchan'] = $hash; $arr['owner_xchan'] = $channel['channel_hash']; $arr['item_origin'] = 1; $arr['item_wall'] = 1; $arr['verb'] = ACTIVITY_POST; $arr['comment_policy'] = 'contacts'; $arr['title'] = html2bbcode($comment['title']); $arr['title'] = htmlspecialchars($arr['title'], ENT_COMPAT, 'UTF-8', false); $arr['body'] = html2bbcode($comment['body']); $arr['body'] = htmlspecialchars($arr['body'], ENT_COMPAT, 'UTF-8', false); $arr['body'] = preg_replace_callback("/\\[url\\=\\/+article\\/(.*?)\\](.*?)\\[url\\]/", 'reflect_article_callback', $arr['body']); $arr['body'] = preg_replace_callback("/\\[img(.*?)\\](.*?)\\[\\/img\\]/", 'reflect_photo_callback', $arr['body']); // logger('comment: ' . print_r($arr,true)); if ($arr['id']) { item_store_update($arr); } else { item_store($arr); } }
public static 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_xchan_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']) : ''; $darray['app_system'] = x($arr, 'system') ? intval($arr['system']) : 0; $darray['app_deleted'] = x($arr, 'deleted') ? intval($arr['deleted']) : 0; $edited = datetime_convert(); $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', app_edited = '%s', app_system = %d, app_deleted = %d where app_id = '%s' and app_channel = %d", 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($edited), intval($darray['app_system']), intval($darray['app_deleted']), dbesc($darray['app_id']), intval($darray['app_channel'])); if ($r) { $ret['success'] = true; $ret['app_id'] = $darray['app_id']; } $x = q("select id from app where app_id = '%s' and app_channel = %d limit 1", dbesc($darray['app_id']), intval($darray['app_channel'])); if ($x) { q("delete from term where otype = %d and oid = %d", intval(TERM_OBJ_APP), intval($x[0]['id'])); if ($arr['categories']) { $y = explode(',', $arr['categories']); if ($y) { foreach ($y as $t) { $t = trim($t); if ($t) { store_item_tag($darray['app_channel'], $x[0]['id'], TERM_OBJ_APP, TERM_CATEGORY, escape_tags($t), escape_tags(z_root() . '/apps/?f=&cat=' . escape_tags($t))); } } } } } return $ret; }
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_hidden, xchan_orphan, xchan_censored, xchan_selfcensored, xchan_system, xchan_pubforum, xchan_deleted, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s',%d, %d, %d, %d, %d, %d, %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['hidden']), intval($arr['orphan']), intval($arr['censored']), intval($arr['selfcensored']), intval($arr['system']), intval($arr['pubforum']), intval($arr['deleted']), dbesc(datetime_convert())); if (!$r) { return $r; } $photos = import_xchan_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; }
function photo_init(&$a) { $prvcachecontrol = false; switch (argc()) { case 4: $person = argv(3); $res = argv(2); $type = argv(1); break; case 2: $photo = argv(1); break; case 1: default: killme(); // NOTREACHED } if ($photo === 'qr') { $t = $_GET['qr']; require_once 'library/phpqrcode/phpqrcode.php'; header("Content-type: image/png"); QRcode::png($t ? $t : '.'); killme(); } $observer_xchan = get_observer_hash(); $default = get_default_profile_photo(); if (isset($type)) { /** * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites. * */ if ($type === 'profile') { switch ($res) { case 'm': $resolution = 5; $default = get_default_profile_photo(80); break; case 's': $resolution = 6; $default = get_default_profile_photo(48); break; case 'l': default: $resolution = 4; break; } } $uid = $person; $r = q("SELECT * FROM photo WHERE scale = %d AND uid = %d AND profile = 1 LIMIT 1", intval($resolution), intval($uid)); if (count($r)) { $data = $r[0]['data']; $mimetype = $r[0]['type']; } if (!isset($data)) { $data = file_get_contents($default); $mimetype = 'image/jpeg'; } } else { /** * Other photos */ /* Check for a cookie to indicate display pixel density, in order to detect high-resolution displays. This procedure was derived from the "Retina Images" by Jeremey Worboys, used in accordance with the Creative Commons Attribution 3.0 Unported License. Project link: https://github.com/Retina-Images/Retina-Images License link: http://creativecommons.org/licenses/by/3.0/ */ $cookie_value = false; if (isset($_COOKIE['devicePixelRatio'])) { $cookie_value = intval($_COOKIE['devicePixelRatio']); } else { // Force revalidation of cache on next request $cache_directive = 'no-cache'; $status = 'no cookie'; } $resolution = 0; if (strpos($photo, '.') !== false) { $photo = substr($photo, 0, strpos($photo, '.')); } if (substr($photo, -2, 1) == '-') { $resolution = intval(substr($photo, -1, 1)); $photo = substr($photo, 0, -2); // If viewing on a high-res screen, attempt to serve a higher resolution image: if ($resolution == 2 && $cookie_value > 1) { $resolution = 1; } } // If using resolution 1, make sure it exists before proceeding: if ($resolution == 1) { $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND scale = %d LIMIT 1", dbesc($photo), intval($resolution)); if (!$r) { $resolution = 2; } } $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND scale = %d LIMIT 1", dbesc($photo), intval($resolution)); if ($r) { $allowed = $r[0]['uid'] ? perm_is_allowed($r[0]['uid'], $observer_xchan, 'view_photos') : true; $sql_extra = permissions_sql($r[0]['uid']); // Now we'll see if we can access the photo $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND scale = %d {$sql_extra} LIMIT 1", dbesc($photo), intval($resolution)); if ($r && $allowed) { $data = $r[0]['data']; $mimetype = $r[0]['type']; } else { // Does the picture exist? It may be a remote person with no credentials, // but who should otherwise be able to view it. Show a default image to let // them know permissions was denied. It may be possible to view the image // through an authenticated profile visit. // There won't be many completely unauthorised people seeing this because // they won't have the photo link, so there's a reasonable chance that the person // might be able to obtain permission to view it. $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `scale` = %d LIMIT 1", dbesc($photo), intval($resolution)); if ($r) { logger('mod_photo: forbidden. ' . $a->query_string); $observer = $a->get_observer(); logger('mod_photo: observer = ' . ($observer ? $observer['xchan_addr'] : '(not authenticated)')); $data = file_get_contents('images/nosign.png'); $mimetype = 'image/png'; $prvcachecontrol = true; } } } } if (!isset($data)) { if (isset($resolution)) { switch ($resolution) { case 4: $data = file_get_contents(get_default_profile_photo()); $mimetype = 'image/jpeg'; break; case 5: $data = file_get_contents(get_default_profile_photo(80)); $mimetype = 'image/jpeg'; break; case 6: $data = file_get_contents(get_default_profile_photo(48)); $mimetype = 'image/jpeg'; break; default: killme(); // NOTREACHED break; } } } if (isset($res) && intval($res) && $res < 500) { $ph = photo_factory($data, $mimetype); if ($ph->is_valid()) { $ph->scaleImageSquare($res); $data = $ph->imageString(); $mimetype = $ph->getType(); } } // Writing in cachefile if (isset($cachefile) && $cachefile != '') { file_put_contents($cachefile, $data); } if (function_exists('header_remove')) { header_remove('Pragma'); header_remove('pragma'); } header("Content-type: " . $mimetype); if ($prvcachecontrol) { // it is a private photo that they have no permission to view. // tell the browser not to cache it, in case they authenticate // and subsequently have permission to see it header("Cache-Control: no-store, no-cache, must-revalidate"); } else { header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600 * 24) . " GMT"); header("Cache-Control: max-age=" . 3600 * 24); } echo $data; killme(); // NOTREACHED }