function profile_photo_post(&$a) { if (!local_channel()) { return; } check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); if (x($_POST, 'cropfinal') && $_POST['cropfinal'] == 1) { // unless proven otherwise $is_default_profile = 1; if ($_REQUEST['profile']) { $r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1", intval($_REQUEST['profile']), intval(local_channel())); if ($r) { $profile = $r[0]; if (!intval($profile['is_default'])) { $is_default_profile = 0; } } } // phase 2 - we have finished cropping if (argc() != 2) { notice(t('Image uploaded but image cropping failed.') . EOL); return; } $image_id = argv(1); if (substr($image_id, -2, 1) == '-') { $scale = substr($image_id, -1, 1); $image_id = substr($image_id, 0, -2); } $srcX = $_POST['xstart']; $srcY = $_POST['ystart']; $srcW = $_POST['xfinal'] - $srcX; $srcH = $_POST['yfinal'] - $srcY; $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND scale = %d LIMIT 1", dbesc($image_id), dbesc(local_channel()), intval($scale)); if ($r) { $base_image = $r[0]; $base_image['data'] = $r[0]['os_storage'] ? @file_get_contents($base_image['data']) : dbunescbin($base_image['data']); $im = photo_factory($base_image['data'], $base_image['type']); if ($im->is_valid()) { $im->cropImage(300, $srcX, $srcY, $srcW, $srcH); $aid = get_account_id(); $p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'], 'filename' => $base_image['filename'], 'album' => t('Profile Photos')); $p['scale'] = 4; $p['photo_usage'] = $is_default_profile ? PHOTO_PROFILE : PHOTO_NORMAL; $r1 = $im->save($p); $im->scaleImage(80); $p['scale'] = 5; $r2 = $im->save($p); $im->scaleImage(48); $p['scale'] = 6; $r3 = $im->save($p); if ($r1 === false || $r2 === false || $r3 === false) { // if one failed, delete them all so we can start over. notice(t('Image resize failed.') . EOL); $x = q("delete from photo where resource_id = '%s' and uid = %d and scale >= 4 ", dbesc($base_image['resource_id']), local_channel()); return; } $channel = App::get_channel(); // If setting for the default profile, unset the profile photo flag from any other photos I own if ($is_default_profile) { $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d\n\t\t\t\t\t\tAND resource_id != '%s' AND `uid` = %d", intval(PHOTO_NORMAL), intval(PHOTO_PROFILE), dbesc($base_image['resource_id']), intval(local_channel())); send_profile_photo_activity($channel, $base_image, $profile); } else { $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-4'), dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-5'), intval($_REQUEST['profile']), intval(local_channel())); } profiles_build_sync(local_channel()); // We'll set the updated profile-photo timestamp even if it isn't the default profile, // so that browsers will do a cache update unconditionally $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s' \n\t\t\t\t\twhere xchan_hash = '%s'", dbesc($im->getType()), dbesc(datetime_convert()), dbesc($channel['xchan_hash'])); info(t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL); // Update directory in background proc_run('php', "include/directory.php", $channel['channel_id']); // Now copy profile-permissions to pictures, to prevent privacyleaks by automatically created folder 'Profile Pictures' profile_photo_set_profile_perms($_REQUEST['profile']); } else { notice(t('Unable to process image') . EOL); } } goaway(z_root() . '/profiles'); return; // NOTREACHED } $hash = photo_new_resource(); $smallest = 0; require_once 'include/attach.php'; $res = attach_store(App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash)); logger('attach_store: ' . print_r($res, true)); if ($res && intval($res['data']['is_photo'])) { $i = q("select * from photo where resource_id = '%s' and uid = %d order by scale", dbesc($hash), intval(local_channel())); if (!$i) { notice(t('Image upload failed.') . EOL); return; } $os_storage = false; foreach ($i as $ii) { if (intval($ii['scale']) < 2) { $smallest = intval($ii['scale']); $os_storage = intval($ii['os_storage']); $imagedata = $ii['data']; $filetype = $ii['type']; } } } $imagedata = $os_storage ? @file_get_contents($imagedata) : $imagedata; $ph = photo_factory($imagedata, $filetype); if (!$ph->is_valid()) { notice(t('Unable to process image.') . EOL); return; } return profile_photo_crop_ui_head($a, $ph, $hash, $smallest); }
function init() { nav_set_selected('profiles'); if (!local_channel()) { return; } if (argc() > 2 && argv(1) === "drop" && intval(argv(2))) { $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is_default` = 0 LIMIT 1", intval(argv(2)), intval(local_channel())); if (!count($r)) { notice(t('Profile not found.') . EOL); goaway(z_root() . '/profiles'); return; // NOTREACHED } $profile_guid = $r['profile_guid']; check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't'); // move every contact using this profile as their default to the user default $r = q("UPDATE abook SET abook_profile = (SELECT profile_guid AS FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1) WHERE abook_profile = '%s' AND abook_channel = %d ", intval(local_channel()), dbesc($profile_guid), intval(local_channel())); $r = q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d", intval(argv(2)), intval(local_channel())); if ($r) { info(t('Profile deleted.') . EOL); } // @fixme this is a much more complicated sync - add any changed abook entries and // also add deleted flag to profile structure // profiles_build_sync is just here as a placeholder - it doesn't work at all here // profiles_build_sync(local_channel()); goaway(z_root() . '/profiles'); return; // NOTREACHED } if (argc() > 1 && argv(1) === 'new') { // check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't'); $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_channel())); $num_profiles = count($r0); $name = t('Profile-') . ($num_profiles + 1); $r1 = q("SELECT `fullname`, `photo`, `thumb` FROM `profile` WHERE `uid` = %d AND `is_default` = 1 LIMIT 1", intval(local_channel())); $r2 = q("INSERT INTO `profile` (`aid`, `uid` , `profile_guid`, `profile_name` , `fullname`, `photo`, `thumb`)\n\t\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s' )", intval(get_account_id()), intval(local_channel()), dbesc(random_string()), dbesc($name), dbesc($r1[0]['fullname']), dbesc($r1[0]['photo']), dbesc($r1[0]['thumb'])); $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile_name` = '%s' LIMIT 1", intval(local_channel()), dbesc($name)); info(t('New profile created.') . EOL); if (count($r3) == 1) { goaway(z_root() . '/profiles/' . $r3[0]['id']); } goaway(z_root() . '/profiles'); } if (argc() > 2 && argv(1) === 'clone') { check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't'); $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_channel())); $num_profiles = count($r0); $name = t('Profile-') . ($num_profiles + 1); $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval(local_channel()), intval(\App::$argv[2])); if (!count($r1)) { notice(t('Profile unavailable to clone.') . EOL); \App::$error = 404; return; } unset($r1[0]['id']); $r1[0]['is_default'] = 0; $r1[0]['publish'] = 0; $r1[0]['profile_name'] = dbesc($name); $r1[0]['profile_guid'] = dbesc(random_string()); dbesc_array($r1[0]); $r2 = dbq("INSERT INTO `profile` (`" . implode("`, `", array_keys($r1[0])) . "`) VALUES ('" . implode("', '", array_values($r1[0])) . "')"); $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile_name` = '%s' LIMIT 1", intval(local_channel()), dbesc($name)); info(t('New profile created.') . EOL); profiles_build_sync(local_channel()); if ($r3 && count($r3) == 1) { goaway(z_root() . '/profiles/' . $r3[0]['id']); } goaway(z_root() . '/profiles'); return; // NOTREACHED } if (argc() > 2 && argv(1) === 'export') { $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval(local_channel()), intval(argv(2))); if (!$r1) { notice(t('Profile unavailable to export.') . EOL); \App::$error = 404; return; } header('content-type: application/octet_stream'); header('content-disposition: attachment; filename="' . $r1[0]['profile_name'] . '.json"'); unset($r1[0]['id']); unset($r1[0]['aid']); unset($r1[0]['uid']); unset($r1[0]['is_default']); unset($r1[0]['publish']); unset($r1[0]['profile_name']); unset($r1[0]['profile_guid']); echo json_encode($r1[0]); killme(); } // Run profile_load() here to make sure the theme is set before // we start loading content if (argc() > 1 && intval(argv(1)) || !feature_enabled(local_channel(), 'multi_profiles')) { if (feature_enabled(local_channel(), 'multi_profiles')) { $id = \App::$argv[1]; } else { $x = q("select id from profile where uid = %d and is_default = 1", intval(local_channel())); if ($x) { $id = $x[0]['id']; } } $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($id), intval(local_channel())); if (!count($r)) { notice(t('Profile not found.') . EOL); \App::$error = 404; return; } $chan = \App::get_channel(); profile_load($chan['channel_address'], $r[0]['id']); } }