function init() { $ret = array(); call_hooks('home_init', $ret); $splash = argc() > 1 && argv(1) === 'splash' ? true : false; $channel = \App::get_channel(); if (local_channel() && $channel && $channel['xchan_url'] && !$splash) { $dest = $channel['channel_startpage']; if (!$dest) { $dest = get_pconfig(local_channel(), 'system', 'startpage'); } if (!$dest) { $dest = get_config('system', 'startpage'); } if (!$dest) { $dest = z_root() . '/network'; } goaway($dest); } if (remote_channel() && !$splash && $_SESSION['atoken']) { $r = q("select * from atoken where atoken_id = %d", intval($_SESSION['atoken'])); if ($r) { $x = channelx_by_n($r[0]['atoken_uid']); if ($x) { goaway(z_root() . '/channel/' . $x['channel_address']); } } } if (get_account_id() && !$splash) { goaway(z_root() . '/new_channel'); } }
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 exec() { $opts = $this->curlopts; $url = $this->url; if ($this->auth) { $opts['http_auth'] = $this->auth; } if ($this->magicauth) { $opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth; $opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth; $opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth)); $c = channelx_by_n($this->magicauth); if ($c) { $url = zid($this->url, channel_reddress($c)); } } if ($this->custom) { $opts['custom'] = $this->custom; } if ($this->headers) { $opts['headers'] = $this->headers; } if ($this->upload) { $opts['upload'] = true; $opts['infile'] = $this->filehandle; $opts['infilesize'] = strlen($this->request_data); $opts['readfunc'] = [$this, 'curl_read']; } $recurse = 0; return z_fetch_url($this->url, true, $recurse, $opts ? $opts : null); }
/** * attach_move() * This function performs an in place directory-to-directory move of a stored attachment or photo. * The data is physically moved in the store/nickname storage location and the paths adjusted * in the attach structure (and if applicable the photo table). The new 'album name' is recorded * for photos and will show up immediately there. * This takes a channel_id, attach.hash of the file to move (this is the same as a photo resource_id), and * the attach.hash of the new parent folder, which must already exist. If $new_folder_hash is blank or empty, * the file is relocated to the root of the channel's storage area. * * @fixme: this operation is currently not synced to clones !! */ function attach_move($channel_id, $resource_id, $new_folder_hash) { $c = channelx_by_n($channel_id); if (!$c) { return false; } $r = q("select * from attach where hash = '%s' and uid = %d limit 1", dbesc($resource_id), intval($channel_id)); if (!$r) { return false; } $oldstorepath = $r[0]['content']; if ($new_folder_hash) { $n = q("select * from attach where hash = '%s' and uid = %d limit 1", dbesc($new_folder_hash), intval($channel_id)); if (!$n) { return; } $newdirname = $n[0]['filename']; $newstorepath = $n[0]['content'] . '/' . $resource_id; } else { $newstorepath = 'store/' . $c['channel_address'] . '/' . $resource_id; } rename($oldstorepath, $newstorepath); // duplicate detection. If 'overwrite' is specified, return false because we can't yet do that. $filename = $r[0]['filename']; $s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", dbesc($filename), dbesc($new_folder_hash)); if ($s) { $overwrite = get_pconfig($channel_id, 'system', 'overwrite_dup_files'); if ($overwrite) { // @fixme return; } else { if (strpos($filename, '.') !== false) { $basename = substr($filename, 0, strrpos($filename, '.')); $ext = substr($filename, strrpos($filename, '.')); } else { $basename = $filename; $ext = ''; } $v = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", dbesc($basename . $ext), dbesc($basename . '(%)' . $ext), dbesc($new_folder_hash)); if ($v) { $x = 1; do { $found = false; foreach ($v as $vv) { if ($vv['filename'] === $basename . '(' . $x . ')' . $ext) { $found = true; break; } } if ($found) { $x++; } } while ($found); $filename = $basename . '(' . $x . ')' . $ext; } else { $filename = $basename . $ext; } } } $t = q("update attach set content = '%s', folder = '%s', filename = '%s' where id = %d", dbesc($newstorepath), dbesc($new_folder_hash), dbesc($filename), intval($r[0]['id'])); if ($r[0]['is_photo']) { $t = q("update photo set album = '%s', filename = '%s' where resource_id = '%s' and uid = %d", dbesc($newdirname), dbesc($filename), dbesc($resource_id), intval($channel_id)); $t = q("update photo set content = '%s' where resource_id = '%s' and uid = %d and imgscale = 0", dbesc($newstorepath), dbesc($resource_id), intval($channel_id)); } return true; }
/** * @brief delete directory */ public function delete() { logger('delete file ' . basename($this->red_path), LOGGER_DEBUG); if (!$this->auth->owner_id || !perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage')) { throw new DAV\Exception\Forbidden('Permission denied.'); } if ($this->auth->owner_id !== $this->auth->channel_id) { if ($this->auth->observer !== $this->data['creator'] || intval($this->data['is_dir'])) { throw new DAV\Exception\Forbidden('Permission denied.'); } } attach_delete($this->auth->owner_id, $this->folder_hash); $ch = channelx_by_n($this->auth->owner_id); if ($ch) { $sync = attach_export_data($ch, $this->folder_hash, true); if ($sync) { build_sync_packet($ch['channel_id'], array('file' => array($sync))); } } }
function channel_export_items($channel_id, $start, $finish) { if (!$start) { return array(); } else { $start = datetime_convert('UTC', 'UTC', $start); } $finish = datetime_convert('UTC', 'UTC', $finish ? $finish : 'now'); if ($finish < $start) { return array(); } $ret = array(); $ch = channelx_by_n($channel_id); if ($ch) { $ret['relocate'] = ['channel_address' => $ch['channel_address'], 'url' => z_root()]; } $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created", intval(ITEM_TYPE_POST), intval($channel_id), dbesc($start), dbesc($finish)); if ($r) { $ret['item'] = array(); xchan_query($r); $r = fetch_post_tags($r, true); foreach ($r as $rr) { $ret['item'][] = encode_item($rr, true); } } return $ret; }
function jappixmini_cron(&$a, $d) { require_once 'include/Contact.php'; // For autosubscribe/autoapprove, we need to maintain a list of jabber addresses of our contacts. set_config("jappixmini", "last_cron_execution", $d); // go through list of users with jabber enabled $users = q("SELECT uid FROM pconfig WHERE cat = 'jappixmini' AND ( k = 'autosubscribe' OR k = 'autoapprove') AND v = '1' group by uid "); logger("jappixmini: Update list of contacts' jabber accounts for " . count($users) . " users."); if (!count($users)) { return; } foreach ($users as $row) { $uid = $row["uid"]; // for each user, go through list of contacts $rand = db_getfunc('rand'); $contacts = q("SELECT * FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel`=%d AND not (abook_flags & %d) > 0 order by {$rand}", intval($uid), intval(ABOOK_FLAG_SELF)); $channel = channelx_by_n($uid); if (!$channel || !$contacts) { continue; } foreach ($contacts as $contact_row) { $xchan_hash = $contact_row["abook_xchan"]; $pubkey = $contact_row["xchan_pubkey"]; // check if jabber address already present $present = get_pconfig($uid, "jappixmini", "id:" . $xchan_hash); $now = intval(time()); if ($present) { // $present has format "timestamp:jabber_address" $p = strpos($present, ":"); $timestamp = intval(substr($present, 0, $p)); // do not re-retrieve jabber address if last retrieval // is not older than a week if ($now - $timestamp < 3600 * 24 * 7) { continue; } } logger('jappixmini: checking ' . $contact_row['xchan_name'] . ' for channel ' . $channel['channel_name']); // construct base retrieval address $pos = strpos($contact_row['xchan_connurl'], "/poco/"); if ($pos === false) { continue; } $url = substr($contact_row['xchan_connurl'], 0, $pos) . "/jappixmini?f="; // construct own address $username = get_pconfig($uid, 'jappixmini', 'username'); if (!$username) { continue; } $server = get_pconfig($uid, 'jappixmini', 'server'); if (!$server) { continue; } $address = $username . "@" . $server; // sign address $signed_address = ""; openssl_private_encrypt($address, $signed_address, $channel['channel_prvkey']); // construct request url $signed_address_hex = base64url_encode($signed_address); $postvars = array('address' => $signed_address, 'requestor' => $channel['xchan_hash'], 'requestee' => $contact_row['xchan_hash']); try { // send request $answer_json = z_post_url($url, $postvars); logger('jappixmini: url response: ' . print_r($answer_json, true)); if (!$answer_json['success']) { logger('jappixmini: failed z_post_url ' . $url); throw new Exception(); } if ($answer_json['return_code'] == 404) { logger('jappixmini: failed z_post_url (404)' . $url); throw new Exception(); } // parse answer $answer = json_decode($answer_json['body'], true); if ($answer['status'] != "ok") { throw new Exception(); } $address = base64url_decode($answer['address']); if (!$address) { throw new Exception(); } // decrypt address $decrypted_address = ""; openssl_public_decrypt($address, $decrypted_address, $pubkey); if (!$decrypted_address) { throw new Exception(); } } catch (Exception $e) { $decrypted_address = ""; } // save address set_pconfig($uid, "jappixmini", "id:" . $xchan_hash, "{$now}:{$decrypted_address}"); } } }
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 }
/** * @brief Delete the file. * * This method checks the permissions and then calls attach_delete() function * to actually remove the file. * * @throw \Sabre\DAV\Exception\Forbidden */ public function delete() { logger('delete file ' . basename($this->name), LOGGER_DEBUG); if (!$this->auth->owner_id || !perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage')) { throw new DAV\Exception\Forbidden('Permission denied.'); } if ($this->auth->owner_id !== $this->auth->channel_id) { if ($this->auth->observer !== $this->data['creator'] || intval($this->data['is_dir'])) { throw new DAV\Exception\Forbidden('Permission denied.'); } } if (get_pconfig($this->auth->owner_id, 'system', 'os_delete_prohibit') && \App::$module == 'dav') { throw new DAV\Exception\Forbidden('Permission denied.'); } attach_delete($this->auth->owner_id, $this->data['hash']); $ch = channelx_by_n($this->auth->owner_id); if ($ch) { $sync = attach_export_data($ch, $this->data['hash'], true); if ($sync) { build_sync_packet($ch['channel_id'], array('file' => array($sync))); } } }
function widget_cover_photo($arr) { require_once 'include/channel.php'; $o = ''; if (App::$module == 'channel' && $_REQUEST['mid']) { return ''; } $channel_id = 0; if (array_key_exists('channel_id', $arr) && intval($arr['channel_id'])) { $channel_id = intval($arr['channel_id']); } if (!$channel_id) { $channel_id = App::$profile_uid; } if (!$channel_id) { return ''; } $channel = channelx_by_n($channel_id); if (array_key_exists('style', $arr) && isset($arr['style'])) { $style = $arr['style']; } else { $style = 'width:100%; height: auto;'; } // ensure they can't sneak in an eval(js) function if (strpbrk($style, '(\'"<>') !== false) { $style = ''; } if (array_key_exists('title', $arr) && isset($arr['title'])) { $title = $arr['title']; } else { $title = $channel['channel_name']; } if (array_key_exists('subtitle', $arr) && isset($arr['subtitle'])) { $subtitle = $arr['subtitle']; } else { $subtitle = str_replace('@', '@', $channel['xchan_addr']); } $c = get_cover_photo($channel_id, 'html'); if ($c) { $photo_html = $style ? str_replace('alt=', ' style="' . $style . '" alt=', $c) : $c; $o = replace_macros(get_markup_template('cover_photo_widget.tpl'), array('$photo_html' => $photo_html, '$title' => $title, '$subtitle' => $subtitle, '$hovertitle' => t('Click to show more'))); } return $o; }
/** * This is our general purpose content editor. * It was once nicknamed "jot" and you may see references to "jot" littered throughout the code. * They are referring to the content editor or components thereof. */ function status_editor($a, $x, $popup = false) { $o = ''; $c = channelx_by_n($x['profile_uid']); if ($c && $c['channel_moved']) { return $o; } $plaintext = true; // if(feature_enabled(local_channel(),'richtext')) // $plaintext = false; $feature_voting = feature_enabled($x['profile_uid'], 'consensus_tools'); if (x($x, 'hide_voting')) { $feature_voting = false; } $feature_expire = feature_enabled($x['profile_uid'], 'content_expire') && !$webpage ? true : false; if (x($x, 'hide_expire')) { $feature_expire = false; } $feature_future = feature_enabled($x['profile_uid'], 'delayed_posting') && !$webpage ? true : false; if (x($x, 'hide_future')) { $feature_future = false; } $geotag = $x['allow_location'] ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : ''; $setloc = t('Set your location'); $clearloc = get_pconfig($x['profile_uid'], 'system', 'use_browser_location') ? t('Clear browser location') : ''; if (x($x, 'hide_location')) { $geotag = $setloc = $clearloc = ''; } $mimetype = x($x, 'mimetype') ? $x['mimetype'] : 'text/bbcode'; $mimeselect = x($x, 'mimeselect') ? $x['mimeselect'] : false; if ($mimeselect) { $mimeselect = mimetype_select($x['profile_uid'], $mimetype); } else { $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />'; } $weblink = $mimetype === 'text/bbcode' ? t('Insert web link') : false; if (x($x, 'hide_weblink')) { $weblink = false; } $embedPhotos = t('Embed image from photo albums'); $writefiles = $mimetype === 'text/bbcode' ? perm_is_allowed($x['profile_uid'], get_observer_hash(), 'write_storage') : false; if (x($x, 'hide_attach')) { $writefiles = false; } $layout = x($x, 'layout') ? $x['layout'] : ''; $layoutselect = x($x, 'layoutselect') ? $x['layoutselect'] : false; if ($layoutselect) { $layoutselect = layout_select($x['profile_uid'], $layout); } else { $layoutselect = '<input type="hidden" name="layout_mid" value="' . $layout . '" />'; } if (array_key_exists('channel_select', $x) && $x['channel_select']) { require_once 'include/channel.php'; $id_select = identity_selector(); } else { $id_select = ''; } $webpage = x($x, 'webpage') ? $x['webpage'] : ''; $tpl = get_markup_template('jot-header.tpl'); App::$page['htmlhead'] .= replace_macros($tpl, array('$baseurl' => z_root(), '$editselect' => $plaintext ? 'none' : '/(profile-jot-text|prvmail-text)/', '$pretext' => x($x, 'pretext') ? $x['pretext'] : '', '$geotag' => $geotag, '$nickname' => $x['nickname'], '$linkurl' => t('Please enter a link URL:'), '$term' => t('Tag term:'), '$whereareu' => t('Where are you right now?'), '$editor_autocomplete' => x($x, 'editor_autocomplete') ? $x['editor_autocomplete'] : '', '$bbco_autocomplete' => x($x, 'bbco_autocomplete') ? $x['bbco_autocomplete'] : '', '$modalchooseimages' => t('Choose images to embed'), '$modalchoosealbum' => t('Choose an album'), '$modaldiffalbum' => t('Choose a different album...'), '$modalerrorlist' => t('Error getting album list'), '$modalerrorlink' => t('Error getting photo link'), '$modalerroralbum' => t('Error getting album'))); $tpl = get_markup_template('jot.tpl'); $jotplugins = ''; $preview = t('Preview'); if (x($x, 'hide_preview')) { $preview = ''; } $defexpire = ($z = get_pconfig($x['profile_uid'], 'system', 'default_post_expire')) && !$webpage ? $z : ''; if ($defexpire) { $defexpire = datetime_convert('UTC', date_default_timezone_get(), $defexpire, 'Y-m-d H:i'); } $defpublish = ($z = get_pconfig($x['profile_uid'], 'system', 'default_post_publish')) && !$webpage ? $z : ''; if ($defpublish) { $defpublish = datetime_convert('UTC', date_default_timezone_get(), $defpublish, 'Y-m-d H:i'); } $cipher = get_pconfig($x['profile_uid'], 'system', 'default_cipher'); if (!$cipher) { $cipher = 'aes256'; } call_hooks('jot_tool', $jotplugins); $o .= replace_macros($tpl, array('$return_path' => x($x, 'return_path') ? $x['return_path'] : App::$query_string, '$action' => z_root() . '/item', '$share' => x($x, 'button') ? $x['button'] : t('Share'), '$webpage' => $webpage, '$placeholdpagetitle' => x($x, 'ptlabel') ? $x['ptlabel'] : t('Page link name'), '$pagetitle' => x($x, 'pagetitle') ? $x['pagetitle'] : '', '$id_select' => $id_select, '$id_seltext' => t('Post as'), '$writefiles' => $writefiles, '$bold' => t('Bold'), '$italic' => t('Italic'), '$underline' => t('Underline'), '$quote' => t('Quote'), '$code' => t('Code'), '$attach' => t('Attach file'), '$weblink' => $weblink, '$embedPhotos' => $embedPhotos, '$embedPhotosModalTitle' => t('Embed an image from your albums'), '$embedPhotosModalCancel' => t('Cancel'), '$embedPhotosModalOK' => t('OK'), '$setloc' => $setloc, '$voting' => t('Toggle voting'), '$feature_voting' => $feature_voting, '$consensus' => 0, '$clearloc' => $clearloc, '$title' => x($x, 'title') ? htmlspecialchars($x['title'], ENT_COMPAT, 'UTF-8') : '', '$placeholdertitle' => x($x, 'placeholdertitle') ? $x['placeholdertitle'] : t('Title (optional)'), '$catsenabled' => feature_enabled($x['profile_uid'], 'categories') && !$webpage ? 'categories' : '', '$category' => x($x, 'category') ? $x['category'] : '', '$placeholdercategory' => t('Categories (optional, comma-separated list)'), '$permset' => t('Permission settings'), '$ptyp' => x($x, 'ptyp') ? $x['ptyp'] : '', '$content' => x($x, 'body') ? htmlspecialchars($x['body'], ENT_COMPAT, 'UTF-8') : '', '$attachment' => x($x, 'attachment') ? $x['attachment'] : '', '$post_id' => x($x, 'post_id') ? $x['post_id'] : '', '$defloc' => $x['default_location'], '$visitor' => $x['visitor'], '$lockstate' => $x['lockstate'], '$acl' => $x['acl'], '$mimeselect' => $mimeselect, '$layoutselect' => $layoutselect, '$showacl' => array_key_exists('showacl', $x) ? $x['showacl'] : true, '$bang' => $x['bang'], '$profile_uid' => $x['profile_uid'], '$preview' => $preview, '$source' => x($x, 'source') ? $x['source'] : '', '$jotplugins' => $jotplugins, '$defexpire' => $defexpire, '$feature_expire' => $feature_expire, '$expires' => t('Set expiration date'), '$defpublish' => $defpublish, '$feature_future' => $feature_future, '$future_txt' => t('Set publish date'), '$feature_encrypt' => feature_enabled($x['profile_uid'], 'content_encrypt') && !$webpage ? true : false, '$encrypt' => t('Encrypt text'), '$cipher' => $cipher, '$expiryModalOK' => t('OK'), '$expiryModalCANCEL' => t('Cancel'), '$expanded' => x($x, 'expanded') ? $x['expanded'] : false, '$bbcode' => x($x, 'bbcode') ? $x['bbcode'] : false)); if ($popup === true) { $o = '<div id="jot-popup" style="display:none">' . $o . '</div>'; } return $o; }
// already logged in user returning if (x($_SESSION, 'uid') || x($_SESSION, 'account_id')) { App::$session->return_check(); $r = q("select * from account where account_id = %d limit 1", intval($_SESSION['account_id'])); if ($r && ($r[0]['account_flags'] == ACCOUNT_OK || $r[0]['account_flags'] == ACCOUNT_UNVERIFIED)) { App::$account = $r[0]; $login_refresh = false; if (!x($_SESSION, 'last_login_date')) { $_SESSION['last_login_date'] = datetime_convert('UTC', 'UTC'); } if (strcmp(datetime_convert('UTC', 'UTC', 'now - 12 hours'), $_SESSION['last_login_date']) > 0) { $_SESSION['last_login_date'] = datetime_convert(); App::$session->extend_cookie(); $login_refresh = true; } $ch = $_SESSION['uid'] ? channelx_by_n($_SESSION['uid']) : null; authenticate_success($r[0], null, $ch, false, false, $login_refresh); } else { $_SESSION['account_id'] = 0; App::$session->nuke(); goaway(z_root()); } } // end logged in user returning } else { if (isset($_SESSION)) { App::$session->nuke(); } // handle a fresh login request if (x($_POST, 'password') && strlen($_POST['password'])) { $encrypted = hash('whirlpool', trim($_POST['password']));
function menu_sync_packet($uid, $observer_hash, $menu_id, $delete = false) { $r = menu_fetch_id($menu_id, $uid); $c = channelx_by_n($uid); if ($r) { $m = menu_fetch($r['menu_name'], $uid, $observer_hash); if ($m) { if ($delete) { $m['menu_delete'] = 1; } build_sync_packet($uid, array('menu' => array(menu_element($c, $m)))); } } }
/** * @brief Creates a form to add new folders and upload files. * * @param \Sabre\DAV\INode $node * @param string &$output */ public function htmlActionsPanel(DAV\INode $node, &$output, $path) { if (!$node instanceof DAV\ICollection) { return; } // We also know fairly certain that if an object is a non-extended // SimpleCollection, we won't need to show the panel either. if (get_class($node) === 'Sabre\\DAV\\SimpleCollection') { return; } require_once 'include/acl_selectors.php'; $aclselect = null; $lockstate = ''; if ($this->auth->owner_id) { $channel = channelx_by_n($this->auth->owner_id); if ($channel) { $acl = new \Zotlabs\Access\AccessList($channel); $channel_acl = $acl->get(); $lockstate = $acl->is_private() ? 'lock' : 'unlock'; $aclselect = local_channel() == $this->auth->owner_id ? populate_acl($channel_acl, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''; } } // Storage and quota for the account (all channels of the owner of this directory)! $limit = engr_units_to_bytes(service_class_fetch($owner, 'attach_upload_limit')); $r = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d", intval($this->auth->channel_account_id)); $used = $r[0]['total']; if ($used) { $quotaDesc = t('You are using %1$s of your available file storage.'); $quotaDesc = sprintf($quotaDesc, userReadableSize($used)); } if ($limit && $used) { $quotaDesc = t('You are using %1$s of %2$s available file storage. (%3$s%)'); $quotaDesc = sprintf($quotaDesc, userReadableSize($used), userReadableSize($limit), round($used / $limit, 1) * 100); } // prepare quota for template $quota = array(); $quota['used'] = $used; $quota['limit'] = $limit; $quota['desc'] = $quotaDesc; $quota['warning'] = $limit && round($used / $limit, 1) * 100 >= 90 ? t('WARNING:') : ''; // 10485760 bytes = 100MB $path = trim(str_replace('cloud/' . $this->auth->owner_nick, '', $path), '/'); $output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array('$folder_header' => t('Create new folder'), '$folder_submit' => t('Create'), '$upload_header' => t('Upload file'), '$upload_submit' => t('Upload'), '$quota' => $quota, '$channick' => $this->auth->owner_nick, '$aclselect' => $aclselect, '$allow_cid' => acl2json($channel_acl['allow_cid']), '$allow_gid' => acl2json($channel_acl['allow_gid']), '$deny_cid' => acl2json($channel_acl['deny_cid']), '$deny_gid' => acl2json($channel_acl['deny_gid']), '$lockstate' => $lockstate, '$return_url' => \App::$cmd, '$path' => $path, '$folder' => find_folder_hash_by_path($this->auth->owner_id, $path), '$dragdroptext' => t('Drop files here to immediately upload'))); }
function handle_feed($uid, $abook_id, $url) { require_once 'include/Contact.php'; $channel = channelx_by_n($uid); if (!$channel) { return; } $x = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d limit 1", dbesc($abook_id), intval($uid)); $recurse = 0; $z = z_fetch_url($url, false, $recurse, array('novalidate' => true)); //logger('handle_feed:' . print_r($z,true)); if ($z['success']) { consume_feed($z['body'], $channel, $x[0], 0); consume_feed($z['body'], $channel, $x[0], 1); } }
function widget_photo_albums($arr) { $a = get_app(); if (!$a->profile['profile_uid']) { return ''; } $channelx = channelx_by_n($a->profile['profile_uid']); if (!$channelx || !perm_is_allowed($a->profile['profile_uid'], get_observer_hash(), 'view_photos')) { return ''; } return photos_album_widget($channelx, $a->get_observer()); }
function notifier_run($argv, $argc) { cli_startup(); $a = get_app(); if ($argc < 3) { return; } logger('notifier: invoked: ' . print_r($argv, true), LOGGER_DEBUG); $cmd = $argv[1]; $item_id = $argv[2]; $extra = $argc > 3 ? $argv[3] : null; if (!$item_id) { return; } $sys = get_sys_channel(); $deliveries = array(); $dead_hubs = array(); $dh = q("select site_url from site where site_dead = 1"); if ($dh) { foreach ($dh as $dead) { $dead_hubs[] = $dead['site_url']; } } $request = false; $mail = false; $top_level = false; $location = false; $recipients = array(); $url_recipients = array(); $normal_mode = true; $packet_type = 'undefined'; if ($cmd === 'mail') { $normal_mode = false; $mail = true; $private = true; $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1", intval($item_id)); if (!$message) { return; } xchan_mail_query($message[0]); $uid = $message[0]['channel_id']; $recipients[] = $message[0]['from_xchan']; // include clones $recipients[] = $message[0]['to_xchan']; $item = $message[0]; $encoded_item = encode_mail($item); $s = q("select * from channel where channel_id = %d limit 1", intval($item['channel_id'])); if ($s) { $channel = $s[0]; } } elseif ($cmd === 'request') { $channel_id = $item_id; $xchan = $argv[3]; $request_message_id = $argv[4]; $s = q("select * from channel where channel_id = %d limit 1", intval($channel_id)); if ($s) { $channel = $s[0]; } $private = true; $recipients[] = $xchan; $packet_type = 'request'; $normal_mode = false; } elseif ($cmd == 'permission_update' || $cmd == 'permission_create') { // Get the (single) recipient $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0", intval($item_id)); if ($r) { $uid = $r[0]['abook_channel']; // Get the sender $channel = channelx_by_n($uid); if ($channel) { $perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''); if ($cmd == 'permission_create') { call_hooks('permissions_create', $perm_update); } else { call_hooks('permissions_update', $perm_update); } if ($perm_update['success']) { if ($perm_update['deliveries']) { $deliveries[] = $perm_update['deliveries']; do_delivery($deliveries); } return; } else { $recipients[] = $r[0]['abook_xchan']; $private = false; $packet_type = 'refresh'; $packet_recips = array(array('guid' => $r[0]['xchan_guid'], 'guid_sig' => $r[0]['xchan_guid_sig'], 'hash' => $r[0]['xchan_hash'])); } } } } elseif ($cmd === 'refresh_all') { logger('notifier: refresh_all: ' . $item_id); $uid = $item_id; $channel = channelx_by_n($item_id); $r = q("select abook_xchan from abook where abook_channel = %d", intval($item_id)); if ($r) { foreach ($r as $rr) { $recipients[] = $rr['abook_xchan']; } } $private = false; $packet_type = 'refresh'; } elseif ($cmd === 'location') { logger('notifier: location: ' . $item_id); $s = q("select * from channel where channel_id = %d limit 1", intval($item_id)); if ($s) { $channel = $s[0]; } $uid = $item_id; $recipients = array(); $r = q("select abook_xchan from abook where abook_channel = %d", intval($item_id)); if ($r) { foreach ($r as $rr) { $recipients[] = $rr['abook_xchan']; } } $encoded_item = array('locations' => zot_encode_locations($channel), 'type' => 'location', 'encoding' => 'zot'); $target_item = array('aid' => $channel['channel_account_id'], 'uid' => $channel['channel_id']); $private = false; $packet_type = 'location'; $location = true; } elseif ($cmd === 'purge_all') { logger('notifier: purge_all: ' . $item_id); $s = q("select * from channel where channel_id = %d limit 1", intval($item_id)); if ($s) { $channel = $s[0]; } $uid = $item_id; $recipients = array(); $r = q("select abook_xchan from abook where abook_channel = %d", intval($item_id)); if ($r) { foreach ($r as $rr) { $recipients[] = $rr['abook_xchan']; } } $private = false; $packet_type = 'purge'; } else { // Normal items // Fetch the target item $r = q("SELECT * FROM item WHERE id = %d and parent != 0 LIMIT 1", intval($item_id)); if (!$r) { return; } xchan_query($r); $r = fetch_post_tags($r); $target_item = $r[0]; $deleted_item = false; if (intval($target_item['item_deleted'])) { logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG); $deleted_item = true; } if (intval($target_item['item_type']) != ITEM_TYPE_POST) { logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG); return; } if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed'])) { logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG); return; } if (strpos($target_item['postopts'], 'nodeliver') !== false) { logger('notifier: target item is undeliverable', LOGGER_DEBUG); return; } $s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", intval($target_item['uid'])); if ($s) { $channel = $s[0]; } if ($channel['channel_hash'] !== $target_item['author_xchan'] && $channel['channel_hash'] !== $target_item['owner_xchan']) { logger("notifier: Sending channel {$channel['channel_hash']} is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING); return; } if ($target_item['id'] == $target_item['parent']) { $parent_item = $target_item; $top_level_post = true; } else { // fetch the parent item $r = q("SELECT * from item where id = %d order by id asc", intval($target_item['parent'])); if (!$r) { return; } if (strpos($r[0]['postopts'], 'nodeliver') !== false) { logger('notifier: target item is undeliverable', LOGGER_DEBUG, LOG_NOTICE); return; } xchan_query($r); $r = fetch_post_tags($r); $parent_item = $r[0]; $top_level_post = false; } // avoid looping of discover items 12/4/2014 if ($sys && $parent_item['uid'] == $sys['channel_id']) { return; } $encoded_item = encode_item($target_item); // Send comments to the owner to re-deliver to everybody in the conversation // We only do this if the item in question originated on this site. This prevents looping. // To clarify, a site accepting a new comment is responsible for sending it to the owner for relay. // Relaying should never be initiated on a post that arrived from elsewhere. // We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this // flag on comments for an extended period. So we'll also call comment_local_origin() which looks at // the hostname in the message_id and provides a second (fallback) opinion. $relay_to_owner = !$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item) ? true : false; $uplink = false; // $cmd === 'relay' indicates the owner is sending it to the original recipients // don't allow the item in the relay command to relay to owner under any circumstances, it will loop logger('notifier: relay_to_owner: ' . ($relay_to_owner ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG); logger('notifier: top_level_post: ' . ($top_level_post ? 'true' : 'false'), LOGGER_DATA, LOG_DEBUG); // tag_deliver'd post which needs to be sent back to the original author if ($cmd === 'uplink' && intval($parent_item['item_uplink']) && !$top_level_post) { logger('notifier: uplink'); $uplink = true; } if (($relay_to_owner || $uplink) && $cmd !== 'relay') { logger('notifier: followup relay', LOGGER_DEBUG); $recipients = array($uplink ? $parent_item['source_xchan'] : $parent_item['owner_xchan']); $private = true; if (!$encoded_item['flags']) { $encoded_item['flags'] = array(); } $encoded_item['flags'][] = 'relay'; } else { logger('notifier: normal distribution', LOGGER_DEBUG); if ($cmd === 'relay') { logger('notifier: owner relay'); } // if our parent is a tag_delivery recipient, uplink to the original author causing // a delivery fork. if ($parent_item && intval($parent_item['item_uplink']) && !$top_level_post && $cmd !== 'uplink') { // don't uplink a relayed post to the relay owner if ($parent_item['source_xchan'] !== $parent_item['owner_xchan']) { logger('notifier: uplinking this item'); proc_run('php', 'include/notifier.php', 'uplink', $item_id); } } $private = false; $recipients = collect_recipients($parent_item, $private); // FIXME add any additional recipients such as mentions, etc. // don't send deletions onward for other people's stuff // TODO verify this is needed - copied logic from same place in old code if (intval($target_item['item_deleted']) && !intval($target_item['item_wall'])) { logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE); return; } } } $walltowall = $top_level_post && $channel['xchan_hash'] === $target_item['author_xchan'] ? true : false; // Generic delivery section, we have an encoded item and recipients // Now start the delivery process $x = $encoded_item; $x['title'] = 'private'; $x['body'] = 'private'; logger('notifier: encoded item: ' . print_r($x, true), LOGGER_DATA, LOG_DEBUG); stringify_array_elms($recipients); if (!$recipients) { return; } // logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG); $env_recips = $private ? array() : null; $details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . implode(',', $recipients) . ")"); $recip_list = array(); if ($details) { foreach ($details as $d) { $recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')'; if ($private) { $env_recips[] = array('guid' => $d['xchan_guid'], 'guid_sig' => $d['xchan_guid_sig'], 'hash' => $d['xchan_hash']); } if ($d['xchan_network'] === 'mail' && $normal_mode) { $delivery_options = get_xconfig($d['xchan_hash'], 'system', 'delivery_mode'); if (!$delivery_options) { format_and_send_email($channel, $d, $target_item); } } } } $narr = array('channel' => $channel, 'env_recips' => $env_recips, 'packet_recips' => $packet_recips, 'recipients' => $recipients, 'item' => $item, 'target_item' => $target_item, 'top_level_post' => $top_level_post, 'private' => $private, 'followup' => $followup, 'relay_to_owner' => $relay_to_owner, 'uplink' => $uplink, 'cmd' => $cmd, 'mail' => $mail, 'location' => $location, 'request' => $request, 'normal_mode' => $normal_mode, 'packet_type' => $packet_type, 'walltowall' => $walltowall, 'queued' => array()); call_hooks('notifier_process', $narr); if ($narr['queued']) { foreach ($narr['queued'] as $pq) { $deliveries[] = $pq; } } if ($private && !$env_recips) { // shouldn't happen logger('notifier: private message with no envelope recipients.' . print_r($argv, true), LOGGER_NORMAL, LOG_NOTICE); } logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list, true), LOGGER_DEBUG); // Now we have collected recipients (except for external mentions, FIXME) // Let's reduce this to a set of hubs. $r = q("select * from hubloc where hubloc_hash in (" . implode(',', $recipients) . ") \n\t\tand hubloc_error = 0 and hubloc_deleted = 0"); if (!$r) { logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE); return; } $hubs = $r; /** * Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, since it may have been * a re-install which has not yet been detected and pruned. * For other networks which don't have or require sitekeys, we'll have to use the URL */ $hublist = array(); // this provides an easily printable list for the logs $dhubs = array(); // delivery hubs where we store our resulting unique array $keys = array(); // array of keys to check uniquness for zot hubs $urls = array(); // array of urls to check uniqueness of hubs from other networks foreach ($hubs as $hub) { if (in_array($hub['hubloc_url'], $dead_hubs)) { logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG, LOG_INFO); continue; } if ($hub['hubloc_network'] == 'zot') { if (!in_array($hub['hubloc_sitekey'], $keys)) { $hublist[] = $hub['hubloc_host']; $dhubs[] = $hub; $keys[] = $hub['hubloc_sitekey']; } } else { if (!in_array($hub['hubloc_url'], $urls)) { $hublist[] = $hub['hubloc_host']; $dhubs[] = $hub; $urls[] = $hub['hubloc_url']; } } } logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist, true), LOGGER_DEBUG, LOG_DEBUG); foreach ($dhubs as $hub) { if ($hub['hubloc_network'] !== 'zot') { $narr = array('channel' => $channel, 'env_recips' => $env_recips, 'packet_recips' => $packet_recips, 'recipients' => $recipients, 'item' => $item, 'target_item' => $target_item, 'hub' => $hub, 'top_level_post' => $top_level_post, 'private' => $private, 'followup' => $followup, 'relay_to_owner' => $relay_to_owner, 'uplink' => $uplink, 'cmd' => $cmd, 'mail' => $mail, 'location' => $location, 'request' => $request, 'normal_mode' => $normal_mode, 'packet_type' => $packet_type, 'walltowall' => $walltowall, 'queued' => array()); call_hooks('notifier_hub', $narr); if ($narr['queued']) { foreach ($narr['queued'] as $pq) { $deliveries[] = $pq; } } continue; } // default: zot protocol $hash = random_string(); $packet = null; if ($packet_type === 'refresh' || $packet_type === 'purge') { $packet = zot_build_packet($channel, $packet_type, $packet_recips ? $packet_recips : null); } elseif ($packet_type === 'request') { $packet = zot_build_packet($channel, $packet_type, $env_recips, $hub['hubloc_sitekey'], $hash, array('message_id' => $request_message_id)); } if ($packet) { queue_insert(array('hash' => $hash, 'account_id' => $channel['channel_account_id'], 'channel_id' => $channel['channel_id'], 'posturl' => $hub['hubloc_callback'], 'notify' => $packet)); } else { $packet = zot_build_packet($channel, 'notify', $env_recips, $private ? $hub['hubloc_sitekey'] : null, $hash); queue_insert(array('hash' => $hash, 'account_id' => $target_item['aid'], 'channel_id' => $target_item['uid'], 'posturl' => $hub['hubloc_callback'], 'notify' => $packet, 'msg' => json_encode($encoded_item))); // only create delivery reports for normal undeleted items if (is_array($target_item) && array_key_exists('postopts', $target_item) && !$target_item['item_deleted'] && !get_config('system', 'disable_dreport')) { q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ", dbesc($target_item['mid']), dbesc($hub['hubloc_host']), dbesc($hub['hubloc_host']), dbesc('queued'), dbesc(datetime_convert()), dbesc($channel['channel_hash']), dbesc($hash)); } } $deliveries[] = $hash; } if ($normal_mode) { $x = q("select * from hook where hook = 'notifier_normal'"); if ($x) { proc_run('php', 'include/deliver_hooks.php', $target_item['id']); } } if ($deliveries) { do_delivery($deliveries); } logger('notifier: basic loop complete.', LOGGER_DEBUG); call_hooks('notifier_end', $target_item); logger('notifer: complete.'); return; }