function privacy_image_cache_init()
{
    $urlhash = 'pic:' . sha1($_REQUEST['url']);
    $r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' LIMIT 1", $urlhash);
    if (count($r)) {
        $img_str = $r[0]['data'];
        $mime = $r[0]["desc"];
        if ($mime == "") {
            $mime = "image/jpeg";
        }
    } else {
        require_once "Photo.php";
        $img_str = fetch_url($_REQUEST['url'], true);
        if (substr($img_str, 0, 6) == "GIF89a") {
            $mime = "image/gif";
            $image = @imagecreatefromstring($img_str);
            if ($image === FALSE) {
                die;
            }
            q("INSERT INTO `photo`\n\t\t\t( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, `album`, `height`, `width`, `desc`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' )", 0, 0, get_guid(), dbesc($urlhash), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(basename(dbesc($_REQUEST["url"]))), dbesc(''), intval(imagesy($image)), intval(imagesx($image)), 'image/gif', dbesc($img_str), 100, intval(0), dbesc(''), dbesc(''), dbesc(''), dbesc(''));
        } else {
            $img = new Photo($img_str);
            if ($img->is_valid()) {
                $img->store(0, 0, $urlhash, $_REQUEST['url'], '', 100);
                $img_str = $img->imageString();
            }
            $mime = "image/jpeg";
        }
    }
    header("Content-type: {$mime}");
    header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600 * 24) . " GMT");
    header("Cache-Control: max-age=" . 3600 * 24);
    echo $img_str;
    killme();
}
Exemple #2
0
	public function gen_vs($name) {
		$this->name = strtolower($name);
		$this->projects = array();

		foreach(array("lib", "dll", "util") as $type) {
			$name = "{$this->name}_{$type}";
			$this->projects[$type] = array("name"=>$name, "guid"=>get_guid($name));
		}

		$this->include_dirs = array("./", "../app/include", "../app/extensions", "../framework/include", "../framework/driver", "../framework/driver/x86");
	}
Exemple #3
0
function terminate_friendship($user, $self, $contact)
{
    $a = get_app();
    require_once 'include/datetime.php';
    if ($contact['network'] === NETWORK_OSTATUS) {
        $slap = replace_macros(get_markup_template('follow_slap.tpl'), array('$name' => $user['username'], '$profile_page' => $a->get_baseurl() . '/profile/' . $user['nickname'], '$photo' => $self['photo'], '$thumb' => $self['thumb'], '$published' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME), '$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':unfollow:' . get_guid(32), '$title' => '', '$type' => 'text', '$content' => t('stopped following'), '$nick' => $user['nickname'], '$verb' => 'http://ostatus.org/schema/1.0/unfollow', '$ostat_follow' => ''));
        if (x($contact, 'notify') && strlen($contact['notify'])) {
            require_once 'include/salmon.php';
            slapper($user, $contact['notify'], $slap);
        }
    } elseif ($contact['network'] === NETWORK_DIASPORA) {
        require_once 'include/diaspora.php';
        diaspora_unshare($user, $contact);
    } elseif ($contact['network'] === NETWORK_DFRN) {
        require_once 'include/items.php';
        dfrn_deliver($user, $contact, 'placeholder', 1);
    }
}
Exemple #4
0
 /**
  * Save Business Unit
  *
  * @return void
  * @author
  **/
 function save_business_unit()
 {
     $out = array();
     if (!$_POST) {
         $out['error'] = 'No data';
     } elseif (isset($_POST['unitid'])) {
         $business_unit = new Business_unit();
         // Translate groups to single entries
         $translate = array('keys' => 'key', 'machine_groups' => 'machine_group', 'users' => 'user', 'managers' => 'manager');
         $unitid = $_POST['unitid'];
         // Check if new unit
         if ($unitid == 'new') {
             $unitid = $business_unit->get_max_unitid() + 1;
         }
         $out['unitid'] = $unitid;
         // Check if there are changed items
         if (isset($_POST['iteminfo'])) {
             $groups = array();
             // If sent a '#', no items are in the iteminfo array
             // proceed with empty groups array
             if (!in_array('#', $_POST['iteminfo'])) {
                 // Loop through iteminfo
                 foreach ($_POST['iteminfo'] as $entry) {
                     // No key, create new
                     if ($entry['key'] === '') {
                         $mg = new Machine_group();
                         $newgroup = $mg->get_max_groupid() + 1;
                         // Store name
                         $mg->merge(array('id' => '', 'groupid' => $newgroup, 'property' => 'name', 'value' => $entry['name']));
                         $mg->save();
                         // Store GUID key
                         $mg->merge(array('id' => '', 'groupid' => $newgroup, 'property' => 'key', 'value' => get_guid()));
                         $mg->save();
                         $groups[] = $newgroup;
                     } else {
                         // Add key to list
                         $groups[] = intval($entry['key']);
                     }
                 }
             }
             // Set new machine_groups to list
             $_POST['machine_groups'] = $groups;
             unset($_POST['iteminfo']);
         }
         foreach ($_POST as $property => $val) {
             // Skip unitid
             if ($property == 'unitid') {
                 continue;
             }
             if (is_scalar($val)) {
                 $business_unit->id = '';
                 $business_unit->retrieve_one('unitid=? AND property=?', array($unitid, $property));
                 $business_unit->unitid = $unitid;
                 $business_unit->property = $property;
                 $business_unit->value = $val;
                 $business_unit->save();
                 $out[$property] = $val;
             } else {
                 // Check if this is a valid property
                 if (!isset($translate[$property])) {
                     $out['error'][] = 'Illegal property: ' . $property;
                     continue;
                 }
                 // Translate property to db entry
                 $name = $translate[$property];
                 $business_unit->delete_where('unitid=? AND property=?', array($unitid, $name));
                 foreach ($val as $entry) {
                     // Empty array placeholder
                     if ($entry === '#') {
                         $out[$property] = array();
                         continue;
                     }
                     $business_unit->id = '';
                     $business_unit->unitid = $unitid;
                     $business_unit->property = $name;
                     $business_unit->value = is_numeric($entry) ? 0 + $entry : $entry;
                     $business_unit->save();
                     $out[$property][] = is_numeric($entry) ? 0 + $entry : $entry;
                 }
             }
         }
     } else {
         $out['error'] = 'Unitid missing';
     }
     $obj = new View();
     $obj->view('json', array('msg' => $out));
 }
Exemple #5
0
 /**
  * Get's the splash-only user.
  *
  * This is the user that people logged-in at a splash-only hotspot will
  * show up as.  This user always has multiple-login capabilities.
  *
  * @param string $username The username of the user
  * @param string $account_origin The account origin
  *
  * @return object A User object
  *
  * @access public
  */
 public function getSplashOnlyUser()
 {
     $username = '******';
     if (!empty($this->splashOnlyUser)) {
         $user = $this->splashOnlyUser;
     } else {
         $user = User::getUserByUsernameAndOrigin($username, $this);
         if (!$user) {
             $user = User::createUser(get_guid(), $username, $this, '', '');
             $user->setAccountStatus(ACCOUNT_STATUS_ALLOWED);
         }
         $this->splashOnlyUser = $user;
     }
     return $user;
 }
Exemple #6
0
function new_contact($uid, $url, $interactive = false)
{
    $result = array('cid' => -1, 'success' => false, 'message' => '');
    $a = get_app();
    // remove ajax junk, e.g. Twitter
    $url = str_replace('/#!/', '/', $url);
    if (!allowed_url($url)) {
        $result['message'] = t('Disallowed profile URL.');
        return $result;
    }
    if (!$url) {
        $result['message'] = t('Connect URL missing.');
        return $result;
    }
    $arr = array('url' => $url, 'contact' => array());
    call_hooks('follow', $arr);
    if (x($arr['contact'], 'name')) {
        $ret = $arr['contact'];
    } else {
        $ret = probe_url($url);
    }
    if ($ret['network'] === NETWORK_DFRN) {
        if ($interactive) {
            if (strlen($a->path)) {
                $myaddr = bin2hex($a->get_baseurl() . '/profile/' . $a->user['nickname']);
            } else {
                $myaddr = bin2hex($a->user['nickname'] . '@' . $a->get_hostname());
            }
            goaway($ret['request'] . "&addr={$myaddr}");
            // NOTREACHED
        }
    } else {
        if (get_config('system', 'dfrn_only')) {
            $result['message'] = t('This site is not configured to allow communications with other networks.') . EOL;
            $result['message'] != t('No compatible communication protocols or feeds were discovered.') . EOL;
            return $result;
        }
    }
    // This extra param just confuses things, remove it
    if ($ret['network'] === NETWORK_DIASPORA) {
        $ret['url'] = str_replace('?absolute=true', '', $ret['url']);
    }
    // do we have enough information?
    if (!(x($ret, 'name') && x($ret, 'poll') && (x($ret, 'url') || x($ret, 'addr')))) {
        $result['message'] .= t('The profile address specified does not provide adequate information.') . EOL;
        if (!x($ret, 'poll')) {
            $result['message'] .= t('No compatible communication protocols or feeds were discovered.') . EOL;
        }
        if (!x($ret, 'name')) {
            $result['message'] .= t('An author or name was not found.') . EOL;
        }
        if (!x($ret, 'url')) {
            $result['message'] .= t('No browser URL could be matched to this address.') . EOL;
        }
        if (strpos($url, '@') !== false) {
            $result['message'] .= t('Unable to match @-style Identity Address with a known protocol or email contact.') . EOL;
            $result['message'] .= t('Use mailto: in front of address to force email check.') . EOL;
        }
        return $result;
    }
    if ($ret['network'] === NETWORK_OSTATUS && get_config('system', 'ostatus_disabled')) {
        $result['message'] .= t('The profile address specified belongs to a network which has been disabled on this site.') . EOL;
        $ret['notify'] = '';
    }
    if (!$ret['notify']) {
        $result['message'] .= t('Limited profile. This person will be unable to receive direct/personal notifications from you.') . EOL;
    }
    $writeable = $ret['network'] === NETWORK_OSTATUS && $ret['notify'] ? 1 : 0;
    $subhub = $ret['network'] === NETWORK_OSTATUS ? true : false;
    $hidden = $ret['network'] === NETWORK_MAIL ? 1 : 0;
    if ($ret['network'] === NETWORK_MAIL) {
        $writeable = 1;
    }
    if ($ret['network'] === NETWORK_DIASPORA) {
        $writeable = 1;
    }
    // check if we already have a contact
    // the poll url is more reliable than the profile url, as we may have
    // indirect links or webfinger links
    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` IN ('%s', '%s') AND `network` = '%s' LIMIT 1", intval($uid), dbesc($ret['poll']), dbesc(normalise_link($ret['poll'])), dbesc($ret['network']));
    if (!count($r)) {
        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` = '%s' LIMIT 1", intval($uid), dbesc(normalise_link($url)), dbesc($ret['network']));
    }
    if (count($r)) {
        // update contact
        if ($r[0]['rel'] == CONTACT_IS_FOLLOWER || $network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING) {
            q("UPDATE `contact` SET `rel` = %d , `subhub` = %d, `readonly` = 0 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($subhub), intval($r[0]['id']), intval($uid));
        }
    } else {
        // check service class limits
        $r = q("select count(*) as total from contact where uid = %d and pending = 0 and self = 0", intval($uid));
        if (count($r)) {
            $total_contacts = $r[0]['total'];
        }
        if (!service_class_allows($uid, 'total_contacts', $total_contacts)) {
            $result['message'] .= upgrade_message();
            return $result;
        }
        $r = q("select count(network) as total from contact where uid = %d and network = '%s' and pending = 0 and self = 0", intval($uid), dbesc($network));
        if (count($r)) {
            $total_network = $r[0]['total'];
        }
        if (!service_class_allows($uid, 'total_contacts_' . $network, $total_network)) {
            $result['message'] .= upgrade_message();
            return $result;
        }
        $new_relation = $ret['network'] === NETWORK_MAIL ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING;
        if ($ret['network'] === NETWORK_DIASPORA) {
            $new_relation = CONTACT_IS_FOLLOWER;
        }
        // create contact record
        $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `name`, `nick`, `network`, `pubkey`, `rel`, `priority`,\n\t\t\t`writable`, `hidden`, `blocked`, `readonly`, `pending`, `subhub` )\n\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, 0, 0, 0, %d ) ", intval($uid), dbesc(datetime_convert()), dbesc($ret['url']), dbesc(normalise_link($ret['url'])), dbesc($ret['addr']), dbesc($ret['alias']), dbesc($ret['batch']), dbesc($ret['notify']), dbesc($ret['poll']), dbesc($ret['poco']), dbesc($ret['name']), dbesc($ret['nick']), dbesc($ret['network']), dbesc($ret['pubkey']), intval($new_relation), intval($ret['priority']), intval($writeable), intval($hidden), intval($subhub));
    }
    $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1", dbesc($ret['url']), dbesc($ret['network']), intval($uid));
    if (!count($r)) {
        $result['message'] .= t('Unable to retrieve contact information.') . EOL;
        return $result;
    }
    $contact = $r[0];
    $contact_id = $r[0]['id'];
    $result['cid'] = $contact_id;
    $g = q("select def_gid from user where uid = %d limit 1", intval($uid));
    if ($g && intval($g[0]['def_gid'])) {
        require_once 'include/group.php';
        group_add_member($uid, '', $contact_id, $g[0]['def_gid']);
    }
    require_once "include/Photo.php";
    $photos = import_profile_photo($ret['photo'], $uid, $contact_id);
    $r = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id));
    // pull feed and consume it, which should subscribe to the hub.
    proc_run('php', "include/onepoll.php", "{$contact_id}", "force");
    // create a follow slap
    $tpl = get_markup_template('follow_slap.tpl');
    $slap = replace_macros($tpl, array('$name' => $a->user['username'], '$profile_page' => $a->get_baseurl() . '/profile/' . $a->user['nickname'], '$photo' => $a->contact['photo'], '$thumb' => $a->contact['thumb'], '$published' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME), '$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . get_guid(32), '$title' => '', '$type' => 'text', '$content' => t('following'), '$nick' => $a->user['nickname'], '$verb' => ACTIVITY_FOLLOW, '$ostat_follow' => ''));
    $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", intval($uid));
    if (count($r)) {
        if ($contact['network'] == NETWORK_OSTATUS && strlen($contact['notify'])) {
            require_once 'include/salmon.php';
            slapper($r[0], $contact['notify'], $slap);
        }
        if ($contact['network'] == NETWORK_DIASPORA) {
            require_once 'include/diaspora.php';
            $ret = diaspora_share($a->user, $contact);
            logger('mod_follow: diaspora_share returns: ' . $ret);
        }
    }
    $result['success'] = true;
    return $result;
}
Exemple #7
0
function item_is_remote_self($contact, &$datarray)
{
    $a = get_app();
    if (!$contact['remote_self']) {
        return false;
    }
    // Prevent the forwarding of posts that are forwarded
    if ($datarray["extid"] == NETWORK_DFRN) {
        return false;
    }
    // Prevent to forward already forwarded posts
    if ($datarray["app"] == $a->get_hostname()) {
        return false;
    }
    // Only forward posts
    if ($datarray["verb"] != ACTIVITY_POST) {
        return false;
    }
    if ($contact['network'] != NETWORK_FEED and $datarray['private']) {
        return false;
    }
    $datarray2 = $datarray;
    logger('remote-self start - Contact ' . $contact['url'] . ' - ' . $contact['remote_self'] . ' Item ' . print_r($datarray, true), LOGGER_DEBUG);
    if ($contact['remote_self'] == 2) {
        $r = q("SELECT `id`,`url`,`name`,`thumb` FROM `contact` WHERE `uid` = %d AND `self`", intval($contact['uid']));
        if (count($r)) {
            $datarray['contact-id'] = $r[0]["id"];
            $datarray['owner-name'] = $r[0]["name"];
            $datarray['owner-link'] = $r[0]["url"];
            $datarray['owner-avatar'] = $r[0]["thumb"];
            $datarray['author-name'] = $datarray['owner-name'];
            $datarray['author-link'] = $datarray['owner-link'];
            $datarray['author-avatar'] = $datarray['owner-avatar'];
        }
        if ($contact['network'] != NETWORK_FEED) {
            $datarray["guid"] = get_guid(32);
            unset($datarray["plink"]);
            $datarray["uri"] = item_new_uri($a->get_hostname(), $contact['uid'], $datarray["guid"]);
            $datarray["parent-uri"] = $datarray["uri"];
            $datarray["extid"] = $contact['network'];
            $urlpart = parse_url($datarray2['author-link']);
            $datarray["app"] = $urlpart["host"];
        } else {
            $datarray['private'] = 0;
        }
    }
    if ($contact['network'] != NETWORK_FEED) {
        // Store the original post
        $r = item_store($datarray2, false, false);
        logger('remote-self post original item - Contact ' . $contact['url'] . ' return ' . $r . ' Item ' . print_r($datarray2, true), LOGGER_DEBUG);
    } else {
        $datarray["app"] = "Feed";
    }
    return true;
}
Exemple #8
0
function item_post(&$a)
{
    if (!local_user() && !remote_user() && !x($_REQUEST, 'commenter')) {
        return;
    }
    require_once 'include/security.php';
    $uid = local_user();
    if (x($_REQUEST, 'dropitems')) {
        $arr_drop = explode(',', $_REQUEST['dropitems']);
        drop_items($arr_drop);
        $json = array('success' => 1);
        echo json_encode($json);
        killme();
    }
    call_hooks('post_local_start', $_REQUEST);
    //	logger('postinput ' . file_get_contents('php://input'));
    logger('postvars ' . print_r($_REQUEST, true), LOGGER_DATA);
    $api_source = x($_REQUEST, 'api_source') && $_REQUEST['api_source'] ? true : false;
    $message_id = x($_REQUEST, 'message_id') && $api_source ? strip_tags($_REQUEST['message_id']) : '';
    $return_path = x($_REQUEST, 'return') ? $_REQUEST['return'] : '';
    $preview = x($_REQUEST, 'preview') ? intval($_REQUEST['preview']) : 0;
    // Check for doubly-submitted posts, and reject duplicates
    // Note that we have to ignore previews, otherwise nothing will post
    // after it's been previewed
    if (!$preview && x($_REQUEST['post_id_random'])) {
        if (x($_SESSION['post-random']) && $_SESSION['post-random'] == $_REQUEST['post_id_random']) {
            logger("item post: duplicate post", LOGGER_DEBUG);
            item_post_return($a->get_baseurl(), $api_source, $return_path);
        } else {
            $_SESSION['post-random'] = $_REQUEST['post_id_random'];
        }
    }
    /**
     * Is this a reply to something?
     */
    $parent = x($_REQUEST, 'parent') ? intval($_REQUEST['parent']) : 0;
    $parent_uri = x($_REQUEST, 'parent_uri') ? trim($_REQUEST['parent_uri']) : '';
    $parent_item = null;
    $parent_contact = null;
    $thr_parent = '';
    $parid = 0;
    $r = false;
    $objecttype = null;
    if ($parent || $parent_uri) {
        $objecttype = ACTIVITY_OBJ_COMMENT;
        if (!x($_REQUEST, 'type')) {
            $_REQUEST['type'] = 'net-comment';
        }
        if ($parent) {
            $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent));
        } elseif ($parent_uri && local_user()) {
            // This is coming from an API source, and we are logged in
            $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_uri), intval(local_user()));
        }
        // if this isn't the real parent of the conversation, find it
        if ($r !== false && count($r)) {
            $parid = $r[0]['parent'];
            $parent_uri = $r[0]['uri'];
            if ($r[0]['id'] != $r[0]['parent']) {
                $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid));
            }
        }
        if ($r === false || !count($r)) {
            notice(t('Unable to locate original post.') . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
        $parent_item = $r[0];
        $parent = $r[0]['id'];
        // multi-level threading - preserve the info but re-parent to our single level threading
        //if(($parid) && ($parid != $parent))
        $thr_parent = $parent_uri;
        if ($parent_item['contact-id'] && $uid) {
            $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($parent_item['contact-id']), intval($uid));
            if (count($r)) {
                $parent_contact = $r[0];
                // If the contact id doesn't fit with the contact, then set the contact to null
                $thrparent = q("SELECT `author-link`, `network` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($thr_parent));
                if (count($thrparent) and $thrparent[0]["network"] === NETWORK_OSTATUS and normalise_link($parent_contact["url"]) != normalise_link($thrparent[0]["author-link"])) {
                    $parent_contact = null;
                    require_once "include/Scrape.php";
                    $probed_contact = probe_url($thrparent[0]["author-link"]);
                    if ($probed_contact["network"] != NETWORK_FEED) {
                        $parent_contact = $probed_contact;
                        $parent_contact["nurl"] = normalise_link($probed_contact["url"]);
                        $parent_contact["thumb"] = $probed_contact["photo"];
                        $parent_contact["micro"] = $probed_contact["photo"];
                    }
                    logger('parent contact: ' . print_r($parent_contact, true), LOGGER_DEBUG);
                } else {
                    logger('no contact found: ' . print_r($thrparent, true), LOGGER_DEBUG);
                }
            }
        }
    }
    if ($parent) {
        logger('mod_item: item_post parent=' . $parent);
    }
    $profile_uid = x($_REQUEST, 'profile_uid') ? intval($_REQUEST['profile_uid']) : 0;
    $post_id = x($_REQUEST, 'post_id') ? intval($_REQUEST['post_id']) : 0;
    $app = x($_REQUEST, 'source') ? strip_tags($_REQUEST['source']) : '';
    $extid = x($_REQUEST, 'extid') ? strip_tags($_REQUEST['extid']) : '';
    $allow_moderated = false;
    // here is where we are going to check for permission to post a moderated comment.
    // First check that the parent exists and it is a wall item.
    if (x($_REQUEST, 'commenter') && (!$parent || !$parent_item['wall'])) {
        notice(t('Permission denied.') . EOL);
        if (x($_REQUEST, 'return')) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    }
    // Now check that it is a page_type of PAGE_BLOG, and that valid personal details
    // have been provided, and run any anti-spam plugins
    // TODO
    if (!can_write_wall($a, $profile_uid) && !$allow_moderated) {
        notice(t('Permission denied.') . EOL);
        if (x($_REQUEST, 'return')) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    }
    // is this an edited post?
    $orig_post = null;
    if ($post_id) {
        $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id));
        if (!count($i)) {
            killme();
        }
        $orig_post = $i[0];
    }
    $user = null;
    $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid));
    if (count($r)) {
        $user = $r[0];
    }
    if ($orig_post) {
        $str_group_allow = $orig_post['allow_gid'];
        $str_contact_allow = $orig_post['allow_cid'];
        $str_group_deny = $orig_post['deny_gid'];
        $str_contact_deny = $orig_post['deny_cid'];
        $location = $orig_post['location'];
        $coord = $orig_post['coord'];
        $verb = $orig_post['verb'];
        $objecttype = $orig_post['object-type'];
        $emailcc = $orig_post['emailcc'];
        $app = $orig_post['app'];
        $categories = $orig_post['file'];
        $title = notags(trim($_REQUEST['title']));
        $body = escape_tags(trim($_REQUEST['body']));
        $private = $orig_post['private'];
        $pubmail_enable = $orig_post['pubmail'];
        $network = $orig_post['network'];
        $guid = $orig_post['guid'];
        $extid = $orig_post['extid'];
    } else {
        // if coming from the API and no privacy settings are set,
        // use the user default permissions - as they won't have
        // been supplied via a form.
        if ($api_source && !array_key_exists('contact_allow', $_REQUEST) && !array_key_exists('group_allow', $_REQUEST) && !array_key_exists('contact_deny', $_REQUEST) && !array_key_exists('group_deny', $_REQUEST)) {
            $str_group_allow = $user['allow_gid'];
            $str_contact_allow = $user['allow_cid'];
            $str_group_deny = $user['deny_gid'];
            $str_contact_deny = $user['deny_cid'];
        } else {
            // use the posted permissions
            $str_group_allow = perms2str($_REQUEST['group_allow']);
            $str_contact_allow = perms2str($_REQUEST['contact_allow']);
            $str_group_deny = perms2str($_REQUEST['group_deny']);
            $str_contact_deny = perms2str($_REQUEST['contact_deny']);
        }
        $title = notags(trim($_REQUEST['title']));
        $location = notags(trim($_REQUEST['location']));
        $coord = notags(trim($_REQUEST['coord']));
        $verb = notags(trim($_REQUEST['verb']));
        $emailcc = notags(trim($_REQUEST['emailcc']));
        $body = escape_tags(trim($_REQUEST['body']));
        $network = notags(trim($_REQUEST['network']));
        $guid = get_guid(32);
        $naked_body = preg_replace('/\\[(.+?)\\]/', '', $body);
        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
            $l = new Text_LanguageDetect();
            //$lng = $l->detectConfidence($naked_body);
            //$postopts = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : '');
            $lng = $l->detect($naked_body, 3);
            if (sizeof($lng) > 0) {
                $postopts = "";
                foreach ($lng as $language => $score) {
                    if ($postopts == "") {
                        $postopts = "lang=";
                    } else {
                        $postopts .= ":";
                    }
                    $postopts .= $language . ";" . $score;
                }
            }
            logger('mod_item: detect language' . print_r($lng, true) . $naked_body, LOGGER_DATA);
        } else {
            $postopts = '';
        }
        $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) ? 1 : 0;
        if ($user['hidewall']) {
            $private = 2;
        }
        // If this is a comment, set the permissions from the parent.
        if ($parent_item) {
            $private = 0;
            // for non native networks use the network of the original post as network of the item
            if ($parent_item['network'] != NETWORK_DIASPORA and $parent_item['network'] != NETWORK_OSTATUS and $network == "") {
                $network = $parent_item['network'];
            }
            if ($parent_item['private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid'])) {
                $private = $parent_item['private'] ? $parent_item['private'] : 1;
            }
            $str_contact_allow = $parent_item['allow_cid'];
            $str_group_allow = $parent_item['allow_gid'];
            $str_contact_deny = $parent_item['deny_cid'];
            $str_group_deny = $parent_item['deny_gid'];
        }
        $pubmail_enable = x($_REQUEST, 'pubmail_enable') && intval($_REQUEST['pubmail_enable']) && !$private ? 1 : 0;
        // if using the API, we won't see pubmail_enable - figure out if it should be set
        if ($api_source && $profile_uid && $profile_uid == local_user() && !$private) {
            $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1;
            if (!$mail_disabled) {
                $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user()));
                if (count($r) && intval($r[0]['pubmail'])) {
                    $pubmail_enabled = true;
                }
            }
        }
        if (!strlen($body)) {
            if ($preview) {
                killme();
            }
            info(t('Empty post discarded.') . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
    }
    if (strlen($categories)) {
        // get the "fileas" tags for this post
        $filedas = file_tag_file_to_list($categories, 'file');
    }
    // save old and new categories, so we can determine what needs to be deleted from pconfig
    $categories_old = $categories;
    $categories = file_tag_list_to_file(trim($_REQUEST['category']), 'category');
    $categories_new = $categories;
    if (strlen($filedas)) {
        // append the fileas stuff to the new categories list
        $categories .= file_tag_list_to_file($filedas, 'file');
    }
    // Work around doubled linefeeds in Tinymce 3.5b2
    // First figure out if it's a status post that would've been
    // created using tinymce. Otherwise leave it alone.
    /*	$plaintext = (local_user() ? intval(get_pconfig(local_user(),'system','plaintext')) || !feature_enabled($profile_uid,'richtext') : 0);
    	if((! $parent) && (! $api_source) && (! $plaintext)) {
    		$body = fix_mce_lf($body);
    	}*/
    $plaintext = local_user() ? !feature_enabled($profile_uid, 'richtext') : 0;
    if (!$parent && !$api_source && !$plaintext) {
        $body = fix_mce_lf($body);
    }
    // get contact info for poster
    $author = null;
    $self = false;
    $contact_id = 0;
    if (local_user() && local_user() == $profile_uid) {
        $self = true;
        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($_SESSION['uid']));
    } elseif (remote_user()) {
        if (is_array($_SESSION['remote'])) {
            foreach ($_SESSION['remote'] as $v) {
                if ($v['uid'] == $profile_uid) {
                    $contact_id = $v['cid'];
                    break;
                }
            }
        }
        if ($contact_id) {
            $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id));
        }
    }
    if (count($r)) {
        $author = $r[0];
        $contact_id = $author['id'];
    }
    // get contact info for owner
    if ($profile_uid == local_user()) {
        $contact_record = $author;
    } else {
        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid));
        if (count($r)) {
            $contact_record = $r[0];
        }
    }
    $post_type = notags(trim($_REQUEST['type']));
    if ($post_type === 'net-comment') {
        if ($parent_item !== null) {
            if ($parent_item['wall'] == 1) {
                $post_type = 'wall-comment';
            } else {
                $post_type = 'remote-comment';
            }
        }
    }
    /**
     *
     * When a photo was uploaded into the message using the (profile wall) ajax
     * uploader, The permissions are initially set to disallow anybody but the
     * owner from seeing it. This is because the permissions may not yet have been
     * set for the post. If it's private, the photo permissions should be set
     * appropriately. But we didn't know the final permissions on the post until
     * now. So now we'll look for links of uploaded messages that are in the
     * post and set them to the same permissions as the post itself.
     *
     */
    $match = null;
    if (!$preview && preg_match_all("/\\[img([\\=0-9x]*?)\\](.*?)\\[\\/img\\]/", $body, $match)) {
        $images = $match[2];
        if (count($images)) {
            $objecttype = ACTIVITY_OBJ_IMAGE;
            foreach ($images as $image) {
                if (!stristr($image, $a->get_baseurl() . '/photo/')) {
                    continue;
                }
                $image_uri = substr($image, strrpos($image, '/') + 1);
                $image_uri = substr($image_uri, 0, strpos($image_uri, '-'));
                if (!strlen($image_uri)) {
                    continue;
                }
                $srch = '<' . intval($contact_id) . '>';
                $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''\n\t\t\t\t\tAND `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($srch), dbesc($image_uri), intval($profile_uid));
                if (!count($r)) {
                    continue;
                }
                $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), intval($profile_uid), dbesc(t('Wall Photos')));
            }
        }
    }
    /**
     * Next link in any attachment references we find in the post.
     */
    $match = false;
    if (!$preview && preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", $body, $match)) {
        $attaches = $match[1];
        if (count($attaches)) {
            foreach ($attaches as $attach) {
                $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($attach));
                if (count($r)) {
                    $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\t\tWHERE `uid` = %d AND `id` = %d", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($profile_uid), intval($attach));
                }
            }
        }
    }
    // embedded bookmark in post? set bookmark flag
    $bookmark = 0;
    if (preg_match_all("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/ism", $body, $match, PREG_SET_ORDER)) {
        $objecttype = ACTIVITY_OBJ_BOOKMARK;
        $bookmark = 1;
    }
    $body = bb_translate_video($body);
    /**
     * Fold multi-line [code] sequences
     */
    $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body);
    $body = scale_external_images($body, false);
    // Setting the object type if not defined before
    if (!$objecttype) {
        $objecttype = ACTIVITY_OBJ_NOTE;
        // Default value
        require_once "include/plaintext.php";
        $objectdata = get_attached_data($body);
        if ($post["type"] == "link") {
            $objecttype = ACTIVITY_OBJ_BOOKMARK;
        } elseif ($post["type"] == "video") {
            $objecttype = ACTIVITY_OBJ_VIDEO;
        } elseif ($post["type"] == "photo") {
            $objecttype = ACTIVITY_OBJ_IMAGE;
        }
    }
    /**
     * Look for any tags and linkify them
     */
    $str_tags = '';
    $inform = '';
    $tags = get_tags($body);
    /**
     * add a statusnet style reply tag if the original post was from there
     * and we are replying, and there isn't one already
     */
    if ($parent_contact && $parent_contact['network'] === NETWORK_OSTATUS && $parent_contact['nick'] && !in_array('@' . $parent_contact['nick'], $tags)) {
        $body = '@' . $parent_contact['nick'] . ' ' . $body;
        $tags[] = '@' . $parent_contact['nick'];
    }
    $tagged = array();
    $private_forum = false;
    if (count($tags)) {
        foreach ($tags as $tag) {
            if (strpos($tag, '#') === 0) {
                continue;
            }
            // If we already tagged 'Robert Johnson', don't try and tag 'Robert'.
            // Robert Johnson should be first in the $tags array
            $fullnametagged = false;
            for ($x = 0; $x < count($tagged); $x++) {
                if (stristr($tagged[$x], $tag . ' ')) {
                    $fullnametagged = true;
                    break;
                }
            }
            if ($fullnametagged) {
                continue;
            }
            $success = handle_tag($a, $body, $inform, $str_tags, local_user() ? local_user() : $profile_uid, $tag, $network);
            if ($success['replaced']) {
                $tagged[] = $tag;
            }
            if (is_array($success['contact']) && intval($success['contact']['prv'])) {
                $private_forum = true;
                $private_id = $success['contact']['id'];
            }
        }
    }
    if ($private_forum && !$parent && !$private) {
        // we tagged a private forum in a top level post and the message was public.
        // Restrict it.
        $private = 1;
        $str_contact_allow = '<' . $private_id . '>';
    }
    $attachments = '';
    $match = false;
    if (preg_match_all('/(\\[attachment\\]([0-9]+)\\[\\/attachment\\])/', $body, $match)) {
        foreach ($match[2] as $mtch) {
            $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($mtch));
            if (count($r)) {
                if (strlen($attachments)) {
                    $attachments .= ',';
                }
                $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . ($r[0]['filename'] ? $r[0]['filename'] : '') . '"[/attach]';
            }
            $body = str_replace($match[1], '', $body);
        }
    }
    $wall = 0;
    if ($post_type === 'wall' || $post_type === 'wall-comment') {
        $wall = 1;
    }
    if (!strlen($verb)) {
        $verb = ACTIVITY_POST;
    }
    if ($network == "") {
        $network = NETWORK_DFRN;
    }
    $gravity = $parent ? 6 : 0;
    // even if the post arrived via API we are considering that it
    // originated on this site by default for determining relayability.
    $origin = x($_REQUEST, 'origin') ? intval($_REQUEST['origin']) : 1;
    $notify_type = $parent ? 'comment-new' : 'wall-new';
    $uri = $message_id ? $message_id : item_new_uri($a->get_hostname(), $profile_uid);
    // Fallback so that we alway have a thr-parent
    if (!$thr_parent) {
        $thr_parent = $uri;
    }
    $datarray = array();
    $datarray['uid'] = $profile_uid;
    $datarray['type'] = $post_type;
    $datarray['wall'] = $wall;
    $datarray['gravity'] = $gravity;
    $datarray['network'] = $network;
    $datarray['contact-id'] = $contact_id;
    $datarray['owner-name'] = $contact_record['name'];
    $datarray['owner-link'] = $contact_record['url'];
    $datarray['owner-avatar'] = $contact_record['thumb'];
    $datarray['author-name'] = $author['name'];
    $datarray['author-link'] = $author['url'];
    $datarray['author-avatar'] = $author['thumb'];
    $datarray['created'] = datetime_convert();
    $datarray['edited'] = datetime_convert();
    $datarray['commented'] = datetime_convert();
    $datarray['received'] = datetime_convert();
    $datarray['changed'] = datetime_convert();
    $datarray['extid'] = $extid;
    $datarray['guid'] = $guid;
    $datarray['uri'] = $uri;
    $datarray['title'] = $title;
    $datarray['body'] = $body;
    $datarray['app'] = $app;
    $datarray['location'] = $location;
    $datarray['coord'] = $coord;
    $datarray['tag'] = $str_tags;
    $datarray['file'] = $categories;
    $datarray['inform'] = $inform;
    $datarray['verb'] = $verb;
    $datarray['object-type'] = $objecttype;
    $datarray['allow_cid'] = $str_contact_allow;
    $datarray['allow_gid'] = $str_group_allow;
    $datarray['deny_cid'] = $str_contact_deny;
    $datarray['deny_gid'] = $str_group_deny;
    $datarray['private'] = $private;
    $datarray['pubmail'] = $pubmail_enable;
    $datarray['attach'] = $attachments;
    $datarray['bookmark'] = intval($bookmark);
    $datarray['thr-parent'] = $thr_parent;
    $datarray['postopts'] = $postopts;
    $datarray['origin'] = $origin;
    $datarray['moderated'] = $allow_moderated;
    /**
     * These fields are for the convenience of plugins...
     * 'self' if true indicates the owner is posting on their own wall
     * If parent is 0 it is a top-level post.
     */
    $datarray['parent'] = $parent;
    $datarray['self'] = $self;
    //	$datarray['prvnets']       = $user['prvnets'];
    if ($orig_post) {
        $datarray['edit'] = true;
    }
    // Search for hashtags
    item_body_set_hashtags($datarray);
    // preview mode - prepare the body for display and send it via json
    if ($preview) {
        require_once 'include/conversation.php';
        $o = conversation($a, array(array_merge($contact_record, $datarray)), 'search', false, true);
        logger('preview: ' . $o);
        echo json_encode(array('preview' => $o));
        killme();
    }
    call_hooks('post_local', $datarray);
    if (x($datarray, 'cancel')) {
        logger('mod_item: post cancelled by plugin.');
        if ($return_path) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        $json = array('cancel' => 1);
        if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) {
            $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload'];
        }
        echo json_encode($json);
        killme();
    }
    // Fill the cache field
    put_item_in_cache($datarray);
    if ($orig_post) {
        $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `attach` = '%s', `file` = '%s', `rendered-html` = '%s', `rendered-hash` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc($datarray['attach']), dbesc($datarray['file']), dbesc($datarray['rendered-html']), dbesc($datarray['rendered-hash']), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($post_id), intval($profile_uid));
        create_tags_from_item($post_id);
        create_files_from_item($post_id);
        update_thread($post_id);
        // update filetags in pconfig
        file_tag_update_pconfig($uid, $categories_old, $categories_new, 'category');
        proc_run('php', "include/notifier.php", 'edit_post', "{$post_id}");
        if (x($_REQUEST, 'return') && strlen($return_path)) {
            logger('return: ' . $return_path);
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    } else {
        $post_id = 0;
    }
    $r = q("INSERT INTO `item` (`guid`, `extid`, `uid`,`type`,`wall`,`gravity`, `network`, `contact-id`,`owner-name`,`owner-link`,`owner-avatar`, `author-name`, `author-link`, `author-avatar`,\n\t\t`created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, `tag`, `inform`, `verb`, `object-type`, `postopts`,\n\t\t`allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin`, `moderated`, `file`, `rendered-html`, `rendered-hash`)\n\t\tVALUES( '%s', '%s', %d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s')", dbesc($datarray['guid']), dbesc($datarray['extid']), intval($datarray['uid']), dbesc($datarray['type']), intval($datarray['wall']), intval($datarray['gravity']), dbesc($datarray['network']), intval($datarray['contact-id']), dbesc($datarray['owner-name']), dbesc($datarray['owner-link']), dbesc($datarray['owner-avatar']), dbesc($datarray['author-name']), dbesc($datarray['author-link']), dbesc($datarray['author-avatar']), dbesc($datarray['created']), dbesc($datarray['edited']), dbesc($datarray['commented']), dbesc($datarray['received']), dbesc($datarray['changed']), dbesc($datarray['uri']), dbesc($datarray['thr-parent']), dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['app']), dbesc($datarray['location']), dbesc($datarray['coord']), dbesc($datarray['tag']), dbesc($datarray['inform']), dbesc($datarray['verb']), dbesc($datarray['object-type']), dbesc($datarray['postopts']), dbesc($datarray['allow_cid']), dbesc($datarray['allow_gid']), dbesc($datarray['deny_cid']), dbesc($datarray['deny_gid']), intval($datarray['private']), intval($datarray['pubmail']), dbesc($datarray['attach']), intval($datarray['bookmark']), intval($datarray['origin']), intval($datarray['moderated']), dbesc($datarray['file']), dbesc($datarray['rendered-html']), dbesc($datarray['rendered-hash']));
    $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($datarray['uri']));
    if (!count($r)) {
        logger('mod_item: unable to retrieve post that was just stored.');
        notice(t('System error. Post not saved.') . EOL);
        goaway($a->get_baseurl() . "/" . $return_path);
        // NOTREACHED
    }
    $post_id = $r[0]['id'];
    logger('mod_item: saved item ' . $post_id);
    $datarray["id"] = $post_id;
    $datarray["plink"] = $a->get_baseurl() . '/display/' . urlencode($datarray["guid"]);
    // update filetags in pconfig
    file_tag_update_pconfig($uid, $categories_old, $categories_new, 'category');
    if ($parent) {
        // This item is the last leaf and gets the comment box, clear any ancestors
        $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent));
        update_thread($parent, true);
        // Inherit ACLs from the parent item.
        $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d\n\t\t\tWHERE `id` = %d", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($parent_item['private']), intval($post_id));
        if ($contact_record != $author) {
            notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_uri' => $parent_item['uri']));
        }
        // Store the comment signature information in case we need to relay to Diaspora
        store_diaspora_comment_sig($datarray, $author, $self ? $a->user['prvkey'] : false, $parent_item, $post_id);
    } else {
        $parent = $post_id;
        if ($contact_record != $author) {
            notification(array('type' => NOTIFY_WALL, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item'));
        }
    }
    // fallback so that parent always gets set to non-zero.
    if (!$parent) {
        $parent = $post_id;
    }
    $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\tWHERE `id` = %d", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc($a->get_baseurl() . '/display/' . urlencode($datarray['guid'])), dbesc(datetime_convert()), intval($post_id));
    // photo comments turn the corresponding item visible to the profile wall
    // This way we don't see every picture in your new photo album posted to your wall at once.
    // They will show up as people comment on them.
    if (!$parent_item['visible']) {
        $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d", intval($parent_item['id']));
        update_thread($parent_item['id']);
    }
    // update the commented timestamp on the parent
    q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent));
    if ($post_id != $parent) {
        update_thread($parent);
    }
    call_hooks('post_local_end', $datarray);
    if (strlen($emailcc) && $profile_uid == local_user()) {
        $erecips = explode(',', $emailcc);
        if (count($erecips)) {
            foreach ($erecips as $recip) {
                $addr = trim($recip);
                if (!strlen($addr)) {
                    continue;
                }
                $disclaimer = '<hr />' . sprintf(t('This message was sent to you by %s, a member of the Friendica social network.'), $a->user['username']) . '<br />';
                $disclaimer .= sprintf(t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL;
                $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL;
                if (!$datarray['title'] == '') {
                    $subject = email_header_encode($datarray['title'], 'UTF-8');
                } else {
                    $subject = email_header_encode('[Friendica]' . ' ' . sprintf(t('%s posted an update.'), $a->user['username']), 'UTF-8');
                }
                $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
                $html = prepare_body($datarray);
                $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';
                include_once 'include/html2plain.php';
                $params = array('fromName' => $a->user['username'], 'fromEmail' => $a->user['email'], 'toEmail' => $addr, 'replyTo' => $a->user['email'], 'messageSubject' => $subject, 'htmlVersion' => $message, 'textVersion' => html2plain($html . $disclaimer));
                Emailer::send($params);
            }
        }
    }
    create_tags_from_item($post_id);
    create_files_from_item($post_id);
    if ($post_id == $parent) {
        add_thread($post_id);
    }
    // This is a real juggling act on shared hosting services which kill your processes
    // e.g. dreamhost. We used to start delivery to our native delivery agents in the background
    // and then run our plugin delivery from the foreground. We're now doing plugin delivery first,
    // because as soon as you start loading up a bunch of remote delivey processes, *this* page is
    // likely to get killed off. If you end up looking at an /item URL and a blank page,
    // it's very likely the delivery got killed before all your friends could be notified.
    // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting,
    // or cut back on plugins which do remote deliveries.
    proc_run('php', "include/notifier.php", $notify_type, "{$post_id}");
    logger('post_complete');
    item_post_return($a->get_baseurl(), $api_source, $return_path);
    // NOTREACHED
}
 /**
  * Create a new GraphElement object in the database
  *
  * @param string $element_id The element id of the new element.  Must be specified
  * @param string $element_type The element type of this element.  Must be specified
  *
  * @return mixed The newly created object, or null if there was an error
  *
  * @see GenericObject
  * @static
  * @access public
  */
 public static function createNewObject($element_id, $element_type, $parent_element = null)
 {
     $db = AbstractDb::getObject();
     $graph_element_id = get_guid();
     if (!(class_exists($element_type) && get_parent_class($element_type) == 'HotspotGraphElement')) {
         throw new Exception(_('Cannot add element to hotspot graph. Wrong type specified: ') . $element_type);
     }
     $sql = "INSERT INTO hotspot_graph_elements (hotspot_graph_element_id, element_id, element_type) VALUES ('{$graph_element_id}', '{$element_id}', '{$element_type}')";
     if (!$db->execSqlUpdate($sql, false)) {
         throw new Exception(_('Unable to insert the new element in the database!'));
     }
     $object = self::getObject($element_id, $element_type);
     if (!is_null($parent_element)) {
         if (method_exists($parent_element, 'getHgeId')) {
             $parentid = $parent_element->getHgeId();
             $childid = $object->getHgeId();
             HotspotGraph::addRelation($parentid, $childid);
         }
     }
     return $object;
 }
Exemple #10
0
 public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '')
 {
     $r = q("select `guid` from photo where `resource-id` = '%s' and `guid` != '' limit 1", dbesc($rid));
     if (count($r)) {
         $guid = $r[0]['guid'];
     } else {
         $guid = get_guid();
     }
     $r = q("INSERT INTO `photo`\n\t\t\t( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, `album`, `height`, `width`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s' )", intval($uid), intval($cid), dbesc($guid), dbesc($rid), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(basename($filename)), dbesc($album), intval($this->height), intval($this->width), dbesc($this->imageString()), intval($scale), intval($profile), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid));
     return $r;
 }
Exemple #11
0
function item_post(&$a)
{
    if (!local_user() && !remote_user()) {
        return;
    }
    require_once 'include/security.php';
    $uid = local_user();
    if (x($_POST, 'dropitems')) {
        require_once 'include/items.php';
        $arr_drop = explode(',', $_POST['dropitems']);
        drop_items($arr_drop);
        $json = array('success' => 1);
        echo json_encode($json);
        killme();
    }
    call_hooks('post_local_start', $_POST);
    $api_source = x($_POST, 'api_source') && $_POST['api_source'] ? true : false;
    $return_path = x($_POST, 'return') ? $_POST['return'] : '';
    /**
     * Is this a reply to something?
     */
    $parent = x($_POST, 'parent') ? intval($_POST['parent']) : 0;
    $parent_uri = x($_POST, 'parent_uri') ? trim($_POST['parent_uri']) : '';
    $parent_item = null;
    $parent_contact = null;
    $thr_parent = '';
    $parid = 0;
    $r = false;
    $preview = x($_POST, 'preview') ? intval($_POST['preview']) : 0;
    if ($parent || $parent_uri) {
        if (!x($_POST, 'type')) {
            $_POST['type'] = 'net-comment';
        }
        if ($parent) {
            $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent));
        } elseif ($parent_uri && local_user()) {
            // This is coming from an API source, and we are logged in
            $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_uri), intval(local_user()));
        }
        // if this isn't the real parent of the conversation, find it
        if ($r !== false && count($r)) {
            $parid = $r[0]['parent'];
            if ($r[0]['id'] != $r[0]['parent']) {
                $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid));
            }
        }
        if ($r === false || !count($r)) {
            notice(t('Unable to locate original post.') . EOL);
            if (x($_POST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
        $parent_item = $r[0];
        $parent = $r[0]['id'];
        // multi-level threading - preserve the info but re-parent to our single level threading
        if ($parid && $parid != $parent) {
            $thr_parent = $parent_uri;
        }
        if ($parent_item['contact-id'] && $uid) {
            $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($parent_item['contact-id']), intval($uid));
            if (count($r)) {
                $parent_contact = $r[0];
            }
        }
    }
    if ($parent) {
        logger('mod_post: parent=' . $parent);
    }
    $profile_uid = x($_POST, 'profile_uid') ? intval($_POST['profile_uid']) : 0;
    $post_id = x($_POST['post_id']) ? intval($_POST['post_id']) : 0;
    $app = x($_POST['source']) ? strip_tags($_POST['source']) : '';
    if (!can_write_wall($a, $profile_uid)) {
        notice(t('Permission denied.') . EOL);
        if (x($_POST, 'return')) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    }
    // is this an edited post?
    $orig_post = null;
    if ($post_id) {
        $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id));
        if (!count($i)) {
            killme();
        }
        $orig_post = $i[0];
    }
    $user = null;
    $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid));
    if (count($r)) {
        $user = $r[0];
    }
    if ($orig_post) {
        $str_group_allow = $orig_post['allow_gid'];
        $str_contact_allow = $orig_post['allow_cid'];
        $str_group_deny = $orig_post['deny_gid'];
        $str_contact_deny = $orig_post['deny_cid'];
        $title = $orig_post['title'];
        $location = $orig_post['location'];
        $coord = $orig_post['coord'];
        $verb = $orig_post['verb'];
        $emailcc = $orig_post['emailcc'];
        $app = $orig_post['app'];
        $body = escape_tags(trim($_POST['body']));
        $private = $orig_post['private'];
        $pubmail_enable = $orig_post['pubmail'];
    } else {
        $str_group_allow = perms2str($_POST['group_allow']);
        $str_contact_allow = perms2str($_POST['contact_allow']);
        $str_group_deny = perms2str($_POST['group_deny']);
        $str_contact_deny = perms2str($_POST['contact_deny']);
        $title = notags(trim($_POST['title']));
        $location = notags(trim($_POST['location']));
        $coord = notags(trim($_POST['coord']));
        $verb = notags(trim($_POST['verb']));
        $emailcc = notags(trim($_POST['emailcc']));
        $body = escape_tags(trim($_POST['body']));
        $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) ? 1 : 0;
        if ($parent_item && ($parent_item['private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid']))) {
            $private = 1;
        }
        $pubmail_enable = x($_POST, 'pubmail_enable') && intval($_POST['pubmail_enable']) && !$private ? 1 : 0;
        // if using the API, we won't see pubmail_enable - figure out if it should be set
        if ($api_source && $profile_uid && $profile_uid == local_user() && !$private) {
            $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1;
            if (!$mail_disabled) {
                $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user()));
                if (count($r) && intval($r[0]['pubmail'])) {
                    $pubmail_enabled = true;
                }
            }
        }
        if (!strlen($body)) {
            info(t('Empty post discarded.') . EOL);
            if (x($_POST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
    }
    if ($api_source && !array_key_exists('allow_cid', $_REQUEST) && !array_key_exists('allow_gid', $_REQUEST) && !array_key_exists('deny_cid', $_REQUEST) && !array_key_exists('deny_gid', $_REQUEST)) {
        $str_group_allow = $user['allow_gid'];
        $str_contact_allow = $user['allow_cid'];
        $str_group_deny = $user['deny_gid'];
        $str_contact_deny = $user['deny_cid'];
    }
    // get contact info for poster
    $author = null;
    $self = false;
    if ($_SESSION['uid'] && $_SESSION['uid'] == $profile_uid) {
        $self = true;
        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($_SESSION['uid']));
    } else {
        if (x($_SESSION, 'visitor_id') && intval($_SESSION['visitor_id'])) {
            $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($_SESSION['visitor_id']));
        }
    }
    if (count($r)) {
        $author = $r[0];
        $contact_id = $author['id'];
    }
    // get contact info for owner
    if ($profile_uid == $_SESSION['uid']) {
        $contact_record = $author;
    } else {
        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid));
        if (count($r)) {
            $contact_record = $r[0];
        }
    }
    $post_type = notags(trim($_POST['type']));
    if ($post_type === 'net-comment') {
        if ($parent_item !== null) {
            if ($parent_item['wall'] == 1) {
                $post_type = 'wall-comment';
            } else {
                $post_type = 'remote-comment';
            }
        }
    }
    /**
     *
     * When a photo was uploaded into the message using the (profile wall) ajax 
     * uploader, The permissions are initially set to disallow anybody but the
     * owner from seeing it. This is because the permissions may not yet have been
     * set for the post. If it's private, the photo permissions should be set
     * appropriately. But we didn't know the final permissions on the post until
     * now. So now we'll look for links of uploaded messages that are in the
     * post and set them to the same permissions as the post itself.
     *
     */
    $match = null;
    if (!$preview && preg_match_all("/\\[img\\](.*?)\\[\\/img\\]/", $body, $match)) {
        $images = $match[1];
        if (count($images)) {
            foreach ($images as $image) {
                if (!stristr($image, $a->get_baseurl() . '/photo/')) {
                    continue;
                }
                $image_uri = substr($image, strrpos($image, '/') + 1);
                $image_uri = substr($image_uri, 0, strpos($image_uri, '-'));
                if (!strlen($image_uri)) {
                    continue;
                }
                $srch = '<' . intval($profile_uid) . '>';
                $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''\n\t\t\t\t\tAND `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($srch), dbesc($image_uri), intval($profile_uid));
                if (!count($r)) {
                    continue;
                }
                $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), intval($profile_uid), dbesc(t('Wall Photos')));
            }
        }
    }
    /**
     * Next link in any attachment references we find in the post.
     */
    $match = false;
    if (!$preview && preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", $body, $match)) {
        $attaches = $match[1];
        if (count($attaches)) {
            foreach ($attaches as $attach) {
                $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($attach));
                if (count($r)) {
                    $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\t\tWHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($profile_uid), intval($attach));
                }
            }
        }
    }
    // embedded bookmark in post? set bookmark flag
    $bookmark = 0;
    if (preg_match_all("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/ism", $body, $match, PREG_SET_ORDER)) {
        $bookmark = 1;
    }
    $body = bb_translate_video($body);
    /**
     * Fold multi-line [code] sequences
     */
    $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body);
    /**
     * Look for any tags and linkify them
     */
    $str_tags = '';
    $inform = '';
    $tags = get_tags($body);
    /**
     * add a statusnet style reply tag if the original post was from there
     * and we are replying, and there isn't one already
     */
    if ($parent_contact && $parent_contact['network'] === NETWORK_OSTATUS && $parent_contact['nick'] && !in_array('@' . $parent_contact['nick'], $tags)) {
        $body = '@' . $parent_contact['nick'] . ' ' . $body;
        $tags[] = '@' . $parent_contact['nick'];
    }
    if (count($tags)) {
        foreach ($tags as $tag) {
            if (isset($profile)) {
                unset($profile);
            }
            if (strpos($tag, '#') === 0) {
                if (strpos($tag, '[url=')) {
                    continue;
                }
                $basetag = str_replace('_', ' ', substr($tag, 1));
                $body = str_replace($tag, '#[url=' . $a->get_baseurl() . '/search?search=' . rawurlencode($basetag) . ']' . $basetag . '[/url]', $body);
                $newtag = '#[url=' . $a->get_baseurl() . '/search?search=' . rawurlencode($basetag) . ']' . $basetag . '[/url]';
                if (!stristr($str_tags, $newtag)) {
                    if (strlen($str_tags)) {
                        $str_tags .= ',';
                    }
                    $str_tags .= $newtag;
                }
                continue;
            }
            if (strpos($tag, '@') === 0) {
                if (strpos($tag, '[url=')) {
                    continue;
                }
                $stat = false;
                $name = substr($tag, 1);
                if (strpos($name, '@') || strpos($name, 'http://')) {
                    $newname = $name;
                    $links = @lrdd($name);
                    if (count($links)) {
                        foreach ($links as $link) {
                            if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') {
                                $profile = $link['@attributes']['href'];
                            }
                            if ($link['@attributes']['rel'] === 'salmon') {
                                if (strlen($inform)) {
                                    $inform .= ',';
                                }
                                $inform .= 'url:' . str_replace(',', '%2c', $link['@attributes']['href']);
                            }
                        }
                    }
                } else {
                    $newname = $name;
                    $alias = '';
                    $tagcid = 0;
                    if (strrpos($newname, '+')) {
                        $tagcid = intval(substr($newname, strrpos($newname, '+') + 1));
                        if (strpos($name, ' ')) {
                            $name = substr($name, 0, strpos($name, ' '));
                        }
                    }
                    if ($tagcid) {
                        $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($tagcid), intval($profile_uid));
                    } elseif (strstr($name, '_') || strstr($name, ' ')) {
                        $newname = str_replace('_', ' ', $name);
                        $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1", dbesc($newname), intval($profile_uid));
                    } else {
                        $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), dbesc($name), intval($profile_uid));
                    }
                    if (count($r)) {
                        $profile = $r[0]['url'];
                        if ($r[0]['network'] === 'stat') {
                            $newname = $r[0]['nick'];
                            $stat = true;
                            if ($r[0]['alias']) {
                                $alias = $r[0]['alias'];
                            }
                        } else {
                            $newname = $r[0]['name'];
                        }
                        if (strlen($inform)) {
                            $inform .= ',';
                        }
                        $inform .= 'cid:' . $r[0]['id'];
                    }
                }
                if ($profile) {
                    $body = str_replace('@' . $name, '@' . '[url=' . $profile . ']' . $newname . '[/url]', $body);
                    $profile = str_replace(',', '%2c', $profile);
                    $newtag = '@[url=' . $profile . ']' . $newname . '[/url]';
                    if (!stristr($str_tags, $newtag)) {
                        if (strlen($str_tags)) {
                            $str_tags .= ',';
                        }
                        $str_tags .= $newtag;
                    }
                    // Status.Net seems to require the numeric ID URL in a mention if the person isn't
                    // subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both.
                    if (strlen($alias)) {
                        $newtag = '@[url=' . $alias . ']' . $newname . '[/url]';
                        if (!stristr($str_tags, $newtag)) {
                            if (strlen($str_tags)) {
                                $str_tags .= ',';
                            }
                            $str_tags .= $newtag;
                        }
                    }
                }
            }
        }
    }
    $attachments = '';
    $match = false;
    if (preg_match_all('/(\\[attachment\\]([0-9]+)\\[\\/attachment\\])/', $body, $match)) {
        foreach ($match[2] as $mtch) {
            $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($mtch));
            if (count($r)) {
                if (strlen($attachments)) {
                    $attachments .= ',';
                }
                $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . ($r[0]['filename'] ? $r[0]['filename'] : '') . '"[/attach]';
            }
            $body = str_replace($match[1], '', $body);
        }
    }
    $wall = 0;
    if ($post_type === 'wall' || $post_type === 'wall-comment') {
        $wall = 1;
    }
    if (!strlen($verb)) {
        $verb = ACTIVITY_POST;
    }
    $gravity = $parent ? 6 : 0;
    // even if the post arrived via API we are considering that it
    // originated on this site by default for determining relayability.
    $origin = x($_REQUEST, 'origin') ? intval($_REQUEST['origin']) : 1;
    $notify_type = $parent ? 'comment-new' : 'wall-new';
    $uri = item_new_uri($a->get_hostname(), $profile_uid);
    $datarray = array();
    $datarray['uid'] = $profile_uid;
    $datarray['type'] = $post_type;
    $datarray['wall'] = $wall;
    $datarray['gravity'] = $gravity;
    $datarray['contact-id'] = $contact_id;
    $datarray['owner-name'] = $contact_record['name'];
    $datarray['owner-link'] = $contact_record['url'];
    $datarray['owner-avatar'] = $contact_record['thumb'];
    $datarray['author-name'] = $author['name'];
    $datarray['author-link'] = $author['url'];
    $datarray['author-avatar'] = $author['thumb'];
    $datarray['created'] = datetime_convert();
    $datarray['edited'] = datetime_convert();
    $datarray['commented'] = datetime_convert();
    $datarray['received'] = datetime_convert();
    $datarray['changed'] = datetime_convert();
    $datarray['uri'] = $uri;
    $datarray['title'] = $title;
    $datarray['body'] = $body;
    $datarray['app'] = $app;
    $datarray['location'] = $location;
    $datarray['coord'] = $coord;
    $datarray['tag'] = $str_tags;
    $datarray['inform'] = $inform;
    $datarray['verb'] = $verb;
    $datarray['allow_cid'] = $str_contact_allow;
    $datarray['allow_gid'] = $str_group_allow;
    $datarray['deny_cid'] = $str_contact_deny;
    $datarray['deny_gid'] = $str_group_deny;
    $datarray['private'] = $private;
    $datarray['pubmail'] = $pubmail_enable;
    $datarray['attach'] = $attachments;
    $datarray['bookmark'] = intval($bookmark);
    $datarray['thr-parent'] = $thr_parent;
    $datarray['postopts'] = '';
    $datarray['origin'] = $origin;
    /**
     * These fields are for the convenience of plugins...
     * 'self' if true indicates the owner is posting on their own wall
     * If parent is 0 it is a top-level post.
     */
    $datarray['parent'] = $parent;
    $datarray['self'] = $self;
    //	$datarray['prvnets']       = $user['prvnets'];
    if ($orig_post) {
        $datarray['edit'] = true;
    } else {
        $datarray['guid'] = get_guid();
    }
    // preview mode - prepare the body for display and send it via json
    if ($preview) {
        require_once 'include/conversation.php';
        $o = conversation(&$a, array(array_merge($contact_record, $datarray)), 'search', false, true);
        echo json_encode(array('preview' => $o));
        killme();
    }
    call_hooks('post_local', $datarray);
    if ($orig_post) {
        $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($body), dbesc(datetime_convert()), intval($post_id), intval($profile_uid));
        proc_run('php', "include/notifier.php", 'edit_post', "{$post_id}");
        if (x($_POST, 'return') && strlen($return_path)) {
            logger('return: ' . $return_path);
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    } else {
        $post_id = 0;
    }
    $r = q("INSERT INTO `item` (`guid`, `uid`,`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`, \n\t\t`author-name`, `author-link`, `author-avatar`, `created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, \n\t\t`tag`, `inform`, `verb`, `postopts`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin` )\n\t\tVALUES( '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d )", dbesc($datarray['guid']), intval($datarray['uid']), dbesc($datarray['type']), intval($datarray['wall']), intval($datarray['gravity']), intval($datarray['contact-id']), dbesc($datarray['owner-name']), dbesc($datarray['owner-link']), dbesc($datarray['owner-avatar']), dbesc($datarray['author-name']), dbesc($datarray['author-link']), dbesc($datarray['author-avatar']), dbesc($datarray['created']), dbesc($datarray['edited']), dbesc($datarray['commented']), dbesc($datarray['received']), dbesc($datarray['changed']), dbesc($datarray['uri']), dbesc($datarray['thr-parent']), dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['app']), dbesc($datarray['location']), dbesc($datarray['coord']), dbesc($datarray['tag']), dbesc($datarray['inform']), dbesc($datarray['verb']), dbesc($datarray['postopts']), dbesc($datarray['allow_cid']), dbesc($datarray['allow_gid']), dbesc($datarray['deny_cid']), dbesc($datarray['deny_gid']), intval($datarray['private']), intval($datarray['pubmail']), dbesc($datarray['attach']), intval($datarray['bookmark']), intval($datarray['origin']));
    $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($datarray['uri']));
    if (count($r)) {
        $post_id = $r[0]['id'];
        logger('mod_item: saved item ' . $post_id);
        if ($parent) {
            // This item is the last leaf and gets the comment box, clear any ancestors
            $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent));
            // Inherit ACL's from the parent item.
            $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d\n\t\t\t\tWHERE `id` = %d LIMIT 1", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($parent_item['private']), intval($post_id));
            if ($contact_record != $author) {
                notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id, 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item'));
            }
            // We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key
            if ($self) {
                require_once 'include/bb2diaspora.php';
                $signed_body = html_entity_decode(bb2diaspora($datarray['body']));
                $myaddr = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
                if ($datarray['verb'] === ACTIVITY_LIKE) {
                    $signed_text = $datarray['guid'] . ';' . 'Post' . ';' . $parent_item['guid'] . ';' . 'true' . ';' . $myaddr;
                } else {
                    $signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $myaddr;
                }
                $authorsig = base64_encode(rsa_sign($signed_text, $a->user['prvkey'], 'sha256'));
                q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($post_id), dbesc($signed_text), dbesc(base64_encode($authorsig)), dbesc($myaddr));
            }
        } else {
            $parent = $post_id;
            if ($contact_record != $author) {
                notification(array('type' => NOTIFY_WALL, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id, 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item'));
            }
        }
        // fallback so that parent always gets set to non-zero.
        if (!$parent) {
            $parent = $post_id;
        }
        $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\t\tWHERE `id` = %d LIMIT 1", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc($a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id), dbesc(datetime_convert()), intval($post_id));
        // photo comments turn the corresponding item visible to the profile wall
        // This way we don't see every picture in your new photo album posted to your wall at once.
        // They will show up as people comment on them.
        if (!$parent_item['visible']) {
            $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d LIMIT 1", intval($parent_item['id']));
        }
    } else {
        logger('mod_item: unable to retrieve post that was just stored.');
        notify(t('System error. Post not saved.'));
        goaway($a->get_baseurl() . "/" . $return_path);
        // NOTREACHED
    }
    // update the commented timestamp on the parent
    q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent));
    $datarray['id'] = $post_id;
    $datarray['plink'] = $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id;
    call_hooks('post_local_end', $datarray);
    if (strlen($emailcc) && $profile_uid == local_user()) {
        $erecips = explode(',', $emailcc);
        if (count($erecips)) {
            foreach ($erecips as $recip) {
                $addr = trim($recip);
                if (!strlen($addr)) {
                    continue;
                }
                $disclaimer = '<hr />' . sprintf(t('This message was sent to you by %s, a member of the Friendica social network.'), $a->user['username']) . '<br />';
                $disclaimer .= sprintf(t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL;
                $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL;
                $subject = '[Friendica]' . ' ' . sprintf(t('%s posted an update.'), $a->user['username']);
                $headers = 'From: ' . $a->user['username'] . ' <' . $a->user['email'] . '>' . "\n";
                $headers .= 'MIME-Version: 1.0' . "\n";
                $headers .= 'Content-Type: text/html; charset=UTF-8' . "\n";
                $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n";
                $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
                $html = prepare_body($datarray);
                $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';
                @mail($addr, $subject, $message, $headers);
            }
        }
    }
    // This is a real juggling act on shared hosting services which kill your processes
    // e.g. dreamhost. We used to start delivery to our native delivery agents in the background
    // and then run our plugin delivery from the foreground. We're now doing plugin delivery first,
    // because as soon as you start loading up a bunch of remote delivey processes, *this* page is
    // likely to get killed off. If you end up looking at an /item URL and a blank page,
    // it's very likely the delivery got killed before all your friends could be notified.
    // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting,
    // or cut back on plugins which do remote deliveries.
    proc_run('php', "include/notifier.php", $notify_type, "{$post_id}");
    logger('post_complete');
    // figure out how to return, depending on from whence we came
    if ($api_source) {
        return;
    }
    if ($return_path) {
        goaway($a->get_baseurl() . "/" . $return_path);
    }
    $json = array('success' => 1);
    if (x($_POST, 'jsreload') && strlen($_POST['jsreload'])) {
        $json['reload'] = $a->get_baseurl() . '/' . $_POST['jsreload'];
    }
    logger('post_json: ' . print_r($json, true), LOGGER_DEBUG);
    echo json_encode($json);
    killme();
    // NOTREACHED
}
Exemple #12
0
 /**
  * Create a new Content object in the database
  *
  * @param string $server_id The server id of the new server. If absent,
  *                           will be assigned a guid.
  *
  * @return mixed The newly created object, or null if there was an error
  *
  * @see GenericObject
  *
  * @static
  * @access public
  */
 public static function createNewObject($server_id = null)
 {
     $db = AbstractDb::getObject();
     if (empty($server_id)) {
         $server_id = get_guid();
     }
     $server_id = $db->escapeString($server_id);
     $sql = "INSERT INTO servers (server_id) VALUES ('{$server_id}')";
     if (!$db->execSqlUpdate($sql, false)) {
         throw new Exception(_('Unable to insert the new server in the database!'));
     }
     $_object = self::getObject($server_id);
     return $_object;
 }
 /**
  * Attempts to login a user against the authentication source
  *
  * If successfull, returns a User object
  *
  * @param string $username A valid identifying token for the source. Not
  *                         necessarily unique.
  * @param string $password Clear text password.
  * @param string $errmsg   Reference of error message
  *
  * @return object The actual User object if login was successfull, false
  *                otherwise.
  */
 public function login($username, $password, &$errmsg = null)
 {
     $db = AbstractDb::getObject();
     // Init values
     $retval = false;
     $username = $db->EscapeString($username);
     $password = $db->EscapeString($password);
     // Check if php-ldap extension is loaded
     if (Dependency::check("ldap", $errmsg)) {
         if ($this->checkLdapUser($username, $password, $this->mldap_hostname, $this->mldap_o, $this->mldap_filter, $errmsg)) {
             //LDAP Authentication Successful
             $sql = "SELECT user_id, pass FROM users WHERE (username='******') AND account_origin='" . $this->getNetwork()->getId() . "'";
             $db->ExecSqlUniqueRes($sql, $user_info, false);
             if ($user_info != null) {
                 $user = User::getObject($user_info['user_id']);
                 if ($user->isUserValid($errmsg)) {
                     $retval = $user;
                     User::setCurrentUser($user);
                     $errmsg = _("Login successfull");
                 } else {
                     $retval = false;
                     //Error already been set
                 }
             } else {
                 $user = User::createUser(get_guid(), $username, $this->getNetwork(), "", "");
                 $retval =& $user;
                 $user->setAccountStatus(ACCOUNT_STATUS_ALLOWED);
                 $errmsg = _("Login successfull");
             }
         } else {
             $retval = false;
             //Error already been set
         }
     }
     User::setCurrentUser($retval);
     return $retval;
 }
Exemple #14
0
function send_message($recipient = 0, $body = '', $subject = '', $replyto = '')
{
    $a = get_app();
    if (!$recipient) {
        return -1;
    }
    if (!strlen($subject)) {
        $subject = t('[no subject]');
    }
    $me = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval(local_user()));
    $contact = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($recipient), intval(local_user()));
    if (!(count($me) && count($contact))) {
        return -2;
    }
    $hash = random_string();
    $uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $hash;
    $convid = 0;
    $reply = false;
    // look for any existing conversation structure
    if (strlen($replyto)) {
        $reply = true;
        $r = q("select convid from mail where uid = %d and ( uri = '%s' or `parent-uri` = '%s' ) limit 1", intval(local_user()), dbesc($replyto), dbesc($replyto));
        if (count($r)) {
            $convid = $r[0]['convid'];
        }
    }
    if (!$convid) {
        // create a new conversation
        $conv_guid = get_guid();
        $recip_host = substr($contact[0]['url'], strpos($contact[0]['url'], '://') + 3);
        $recip_host = substr($recip_host, 0, strpos($recip_host, '/'));
        $recip_handle = $contact[0]['addr'] ? $contact[0]['addr'] : $contact[0]['nick'] . '@' . $recip_host;
        $sender_handle = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
        $handles = $recip_handle . ';' . $sender_handle;
        $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ", intval(local_user()), dbesc($conv_guid), dbesc($sender_handle), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($subject), dbesc($handles));
        $r = q("select * from conv where guid = '%s' and uid = %d limit 1", dbesc($conv_guid), intval(local_user()));
        if (count($r)) {
            $convid = $r[0]['id'];
        }
    }
    if (!$convid) {
        logger('send message: conversation not found.');
        return -4;
    }
    if (!strlen($replyto)) {
        $replyto = $uri;
    }
    $r = q("INSERT INTO `mail` ( `uid`, `guid`, `convid`, `from-name`, `from-photo`, `from-url`, \n\t\t`contact-id`, `title`, `body`, `seen`, `reply`, `replied`, `uri`, `parent-uri`, `created`)\n\t\tVALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, %d, '%s', '%s', '%s' )", intval(local_user()), dbesc(get_guid()), intval($convid), dbesc($me[0]['name']), dbesc($me[0]['thumb']), dbesc($me[0]['url']), intval($recipient), dbesc($subject), dbesc($body), 1, intval($reply), 0, dbesc($uri), dbesc($replyto), datetime_convert());
    $r = q("SELECT * FROM `mail` WHERE `uri` = '%s' and `uid` = %d LIMIT 1", dbesc($uri), intval(local_user()));
    if (count($r)) {
        $post_id = $r[0]['id'];
    }
    /**
     *
     * When a photo was uploaded into the message using the (profile wall) ajax 
     * uploader, The permissions are initially set to disallow anybody but the
     * owner from seeing it. This is because the permissions may not yet have been
     * set for the post. If it's private, the photo permissions should be set
     * appropriately. But we didn't know the final permissions on the post until
     * now. So now we'll look for links of uploaded messages that are in the
     * post and set them to the same permissions as the post itself.
     *
     */
    $match = null;
    if (preg_match_all("/\\[img\\](.*?)\\[\\/img\\]/", $body, $match)) {
        $images = $match[1];
        if (count($images)) {
            foreach ($images as $image) {
                if (!stristr($image, $a->get_baseurl() . '/photo/')) {
                    continue;
                }
                $image_uri = substr($image, strrpos($image, '/') + 1);
                $image_uri = substr($image_uri, 0, strpos($image_uri, '-'));
                $r = q("UPDATE `photo` SET `allow_cid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `album` = '%s' AND `uid` = %d ", dbesc('<' . $recipient . '>'), dbesc($image_uri), dbesc(t('Wall Photos')), intval(local_user()));
            }
        }
    }
    if ($post_id) {
        proc_run('php', "include/notifier.php", "mail", "{$post_id}");
        return intval($post_id);
    } else {
        return -3;
    }
}
Exemple #15
0
function item_store($arr, $force_parent = false)
{
    // If a Diaspora signature structure was passed in, pull it out of the
    // item array and set it aside for later storage.
    $dsprsig = null;
    if (x($arr, 'dsprsig')) {
        $dsprsig = json_decode(base64_decode($arr['dsprsig']));
        unset($arr['dsprsig']);
    }
    // if an OStatus conversation url was passed in, it is stored and then
    // removed from the array.
    $ostatus_conversation = null;
    if (isset($arr["ostatus_conversation"])) {
        $ostatus_conversation = $arr["ostatus_conversation"];
        unset($arr["ostatus_conversation"]);
    }
    if (x($arr, 'gravity')) {
        $arr['gravity'] = intval($arr['gravity']);
    } elseif ($arr['parent-uri'] === $arr['uri']) {
        $arr['gravity'] = 0;
    } elseif (activity_match($arr['verb'], ACTIVITY_POST)) {
        $arr['gravity'] = 6;
    } else {
        $arr['gravity'] = 6;
    }
    // extensible catchall
    if (!x($arr, 'type')) {
        $arr['type'] = 'remote';
    }
    // Shouldn't happen but we want to make absolutely sure it doesn't leak from a plugin.
    if (strpos($arr['body'], '<') !== false || strpos($arr['body'], '>') !== false) {
        $arr['body'] = strip_tags($arr['body']);
    }
    if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
        require_once 'library/langdet/Text/LanguageDetect.php';
        $naked_body = preg_replace('/\\[(.+?)\\]/', '', $arr['body']);
        $l = new Text_LanguageDetect();
        //$lng = $l->detectConfidence($naked_body);
        //$arr['postopts'] = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : '');
        $lng = $l->detect($naked_body, 3);
        if (sizeof($lng) > 0) {
            $postopts = "";
            foreach ($lng as $language => $score) {
                if ($postopts == "") {
                    $postopts = "lang=";
                } else {
                    $postopts .= ":";
                }
                $postopts .= $language . ";" . $score;
            }
            $arr['postopts'] = $postopts;
        }
    }
    $arr['wall'] = x($arr, 'wall') ? intval($arr['wall']) : 0;
    $arr['uri'] = x($arr, 'uri') ? notags(trim($arr['uri'])) : random_string();
    $arr['extid'] = x($arr, 'extid') ? notags(trim($arr['extid'])) : '';
    $arr['author-name'] = x($arr, 'author-name') ? notags(trim($arr['author-name'])) : '';
    $arr['author-link'] = x($arr, 'author-link') ? notags(trim($arr['author-link'])) : '';
    $arr['author-avatar'] = x($arr, 'author-avatar') ? notags(trim($arr['author-avatar'])) : '';
    $arr['owner-name'] = x($arr, 'owner-name') ? notags(trim($arr['owner-name'])) : '';
    $arr['owner-link'] = x($arr, 'owner-link') ? notags(trim($arr['owner-link'])) : '';
    $arr['owner-avatar'] = x($arr, 'owner-avatar') ? notags(trim($arr['owner-avatar'])) : '';
    $arr['created'] = x($arr, 'created') !== false ? datetime_convert('UTC', 'UTC', $arr['created']) : datetime_convert();
    $arr['edited'] = x($arr, 'edited') !== false ? datetime_convert('UTC', 'UTC', $arr['edited']) : datetime_convert();
    $arr['commented'] = datetime_convert();
    $arr['received'] = datetime_convert();
    $arr['changed'] = datetime_convert();
    $arr['title'] = x($arr, 'title') ? notags(trim($arr['title'])) : '';
    $arr['location'] = x($arr, 'location') ? notags(trim($arr['location'])) : '';
    $arr['coord'] = x($arr, 'coord') ? notags(trim($arr['coord'])) : '';
    $arr['last-child'] = x($arr, 'last-child') ? intval($arr['last-child']) : 0;
    $arr['visible'] = x($arr, 'visible') !== false ? intval($arr['visible']) : 1;
    $arr['deleted'] = 0;
    $arr['parent-uri'] = x($arr, 'parent-uri') ? notags(trim($arr['parent-uri'])) : '';
    $arr['verb'] = x($arr, 'verb') ? notags(trim($arr['verb'])) : '';
    $arr['object-type'] = x($arr, 'object-type') ? notags(trim($arr['object-type'])) : '';
    $arr['object'] = x($arr, 'object') ? trim($arr['object']) : '';
    $arr['target-type'] = x($arr, 'target-type') ? notags(trim($arr['target-type'])) : '';
    $arr['target'] = x($arr, 'target') ? trim($arr['target']) : '';
    $arr['plink'] = x($arr, 'plink') ? notags(trim($arr['plink'])) : '';
    $arr['allow_cid'] = x($arr, 'allow_cid') ? trim($arr['allow_cid']) : '';
    $arr['allow_gid'] = x($arr, 'allow_gid') ? trim($arr['allow_gid']) : '';
    $arr['deny_cid'] = x($arr, 'deny_cid') ? trim($arr['deny_cid']) : '';
    $arr['deny_gid'] = x($arr, 'deny_gid') ? trim($arr['deny_gid']) : '';
    $arr['private'] = x($arr, 'private') ? intval($arr['private']) : 0;
    $arr['bookmark'] = x($arr, 'bookmark') ? intval($arr['bookmark']) : 0;
    $arr['body'] = x($arr, 'body') ? trim($arr['body']) : '';
    $arr['tag'] = x($arr, 'tag') ? notags(trim($arr['tag'])) : '';
    $arr['attach'] = x($arr, 'attach') ? notags(trim($arr['attach'])) : '';
    $arr['app'] = x($arr, 'app') ? notags(trim($arr['app'])) : '';
    $arr['origin'] = x($arr, 'origin') ? intval($arr['origin']) : 0;
    $arr['guid'] = x($arr, 'guid') ? notags(trim($arr['guid'])) : get_guid();
    $arr['thr-parent'] = $arr['parent-uri'];
    if ($arr['parent-uri'] === $arr['uri']) {
        $parent_id = 0;
        $parent_deleted = 0;
        $allow_cid = $arr['allow_cid'];
        $allow_gid = $arr['allow_gid'];
        $deny_cid = $arr['deny_cid'];
        $deny_gid = $arr['deny_gid'];
    } else {
        // find the parent and snarf the item id and ACLs
        // and anything else we need to inherit
        $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1", dbesc($arr['parent-uri']), intval($arr['uid']));
        if (count($r)) {
            // is the new message multi-level threaded?
            // even though we don't support it now, preserve the info
            // and re-attach to the conversation parent.
            if ($r[0]['uri'] != $r[0]['parent-uri']) {
                $arr['parent-uri'] = $r[0]['parent-uri'];
                $z = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d \n\t\t\t\t\tORDER BY `id` ASC LIMIT 1", dbesc($r[0]['parent-uri']), dbesc($r[0]['parent-uri']), intval($arr['uid']));
                if ($z && count($z)) {
                    $r = $z;
                }
            }
            $parent_id = $r[0]['id'];
            $parent_deleted = $r[0]['deleted'];
            $allow_cid = $r[0]['allow_cid'];
            $allow_gid = $r[0]['allow_gid'];
            $deny_cid = $r[0]['deny_cid'];
            $deny_gid = $r[0]['deny_gid'];
            $arr['wall'] = $r[0]['wall'];
            // if the parent is private, force privacy for the entire conversation
            // This differs from the above settings as it subtly allows comments from
            // email correspondents to be private even if the overall thread is not.
            if ($r[0]['private']) {
                $arr['private'] = $r[0]['private'];
            }
            // Edge case. We host a public forum that was originally posted to privately.
            // The original author commented, but as this is a comment, the permissions
            // weren't fixed up so it will still show the comment as private unless we fix it here.
            if (intval($r[0]['forum_mode']) == 1 && !$r[0]['private']) {
                $arr['private'] = 0;
            }
        } else {
            // Allow one to see reply tweets from status.net even when
            // we don't have or can't see the original post.
            if ($force_parent) {
                logger('item_store: $force_parent=true, reply converted to top-level post.');
                $parent_id = 0;
                $arr['parent-uri'] = $arr['uri'];
                $arr['gravity'] = 0;
            } else {
                logger('item_store: item parent was not found - ignoring item');
                return 0;
            }
            $parent_deleted = 0;
        }
    }
    $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($arr['uri']), intval($arr['uid']));
    if ($r && count($r)) {
        logger('item-store: duplicate item ignored. ' . print_r($arr, true));
        return 0;
    }
    call_hooks('post_remote', $arr);
    if (x($arr, 'cancel')) {
        logger('item_store: post cancelled by plugin.');
        return 0;
    }
    dbesc_array($arr);
    logger('item_store: ' . print_r($arr, true), LOGGER_DATA);
    $r = dbq("INSERT INTO `item` (`" . implode("`, `", array_keys($arr)) . "`) VALUES ('" . implode("', '", array_values($arr)) . "')");
    // find the item we just created
    $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC ", $arr['uri'], intval($arr['uid']));
    if (count($r)) {
        $current_post = $r[0]['id'];
        logger('item_store: created item ' . $current_post);
        create_tags_from_item($r[0]['id']);
    } else {
        logger('item_store: could not locate created item');
        return 0;
    }
    if (count($r) > 1) {
        logger('item_store: duplicated post occurred. Removing duplicates.');
        q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `id` != %d ", $arr['uri'], intval($arr['uid']), intval($current_post));
    }
    if (!$parent_id || $arr['parent-uri'] === $arr['uri']) {
        $parent_id = $current_post;
    }
    if (strlen($allow_cid) || strlen($allow_gid) || strlen($deny_cid) || strlen($deny_gid)) {
        $private = 1;
    } else {
        $private = $arr['private'];
    }
    // Set parent id - and also make sure to inherit the parent's ACL's.
    $r = q("UPDATE `item` SET `parent` = %d, `allow_cid` = '%s', `allow_gid` = '%s',\n\t\t`deny_cid` = '%s', `deny_gid` = '%s', `private` = %d, `deleted` = %d WHERE `id` = %d LIMIT 1", intval($parent_id), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid), intval($private), intval($parent_deleted), intval($current_post));
    create_tags_from_item($current_post);
    // Complete ostatus threads
    if ($ostatus_conversation) {
        complete_conversation($current_post, $ostatus_conversation);
    }
    $arr['id'] = $current_post;
    $arr['parent'] = $parent_id;
    $arr['allow_cid'] = $allow_cid;
    $arr['allow_gid'] = $allow_gid;
    $arr['deny_cid'] = $deny_cid;
    $arr['deny_gid'] = $deny_gid;
    $arr['private'] = $private;
    $arr['deleted'] = $parent_deleted;
    // update the commented timestamp on the parent
    q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent_id));
    if ($dsprsig) {
        q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($current_post), dbesc($dsprsig->signed_text), dbesc($dsprsig->signature), dbesc($dsprsig->signer));
    }
    /**
     * If this is now the last-child, force all _other_ children of this parent to *not* be last-child
     */
    if ($arr['last-child']) {
        $r = q("UPDATE `item` SET `last-child` = 0 WHERE `parent-uri` = '%s' AND `uid` = %d AND `id` != %d", dbesc($arr['uri']), intval($arr['uid']), intval($current_post));
    }
    tag_deliver($arr['uid'], $current_post);
    // Store the fresh generated item into the cache
    $cachefile = get_cachefile($arr["guid"] . "-" . hash("md5", $arr['body']));
    if ($cachefile != '' and !file_exists($cachefile)) {
        $s = prepare_text($arr['body']);
        $a = get_app();
        $stamp1 = microtime(true);
        file_put_contents($cachefile, $s);
        $a->save_timestamp($stamp1, "file");
        logger('item_store: put item ' . $current_post . ' into cachefile ' . $cachefile);
    }
    $r = q('SELECT * FROM `item` WHERE id = %d', intval($current_post));
    if (count($r) == 1) {
        call_hooks('post_remote_end', $r[0]);
    } else {
        logger('item_store: new item not found in DB, id ' . $current_post);
    }
    return $current_post;
}
Exemple #16
0
 public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '')
 {
     $r = q("select `guid` from photo where `resource-id` = '%s' and `guid` != '' limit 1", dbesc($rid));
     if (count($r)) {
         $guid = $r[0]['guid'];
     } else {
         $guid = get_guid();
     }
     $x = q("select id from photo where `resource-id` = '%s' and uid = %d and `contact-id` = %d and `scale` = %d limit 1", dbesc($rid), intval($uid), intval($cid), intval($scale));
     if (count($x)) {
         $r = q("UPDATE `photo`\n\t\tset `uid` = %d,\n\t\t`contact-id` = %d,\n\t\t`guid` = '%s',\n\t\t`resource-id` = '%s',\n\t\t`created` = '%s',\n\t\t`edited` = '%s',\n\t\t`filename` = '%s',\n\t\t`type` = '%s',\n\t\t`album` = '%s',\n\t\t`height` = %d,\n\t\t`width` = %d,\n\t\t\t\t`datasize` = %d,\n\t\t`data` = '%s',\n\t\t`scale` = %d,\n\t\t`profile` = %d,\n\t\t`allow_cid` = '%s',\n\t\t`allow_gid` = '%s',\n\t\t`deny_cid` = '%s',\n\t\t`deny_gid` = '%s'\n\t\twhere id = %d", intval($uid), intval($cid), dbesc($guid), dbesc($rid), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(basename($filename)), dbesc($this->getType()), dbesc($album), intval($this->getHeight()), intval($this->getWidth()), dbesc(strlen($this->imageString())), dbesc($this->imageString()), intval($scale), intval($profile), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid), intval($x[0]['id']));
     } else {
         $r = q("INSERT INTO `photo`\n\t\t( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `datasize`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` )\n\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s' )", intval($uid), intval($cid), dbesc($guid), dbesc($rid), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(basename($filename)), dbesc($this->getType()), dbesc($album), intval($this->getHeight()), intval($this->getWidth()), dbesc(strlen($this->imageString())), dbesc($this->imageString()), intval($scale), intval($profile), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid));
     }
     return $r;
 }
 /**
  * This method will create a ProfileTemplateField based on the content type filter specified
  *
  * @param string $user_prefix                A identifier provided by the programmer to
  *                                           recognise it's generated form
  * @param string $profile_template              Must be present
  *
  * @return object The ProfileTemplateField object, or null if the user didn't create one
  * @static
  */
 public static function processCreateFieldUI($user_prefix, ProfileTemplate $profile_template)
 {
     $db = AbstractDb::getObject();
     // Init values
     $profile_template_field_object = null;
     $max_display_order_row = null;
     $name = "get_new_profile_template_field_{$user_prefix}_add";
     if (!empty($_REQUEST[$name])) {
         /* Get the display order to add the ProfileTemplateField at the end */
         $sql = "SELECT MAX(display_order) as max_display_order FROM profile_template_fields WHERE profile_template_id = '" . $profile_template->getId() . "'";
         $db->execSqlUniqueRes($sql, $max_display_order_row, false);
         $display_order = $max_display_order_row['max_display_order'] + 1;
         $profile_template_field_id = get_guid();
         $sql = "INSERT INTO profile_template_fields (profile_template_field_id, profile_template_id, display_order) VALUES ('{$profile_template_field_id}', '{$profile_template->getId()}', {$display_order});";
         if (!$db->execSqlUpdate($sql, false)) {
             throw new Exception(_('Unable to insert new content into database!'));
         }
         $profile_template_field_object = self::getObject($profile_template_field_id);
         $name = "get_new_profile_template_field_{$user_prefix}_content_type_filter";
         $content_type_filter_ui_result = FormSelectGenerator::getResult($name, null);
         if (empty($content_type_filter_ui_result)) {
             throw new exception("Unable to retrieve the content type filter to associate with the new field");
         }
         $content_type_filter = ContentTypeFilter::getObject($content_type_filter_ui_result);
         $profile_template_field_object->replaceContentTypeFilter($content_type_filter);
     }
     return $profile_template_field_object;
 }
Exemple #18
0
 empty($_REQUEST['username']) ? $username = '******' : ($username = $_REQUEST['username']);
 empty($_REQUEST['password']) ? $password = '' : ($password = $_REQUEST['password']);
 empty($_REQUEST['password2']) ? $password2 = '' : ($password2 = $_REQUEST['password2']);
 empty($_REQUEST['email']) ? $email = $_SERVER['SERVER_ADMIN'] : ($email = $_REQUEST['email']);
 $conn_string = "host={$CONF_DATABASE_HOST} port={$CONF_DATABASE_PORT} dbname={$CONF_DATABASE_NAME} user={$CONF_DATABASE_USER} password={$CONF_DATABASE_PASSWORD}";
 $connection = pg_connect($conn_string) or die;
 $sql = "SELECT * FROM users NATURAL JOIN server_stakeholders";
 $result = pg_query($connection, $sql);
 $result_array = pg_fetch_all($result);
 $username_db = $result_array[0]['username'];
 if (empty($username_db) && $action == 'create') {
     //Only allow creating an adminstrator if we don't already have one.  Otherwise we have a HUGE security hole.
     //      require_once(dirname(__FILE__) . '/config.php');
     require_once dirname(__FILE__) . '/include/common.php';
     require_once dirname(__FILE__) . '/classes/User.php';
     $created_user = User::createUser(get_guid(), $username, Network::getDefaultNetwork(), $email, $password);
     $user_id = $created_user->getId();
     # Add user to admin table, hide his username and set his account status to 1 (allowed)
     $sql = "INSERT INTO server_stakeholders (user_id, role_id, object_id) VALUES ('{$user_id}', 'SERVER_OWNER', 'SERVER_ID');\n";
     $sql .= "INSERT INTO network_stakeholders (user_id, role_id, object_id) VALUES ('{$user_id}', 'NETWORK_OWNER', 'default-network');\n";
     $sql .= "UPDATE users SET account_status='1' WHERE user_id='{$user_id}'";
     $result = pg_query($connection, $sql);
 }
 $sql = "SELECT * FROM users NATURAL JOIN server_stakeholders";
 $result = pg_query($connection, $sql);
 $result_array = pg_fetch_all($result);
 $username_db = $result_array[0]['username'];
 if (!empty($username_db)) {
     #if a username exists
     print "<table>\n";
     print "<tr><th colspan=2>Your current administrator accounts are:</th></tr>\n";
 /**
  * Like the same method as defined in Content, this method will create a
  * ContentGroupElement based on the content type specified by
  * getNewContentUI OR get an existing element by getSelectExistingContentUI
  *
  * @param string $user_prefix                A identifier provided by the programmer to
  *                                           recognise it's generated form
  * @param string $content_group              Must be present
  * @param bool   $associate_existing_content If set to true, will get an
  *                                           existing element instead of creating a
  *                                           new content.
  *
  * @return object The ContentGroup object, or null if the user didn't greate one
  * @static
  */
 public static function processNewContentUI($user_prefix, ContentGroup $content_group, $associate_existing_content = false)
 {
     $db = AbstractDb::getObject();
     // Init values
     $content_group_element_object = null;
     $max_display_order_row = null;
     if ($associate_existing_content == true) {
         $displayed_content_object = Content::processSelectExistingContentUI($user_prefix);
     } else {
         $displayed_content_object = Content::processNewContentUI($user_prefix);
     }
     if ($displayed_content_object) {
         /* Get the display order to add the GontentGroupElement at the end */
         $sql = "SELECT MAX(display_order) as max_display_order FROM content_group_element WHERE content_group_id='" . $content_group->getId() . "'";
         $db->execSqlUniqueRes($sql, $max_display_order_row, false);
         $display_order = $max_display_order_row['max_display_order'] + 1;
         $content_id = get_guid();
         $content_type = 'ContentGroupElement';
         $sql = "INSERT INTO content (content_id, content_type) VALUES ('{$content_id}', '{$content_type}');";
         if (!$db->execSqlUpdate($sql, false)) {
             throw new Exception(_('Unable to insert new content group element into database!'));
         }
         $sql = "INSERT INTO content_group_element (content_group_element_id, content_group_id, display_order) VALUES ('{$content_id}', '" . $content_group->GetId() . "', {$display_order});";
         if (!$db->execSqlUpdate($sql, false)) {
             throw new Exception(_('Unable to insert new content group element into database!'));
         }
         $content_group_element_object = self::getObject($content_id);
         $content_group_element_object->replaceDisplayedContent($displayed_content_object);
     }
     return $content_group_element_object;
 }
Exemple #20
0
 public static function createNewObject(StakeholderType $stakeholderType, $id = null)
 {
     $db = AbstractDb::getObject();
     if (empty($id)) {
         $id = get_guid();
     }
     $idStr = $db->escapeString($id);
     $stakeholderTypeIdStr = $db->escapeString($stakeholderType->getId());
     $sql = "INSERT INTO roles (role_id, stakeholder_type_id) VALUES ('{$idStr}', '{$stakeholderTypeIdStr}')";
     if (!$db->execSqlUpdate($sql, false)) {
         throw new Exception(_('Unable to insert the new ContentTypeFilter in the database!'));
     }
     return self::getObject($id);
 }
Exemple #21
0
function update_1082()
{
    q("ALTER TABLE `photo` ADD `guid` CHAR( 64 ) NOT NULL AFTER `contact-id`,\n\t\tADD INDEX ( `guid` )  ");
    // make certain the following code is only executed once
    $r = q("select `id` from `photo` where `guid` != '' limit 1");
    if ($r && count($r)) {
        return;
    }
    $r = q("SELECT distinct(`resource-id`) FROM `photo` WHERE 1 group by `id`");
    if (count($r)) {
        foreach ($r as $rr) {
            $guid = get_guid();
            q("update `photo` set `guid` = '%s' where `resource-id` = '%s'", dbesc($guid), dbesc($rr['resource-id']));
        }
    }
}
Exemple #22
0
function send_wallmessage($recipient = '', $body = '', $subject = '', $replyto = '')
{
    $a = get_app();
    if (!$recipient) {
        return -1;
    }
    if (!strlen($subject)) {
        $subject = t('[no subject]');
    }
    $hash = random_string();
    $uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $hash;
    $convid = 0;
    $reply = false;
    require_once 'include/Scrape.php';
    $me = probe_url($replyto);
    if (!$me['name']) {
        return -2;
    }
    $conv_guid = get_guid();
    $recip_handle = $recipient['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3);
    $sender_nick = basename($replyto);
    $sender_host = substr($replyto, strpos($replyto, '://') + 3);
    $sender_host = substr($sender_host, 0, strpos($sender_host, '/'));
    $sender_handle = $sender_nick . '@' . $sender_host;
    $handles = $recip_handle . ';' . $sender_handle;
    $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ", intval($recipient['uid']), dbesc($conv_guid), dbesc($sender_handle), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($subject), dbesc($handles));
    $r = q("select * from conv where guid = '%s' and uid = %d limit 1", dbesc($conv_guid), intval($recipient['uid']));
    if (count($r)) {
        $convid = $r[0]['id'];
    }
    if (!$convid) {
        logger('send message: conversation not found.');
        return -4;
    }
    $r = q("INSERT INTO `mail` ( `uid`, `guid`, `convid`, `from-name`, `from-photo`, `from-url`, \n\t\t`contact-id`, `title`, `body`, `seen`, `reply`, `replied`, `uri`, `parent-uri`, `created`, `unknown`)\n\t\tVALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, %d, '%s', '%s', '%s', %d )", intval($recipient['uid']), dbesc(get_guid()), intval($convid), dbesc($me['name']), dbesc($me['photo']), dbesc($me['url']), 0, dbesc($subject), dbesc($body), 0, 0, 0, dbesc($uri), dbesc($replyto), datetime_convert(), 1);
    return 0;
}
Exemple #23
0
 if (!$selectedNetwork->getAuthenticator()->isRegistrationPermitted()) {
     throw new Exception(_("Sorry, this network does not accept new user registration !"));
 }
 // Validate entered values
 validate_username($username);
 validate_email($email);
 validate_passwords($password, $password_again);
 // Check if user exists
 if (User::getUserByUsernameAndOrigin($username, $selectedNetwork)) {
     throw new Exception(_("Sorry, a user account is already associated to this username. Pick another one."));
 }
 if (User::getUserByEmailAndOrigin($email, $selectedNetwork)) {
     throw new Exception(_("Sorry, a user account is already associated to this email address."));
 }
 // Create user and send him the validation email
 $created_user = User::createUser(get_guid(), $username, $selectedNetwork, $email, $password);
 $created_user->sendValidationEmail();
 // Authenticate this new user automatically
 $errmsg = "";
 $authenticated_user = $selectedNetwork->getAuthenticator()->login($username, $password, $errmsg);
 if (empty($authenticated_user)) {
     throw new Exception(_("Unable to authenticate newly created user.  Please report this bug.  Error was: {$errmsg}"));
 }
 // While in validation period, alert user that he should validate his account ASAP
 $validationMsgHtml = "<div id='warning_message_area'>\n";
 $validationMsgHtml .= _("An email with confirmation instructions was sent to your email address.");
 $validationMsgHtml .= sprintf(_("Your account has been granted %s minutes of access to retrieve your email and validate your account."), $selectedNetwork->getValidationGraceTime() / 60);
 $validationMsgHtml .= _('You may now open a browser window or start your email client and go to any remote Internet address to obtain the validation email.');
 $validationMsgHtml .= "</div>\n";
 // If the user is at a REAL hotspot, login the user and give him his sign-up minutes right away
 $session = Session::getObject();
Exemple #24
0
function item_store($arr, $force_parent = false)
{
    // If a Diaspora signature structure was passed in, pull it out of the
    // item array and set it aside for later storage.
    $dsprsig = null;
    if (x($arr, 'dsprsig')) {
        $dsprsig = json_decode(base64_decode($arr['dsprsig']));
        unset($arr['dsprsig']);
    }
    if (x($arr, 'gravity')) {
        $arr['gravity'] = intval($arr['gravity']);
    } elseif ($arr['parent-uri'] === $arr['uri']) {
        $arr['gravity'] = 0;
    } elseif (activity_match($arr['verb'], ACTIVITY_POST)) {
        $arr['gravity'] = 6;
    } else {
        $arr['gravity'] = 6;
    }
    // extensible catchall
    if (!x($arr, 'type')) {
        $arr['type'] = 'remote';
    }
    // Shouldn't happen but we want to make absolutely sure it doesn't leak from a plugin.
    if (strpos($arr['body'], '<') !== false || strpos($arr['body'], '>') !== false) {
        $arr['body'] = strip_tags($arr['body']);
    }
    $arr['wall'] = x($arr, 'wall') ? intval($arr['wall']) : 0;
    $arr['uri'] = x($arr, 'uri') ? notags(trim($arr['uri'])) : random_string();
    $arr['extid'] = x($arr, 'extid') ? notags(trim($arr['extid'])) : '';
    $arr['author-name'] = x($arr, 'author-name') ? notags(trim($arr['author-name'])) : '';
    $arr['author-link'] = x($arr, 'author-link') ? notags(trim($arr['author-link'])) : '';
    $arr['author-avatar'] = x($arr, 'author-avatar') ? notags(trim($arr['author-avatar'])) : '';
    $arr['owner-name'] = x($arr, 'owner-name') ? notags(trim($arr['owner-name'])) : '';
    $arr['owner-link'] = x($arr, 'owner-link') ? notags(trim($arr['owner-link'])) : '';
    $arr['owner-avatar'] = x($arr, 'owner-avatar') ? notags(trim($arr['owner-avatar'])) : '';
    $arr['created'] = x($arr, 'created') !== false ? datetime_convert('UTC', 'UTC', $arr['created']) : datetime_convert();
    $arr['edited'] = x($arr, 'edited') !== false ? datetime_convert('UTC', 'UTC', $arr['edited']) : datetime_convert();
    $arr['commented'] = datetime_convert();
    $arr['received'] = datetime_convert();
    $arr['changed'] = datetime_convert();
    $arr['title'] = x($arr, 'title') ? notags(trim($arr['title'])) : '';
    $arr['location'] = x($arr, 'location') ? notags(trim($arr['location'])) : '';
    $arr['coord'] = x($arr, 'coord') ? notags(trim($arr['coord'])) : '';
    $arr['last-child'] = x($arr, 'last-child') ? intval($arr['last-child']) : 0;
    $arr['visible'] = x($arr, 'visible') !== false ? intval($arr['visible']) : 1;
    $arr['deleted'] = 0;
    $arr['parent-uri'] = x($arr, 'parent-uri') ? notags(trim($arr['parent-uri'])) : '';
    $arr['verb'] = x($arr, 'verb') ? notags(trim($arr['verb'])) : '';
    $arr['object-type'] = x($arr, 'object-type') ? notags(trim($arr['object-type'])) : '';
    $arr['object'] = x($arr, 'object') ? trim($arr['object']) : '';
    $arr['target-type'] = x($arr, 'target-type') ? notags(trim($arr['target-type'])) : '';
    $arr['target'] = x($arr, 'target') ? trim($arr['target']) : '';
    $arr['plink'] = x($arr, 'plink') ? notags(trim($arr['plink'])) : '';
    $arr['allow_cid'] = x($arr, 'allow_cid') ? trim($arr['allow_cid']) : '';
    $arr['allow_gid'] = x($arr, 'allow_gid') ? trim($arr['allow_gid']) : '';
    $arr['deny_cid'] = x($arr, 'deny_cid') ? trim($arr['deny_cid']) : '';
    $arr['deny_gid'] = x($arr, 'deny_gid') ? trim($arr['deny_gid']) : '';
    $arr['private'] = x($arr, 'private') ? intval($arr['private']) : 0;
    $arr['bookmark'] = x($arr, 'bookmark') ? intval($arr['bookmark']) : 0;
    $arr['body'] = x($arr, 'body') ? trim($arr['body']) : '';
    $arr['tag'] = x($arr, 'tag') ? notags(trim($arr['tag'])) : '';
    $arr['attach'] = x($arr, 'attach') ? notags(trim($arr['attach'])) : '';
    $arr['app'] = x($arr, 'app') ? notags(trim($arr['app'])) : '';
    $arr['origin'] = x($arr, 'origin') ? intval($arr['origin']) : 0;
    $arr['guid'] = x($arr, 'guid') ? notags(trim($arr['guid'])) : get_guid();
    if ($arr['parent-uri'] === $arr['uri']) {
        $parent_id = 0;
        $parent_deleted = 0;
        $allow_cid = $arr['allow_cid'];
        $allow_gid = $arr['allow_gid'];
        $deny_cid = $arr['deny_cid'];
        $deny_gid = $arr['deny_gid'];
    } else {
        // find the parent and snarf the item id and ACL's
        // and anything else we need to inherit
        $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1", dbesc($arr['parent-uri']), intval($arr['uid']));
        if (count($r)) {
            // is the new message multi-level threaded?
            // even though we don't support it now, preserve the info
            // and re-attach to the conversation parent.
            if ($r[0]['uri'] != $r[0]['parent-uri']) {
                $arr['thr-parent'] = $arr['parent-uri'];
                $arr['parent-uri'] = $r[0]['parent-uri'];
                $z = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d \n\t\t\t\t\tORDER BY `id` ASC LIMIT 1", dbesc($r[0]['parent-uri']), dbesc($r[0]['parent-uri']), intval($arr['uid']));
                if ($z && count($z)) {
                    $r = $z;
                }
            }
            $parent_id = $r[0]['id'];
            $parent_deleted = $r[0]['deleted'];
            $allow_cid = $r[0]['allow_cid'];
            $allow_gid = $r[0]['allow_gid'];
            $deny_cid = $r[0]['deny_cid'];
            $deny_gid = $r[0]['deny_gid'];
            $arr['wall'] = $r[0]['wall'];
        } else {
            // Allow one to see reply tweets from status.net even when
            // we don't have or can't see the original post.
            if ($force_parent) {
                logger('item_store: $force_parent=true, reply converted to top-level post.');
                $parent_id = 0;
                $arr['thr-parent'] = $arr['parent-uri'];
                $arr['parent-uri'] = $arr['uri'];
                $arr['gravity'] = 0;
            } else {
                logger('item_store: item parent was not found - ignoring item');
                return 0;
            }
            $parent_deleted = 0;
        }
    }
    $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($arr['uri']), intval($arr['uid']));
    if ($r && count($r)) {
        logger('item-store: duplicate item ignored. ' . print_r($arr, true));
        return 0;
    }
    call_hooks('post_remote', $arr);
    if (x($arr, 'cancel')) {
        logger('item_store: post cancelled by plugin.');
        return 0;
    }
    dbesc_array($arr);
    logger('item_store: ' . print_r($arr, true), LOGGER_DATA);
    $r = dbq("INSERT INTO `item` (`" . implode("`, `", array_keys($arr)) . "`) VALUES ('" . implode("', '", array_values($arr)) . "')");
    // find the item we just created
    $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC ", $arr['uri'], intval($arr['uid']));
    if (count($r)) {
        $current_post = $r[0]['id'];
        logger('item_store: created item ' . $current_post);
    } else {
        logger('item_store: could not locate created item');
        return 0;
    }
    if (count($r) > 1) {
        logger('item_store: duplicated post occurred. Removing duplicates.');
        q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `id` != %d ", $arr['uri'], intval($arr['uid']), intval($current_post));
    }
    if (!$parent_id || $arr['parent-uri'] === $arr['uri']) {
        $parent_id = $current_post;
    }
    if (strlen($allow_cid) || strlen($allow_gid) || strlen($deny_cid) || strlen($deny_gid)) {
        $private = 1;
    } else {
        $private = $arr['private'];
    }
    // Set parent id - and also make sure to inherit the parent's ACL's.
    $r = q("UPDATE `item` SET `parent` = %d, `allow_cid` = '%s', `allow_gid` = '%s',\n\t\t`deny_cid` = '%s', `deny_gid` = '%s', `private` = %d, `deleted` = %d WHERE `id` = %d LIMIT 1", intval($parent_id), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid), intval($private), intval($parent_deleted), intval($current_post));
    // update the commented timestamp on the parent
    q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent_id));
    if ($dsprsig) {
        q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($current_post), dbesc($dsprsig->signed_text), dbesc($dsprsig->signature), dbesc($dsprsig->signer));
    }
    /**
     * If this is now the last-child, force all _other_ children of this parent to *not* be last-child
     */
    if ($arr['last-child']) {
        $r = q("UPDATE `item` SET `last-child` = 0 WHERE `parent-uri` = '%s' AND `uid` = %d AND `id` != %d", dbesc($arr['uri']), intval($arr['uid']), intval($current_post));
    }
    tag_deliver($arr['uid'], $current_post);
    return $current_post;
}
         } else {
             $username_str = $db->escapeString($username);
             $db->execSqlUniqueRes("SELECT username FROM users WHERE username='******'", $user_info_username, false);
             if ($user_info_username != null) {
                 $import_user[$username]['is_rejected'] = true;
                 $import_user[$username]['reject_reason'] .= "<p class=error>" . _('Sorry, a user account already exists with the username: '******'import_confirm']) && $_REQUEST['import_confirm'] == 'true' && $import_user[$username]['is_rejected'] == false) {
         $status = ACCOUNT_STATUS_ALLOWED;
         $token = User::generateToken();
         $password_hash = $db->escapeString($user['passwd_hash']);
         $username = $db->escapeString($username);
         $email = $db->escapeString($user['email']);
         $sql = "INSERT INTO users (user_id, username,email,pass,account_status,validation_token,reg_date) VALUES ('" . get_guid() . "','{$username}','{$email}','{$password_hash}','{$status}','{$token}',CURRENT_TIMESTAMP)";
         $update_successful = $db->execSqlUpdate($sql);
         if ($update_successful) {
             //send_validation_email($email);
             $showform = false;
         } else {
             $import_user[$username]['is_rejected'] = true;
             $import_user[$username]['reject_reason'] .= "<p class=error>" . _('SQL error on: ') . "{$sql}</p>\n";
         }
     }
 }
 $html .= "<h2>" . _('Report') . "</h2>\n";
 /* List rejected users */
 $html .= "<table>\n";
 $count_reject = 0;
 $count_success = 0;
Exemple #26
0
/**
 * @return string
 */
function generate_user_guid()
{
    $found = true;
    do {
        $guid = get_guid(32);
        $x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1", dbesc($guid));
        if (!count($x)) {
            $found = false;
        }
    } while ($found == true);
    return $guid;
}
Exemple #27
0
 /**
  * Ajoute une chaîne de caractère au Langstring
  *
  * @param string $string             La chaîne de caractère à ajouter.  Si la chaîne
  *                                   est vide ('') ou null, la fonction retourne sans
  *                                   toucher à la base de donnée
  * @param string $locale             La langue régionale de la chaîne ajoutée, exemple:
  *                                   'fr_CA', peut être NULL
  * @param bool   $allow_empty_string Allow to store an empty string
  *
  * @return bool True si une chaîne a été ajoutée à la base de donnée,
  * false autrement.
  */
 public function addString($string, $locale = null, $allow_empty_string = false)
 {
     // Init values
     $retval = false;
     $id = 'NULL';
     $idSQL = $id;
     if ($locale) {
         $language = new WifidogLocale($locale);
         $id = $language->GetId();
         $idSQL = "'" . $id . "'";
     }
     if ($allow_empty_string || $string != null && $string != '') {
         $string = $this->mBd->escapeString($string);
         $this->mBd->execSqlUpdate("INSERT INTO content_langstring_entries (langstring_entries_id, langstrings_id, locales_id, value) VALUES ('" . get_guid() . "', '{$this->id}', {$idSQL} , '{$string}')", FALSE);
         // Create new cache object.
         $_cache = new Cache('langstrings_' . $this->id . '_substring_' . $id . '_string', $this->id);
         // Check if caching has been enabled.
         if ($_cache->isCachingEnabled) {
             // Remove old cached data.
             $_cache->eraseCachedData();
             // Save data into cache.
             $_cache->saveCachedData($string);
         }
         $retval = true;
     }
     return $retval;
 }
function retriever_store_photo($item, &$resource)
{
    $hash = photo_new_resource();
    if (class_exists('Imagick')) {
        try {
            $image = new Imagick();
            $image->readImageBlob($resource['data']);
            $resource['width'] = $image->getImageWidth();
            $resource['height'] = $image->getImageHeight();
        } catch (Exception $e) {
            logger("ImageMagick couldn't process image " . $resource['id'] . " " . $resource['url'] . ' length ' . strlen($resource['data']) . ': ' . $e->getMessage(), LOGGER_DEBUG);
            return false;
        }
    }
    if (!array_key_exists('width', $resource)) {
        $image = @imagecreatefromstring($resource['data']);
        if ($image === false) {
            logger("Couldn't process image " . $resource['id'] . " " . $resource['url'], LOGGER_DEBUG);
            return false;
        }
        $resource['width'] = imagesx($image);
        $resource['height'] = imagesy($image);
        imagedestroy($image);
    }
    $url_components = parse_url($resource['url']);
    $filename = basename($url_components['path']);
    if (!strlen($filename)) {
        $filename = 'image';
    }
    $r = q("INSERT INTO `photo`\n                ( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, `type`, `album`, `height`, `width`, `datasize`, `data` )\n                VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' )", intval($item['item-uid']), intval($item['contact-id']), dbesc(get_guid()), dbesc($hash), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($filename), dbesc($resource['type']), dbesc('Retrieved Images'), intval($resource['height']), intval($resource['width']), intval(strlen($resource['data'])), dbesc($resource['data']));
    return $hash;
}
Exemple #29
0
 /**
  * Get a flexible interface to generate new content objects
  *
  * @param string $user_prefix      A identifier provided by the programmer
  *                                 to recognise it's generated HTML form
  * @param string $content_type_filter     If set, the created content must match the filter.  Of only one type matches,
  * the content will be of this type, otherwise, the user will have
  *                                 to choose
  *
  * @return string HTML markup
  */
 public static function getNewContentUI($user_prefix, $content_type_filter = null, $title = null)
 {
     //echo "Content::getNewContentUI()";
     // Init values
     $html = "";
     $getNewUIData = null;
     $html .= "<fieldset class='admin_container Content'>\n";
     if (!empty($title)) {
         $html .= "<legend>{$title}</legend>\n";
     }
     $futureContentId = get_guid();
     $name = "get_new_content_{$user_prefix}_future_id";
     $html .= '<input type="hidden" name="' . $name . '" value="' . $futureContentId . '">';
     $userData['contentTypeFilter'] = $content_type_filter;
     $html .= Content::getNewUI($futureContentId, $userData);
     $html .= "</fieldset>\n";
     return $html;
 }
/**
 * Try to bring the database schema up to date.
 * @param $schema_version The target schema
 * @return void
 */
function real_update_schema($targetSchema)
{
    $sql = '';
    $db = AbstractDb::getObject();
    $db->execSqlUniqueRes("SELECT * FROM schema_info WHERE tag='schema_version'", $row, false);
    //Re-check the schema version, it could have been updated by another thread
    $schema_version = $row['value'];
    $new_schema_version = 2;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE users ADD COLUMN username text;\n";
        $sql .= "ALTER TABLE users ADD COLUMN account_origin text;\n";
        $db->execSql("SELECT user_id FROM users", $results, false);
        foreach ($results as $row) {
            $user_id = $db->escapeString($row['user_id']);
            $sql .= "UPDATE users SET username='******', user_id='" . get_guid() . "', account_origin='LOCAL_USER' WHERE user_id='{$user_id}';\n";
        }
        $sql .= "CREATE UNIQUE INDEX idx_unique_username_and_account_origin ON users (username, account_origin);\n";
        $sql .= "CREATE UNIQUE INDEX idx_unique_email_and_account_origin ON users USING btree (email, account_origin);\n";
    }
    $new_schema_version = 3;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "DROP INDEX idx_unique_email_and_account_origin;\n";
        $sql .= "ALTER TABLE users DROP CONSTRAINT check_email_not_empty;\n";
    }
    $new_schema_version = 4;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE users ALTER COLUMN account_origin SET NOT NULL;\n";
        $sql .= "ALTER TABLE users ADD CONSTRAINT check_account_origin_not_empty CHECK (account_origin::text <> ''::text);\n";
        // We must skip all other updates because schema 5 must be manually updated:
        $schema_version = 1000000;
    }
    $new_schema_version = 5;
    if ($schema_version == $new_schema_version - 1) {
        echo "<h1>Recoding database from ISO-8859-1 to UTF-8</h1>";
        echo "<h1>YOU MUST EXECUTE THESE COMMANDS FROM THE COMMAND_LINE:</h1>";
        echo "pg_dump wifidog -U wifidog > wifidog_dump.sql;<br>";
        echo "dropdb wifidog -U wifidog; <br>";
        echo "createdb --encoding=UNICODE --template=template0 -U wifidog wifidog;<br>";
        echo "psql wifidog -U wifidog < wifidog_dump.sql;<br>\n";
        echo " (Note: You may ignore the following errors:  \"ERROR:  permission denied to set session authorization\" and \"ERROR:  must be owner of schema public\")<br>";
        echo "psql wifidog -U wifidog -c \"UPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version'\";<br>";
        exit;
    }
    $new_schema_version = 6;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE locales ( \n";
        $sql .= "  locales_id text PRIMARY KEY \n";
        $sql .= "  ); \n";
        $sql .= "  INSERT INTO locales VALUES ('fr'); \n";
        $sql .= "  INSERT INTO locales VALUES ('en'); \n";
        $sql .= "ALTER TABLE users ADD COLUMN never_show_username bool;\n";
        $sql .= "ALTER TABLE users ALTER COLUMN never_show_username SET DEFAULT FALSE;\n";
        $sql .= "ALTER TABLE users ADD COLUMN real_name text;\n";
        $sql .= "ALTER TABLE users ALTER COLUMN real_name SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE users ADD COLUMN website text;\n";
        $sql .= "ALTER TABLE users ALTER COLUMN website SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE users ADD COLUMN prefered_locale text REFERENCES locales ON DELETE SET NULL ON UPDATE CASCADE;\n";
        $sql .= "\n                                                CREATE TABLE content\n                                                (\n                                                content_id text NOT NULL PRIMARY KEY,\n                                                content_type text NOT NULL  CONSTRAINT content_type_not_empty_string CHECK (content_type != ''),\n                                                title text REFERENCES content ON DELETE RESTRICT ON UPDATE CASCADE,\n                                                description text REFERENCES content ON DELETE RESTRICT ON UPDATE CASCADE,\n                                                project_info text REFERENCES content ON DELETE RESTRICT ON UPDATE CASCADE,\n                                                sponsor_info text REFERENCES content ON DELETE RESTRICT ON UPDATE CASCADE,\n                                                creation_timestamp timestamp DEFAULT now()\n                                                );\n                                \n                                                CREATE TABLE content_has_owners\n                                                (\n                                                content_id text NOT NULL REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                user_id text NOT NULL REFERENCES users ON DELETE CASCADE ON UPDATE CASCADE,\n                                                is_author bool NOT NULL,\n                                                owner_since timestamp DEFAULT now(),\n                                                PRIMARY KEY  (content_id, user_id)\n                                                );\n                                \n                                                CREATE TABLE langstring_entries (\n                                                  langstring_entries_id text NOT NULL PRIMARY KEY,\n                                                  langstrings_id text REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  locales_id text REFERENCES locales ON DELETE RESTRICT ON UPDATE CASCADE,\n                                                  value text  DEFAULT ''\n                                                );\n                                \n                                                CREATE TABLE content_group (\n                                                  content_group_id text NOT NULL PRIMARY KEY REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  is_artistic_content bool NOT NULL DEFAULT FALSE,\n                                                  is_locative_content bool NOT NULL DEFAULT FALSE,\n                                                  content_selection_mode text\n                                                );\n                                \n                                                CREATE TABLE content_group_element (\n                                                  content_group_element_id text NOT NULL PRIMARY KEY REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  content_group_id text NOT NULL REFERENCES content_group ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  display_order integer DEFAULT '1',\n                                                  displayed_content_id text REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  force_only_allowed_node bool\n                                                );\n                                                CREATE INDEX idx_content_group_element_content_group_id ON content_group_element (content_group_id);\n                                \n                                                CREATE TABLE content_group_element_has_allowed_nodes\n                                                (\n                                                content_group_element_id text NOT NULL REFERENCES content_group_element ON DELETE CASCADE ON UPDATE CASCADE,\n                                                node_id text NOT NULL REFERENCES nodes ON DELETE CASCADE ON UPDATE CASCADE,\n                                                allowed_since timestamp DEFAULT now(),\n                                                PRIMARY KEY  (content_group_element_id, node_id)\n                                                );\n                                \n                                                CREATE TABLE content_group_element_portal_display_log (\n                                                  user_id text NOT NULL REFERENCES users ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  content_group_element_id text NOT NULL REFERENCES content_group_element ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  display_timestamp timestamp NOT NULL DEFAULT now(),\n                                                  node_id text REFERENCES nodes ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  PRIMARY KEY  (user_id,content_group_element_id, display_timestamp)\n                                                );\n                                \n                                                CREATE TABLE user_has_content (\n                                                  user_id text NOT NULL REFERENCES users ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  content_id text NOT NULL REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  subscribe_timestamp timestamp NOT NULL DEFAULT now(),\n                                                  PRIMARY KEY  (user_id,content_id)\n                                                );\n                                \n                                                CREATE TABLE node_has_content (\n                                                  node_id text NOT NULL REFERENCES nodes ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  content_id text NOT NULL REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  subscribe_timestamp timestamp NOT NULL DEFAULT now(),\n                                                  PRIMARY KEY  (node_id,content_id)\n                                                );\n                                \n                                                CREATE TABLE network_has_content (\n                                                  network_id text NOT NULL,\n                                                  content_id text NOT NULL REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,\n                                                  subscribe_timestamp timestamp NOT NULL DEFAULT now(),\n                                                  PRIMARY KEY  (network_id,content_id)\n                                                );";
    }
    $new_schema_version = 7;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content ADD COLUMN is_persistent bool;\n";
        $sql .= "ALTER TABLE content ALTER COLUMN is_persistent SET DEFAULT FALSE;\n";
    }
    $new_schema_version = 8;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE flickr_photostream\n                                                        (\n                                                          flickr_photostream_id text NOT NULL,\n                                                          api_key text,\n                                                          photo_selection_mode text NOT NULL DEFAULT 'PSM_GROUP'::text,\n                                                          user_id text,\n                                                          user_name text,\n                                                          tags text,\n                                                          tag_mode varchar(10) DEFAULT 'any'::character varying,\n                                                          group_id text,\n                                                          random bool NOT NULL DEFAULT true,\n                                                          min_taken_date timestamp,\n                                                          max_taken_date timestamp,\n                                                          photo_batch_size int4 DEFAULT 10,\n                                                          photo_count int4 DEFAULT 1,\n                                                          display_title bool NOT NULL DEFAULT true,\n                                                          display_description bool NOT NULL DEFAULT false,\n                                                          display_tags bool NOT NULL DEFAULT false,\n                                                          CONSTRAINT flickr_photostream_pkey PRIMARY KEY (flickr_photostream_id),\n                                                          CONSTRAINT flickr_photostream_content_group_fkey FOREIGN KEY (flickr_photostream_id) REFERENCES content_group (content_group_id) ON UPDATE CASCADE ON DELETE CASCADE\n                                                        );";
    }
    $new_schema_version = 9;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE files\n                                                        (\n                                                          files_id text NOT NULL,\n                                                          filename text,\n                                                          mime_type text,\n                                                          binary_data bytea,\n                                                          remote_size bigint,\n                                                          CONSTRAINT files_pkey PRIMARY KEY (files_id)\n                                                        );";
    }
    $new_schema_version = 10;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE files ADD COLUMN url text;";
        $sql .= "ALTER TABLE flickr_photostream ADD COLUMN preferred_size text;";
        $sql .= "CREATE TABLE embedded_content (\n                                                            embedded_content_id text NOT NULL,\n                                                            embedded_file_id text,\n                                                            fallback_content_id text,\n                                                            parameters text,\n                                                            attributes text\n                                                        );";
    }
    $new_schema_version = 11;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "DROP TABLE content_group_element_portal_display_log;\n";
        $sql .= "CREATE TABLE content_display_log\n                                            (\n                                              user_id text NOT NULL REFERENCES users ON UPDATE CASCADE ON DELETE CASCADE,\n                                              content_id text NOT NULL REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE,\n                                              first_display_timestamp timestamp NOT NULL DEFAULT now(),\n                                              node_id text NOT NULL REFERENCES nodes ON UPDATE CASCADE ON DELETE CASCADE,\n                                              last_display_timestamp timestamp NOT NULL DEFAULT now(),\n                                              CONSTRAINT content_group_element_portal_display_log_pkey PRIMARY KEY (user_id, content_id, node_id)\n                                            ); \n";
    }
    $new_schema_version = 12;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE flickr_photostream DROP CONSTRAINT flickr_photostream_content_group_fkey;";
        $sql .= "ALTER TABLE flickr_photostream ADD CONSTRAINT flickr_photostream_content_fkey FOREIGN KEY (flickr_photostream_id) REFERENCES content (content_id) ON UPDATE CASCADE ON DELETE CASCADE;";
    }
    $new_schema_version = 13;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content_group DROP COLUMN content_selection_mode;\n";
        $sql .= "ALTER TABLE content_group ADD COLUMN content_changes_on_mode text;\n";
        $sql .= "UPDATE content_group SET content_changes_on_mode='ALWAYS';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN content_changes_on_mode SET DEFAULT 'ALWAYS';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN content_changes_on_mode SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_group ADD COLUMN content_ordering_mode text;\n";
        $sql .= "UPDATE content_group SET content_ordering_mode='RANDOM';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN content_ordering_mode SET DEFAULT 'RANDOM';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN content_ordering_mode SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_group ADD COLUMN display_num_elements int;\n";
        $sql .= "UPDATE content_group SET display_num_elements=1;\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN display_num_elements SET DEFAULT '1';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN display_num_elements SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_group ADD CONSTRAINT display_at_least_one_element CHECK (display_num_elements > 0);\n";
        $sql .= "ALTER TABLE content_group ADD COLUMN allow_repeat text;\n";
        $sql .= "UPDATE content_group SET allow_repeat='YES';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN allow_repeat SET DEFAULT 'YES';\n";
        $sql .= "ALTER TABLE content_group ALTER COLUMN allow_repeat SET NOT NULL;\n";
    }
    $new_schema_version = 14;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE pictures " . "( " . "pictures_id text NOT NULL PRIMARY KEY REFERENCES files ON DELETE CASCADE ON UPDATE CASCADE, " . "width int4, " . "height int4" . ");\n";
    }
    $new_schema_version = 15;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE files ADD COLUMN data_blob oid;\n                                                                ALTER TABLE files ADD COLUMN local_binary_size int8;\n                                                                ALTER TABLE files DROP COLUMN binary_data;\n";
    }
    $new_schema_version = 16;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE flickr_photostream ADD COLUMN requests_cache text; \n";
        $sql .= "ALTER TABLE flickr_photostream ADD COLUMN cache_update_timestamp timestamp; \n";
    }
    $new_schema_version = 17;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN max_monthly_incoming int8; \n";
        $sql .= "ALTER TABLE nodes ADD COLUMN max_monthly_outgoing int8; \n";
        $sql .= "ALTER TABLE nodes ADD COLUMN quota_reset_day_of_month int4; \n";
    }
    $new_schema_version = 18;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content ADD COLUMN long_description text REFERENCES content ON DELETE RESTRICT ON UPDATE CASCADE;\n";
    }
    $new_schema_version = 19;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE iframes (";
        $sql .= "iframes_id text NOT NULL PRIMARY KEY REFERENCES content ON DELETE CASCADE ON UPDATE CASCADE,";
        $sql .= "url text,";
        $sql .= "width int4,";
        $sql .= "height int4";
        $sql .= ");\n";
    }
    $new_schema_version = 20;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN latitude NUMERIC(16, 6);\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN longitude NUMERIC(16, 6);\n";
    }
    $new_schema_version = 21;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE content_rss_aggregator \n";
        $sql .= "( \n";
        $sql .= "content_id text NOT NULL PRIMARY KEY REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "number_of_display_items integer NOT NULL DEFAULT 10, \n";
        $sql .= "algorithm_strength real NOT NULL DEFAULT 0.75, \n";
        $sql .= "max_item_age interval DEFAULT NULL \n";
        $sql .= "); \n";
        $sql .= "CREATE TABLE content_rss_aggregator_feeds \n";
        $sql .= "( ";
        $sql .= "content_id text NOT NULL REFERENCES content_rss_aggregator ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "url text, \n";
        $sql .= "bias real NOT NULL DEFAULT 1, \n";
        $sql .= "default_publication_interval int DEFAULT NULL, \n";
        $sql .= "PRIMARY KEY(content_id, url) \n";
        $sql .= "); \n";
        $sql .= "ALTER TABLE content_has_owners ALTER COLUMN is_author SET DEFAULT 'f';\n";
        $results = null;
        $db->execSql("SELECT node_id, rss_url FROM nodes", $results, false);
        foreach ($results as $row) {
            if (!empty($row['rss_url'])) {
                $content_id = get_guid();
                $sql .= "\nINSERT INTO content (content_id, content_type) VALUES ('{$content_id}', 'RssAggregator');\n";
                $sql .= "INSERT INTO content_rss_aggregator (content_id) VALUES ('{$content_id}');\n";
                $sql .= "INSERT INTO content_rss_aggregator_feeds (content_id, url) VALUES ('{$content_id}', '" . $row['rss_url'] . "');\n";
                $node = Node::getObject($row['node_id']);
                $db->execSql("SELECT user_id FROM node_stakeholders WHERE is_owner = true AND node_id='" . $node->getId() . "'", $ownersRow, false);
                if ($ownersRow != null) {
                    foreach ($ownersRow as $owner_row) {
                        $sql .= "INSERT INTO content_has_owners (content_id, user_id) VALUES ('{$content_id}', '" . $owner_row['user_id'] . "');\n";
                    }
                }
                $sql .= "INSERT INTO node_has_content (content_id, node_id) VALUES ('{$content_id}', '" . $row['node_id'] . "');\n";
            }
        }
        $sql .= "\nALTER TABLE nodes DROP COLUMN rss_url;\n";
        $sql .= "\nDELETE FROM content WHERE content_type='HotspotRss';\n";
    }
    $new_schema_version = 22;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN civic_number text;\n";
        // Dropping street_address and copying data to street_name for the sake of backward compatibility
        $sql .= "ALTER TABLE nodes ADD COLUMN street_name text;\n";
        $sql .= "UPDATE nodes SET street_name = street_address;\n";
        $sql .= "ALTER TABLE nodes DROP COLUMN street_address;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN city text;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN province text;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN country text;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN postal_code text;\n";
    }
    $new_schema_version = 23;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE node_tech_officers (\n";
        $sql .= "  node_id VARCHAR(32) REFERENCES nodes (node_id),\n";
        $sql .= "  user_id VARCHAR(45) REFERENCES users (user_id),\n";
        $sql .= "PRIMARY KEY (node_id, user_id)\n";
        $sql .= ");\n";
    }
    $new_schema_version = 24;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content_rss_aggregator_feeds ADD COLUMN title text; \n";
    }
    $new_schema_version = 25;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE node_stakeholders ( \n";
        $sql .= "  node_id VARCHAR(32) REFERENCES nodes (node_id),\n";
        $sql .= "  user_id VARCHAR(45) REFERENCES users (user_id),\n";
        $sql .= "  is_owner BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "  is_tech_officer BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "PRIMARY KEY (node_id, user_id)\n";
        $sql .= ");\n";
        $sql .= "INSERT INTO node_stakeholders (node_id, user_id) SELECT node_id, user_id FROM node_owners UNION SELECT node_id, user_id FROM node_tech_officers;\n";
        $sql .= "UPDATE node_stakeholders SET is_owner = true FROM node_owners WHERE node_stakeholders.node_id = node_owners.node_id AND node_stakeholders.user_id = node_owners.user_id;\n";
        $sql .= "UPDATE node_stakeholders SET is_tech_officer = true FROM node_tech_officers WHERE node_stakeholders.node_id = node_tech_officers.node_id AND node_stakeholders.user_id = node_tech_officers.user_id;";
        $sql .= "DROP TABLE node_owners;\n";
        $sql .= "DROP TABLE node_tech_officers;\n";
    }
    $new_schema_version = 26;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE networks ( \n";
        $sql .= "  network_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "  network_authenticator_class text NOT NULL CHECK (network_authenticator_class<>''),\n";
        $sql .= "  network_authenticator_params text,\n";
        $sql .= "  is_default_network boolean NOT NULL DEFAULT FALSE,\n";
        $sql .= "  name text NOT NULL DEFAULT 'Unnamed network' CHECK (name<>''),\n";
        $sql .= "  creation_date date NOT NULL DEFAULT now(),\n";
        $sql .= "  homepage_url text,\n";
        $sql .= "  tech_support_email text,\n";
        $sql .= "  validation_grace_time interval NOT NULL DEFAULT '1200 seconds',\n";
        $sql .= "  validation_email_from_address text NOT NULL CHECK (validation_email_from_address<>'') DEFAULT 'validation@wifidognetwork',\n";
        $sql .= "  allow_multiple_login BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "  allow_splash_only_nodes BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "  allow_custom_portal_redirect BOOLEAN NOT NULL DEFAULT FALSE\n";
        $sql .= ");\n";
        $sql .= "INSERT INTO networks (network_id, network_authenticator_class, network_authenticator_params) SELECT  account_origin, COALESCE('AuthenticatorLocalUser') as network_authenticator_class, '\\'' || account_origin || '\\'' FROM users GROUP BY (account_origin) ORDER BY min(reg_date);\n";
        $sql .= "UPDATE networks SET is_default_network=TRUE WHERE network_id=(SELECT account_origin FROM users GROUP BY (account_origin) ORDER BY min(reg_date) LIMIT 1);\n";
        $sql .= "ALTER TABLE users ADD CONSTRAINT account_origin_fkey FOREIGN KEY (account_origin) REFERENCES networks (network_id) ON UPDATE CASCADE ON DELETE RESTRICT;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN network_id text; \n";
        $sql .= "UPDATE nodes SET network_id=(SELECT account_origin FROM users GROUP BY (account_origin) ORDER BY min(reg_date) LIMIT 1);\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN network_id SET NOT NULL; \n";
        $sql .= "ALTER TABLE nodes ADD CONSTRAINT network_id_fkey FOREIGN KEY (network_id) REFERENCES networks ON UPDATE CASCADE ON DELETE RESTRICT;\n";
        $sql .= "ALTER TABLE network_has_content ADD CONSTRAINT network_id_fkey FOREIGN KEY (network_id) REFERENCES networks ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "CREATE TABLE network_stakeholders ( \n";
        $sql .= "  network_id text REFERENCES networks,\n";
        $sql .= "  user_id VARCHAR(45) REFERENCES users,\n";
        $sql .= "  is_admin BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "  is_stat_viewer BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "PRIMARY KEY (network_id, user_id)\n";
        $sql .= ");\n";
    }
    $new_schema_version = 27;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN last_paged timestamp;\n";
    }
    $new_schema_version = 28;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN is_splash_only_node boolean;\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN is_splash_only_node SET DEFAULT FALSE;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN custom_portal_redirect_url text;\n";
    }
    $new_schema_version = 29;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE flickr_photostream ADD COLUMN api_shared_secret text;\n";
    }
    $new_schema_version = 30;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE INDEX idx_connections_user_id ON connections (user_id);\n";
        $sql .= "CREATE INDEX idx_connections_user_mac ON connections (user_mac);\n";
        $sql .= "CREATE INDEX idx_connections_node_id ON connections (node_id);\n";
    }
    $new_schema_version = 31;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE content_display_location ( \n";
        $sql .= "  display_location text NOT NULL PRIMARY KEY\n";
        $sql .= ");\n";
        $sql .= "INSERT INTO content_display_location (display_location) VALUES ('portal_page');\n";
        $sql .= "INSERT INTO content_display_location (display_location) VALUES ('login_page');\n";
        $sql .= "ALTER TABLE network_has_content ADD COLUMN display_location text;\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_location SET DEFAULT 'portal_page';\n";
        $sql .= "UPDATE network_has_content SET display_location='portal_page';\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_location SET NOT NULL;\n";
        $sql .= "ALTER TABLE network_has_content ADD CONSTRAINT display_location_fkey FOREIGN KEY (display_location) REFERENCES content_display_location ON UPDATE CASCADE ON DELETE RESTRICT;\n";
        $sql .= "ALTER TABLE node_has_content ADD COLUMN display_location text;\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_location SET DEFAULT 'portal_page';\n";
        $sql .= "UPDATE node_has_content SET display_location='portal_page';\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_location SET NOT NULL;\n";
        $sql .= "ALTER TABLE node_has_content ADD CONSTRAINT display_location_fkey FOREIGN KEY (display_location) REFERENCES content_display_location ON UPDATE CASCADE ON DELETE RESTRICT;\n";
        /* Convert the existing node logos */
        $results = null;
        $db->execSql("SELECT node_id FROM nodes", $results, false);
        define('HOTSPOT_LOGO_NAME', 'hotspot_logo.jpg');
        foreach ($results as $row) {
            $php_logo_path = WIFIDOG_ABS_FILE_PATH . LOCAL_CONTENT_REL_PATH . $row['node_id'] . '/' . HOTSPOT_LOGO_NAME;
            if (file_exists($php_logo_path)) {
                $node_logo_abs_url = $db->escapeString(BASE_URL_PATH . LOCAL_CONTENT_REL_PATH . $row['node_id'] . '/' . HOTSPOT_LOGO_NAME);
                $content_id = get_guid();
                $sql .= "\nINSERT INTO content (content_id, content_type) VALUES ('{$content_id}', 'Picture');\n";
                $sql .= "INSERT INTO files (files_id, url) VALUES ('{$content_id}', '{$node_logo_abs_url}');\n";
                $sql .= "INSERT INTO pictures (pictures_id) VALUES ('{$content_id}');\n";
                $node = Node::getObject($row['node_id']);
                $db->execSql("SELECT user_id FROM node_stakeholders WHERE is_owner = true AND node_id='" . $node->getId() . "'", $ownersRow, false);
                if ($ownersRow != null) {
                    foreach ($ownersRow as $owner_row) {
                        $sql .= "INSERT INTO content_has_owners (content_id, user_id) VALUES ('{$content_id}', '" . $owner_row['user_id'] . "');\n";
                    }
                }
                $sql .= "INSERT INTO node_has_content (content_id, node_id, display_location) VALUES ('{$content_id}', '" . $row['node_id'] . "', 'login_page');\n";
            }
        }
    }
    $new_schema_version = 32;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "INSERT INTO locales VALUES ('de');\n";
    }
    $new_schema_version = 33;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE flickr_photostream ADD COLUMN photo_display_mode text;\n";
        $sql .= "ALTER TABLE flickr_photostream ALTER COLUMN photo_display_mode SET DEFAULT 'PDM_GRID'::text;\n";
        $sql .= "UPDATE flickr_photostream SET photo_display_mode = 'PDM_GRID';\n";
        $sql .= "ALTER TABLE flickr_photostream ALTER COLUMN photo_display_mode SET NOT NULL;\n";
    }
    $new_schema_version = 34;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE node_stakeholders DROP CONSTRAINT \"\$1\";\n";
        $sql .= "ALTER TABLE node_stakeholders ADD CONSTRAINT nodes_fkey FOREIGN KEY (node_id) REFERENCES nodes(node_id) ON UPDATE CASCADE ON DELETE CASCADE;";
    }
    $new_schema_version = 35;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE servers ( \n";
        $sql .= "  server_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "  is_default_server boolean NOT NULL DEFAULT FALSE,\n";
        $sql .= "  name text NOT NULL DEFAULT 'Unnamed server' CHECK (name<>''),\n";
        $sql .= "  creation_date date NOT NULL DEFAULT now(),\n";
        $sql .= "  hostname text NOT NULL DEFAULT 'localhost' CHECK (name<>''),\n";
        $sql .= "  ssl_available BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "  gmaps_api_key text\n";
        $sql .= ");\n";
        $sql .= "INSERT INTO servers (server_id, is_default_server, name, creation_date, hostname, ssl_available, gmaps_api_key) VALUES ('" . str_replace(".", "-", $_SERVER['SERVER_NAME']) . "', TRUE, 'Unnamed server', (SELECT creation_date FROM networks GROUP BY (creation_date) ORDER BY min(creation_date) LIMIT 1), '{$_SERVER['SERVER_NAME']}', " . (defined("SSL_AVAILABLE") ? SSL_AVAILABLE ? "TRUE" : "FALSE" : "FALSE") . ", " . (defined("GMAPS_PUBLIC_API_KEY") ? "'" . GMAPS_PUBLIC_API_KEY . "'" : "''") . ");\n";
        $sql .= "ALTER TABLE networks ADD COLUMN gmaps_initial_latitude NUMERIC(16, 6);\n";
        $sql .= "ALTER TABLE networks ADD COLUMN gmaps_initial_longitude NUMERIC(16, 6);\n";
        $sql .= "ALTER TABLE networks ADD COLUMN gmaps_initial_zoom_level integer;\n";
        $sql .= "ALTER TABLE networks ADD COLUMN gmaps_map_type text CHECK (gmaps_map_type<>'');\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN gmaps_map_type SET DEFAULT 'G_MAP_TYPE';\n";
        $sql .= "UPDATE networks SET gmaps_map_type = 'G_MAP_TYPE';\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN gmaps_map_type SET NOT NULL;\n";
        $sql .= "UPDATE networks SET gmaps_initial_latitude = " . (defined("GMAPS_INITIAL_LATITUDE") ? "'" . GMAPS_INITIAL_LATITUDE . "'" : "'45.494511'") . ", gmaps_initial_longitude = " . (defined("GMAPS_INITIAL_LONGITUDE") ? "'" . GMAPS_INITIAL_LONGITUDE . "'" : "'-73.560285'") . ", gmaps_initial_zoom_level = " . (defined("GMAPS_INITIAL_ZOOM_LEVEL") ? "'" . GMAPS_INITIAL_ZOOM_LEVEL . "'" : "'5'") . ";\n";
    }
    $new_schema_version = 36;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "INSERT INTO locales VALUES ('pt');\n";
    }
    $new_schema_version = 37;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE flickr_photostream RENAME TO content_flickr_photostream;\n";
        $sql .= "ALTER TABLE embedded_content RENAME TO content_embedded_content;\n";
        $sql .= "ALTER TABLE files RENAME TO content_file;\n";
        $sql .= "ALTER TABLE iframes RENAME TO content_iframe;\n";
        $sql .= "ALTER TABLE langstring_entries RENAME TO content_langstring_entries;\n";
        $sql .= "ALTER TABLE pictures RENAME TO content_file_image;\n";
        $sql .= "ALTER TABLE content_display_location RENAME TO content_available_display_pages; \n";
        $sql .= "ALTER TABLE content_available_display_pages RENAME COLUMN display_location TO display_page; \n";
        $sql .= "UPDATE content_available_display_pages SET display_page = 'login' WHERE display_page = 'login_page';\n";
        $sql .= "UPDATE content_available_display_pages SET display_page = 'portal' WHERE display_page = 'portal_page';\n";
        $sql .= "INSERT INTO content_available_display_pages (display_page) VALUES ('everywhere');\n";
        $sql .= "CREATE TABLE content_available_display_areas ( display_area text PRIMARY KEY);\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('page_header');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('page_footer');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('left_area-top');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('left_area_middle');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('left_area_bottom');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('main_area_top');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('main_area_middle');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('main_area_bottom');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('right_area_top');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('right_area_middle');\n";
        $sql .= "INSERT INTO content_available_display_areas (display_area) VALUES ('right_area_bottom');\n";
        $sql .= "ALTER TABLE network_has_content RENAME COLUMN display_location TO display_page;\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_page SET DEFAULT 'portal'::text;\n";
        $sql .= "ALTER TABLE network_has_content ADD COLUMN display_area text REFERENCES content_available_display_areas ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "UPDATE network_has_content SET display_area = 'main_area_middle';\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_area SET DEFAULT 'main_area_middle'::text;\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_area SET NOT NULL;\n";
        $sql .= "ALTER TABLE network_has_content ADD COLUMN display_order integer;\n";
        $sql .= "UPDATE network_has_content SET display_order = 1;\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_order SET DEFAULT 1;\n";
        $sql .= "ALTER TABLE network_has_content ALTER COLUMN display_order SET NOT NULL;\n";
        $sql .= "ALTER TABLE node_has_content RENAME COLUMN display_location TO display_page;\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_page SET DEFAULT 'portal'::text;\n";
        $sql .= "ALTER TABLE node_has_content ADD COLUMN display_area text REFERENCES content_available_display_areas ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "UPDATE node_has_content SET display_area = 'main_area_middle';\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_area SET DEFAULT 'main_area_middle'::text;\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_area SET NOT NULL;ALTER TABLE node_has_content ADD COLUMN display_order integer;\n";
        $sql .= "UPDATE node_has_content SET display_order = 1;\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_order SET DEFAULT 1;\n";
        $sql .= "ALTER TABLE node_has_content ALTER COLUMN display_order SET NOT NULL;\n";
    }
    $new_schema_version = 38;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "UPDATE content_available_display_areas SET display_area='left_area_top' WHERE display_area='left_area-top';\n";
    }
    $new_schema_version = 39;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        // Update to new Gmaps v2 constants
        $sql .= "ALTER TABLE networks ALTER COLUMN gmaps_map_type SET DEFAULT 'G_NORMAL_MAP'::text;\n";
        $sql .= "UPDATE networks SET gmaps_map_type='G_NORMAL_MAP' WHERE gmaps_map_type = 'G_MAP_TYPE'; \n";
        $sql .= "UPDATE networks SET gmaps_map_type='G_HYBRID_MAP' WHERE gmaps_map_type = 'G_HYBRID_TYPE'; \n";
        $sql .= "UPDATE networks SET gmaps_map_type='G_SATELLITE_MAP' WHERE gmaps_map_type = 'G_SATELLITE_TYPE'; \n";
        // Use formula given here : http://www.google.com/apis/maps/documentation/upgrade.html#Upgrade
        $sql .= "UPDATE networks SET gmaps_initial_zoom_level = 17 - gmaps_initial_zoom_level; \n";
    }
    $new_schema_version = 40;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE networks ADD COLUMN theme_pack text;\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN theme_pack SET DEFAULT NULL;\n";
    }
    $new_schema_version = 41;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "INSERT INTO locales (locales_id) VALUES('ja');\n";
    }
    $new_schema_version = 42;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content_file ADD COLUMN creation_date TIMESTAMP;\n";
        $sql .= "ALTER TABLE content_file ALTER COLUMN creation_date SET DEFAULT NOW();\n";
        $sql .= "ALTER TABLE content_file ADD COLUMN last_update_date TIMESTAMP;\n";
        $sql .= "ALTER TABLE content_file ALTER COLUMN last_update_date SET DEFAULT NOW();\n";
        $sql .= "UPDATE content_file SET creation_date = NOW(), last_update_date = NOW();\n";
        $sql .= "ALTER TABLE content_file_image ADD COLUMN hyperlink_url TEXT;\n";
    }
    $new_schema_version = 43;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE content_clickthrough_log ( \n";
        $sql .= "  user_id text REFERENCES users (user_id) ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "  content_id text NOT NULL REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "  clickthrough_timestamp timestamp NOT NULL DEFAULT now(),\n";
        $sql .= "  node_id text NOT NULL REFERENCES nodes ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "  destination_url text NOT NULL CHECK (destination_url<>'')\n";
        $sql .= ");\n";
    }
    $new_schema_version = 44;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "INSERT INTO locales (locales_id) VALUES('es');\n";
    }
    $new_schema_version = 45;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content DROP COLUMN sponsor_info;\n";
        $sql .= "ALTER TABLE users DROP CONSTRAINT account_origin_fkey;\n";
        $sql .= "ALTER TABLE users ADD CONSTRAINT account_origin_fkey FOREIGN KEY (account_origin) REFERENCES networks (network_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE nodes DROP CONSTRAINT network_id_fkey;\n";
        $sql .= "ALTER TABLE nodes ADD CONSTRAINT network_id_fkey FOREIGN KEY (network_id) REFERENCES networks (network_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE users DROP CONSTRAINT check_account_origin_not_empty;\n";
        $sql .= "ALTER TABLE connections DROP CONSTRAINT fk_nodes;\n";
        $sql .= "ALTER TABLE connections ADD CONSTRAINT fk_nodes FOREIGN KEY (node_id) REFERENCES nodes (node_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE connections DROP CONSTRAINT fk_users;\n";
        $sql .= "ALTER TABLE connections ADD CONSTRAINT fk_users FOREIGN KEY (user_id) REFERENCES users (user_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE node_stakeholders DROP CONSTRAINT \"\$2\";\n";
        $sql .= "ALTER TABLE node_stakeholders ADD CONSTRAINT fk_users FOREIGN KEY (user_id) REFERENCES users (user_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE network_stakeholders DROP CONSTRAINT \"\$1\";\n";
        $sql .= "ALTER TABLE network_stakeholders ADD CONSTRAINT fk_network FOREIGN KEY (network_id) REFERENCES networks (network_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE network_stakeholders DROP CONSTRAINT \"\$2\";\n";
        $sql .= "ALTER TABLE network_stakeholders ADD CONSTRAINT fk_users FOREIGN KEY (user_id) REFERENCES users (user_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE content ADD COLUMN title_is_displayed bool;\n";
        $sql .= "ALTER TABLE content ALTER COLUMN title_is_displayed SET DEFAULT true;\n";
        $sql .= "UPDATE content SET title_is_displayed=true;\n";
        $sql .= "ALTER TABLE content ALTER COLUMN title_is_displayed SET NOT NULL;\n\n";
    }
    $new_schema_version = 46;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content_group_element ADD COLUMN valid_from_timestamp timestamp;\n";
        $sql .= "ALTER TABLE content_group_element ADD COLUMN valid_until_timestamp timestamp;\n";
        $sql .= "CREATE INDEX idx_content_group_element_valid_from_timestamp ON content_group_element (valid_from_timestamp);\n";
        $sql .= "CREATE INDEX idx_content_group_element_valid_until_timestamp ON content_group_element (valid_until_timestamp);\n";
    }
    $new_schema_version = 47;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE users DROP COLUMN real_name;\n";
        $sql .= "ALTER TABLE users DROP COLUMN website;\n";
        $sql .= "ALTER TABLE content_display_log ADD COLUMN num_display integer;\n";
        $sql .= "UPDATE content_display_log SET num_display=1;\n";
        $sql .= "ALTER TABLE content_display_log ALTER COLUMN num_display SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_display_log ALTER COLUMN num_display SET DEFAULT 1;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ADD COLUMN num_clickthrough integer;\n";
        $sql .= "UPDATE content_clickthrough_log SET num_clickthrough=1;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ALTER COLUMN num_clickthrough SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ALTER COLUMN num_clickthrough SET DEFAULT 1;\n";
        $sql .= "ALTER TABLE content_clickthrough_log RENAME COLUMN clickthrough_timestamp TO first_clickthrough_timestamp;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ADD COLUMN last_clickthrough_timestamp timestamp;\n";
        $sql .= "UPDATE content_clickthrough_log SET last_clickthrough_timestamp=first_clickthrough_timestamp;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ALTER COLUMN last_clickthrough_timestamp SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ALTER COLUMN last_clickthrough_timestamp SET DEFAULT NOW();\n";
    }
    $new_schema_version = 48;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "DELETE FROM content_clickthrough_log WHERE user_id IS NULL;\n";
        $sql .= "ALTER TABLE content_clickthrough_log ALTER COLUMN user_id SET NOT NULL;\n";
        $results = null;
        $db->execSql("SELECT COUNT(*) as num_clickthrough, MIN(first_clickthrough_timestamp) as first_clickthrough_timestamp, MAX(last_clickthrough_timestamp) as last_clickthrough_timestamp, user_id, content_id, node_id, destination_url FROM content_clickthrough_log GROUP BY user_id, content_id, node_id, destination_url HAVING COUNT(*) > 1", $results, false);
        if ($results) {
            foreach ($results as $row) {
                $sql .= "DELETE FROM content_clickthrough_log WHERE user_id='{$row['user_id']}' AND content_id='{$row['content_id']}' AND node_id='{$row['node_id']}' AND destination_url='{$row['destination_url']}';\n";
                if (!empty($row['user_id'])) {
                    $sql .= "INSERT INTO content_clickthrough_log (num_clickthrough, first_clickthrough_timestamp, last_clickthrough_timestamp, user_id, content_id, node_id, destination_url) VALUES ({$row['num_clickthrough']}, '{$row['first_clickthrough_timestamp']}', '{$row['last_clickthrough_timestamp']}', '{$row['user_id']}', '{$row['content_id']}', '{$row['node_id']}', '{$row['destination_url']}');\n";
                }
            }
        }
        $sql .= "ALTER TABLE content_clickthrough_log ADD CONSTRAINT content_clickthrough_log_pkey PRIMARY KEY(content_id, user_id, node_id, destination_url);\n";
        $sql .= "ALTER TABLE content_display_log DROP CONSTRAINT content_group_element_portal_display_log_pkey;\n";
        $sql .= "ALTER TABLE content_display_log ADD CONSTRAINT content_display_log_pkey PRIMARY KEY(content_id, user_id, node_id);\n";
    }
    $new_schema_version = 49;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE content_rss_aggregator ADD COLUMN feed_expansion text;\n";
        $sql .= "ALTER TABLE content_rss_aggregator ALTER COLUMN feed_expansion SET DEFAULT 'FIRST';\n";
        $sql .= "UPDATE content_rss_aggregator SET feed_expansion='FIRST';\n";
        $sql .= "ALTER TABLE content_rss_aggregator ALTER COLUMN feed_expansion SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_rss_aggregator ADD COLUMN feed_ordering text;\n";
        $sql .= "ALTER TABLE content_rss_aggregator ALTER COLUMN feed_ordering SET DEFAULT 'REVERSE_DATE';\n";
        $sql .= "UPDATE content_rss_aggregator SET feed_ordering='REVERSE_DATE';\n";
        $sql .= "ALTER TABLE content_rss_aggregator ALTER COLUMN feed_ordering SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_rss_aggregator ADD COLUMN display_empty_feeds boolean;\n";
        $sql .= "ALTER TABLE content_rss_aggregator ALTER COLUMN display_empty_feeds SET DEFAULT TRUE;\n";
        $sql .= "UPDATE content_rss_aggregator SET display_empty_feeds=TRUE;\n";
        $sql .= "ALTER TABLE content_rss_aggregator ALTER COLUMN display_empty_feeds SET NOT NULL;\n";
    }
    $new_schema_version = 50;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN gw_id text;\n";
        $sql .= "UPDATE nodes SET gw_id=node_id;\n";
        $db->execSql("SELECT node_id FROM nodes", $results, false);
        foreach ($results as $row) {
            $sql .= "UPDATE nodes SET node_id='" . get_guid() . "' WHERE node_id='{$row['node_id']}';\n";
        }
        $sql .= "ALTER TABLE nodes ALTER COLUMN gw_id SET NOT NULL;\n";
        $sql .= "CREATE UNIQUE INDEX idx_gw_id ON nodes (gw_id);\n";
    }
    $new_schema_version = 51;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE content_key_value_pairs \n";
        $sql .= "( ";
        $sql .= "content_id text NOT NULL REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "key text NOT NULL, \n";
        $sql .= "value text, \n";
        $sql .= "PRIMARY KEY(content_id, key) \n";
        $sql .= "); \n";
        $sql .= "ALTER TABLE content ADD COLUMN last_update_timestamp timestamp;\n";
        $sql .= "ALTER TABLE content ALTER COLUMN last_update_timestamp SET DEFAULT now();\n";
        $sql .= "UPDATE content SET last_update_timestamp=CURRENT_TIMESTAMP;\n";
        $sql .= "UPDATE content SET last_update_timestamp=last_update_date FROM content_file WHERE content_id=files_id;\n";
        $sql .= "ALTER TABLE content ALTER COLUMN last_update_timestamp SET NOT NULL;\n";
        $sql .= "ALTER TABLE content_file DROP COLUMN last_update_date;\n";
        $sql .= "ALTER TABLE content_file DROP COLUMN creation_date;\n";
        $sql .= "ALTER TABLE content_group DROP COLUMN is_artistic_content;\n";
        $sql .= "ALTER TABLE content_group DROP COLUMN is_locative_content;\n";
    }
    $new_schema_version = 52;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE content_shoutbox_messages \n";
        $sql .= "( \n";
        $sql .= "message_content_id text  PRIMARY KEY REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "shoutbox_id text NOT NULL REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "origin_node_id text NOT NULL REFERENCES nodes ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "author_user_id text NOT NULL REFERENCES users ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "creation_date timestamp DEFAULT now() \n";
        $sql .= "); \n";
    }
    $new_schema_version = 53;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE content_type_filters \n";
        $sql .= "( \n";
        $sql .= "content_type_filter_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "content_type_filter_label text,\n";
        $sql .= "content_type_filter_rules text NOT NULL CONSTRAINT content_type_filter_rules_not_empty_string CHECK (content_type_filter_rules != '')\n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE profile_templates \n";
        $sql .= "( \n";
        $sql .= "profile_template_id text NOT NULL PRIMARY KEY, \n";
        $sql .= "profile_template_label text,\n";
        $sql .= "creation_date timestamp DEFAULT now()\n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE profile_template_fields \n";
        $sql .= "( \n";
        $sql .= "profile_template_field_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "profile_template_id text NOT NULL REFERENCES profile_templates ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "display_label_content_id text REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "admin_label_content_id text REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "content_type_filter_id text REFERENCES content_type_filters ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "display_order integer DEFAULT '1',\n";
        $sql .= "semantic_id text\n";
        $sql .= ");\n";
        $sql .= "CREATE INDEX profile_template_fields_semantic_id ON profile_template_fields(semantic_id);\n\n";
        $sql .= "CREATE TABLE network_has_profile_templates \n";
        $sql .= "( \n";
        $sql .= "network_id text REFERENCES networks ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "profile_template_id text REFERENCES profile_templates ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "PRIMARY KEY(network_id, profile_template_id) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE profiles \n";
        $sql .= "( \n";
        $sql .= "profile_id text NOT NULL PRIMARY KEY, \n";
        $sql .= "profile_template_id text REFERENCES profile_templates ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "creation_date timestamp DEFAULT now(),\n";
        $sql .= "is_visible boolean DEFAULT TRUE\n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE user_has_profiles \n";
        $sql .= "( \n";
        $sql .= "user_id text REFERENCES users ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "profile_id text REFERENCES profiles ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "PRIMARY KEY(user_id, profile_id) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE profile_fields \n";
        $sql .= "( \n";
        $sql .= "profile_field_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "profile_id text REFERENCES profiles ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "profile_template_field_id text REFERENCES profile_template_fields ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "content_id text REFERENCES content ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "last_modified timestamp DEFAULT now()\n";
        $sql .= ");\n";
    }
    $new_schema_version = 54;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE stakeholder_types \n";
        $sql .= "( \n";
        $sql .= "stakeholder_type_id text NOT NULL PRIMARY KEY CONSTRAINT stakeholder_types_id_not_empty_string CHECK (stakeholder_type_id != '')\n";
        $sql .= ");\n\n";
        $sql .= "INSERT into stakeholder_types (stakeholder_type_id) VALUES ('Node');\n\n";
        $sql .= "INSERT into stakeholder_types (stakeholder_type_id) VALUES ('Network');\n\n";
        $sql .= "INSERT into stakeholder_types (stakeholder_type_id) VALUES ('Server');\n\n";
        $sql .= "INSERT into stakeholder_types (stakeholder_type_id) VALUES ('Content');\n\n";
        $sql .= "CREATE TABLE permissions \n";
        $sql .= "( \n";
        $sql .= "permission_id text NOT NULL PRIMARY KEY CONSTRAINT permission_rules_id_not_empty_string CHECK (permission_id != ''),\n";
        $sql .= "stakeholder_type_id text NOT NULL REFERENCES stakeholder_types ON UPDATE CASCADE ON DELETE CASCADE\n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE roles \n";
        $sql .= "( \n";
        $sql .= "role_id text NOT NULL PRIMARY KEY CONSTRAINT roles_rules_id_not_empty_string CHECK (role_id != ''), \n";
        $sql .= "role_description_content_id text REFERENCES content ON UPDATE CASCADE ON DELETE SET NULL,\n";
        $sql .= "is_system_role boolean NOT NULL DEFAULT FALSE,\n";
        $sql .= "stakeholder_type_id text NOT NULL REFERENCES stakeholder_types ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "role_creation_date timestamp DEFAULT now()\n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE role_has_permissions \n";
        $sql .= "( \n";
        $sql .= "role_id text REFERENCES roles ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "permission_id text REFERENCES permissions ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "PRIMARY KEY(role_id, permission_id) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE stakeholders \n";
        $sql .= "( \n";
        $sql .= "user_id text REFERENCES users ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "role_id text REFERENCES roles ON UPDATE CASCADE ON DELETE CASCADE,\n";
        $sql .= "object_id text NOT NULL CONSTRAINT user_has_roles_objct_id_not_empty_string CHECK (object_id != ''),\n";
        $sql .= "PRIMARY KEY(user_id, role_id, object_id) \n";
        $sql .= ");\n\n";
        /* Fix the Virtual Host/Server confusion... */
        $sql .= "CREATE TABLE virtual_hosts ( \n";
        $sql .= "  virtual_host_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "  hostname text NOT NULL UNIQUE CHECK (hostname<>''),\n";
        $sql .= "  creation_date date NOT NULL DEFAULT now(),\n";
        $sql .= "  ssl_available BOOLEAN NOT NULL DEFAULT FALSE,\n";
        $sql .= "  gmaps_api_key text,\n";
        $sql .= "  default_network text NOT NULL REFERENCES networks ON UPDATE cascade ON DELETE RESTRICT\n";
        $sql .= ");\n";
        $sql .= "INSERT INTO virtual_hosts (virtual_host_id, hostname, creation_date, ssl_available, gmaps_api_key, default_network) (SELECT server_id, hostname, creation_date, ssl_available, gmaps_api_key, (SELECT network_id FROM networks WHERE is_default_network = true LIMIT 1) FROM servers);\n";
        $sql .= "ALTER TABLE networks DROP column is_default_network;\n";
        $sql .= "CREATE TABLE server ( \n";
        $sql .= "  server_id text NOT NULL PRIMARY KEY,\n";
        $sql .= "  creation_date date NOT NULL DEFAULT now(),\n";
        $sql .= "  default_virtual_host text NOT NULL REFERENCES virtual_hosts ON UPDATE cascade ON DELETE RESTRICT\n";
        $sql .= ");\n";
        $sql .= "INSERT INTO server (server_id, default_virtual_host) VALUES ('SERVER_ID', (SELECT server_id FROM servers WHERE is_default_server = true LIMIT 1));\n";
        $sql .= "DROP TABLE servers;\n";
        $sql .= "DROP TABLE network_stakeholders; \n";
        $sql .= "CREATE TABLE network_stakeholders \n";
        $sql .= "( \n";
        $sql .= "  CONSTRAINT fk_network FOREIGN KEY (object_id) REFERENCES networks (network_id) ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "PRIMARY KEY(user_id, role_id, object_id) \n";
        $sql .= ") inherits(stakeholders);\n\n";
        /* Convert superusers */
        $sql .= "DROP TABLE administrators; \n";
        $sql .= "CREATE TABLE server_stakeholders \n";
        $sql .= "( \n";
        $sql .= "  CONSTRAINT fk_network FOREIGN KEY (object_id) REFERENCES server (server_id) ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "PRIMARY KEY(user_id, role_id, object_id) \n";
        $sql .= ") inherits(stakeholders);\n\n";
        $sql .= "INSERT into roles (role_id, stakeholder_type_id) VALUES ('SERVER_SYSADMIN', 'Server');\n";
        $sql .= "INSERT into roles (role_id, stakeholder_type_id) VALUES ('NETWORK_SYSADMIN', 'Network');\n";
        $db->execSql("SELECT * FROM administrators", $results, false);
        foreach ($results as $row) {
            $sql .= "INSERT into server_stakeholders (user_id, role_id, object_id) VALUES ('{$row['user_id']}', 'SERVER_SYSADMIN', (SELECT server_id FROM server LIMIT 1));\n";
            $db->execSql("SELECT network_id FROM networks", $networkRows, false);
            foreach ($networkRows as $networkRow) {
                $sql .= "INSERT into network_stakeholders (user_id, role_id, object_id) VALUES ('{$row['user_id']}', 'NETWORK_SYSADMIN', '{$networkRow['network_id']}');\n";
            }
        }
        $sql .= "DROP TABLE node_stakeholders; \n";
        $sql .= "CREATE TABLE node_stakeholders \n";
        $sql .= "( \n";
        $sql .= "  CONSTRAINT fk_nodes FOREIGN KEY (object_id) REFERENCES nodes (node_id) ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "PRIMARY KEY(user_id, role_id, object_id) \n";
        $sql .= ") inherits(stakeholders);\n\n";
        /* Convert node owners and tech officer */
        $sql .= "INSERT into roles (role_id, stakeholder_type_id) VALUES ('NODE_OWNER', 'Node');\n";
        $db->execSql("SELECT * FROM node_stakeholders WHERE is_owner = true", $results, false);
        if ($results) {
            foreach ($results as $row) {
                $sql .= "INSERT into node_stakeholders (user_id, role_id, object_id) VALUES ('{$row['user_id']}', 'NODE_OWNER', '{$row['node_id']}');\n";
            }
        }
        $sql .= "INSERT into roles (role_id, stakeholder_type_id) VALUES ('NODE_TECH_OFFICER', 'Node');\n";
        $db->execSql("SELECT * FROM node_stakeholders WHERE is_tech_officer = true", $results, false);
        if ($results) {
            foreach ($results as $row) {
                $sql .= "INSERT into node_stakeholders (user_id, role_id, object_id) VALUES ('{$row['user_id']}', 'NODE_TECH_OFFICER', '{$row['node_id']}');\n";
            }
        }
    }
    $new_schema_version = 55;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN last_heartbeat_sys_uptime INTEGER;\n";
        //68 years of uptime should be enough for anybody ;)
        $sql .= "ALTER TABLE nodes ALTER COLUMN last_heartbeat_sys_uptime SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN last_heartbeat_wifidog_uptime INTEGER;\n";
        //68 years of uptime should be enough for anybody ;)
        $sql .= "ALTER TABLE nodes ALTER COLUMN last_heartbeat_wifidog_uptime SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN last_heartbeat_sys_memfree INTEGER;\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN last_heartbeat_sys_memfree SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN last_heartbeat_sys_load real;\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN last_heartbeat_sys_load SET DEFAULT NULL;\n";
    }
    $new_schema_version = 56;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE INDEX idx_connections_timestamp_in ON connections (timestamp_in);\n";
    }
    $new_schema_version = 57;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE users ADD COLUMN open_id_url text;\n";
        $sql .= "CREATE INDEX idx_users_topen_id_url ON users (open_id_url);\n";
    }
    $new_schema_version = 58;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE network_stakeholders ADD CONSTRAINT fk_roles FOREIGN KEY (role_id) REFERENCES roles (role_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE node_stakeholders ADD CONSTRAINT fk_roles FOREIGN KEY (role_id) REFERENCES roles (role_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "ALTER TABLE server_stakeholders ADD CONSTRAINT fk_roles FOREIGN KEY (role_id) REFERENCES roles (role_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
        $sql .= "UPDATE roles SET role_id='SERVER_OWNER', is_system_role=true WHERE role_id='SERVER_SYSADMIN';\n";
        $sql .= "UPDATE roles SET role_id='NETWORK_OWNER', is_system_role=true WHERE role_id='NETWORK_SYSADMIN';\n";
        $sql .= "UPDATE roles SET is_system_role=true WHERE role_id='NODE_OWNER';\n";
        $sql .= "INSERT into roles (role_id, stakeholder_type_id, is_system_role) VALUES ('CONTENT_OWNER', 'Content', true);\n";
    }
    $new_schema_version = 59;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE INDEX idx_content_display_log ON content_display_log (last_display_timestamp);\n";
        $sql .= "CREATE INDEX idx_nodes_node_deployment_status ON nodes (node_deployment_status);\n";
    }
    $new_schema_version = 60;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE token_templates \n";
        $sql .= "( \n";
        $sql .= "token_template_id text PRIMARY KEY, \n";
        $sql .= "token_template_network text REFERENCES networks (network_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, -- (Note:  Server-wide tokens aren't supported, but the code will look up the tokens of networks you peer with) \n";
        $sql .= "token_template_creation_date timestamp NOT NULL DEFAULT now(),\n";
        $sql .= "token_max_incoming_data integer, -- Ex: Allows capping bandwidth \n";
        $sql .= "token_max_outgoing_data integer, -- Ex: Allows capping bandwidth \n";
        $sql .= "token_max_total_data integer, -- Ex: Allows capping bandwidth \n";
        $sql .= "token_max_connection_duration interval, -- Ex: Allows limiting the length of a single connection \n";
        $sql .= "token_max_usage_duration interval, -- Ex: Allows selling access by the hour (counting only when in use) \n";
        $sql .= "token_max_wall_clock_duration interval, -- Ex:  Allows selling daily, weekly or monthly passes (starting the count as soon as the token is first used) \n";
        $sql .= "token_max_age interval, -- Ex:  Allow setting a maximum time before expiration (starting the count as soon as the token is issued) \n";
        $sql .= "token_is_reusable boolean DEFAULT true --  Can a user connect again using this token? (normally, yes) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE tokens_template_valid_nodes -- (Unfortunately, for hotels selling 24h access to their clients, we have to consider that their network may consist of more than one node.  If the token has no entry in this table, it's considered valid everywhere on the Network (and it's peers)) \n";
        $sql .= "( \n";
        $sql .= "token_template_id text REFERENCES token_templates (token_template_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, \n";
        $sql .= "token_valid_at_node text REFERENCES nodes (node_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, \n";
        $sql .= "PRIMARY KEY (token_template_id, token_valid_at_node) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE token_lots \n";
        $sql .= "( \n";
        $sql .= "token_lot_id text PRIMARY KEY, \n";
        $sql .= "token_lot_comment text, -- A free-form comment about the lot text \n";
        $sql .= "token_lot_creation_date timestamp NOT NULL DEFAULT now()\n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE tokens \n";
        $sql .= "( \n";
        $sql .= "token_id text PRIMARY KEY, \n";
        $sql .= "token_template_id text REFERENCES token_templates (token_template_id) ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "token_status text REFERENCES token_status (token_status)  ON UPDATE CASCADE ON DELETE RESTRICT, \n";
        $sql .= "token_lot_id text REFERENCES token_lots (token_lot_id) ON UPDATE CASCADE ON DELETE CASCADE, \n";
        $sql .= "token_creation_date timestamp NOT NULL DEFAULT now(), -- (not the same as connection start time) \n";
        $sql .= "token_issuer text REFERENCES users (user_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, -- A user in the system.  User responsible for the creation of the token (not necessarily the same as the one using it), \n";
        $sql .= "token_owner text REFERENCES users (user_id) ON UPDATE CASCADE ON DELETE CASCADE -- The user that can USE the token, anyone if empty.\n";
        $sql .= ");\n\n";
        $sql .= "INSERT INTO tokens (token_id, token_status, token_creation_date, token_issuer, token_owner) SELECT token AS token_id, token_status, timestamp_in AS token_creation_date, user_id AS token_issuer, user_id AS token_owner FROM connections; \n";
        $sql .= "CREATE INDEX idx_token_status ON tokens (token_status);\n";
        $sql .= "ALTER TABLE connections ADD CONSTRAINT fk_tokens FOREIGN KEY (token) REFERENCES tokens (token_id) ON UPDATE CASCADE ON DELETE RESTRICT; \n";
        $sql .= "ALTER TABLE connections DROP column token_status; \n";
        $sql .= "ALTER TABLE connections ADD COLUMN max_total_bytes integer;\n";
        $sql .= "ALTER TABLE connections ALTER COLUMN max_total_bytes SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE connections ADD COLUMN max_incoming_bytes integer;\n";
        $sql .= "ALTER TABLE connections ALTER COLUMN max_incoming_bytes SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE connections ADD COLUMN max_outgoing_bytes integer;\n";
        $sql .= "ALTER TABLE connections ALTER COLUMN max_outgoing_bytes SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE connections ADD COLUMN expiration_date timestamp;\n";
        $sql .= "ALTER TABLE connections ALTER COLUMN expiration_date SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE connections ADD COLUMN logout_reason integer;\n";
        $sql .= "ALTER TABLE connections ALTER COLUMN logout_reason SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE connections RENAME COLUMN token TO token_id;\n";
    }
    $new_schema_version = 61;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE networks ADD column connection_limit_window interval; \n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_window SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE networks ADD COLUMN connection_limit_network_max_total_bytes integer;\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_network_max_total_bytes SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE networks ADD COLUMN connection_limit_network_max_usage_duration interval;\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_network_max_usage_duration SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE networks ADD COLUMN connection_limit_node_max_total_bytes integer;\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_node_max_total_bytes SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE networks ADD COLUMN connection_limit_node_max_usage_duration interval;\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_node_max_usage_duration SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN connection_limit_node_max_total_bytes_override integer;\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN connection_limit_node_max_total_bytes_override SET DEFAULT NULL;\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN connection_limit_node_max_usage_duration_override interval;\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN connection_limit_node_max_usage_duration_override SET DEFAULT NULL;\n";
    }
    $new_schema_version = 62;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_network_max_total_bytes TYPE bigint;\n";
        $sql .= "ALTER TABLE networks ALTER COLUMN connection_limit_node_max_total_bytes TYPE bigint;\n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN connection_limit_node_max_total_bytes_override TYPE bigint;\n";
    }
    $new_schema_version = 63;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE networks ADD column allow_original_url_redirect bool; \n";
        $sql .= "ALTER TABLE networks ALTER COLUMN allow_original_url_redirect SET DEFAULT FALSE;\n";
        $sql .= "ALTER TABLE nodes ADD column allow_original_URL_redirect bool; \n";
        $sql .= "ALTER TABLE nodes ALTER COLUMN allow_original_URL_redirect SET DEFAULT FALSE;\n";
    }
    $new_schema_version = 64;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE server ADD use_global_auth bool NOT NULL DEFAULT FALSE;\n";
    }
    $new_schema_version = 65;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "ALTER TABLE nodes ADD COLUMN allows_public_stats boolean NOT NULL DEFAULT false;\n";
    }
    $new_schema_version = 66;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "UPDATE connections SET logout_reason=0, timestamp_out=timestamp_in FROM tokens WHERE connections.token_id=tokens.token_id AND timestamp_out IS NULL AND (token_status = 'USED' OR token_status = 'UNUSED');\n";
    }
    $new_schema_version = 67;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "\n\nALTER TABLE networks ADD COLUMN usernames_case_sensitive boolean NOT NULL DEFAULT true;\n";
    }
    $new_schema_version = 68;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "CREATE TABLE node_groups \n";
        $sql .= "( \n";
        $sql .= "node_group_id character varying(32) PRIMARY KEY, \n";
        $sql .= "name text, \n";
        $sql .= "description text , \n";
        $sql .= "group_creation_date timestamp NOT NULL DEFAULT now() \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE hotspot_graph_elements \n";
        $sql .= "( \n";
        $sql .= "hotspot_graph_element_id character varying(32) PRIMARY KEY, \n";
        $sql .= "element_id text, \n";
        $sql .= "element_type character varying(16) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE hotspot_graph \n";
        $sql .= "( \n";
        $sql .= "child_element_id character varying(32) REFERENCES hotspot_graph_elements (hotspot_graph_element_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL , \n";
        $sql .= "parent_element_id character varying(32) REFERENCES hotspot_graph_elements (hotspot_graph_element_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL , \n";
        $sql .= "link_order integer DEFAULT 1 , \n";
        $sql .= "PRIMARY KEY(child_element_id, parent_element_id) \n";
        $sql .= ");\n\n";
        $sql .= "CREATE TABLE hotspot_graph_element_has_content (\n";
        $sql .= "hotspot_graph_element_id character varying(32) REFERENCES hotspot_graph_elements (hotspot_graph_element_id) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL ,\n";
        $sql .= "content_id text NOT NULL,\n";
        $sql .= "subscribe_timestamp timestamp without time zone DEFAULT now() NOT NULL,\n";
        $sql .= "display_page text DEFAULT 'portal'::text NOT NULL,\n";
        $sql .= "display_area text DEFAULT 'main_area_middle'::text NOT NULL,\n";
        $sql .= "display_order integer DEFAULT 1 NOT NULL\n";
        $sql .= ");\n\n";
        $sql .= "INSERT INTO stakeholder_types (stakeholder_type_id) VALUES ('NodeGroup');\n";
        //$networks = Network::getAllNetworks();
        $networks = array();
        $db->execSql("Select network_id from networks", $networks, false);
        foreach ($networks as $network) {
            $new_guid = get_guid();
            $sql .= "INSERT INTO hotspot_graph_elements values('{$new_guid}', '{$network['network_id']}', 'Network' );\n ";
            $nodes = array();
            $db->execSql("SELECT node_id FROM nodes where network_id = '{$network['network_id']}'", $nodes, false);
            if ($nodes) {
                foreach ($nodes as $node) {
                    $node_guid = get_guid();
                    $sql .= "INSERT INTO hotspot_graph_elements values('{$node_guid}', '{$node['node_id']}', 'Node' );\n ";
                    $sql .= "INSERT INTO hotspot_graph(child_element_id, parent_element_id) VALUES ('{$node_guid}', '{$new_guid}');\n";
                }
            }
        }
        $sql .= "INSERT INTO hotspot_graph_element_has_content (\n";
        $sql .= "SELECT hge.hotspot_graph_element_id, content_id, subscribe_timestamp, display_page, display_area, display_order \n";
        $sql .= "FROM hotspot_graph_elements hge inner join network_has_content nhc on nhc.network_id = hge.element_id \n";
        $sql .= "WHERE hge.element_type = 'Network');\n\n";
        $sql .= "INSERT INTO hotspot_graph_element_has_content (\n";
        $sql .= "SELECT hge.hotspot_graph_element_id, content_id, subscribe_timestamp, display_page, display_area, display_order \n";
        $sql .= "FROM hotspot_graph_elements hge inner join node_has_content nhc on nhc.node_id = hge.element_id \n";
        $sql .= "WHERE hge.element_type = 'Node');\n\n";
        $sql .= "CREATE TABLE nodegroup_stakeholders (\n";
        $sql .= ")\n";
        $sql .= "INHERITS (stakeholders);\n\n";
    }
    $new_schema_version = 69;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "\n\nDELETE FROM hotspot_graph_element_has_content WHERE content_id NOT IN (SELECT content_id from content);\n";
        $sql .= "\n\nALTER TABLE hotspot_graph_element_has_content ADD CONSTRAINT contentfk FOREIGN KEY (content_id) REFERENCES content(content_id) ON UPDATE CASCADE ON DELETE CASCADE;\n";
    }
    $new_schema_version = 70;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "\nALTER TABLE nodes ADD COLUMN show_node_on_map boolean NOT NULL DEFAULT true;";
    }
    $new_schema_version = 71;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
        printUpdateVersion($new_schema_version);
        $sql .= "\n\nUPDATE schema_info SET value='{$new_schema_version}' WHERE tag='schema_version';\n";
        $sql .= "\nCREATE INDEX lower_username ON users USING btree (lower(username));";
        $sql .= "\nCREATE INDEX lower_email ON users USING btree (lower(email));";
    }
    /*
    $new_schema_version = ;
    if ($schema_version < $new_schema_version && $new_schema_version <= $targetSchema) {
    printUpdateVersion($new_schema_version);
    $sql .= "\n\nUPDATE schema_info SET value='$new_schema_version' WHERE tag='schema_version';\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    $sql .= "\n";
    }
    */
    if (SCHEMA_UPDATE_TEST_MODE) {
        $retval = $db->execSqlUpdate("BEGIN;\n{$sql}\nROLLBACK;\n", true);
    } else {
        $retval = $db->execSqlUpdate("BEGIN;\n{$sql}\nCOMMIT;\n", true);
    }
    @ob_flush();
    flush();
    return $retval;
}