Redesign prototype merge #18

Merged
MrPetovan merged 50 commits from feature/redesign-prototype into master 2017-05-06 08:10:18 +02:00
234 changed files with 5285 additions and 2942 deletions

5
.gitignore vendored
View file

@ -2,5 +2,6 @@
.htconfig.php .htconfig.php
#* #*
favicon.* favicon.*
tests/coverage.html
/vendor
/nbproject/private/

0
.htaccess Executable file → Normal file
View file

2
Makefile Normal file
View file

@ -0,0 +1,2 @@
test:
cd tests && phpunit --coverage-html=coverage.html && x-www-browser ./coverage.html/index.html

View file

@ -1,6 +1,23 @@
# Friendica Global Directory # Decentralized Friendica Directory
Example cronjob. ## Installing
### 1. Initialize the database
Create a database with a username and a password.
Then import ````dfrndir.sql```` to it.
### 2. Create an autoloader with composer
Make sure you have composer installed globally, or rewrite the command to use a `.phar`.
```sh
composer dump-autoload
```
### 3. Set up the cronjobs.
Example cronjob using `www-data` user.
``` ```
*/30 * * * * www-data cd /var/www/friendica-directory; php include/cron_maintain.php */30 * * * * www-data cd /var/www/friendica-directory; php include/cron_maintain.php
@ -58,8 +75,6 @@ You can check the backlog of this queue at the `/admin` page.
* `.vcard .region` as `region` * `.vcard .region` as `region`
* `.vcard .postal-code` as `postal-code` * `.vcard .postal-code` as `postal-code`
* `.vcard .country-name` as `country-name` * `.vcard .country-name` as `country-name`
* `.vcard .x-gender` as `gender`
* `.marital-text` as `marital`
3. If the `dfrn-global-visibility` value is set to false. Any existing records will be deleted. 3. If the `dfrn-global-visibility` value is set to false. Any existing records will be deleted.
And the process exits here. And the process exits here.
@ -94,3 +109,23 @@ You can check the backlog of this queue at the `/admin` page.
11. Should there somehow have been an error at this point such as that there is no profile ID known. 11. Should there somehow have been an error at this point such as that there is no profile ID known.
Everything will get deleted based on the original `?url=` parameter. Everything will get deleted based on the original `?url=` parameter.
## Note about search
The Directory uses MySQL fulltext capabilities to index profiles and offer a search feature.
However, the default minimum word size MySQL will index is 4, which ignores words like `PHP` and `USA`.
To index words smaller than 4 characters, you will have to edit your my.cnf/my.ini file to include this:
````
[mysqld]
ft_min_word_len = 3
````
Then restart your MySQL server.
If you already had data in your profile table, you will need to rebuild the index by executing the following query:
````
REPAIR TABLE `profile` QUICK;
````

43
Vagrantfile vendored Normal file
View file

@ -0,0 +1,43 @@
server_ip = "192.168.33.10"
server_memory = "384" # MB
server_timezone = "UTC"
public_folder = "/vagrant"
Vagrant.configure(2) do |config|
# Set server to Ubuntu 14.04
config.vm.box = "ubuntu/trusty64"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a hostname, don't forget to put it to the `hosts` file
# This will point to the server's default virtual host
# TO DO: Make this work with virtualhost along-side xip.io URL
config.vm.hostname = "friendica.dev"
# Create a static IP
config.vm.network :private_network, ip: server_ip
# Share a folder between host and guest
config.vm.synced_folder "./", "/vagrant/", owner: "www-data", group: "vagrant"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
vb.memory = server_memory
end
# Enable provisioning with a shell script.
config.vm.provision "shell", path: "./util/vagrant_provision.sh"
# run: "always"
# run: "once"
end

30
assets/js/main.js Normal file
View file

@ -0,0 +1,30 @@
jQuery(function($){
//Mobile menu, hamburger button.
$('body').on('click', '.hamburger', function(e){
e.preventDefault();
$('nav#links').toggleClass('open');
});
// Show/hide the reset link if the search field is populated/empty
function updateResetButton() {
if ($('.search-field').val()) {
$('.reset').show();
} else {
$('.reset').hide();
}
}
$('body').on('keyup', '.search-field', updateResetButton)
updateResetButton();
// Makes the entire profile card clickable...
$('body').on('click', '.profile', function(event) {
window.open(event.currentTarget.dataset.href, '_blank');
});
// ...while keeping inner a tags clickable
$('body').on('click', '.profile a', function(event) {
event.stopPropagation();
})
});

448
assets/style.css Normal file
View file

@ -0,0 +1,448 @@
* {
box-sizing: border-box;
}
html,body {
margin: 0;
padding: 0;
}
html {
font-family: 'Open Sans', sans-serif;
font-weight: 300;
font-size: 100%;
}
a {color: inherit;}
p {
margin: 0 0 1em 0;
}
.mobile {
display: none !important;
}
#top-bar {
background: #f5f5f5;
padding: 8px 14px;
position: fixed;
z-index: 1;
top: 0;
height: 55px;
width: 100%;
font-weight: 300;
border-bottom: 1px solid #ddd;
display: flex;
justify-content: space-between;
}
#top-bar-spacer {
width: 100%;
height: 55px;
}
#top-bar .header {
display: inline-block;
font-size: 16px;
font-weight: 300;
line-height: 19px;
background: url('/images/friendica.svg') top left no-repeat;
background-size: 14px;
padding-left: 18px;
margin: 0;
white-space: nowrap;
}
#top-bar .search-form {
display: inline-block;
}
#top-bar .search-wrapper {
background: #fff;
}
nav#links {
line-height: 39px;
white-space: nowrap;
}
nav#links a {
display: inline-block;
margin: 0 4px;
padding: 0 5px;
}
.sub-menu-outer {
background: #eee;
line-height: 45px;
height: 45px;
border-bottom: 1px solid #ddd;
}
.sub-menu-outer .sub-menu-inner {
width: 500px;
margin: auto;
}
.sub-menu-inner .option {
padding: 9px 6px;
margin: 0 5px;
}
.sub-menu-inner .option.active {
border-bottom: 2px solid #f00;
}
.homepage-wrapper {
width: 500px;
margin: auto;
text-align: center;
}
.search-results,
.directory-results {
margin-bottom: 25px;
}
.directory-results {
display: flex;
flex-flow: row;
}
.directory-results > aside {
flex: 1 6 20%;
order: 1;
padding: 0 1em;
}
.directory-results > section {
flex: 3 1 80%;
order: 2;
}
.homepage-wrapper {
margin: 120px auto;
}
.homepage-wrapper .header {
font-size: 68px;
font-weight: 100;
line-height: 0.9em;
background: url('/images/friendica.svg') top left no-repeat;
background-size: 61px;
margin-left: 40px;
}
.homepage-wrapper .about {
text-align: justify;
line-height: 1.5em;
color: #555;
}
.homepage-wrapper .profiles {
margin-top: 3em;
}
.profiles {
padding: 0 10px;
column-width: 400px;
}
.profiles > figure {
display: inline-block;
cursor: pointer;
}
nav#links a,
.sub-menu-outer a {
text-decoration: none;
}
.search-results .intro {
text-align: justify;
}
.site,
.profile {
width: 100%;
text-decoration: none;
color: #000;
padding: 2px;
outline: none;
margin: 5px 0;
display: inline;
background-color: rgba(0, 0, 0, .01);
border-radius: 23px .5em 23px .5em;
}
.site {
padding: 14px 2px;
margin: 20px 0;
border-bottom: 1px dashed #ccc;
}
.profile.selected,
.profile: focus,
.profile: hover {
padding: 1px;
border: 1px solid #ccc;
}
.site .site-info,
.site .site-supports,
.profile .profile-photo,
.profile .profile-info {
display: table-cell;
vertical-align: top;
text-align: left;
}
.site .site-supports {
text-align: right;
padding: 8px;
}
.profile .profile-photo {
float: left;
margin: 8px;
border-radius: 15px;
border: 1px solid #ddd;
}
.site .site-info,
.profile .profile-info {
padding: 8px;
width: 100%;
}
.site .site-info strong,
.profile .profile-info strong {
font-weight: 600;
}
.site .site-info .fa,
.profile .profile-info .fa {
line-height: 1.1em;
color: #999;
}
.site .site-info .url,
.profile .profile-info .url {
font-size: 80%;
margin-bottom: 3px;
color: #555;
/** @see https: //css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/ */
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-ms-hyphens: auto;
-moz-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
.profile .profile-info .description {
margin-bottom: .5em;
}
.search-wrapper {
position: relative;
display: inline-block;
width: 500px;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 8px;
height: 38px;
line-height: 22px;
}
.search-wrapper .search-field {
line-height: 22px;
display: block;
border: none;
outline: none;
background: none;
padding: 8px 12px;
padding-right: 117px;
width: 100%;
}
.search-wrapper .reset {
position: absolute;
top: 0;
right: 65px;
height: 25px;
width: 25px;
margin: 6px;
padding: 0;
line-height: 1;
font-size: 12px;
color: #555;
background: #eee;
border: 1px solid #ddd;
border-radius: 20px;
font-family: 'FontAwesome';
font-weight: 100;
line-height: 25px;
text-decoration: none;
}
.search-wrapper .search {
border: none;
border-left: 1px solid #ddd;
color: #555;
background: #eee;
position: absolute;
top: 0;
right: 0;
height: 36px;
width: 65px;
border-radius: 0 8px 8px 0;
}
.health {font-size: 120%; vertical-align: bottom;}
.health.very-bad { color: #f99; }
.health.bad { color: #f1ba7a; }
.health.neutral { color: #e6e782; }
.health.ok { color: #bef273; }
.health.good { color: #7cf273; }
.health.perfect { color: #33ff80; }
.btn {
border: 1px solid #ddd;
color: #555;
background: #eee;
border-radius: 8px 8px;
height: 36px;
line-height: 34px;
min-width: 80px;
padding: 0 10px;
text-decoration: none;
display: inline-block;
}
/* smaller than tablet in portrait */
@media screen and (max-width: 880px) {
body {
overflow-x: hidden;
}
.mobile {
display: inherit !important;
}
#top-bar .header {
overflow: hidden;
width: 0px;
padding-left: 28px;
height: 28px;
background-size: 28px;
}
#top-bar .search-form {
display: block;
width: 100%;
padding: 0 35px;
margin: 0;
}
.homepage-wrapper,
.search-wrapper {
width: 100%;
max-width: 500px;
}
.homepage-wrapper .search-wrapper {
width: 100%;
}
.homepage-wrapper {
margin: 90px auto;
}
.search-results,
.sub-menu-outer .sub-menu-inner {
width: 95%;
max-width: 500px;
}
.hamburger {
padding: 8px;
font-size: 22px;
line-height: 22px;
cursor: pointer;
}
nav#links {
position: absolute;
width: 100%;
top: 54px;
right: 0;
padding-bottom: 5px;
}
nav#links .viewport {
position: absolute;
z-index: 1;
left: 100%;
width: 100%;
transition: left ease 200ms;
background: #fff;
padding: 20px 0;
box-shadow: 1px 3px 3px rgba(0,0,0,0.2);
font-size: 150%;
text-align: center;
}
nav#links.open .viewport {
left: 0%;
}
#top-bar nav#links .viewport {
background: #f5f5f5;
}
nav#links h3 {
margin: 0;
display: block;
line-height: 2em;
}
nav#links a {
display: block;
line-height: 2.5em;
margin: 4px 0;
}
.profile,
.profile .profile-info {
overflow-wrap: break-word;
word-wrap: break-word;
overflow: hidden;
}
.directory-results {
flex-flow: column;
}
.directory-results > aside {
order: 2;
}
.directory-results > section {
order: 1;
}
}
/* The moment the header starts getting squashed */
@media screen and (max-width: 520px) {
.homepage-wrapper {
margin: 30px auto;
}
.homepage-wrapper .header {
font-size: 40px;
background-size: 36px;
display: inline-block;
margin-left: 18px;
width: 275px;
}
}
/* close to mobile in portrait */
@media screen and (max-width: 400px) {
.profile .profile-photo {
width: 60px;
border-radius: 11.25px;
margin: 8px 4px;
}
.profile .profile-info .url {
display: none;
}
}

494
boot.php
View file

@ -1,419 +1,347 @@
<?php <?php
require_once 'vendor/autoload.php';
set_time_limit(0); set_time_limit(0);
define ( 'BUILD_ID', 1000 ); define('BUILD_ID', 1000);
define ( 'EOL', "<br />\r\n"); define('EOL', "<br />\r\n");
define ( 'REGISTER_CLOSED', 0); define('REGISTER_CLOSED', 0);
define ( 'REGISTER_APPROVE', 1); define('REGISTER_APPROVE', 1);
define ( 'REGISTER_OPEN', 2); define('REGISTER_OPEN', 2);
define ( 'DIRECTION_NONE', 0); define('DIRECTION_NONE', 0);
define ( 'DIRECTION_IN', 1); define('DIRECTION_IN', 1);
define ( 'DIRECTION_OUT', 2); define('DIRECTION_OUT', 2);
define ( 'DIRECTION_BOTH', 3); define('DIRECTION_BOTH', 3);
define ( 'NOTIFY_INTRO', 0x0001 ); define('NOTIFY_INTRO', 0x0001);
define ( 'NOTIFY_CONFIRM', 0x0002 ); define('NOTIFY_CONFIRM', 0x0002);
define ( 'NOTIFY_WALL', 0x0004 ); define('NOTIFY_WALL', 0x0004);
define ( 'NOTIFY_COMMENT', 0x0008 ); define('NOTIFY_COMMENT', 0x0008);
define ( 'NOTIFY_MAIL', 0x0010 ); define('NOTIFY_MAIL', 0x0010);
define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' ); define('NAMESPACE_DFRN', 'http://purl.org/macgirvin/dfrn/1.0');
/** /**
* log levels * log levels
*/ */
define('LOGGER_NORMAL', 0);
define('LOGGER_TRACE', 1);
define('LOGGER_DEBUG', 2);
define('LOGGER_DATA', 3);
define('LOGGER_ALL', 4);
define ( 'LOGGER_NORMAL', 0 ); if (!function_exists('x')) {
define ( 'LOGGER_TRACE', 1 ); function x($s, $k = null)
define ( 'LOGGER_DEBUG', 2 ); {
define ( 'LOGGER_DATA', 3 ); if ($k != null) {
define ( 'LOGGER_ALL', 4 ); if ((is_array($s)) && (array_key_exists($k, $s))) {
if ($s[$k]) {
if(! class_exists('App')) {
class App {
public $module_loaded = false;
public $query_string;
public $config;
public $page;
public $profile;
public $user;
public $cid;
public $contact;
public $content;
public $data;
public $error = false;
public $cmd;
public $argv;
public $argc;
public $module;
public $pager;
public $strings;
public $path;
private $scheme;
private $hostname;
private $baseurl;
private $db;
function __construct() {
$this->config = array();
$this->page = array();
$this->pager= array();
$this->scheme = ((isset($_SERVER['HTTPS'])
&& ($_SERVER['HTTPS'])) ? 'https' : 'http' );
$this->hostname = str_replace('www.','',
$_SERVER['SERVER_NAME']);
set_include_path("include/$this->hostname"
. PATH_SEPARATOR . 'include'
. PATH_SEPARATOR . '.' );
if(substr($_SERVER['QUERY_STRING'],0,2) == "q=")
$_SERVER['QUERY_STRING'] = substr($_SERVER['QUERY_STRING'],2);
$this->query_string = $_SERVER['QUERY_STRING'];
$this->cmd = trim($_GET['q'],'/');
$this->argv = explode('/',$this->cmd);
$this->argc = count($this->argv);
if((array_key_exists('0',$this->argv)) && strlen($this->argv[0])) {
$this->module = $this->argv[0];
}
else {
$this->module = 'directory';
}
$this->pager['page'] = ((x($_GET,'page')) ? $_GET['page'] : 1);
$this->pager['itemspage'] = 50;
$this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
$this->pager['total'] = 0;
}
function get_baseurl($ssl = false) {
if(strlen($this->baseurl))
return $this->baseurl;
$this->baseurl = (($ssl) ? 'https' : $this->scheme) . "://" . $this->hostname
. ((isset($this->path) && strlen($this->path))
? '/' . $this->path : '' );
return $this->baseurl;
}
function set_baseurl($url) {
$this->baseurl = $url;
$this->hostname = basename($url);
}
function get_hostname() {
return $this->hostname;
}
function set_hostname($h) {
$this->hostname = $h;
}
function set_path($p) {
$this->path = ltrim(trim($p),'/');
}
function get_path() {
return $this->path;
}
function set_pager_total($n) {
$this->pager['total'] = intval($n);
}
function set_pager_itemspage($n) {
$this->pager['itemspage'] = intval($n);
$this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
}
function init_pagehead() {
if(file_exists("view/head.tpl"))
$s = file_get_contents("view/head.tpl");
$this->page['htmlhead'] = replace_macros($s,array(
'$baseurl' => $this->get_baseurl()
));
}
}}
if(! function_exists('x')) {
function x($s,$k = NULL) {
if($k != NULL) {
if((is_array($s)) && (array_key_exists($k,$s))) {
if($s[$k])
return (int) 1; return (int) 1;
}
return (int) 0; return (int) 0;
} }
return false; return false;
} } else {
else { if (isset($s)) {
if(isset($s)) { if ($s) {
if($s) {
return (int) 1; return (int) 1;
} }
return (int) 0; return (int) 0;
} }
return false; return false;
} }
}} }
}
if(! function_exists('system_unavailable')) { if (!function_exists('system_unavailable')) {
function system_unavailable() { function system_unavailable()
{
include('system_unavailable.php'); include('system_unavailable.php');
killme(); killme();
}} }
}
if(! function_exists('logger')) { if (!function_exists('logger')) {
function logger($msg,$level = 0) { function logger($msg, $level = 0)
{
$debugging = 1; $debugging = 1;
$loglevel = LOGGER_ALL; $loglevel = LOGGER_ALL;
$logfile = 'logfile.out'; $logfile = 'logfile.out';
if((! $debugging) || (! $logfile) || ($level > $loglevel)) if ((!$debugging) || (!$logfile) || ($level > $loglevel)) {
return; return;
}
require_once('include/datetime.php'); require_once('include/datetime.php');
@file_put_contents($logfile, datetime_convert() . ':' . ' ' . $msg . "\n", FILE_APPEND); @file_put_contents($logfile, datetime_convert() . ':' . ' ' . $msg . "\n", FILE_APPEND);
return; return;
}} }
}
if(! function_exists('replace_macros')) { if (!function_exists('replace_macros')) {
function replace_macros($s,$r) { function replace_macros($s, $r)
{
$search = array(); $search = array();
$replace = array(); $replace = array();
if(is_array($r) && count($r)) { if (is_array($r) && count($r)) {
foreach ($r as $k => $v ) { foreach ($r as $k => $v) {
$search[] = $k; $search[] = $k;
$replace[] = $v; $replace[] = $v;
} }
} }
return str_replace($search,$replace,$s); return str_replace($search, $replace, $s);
}} }
}
if(! function_exists('load_translation_table')) { if (!function_exists('load_translation_table')) {
function load_translation_table($lang) { function load_translation_table($lang)
{
global $a;
}
}
if (!function_exists('t')) {
function t($s)
{
global $a; global $a;
}} if ($a->strings[$s]) {
if(! function_exists('t')) {
function t($s) {
global $a;
if($a->strings[$s])
return $a->strings[$s]; return $a->strings[$s];
}
return $s; return $s;
}} }
}
if (!function_exists('fetch_url')) {
function fetch_url($url, $binary = false, $timeout = 20)
{
if(! function_exists('fetch_url')) {
function fetch_url($url,$binary = false, $timeout=20) {
$ch = curl_init($url); $ch = curl_init($url);
if(! $ch) return false; if (!$ch) {
return false;
}
curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, max(intval($timeout), 1)); //Minimum of 1 second timeout. curl_setopt($ch, CURLOPT_TIMEOUT, max(intval($timeout), 1)); //Minimum of 1 second timeout.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS,8); curl_setopt($ch, CURLOPT_MAXREDIRS, 8);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if($binary) if ($binary) {
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$s = curl_exec($ch); $s = curl_exec($ch);
curl_close($ch); curl_close($ch);
return($s); return($s);
}} }
}
if (!function_exists('post_url')) {
if(! function_exists('post_url')) { function post_url($url, $params)
function post_url($url,$params) { {
$ch = curl_init($url); $ch = curl_init($url);
if(! $ch) return false; if (!$ch) {
return false;
}
curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS,8); curl_setopt($ch, CURLOPT_MAXREDIRS, 8);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST,1); curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$params); curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$s = curl_exec($ch); $s = curl_exec($ch);
curl_close($ch); curl_close($ch);
return($s); return($s);
}} }
}
if (!function_exists('random_string')) {
function random_string()
{
return(hash('sha256', uniqid(rand(), true)));
}
}
if(! function_exists('random_string')) { if (!function_exists('notags')) {
function random_string() { function notags($string)
return(hash('sha256',uniqid(rand(),true))); {
}}
if(! function_exists('notags')) {
function notags($string) {
// protect against :<> with high-bit set // protect against :<> with high-bit set
return(str_replace(array("<",">","\xBA","\xBC","\xBE"), array('[',']','','',''), $string)); return(str_replace(array("<", ">", "\xBA", "\xBC", "\xBE"), array('[', ']', '', '', ''), $string));
}} }
}
if(! function_exists('escape_tags')) {
function escape_tags($string) {
if (!function_exists('escape_tags')) {
function escape_tags($string)
{
return(htmlspecialchars($string)); return(htmlspecialchars($string));
}} }
}
if(! function_exists('login')) { if (!function_exists('login')) {
function login($register = false) { function login($register = false)
{
$o = ""; $o = "";
$register_html = (($register) ? file_get_contents("view/register-link.tpl") : ""); $register_html = (($register) ? file_get_contents("view/register-link.tpl") : "");
if(x($_SESSION,'authenticated')) { if (x($_SESSION, 'authenticated')) {
$o = file_get_contents("view/logout.tpl"); $o = file_get_contents("view/logout.tpl");
} } else {
else {
$o = file_get_contents("view/login.tpl"); $o = file_get_contents("view/login.tpl");
$o = replace_macros($o,array('$register_html' => $register_html )); $o = replace_macros($o, array('$register_html' => $register_html));
} }
return $o; return $o;
}} }
}
if (!function_exists('killme')) {
if(! function_exists('killme')) { function killme()
function killme() { {
session_write_close(); session_write_close();
closedb(); closedb();
exit; exit;
}} }
}
if(! function_exists('goaway')) { if (!function_exists('goaway')) {
function goaway($s) { function goaway($s)
{
header("Location: $s"); header("Location: $s");
killme(); killme();
}} }
}
if(! function_exists('local_user')) { if (!function_exists('local_user')) {
function local_user() { function local_user()
if((x($_SESSION,'authenticated')) && (x($_SESSION,'uid'))) {
if ((x($_SESSION, 'authenticated')) && (x($_SESSION, 'uid'))) {
return $_SESSION['uid']; return $_SESSION['uid'];
}
return false; return false;
}} }
}
if(! function_exists('notice')) {
function notice($s) {
if (!function_exists('notice')) {
function notice($s)
{
if (!isset($_SESSION['sysmsg'])) {
$_SESSION['sysmsg'] = '';
}
$_SESSION['sysmsg'] .= $s; $_SESSION['sysmsg'] .= $s;
}
}
}} if (!function_exists('hex2bin')) {
function hex2bin($s)
{
return(pack("H*", $s));
}
}
if(! function_exists('hex2bin')) { if (!function_exists('paginate')) {
function hex2bin($s) { function paginate(&$a)
return(pack("H*",$s)); {
}}
if(! function_exists('paginate')) {
function paginate(&$a) {
$o = ''; $o = '';
$stripped = ereg_replace("(&page=[0-9]*)","",$a->query_string); $stripped = preg_replace("/&page=[0-9]*/", "", $a->query_string);
$stripped = str_replace('q=','',$stripped); $stripped = str_replace('q=', '', $stripped);
$stripped = trim($stripped,'/'); $stripped = trim($stripped, '/');
$pagenum = $a->pager['page']; $pagenum = $a->pager['page'];
$url = $a->get_baseurl() . '/' . $stripped ; $url = $a->get_baseurl() . '/' . $stripped;
if ($a->pager['total'] > $a->pager['itemspage']) {
if($a->pager['total'] > $a->pager['itemspage']) {
$o .= '<div class="pager">'; $o .= '<div class="pager">';
if($a->pager['page'] != 1) if ($a->pager['page'] != 1) {
$o .= '<span class="pager_prev">'."<a href=\"$url".'&page='.($a->pager['page'] - 1).'">' . t('prev') . '</a></span> '; $o .= '<span class="pager_prev">' . "<a href=\"$url" . '&page=' . ($a->pager['page'] - 1) . '">' . t('prev') . '</a></span> ';
}
$o .= "<span class=\"pager_first\"><a href=\"$url"."&page=1\">" . t('first') . "</a></span> "; $o .= "<span class=\"pager_first\"><a href=\"$url" . "&page=1\">" . t('first') . "</a></span> ";
$numpages = $a->pager['total'] / $a->pager['itemspage']; $numpages = $a->pager['total'] / $a->pager['itemspage'];
$numstart = 1; $numstart = 1;
$numstop = $numpages; $numstop = $numpages;
if($numpages > 14) { if ($numpages > 14) {
$numstart = (($pagenum > 7) ? ($pagenum - 7) : 1); $numstart = (($pagenum > 7) ? ($pagenum - 7) : 1);
$numstop = (($pagenum > ($numpages - 7)) ? $numpages : ($numstart + 14)); $numstop = (($pagenum > ($numpages - 7)) ? $numpages : ($numstart + 14));
} }
for($i = $numstart; $i <= $numstop; $i++){ for ($i = $numstart; $i <= $numstop; $i++) {
if($i == $a->pager['page']) if ($i == $a->pager['page']) {
$o .= '<span class="pager_current">'.(($i < 10) ? '&nbsp;'.$i : $i); $o .= '<span class="pager_current">' . (($i < 10) ? '&nbsp;' . $i : $i);
else } else {
$o .= "<span class=\"pager_n\"><a href=\"$url"."&page=$i\">".(($i < 10) ? '&nbsp;'.$i : $i)."</a>"; $o .= "<span class=\"pager_n\"><a href=\"$url" . "&page=$i\">" . (($i < 10) ? '&nbsp;' . $i : $i) . "</a>";
}
$o .= '</span> '; $o .= '</span> ';
} }
if(($a->pager['total'] % $a->pager['itemspage']) != 0) { if (($a->pager['total'] % $a->pager['itemspage']) != 0) {
if($i == $a->pager['page']) if ($i == $a->pager['page']) {
$o .= '<span class="pager_current">'.(($i < 10) ? '&nbsp;'.$i : $i); $o .= '<span class="pager_current">' . (($i < 10) ? '&nbsp;' . $i : $i);
else } else {
$o .= "<span class=\"pager_n\"><a href=\"$url"."&page=$i\">".(($i < 10) ? '&nbsp;'.$i : $i)."</a>"; $o .= "<span class=\"pager_n\"><a href=\"$url" . "&page=$i\">" . (($i < 10) ? '&nbsp;' . $i : $i) . "</a>";
}
$o .= '</span> '; $o .= '</span> ';
} }
$lastpage = (($numpages > intval($numpages)) ? intval($numpages)+1 : $numpages); $lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
$o .= "<span class=\"pager_last\"><a href=\"$url"."&page=$lastpage\">" . t('last') . "</a></span> "; $o .= "<span class=\"pager_last\"><a href=\"$url" . "&page=$lastpage\">" . t('last') . "</a></span> ";
if(($a->pager['total'] - ($a->pager['itemspage'] * $a->pager['page'])) > 0) if (($a->pager['total'] - ($a->pager['itemspage'] * $a->pager['page'])) > 0) {
$o .= '<span class="pager_next">'."<a href=\"$url"."&page=".($a->pager['page'] + 1).'">' . t('next') . '</a></span>'; $o .= '<span class="pager_next">' . "<a href=\"$url" . "&page=" . ($a->pager['page'] + 1) . '">' . t('next') . '</a></span>';
$o .= '</div>'."\r\n"; }
$o .= '</div>' . "\r\n";
} }
return $o; return $o;
}} }
}
function get_my_url()
function get_my_url() { {
if(x($_SESSION,'my_url')) if (x($_SESSION, 'my_url')) {
return $_SESSION['my_url']; return $_SESSION['my_url'];
}
return false; return false;
} }
function zrl($s,$force = false) { function zrl($s, $force = false)
if(! strlen($s)) {
if (!strlen($s)) {
return $s; return $s;
if((! strpos($s,'/profile/')) && (! $force)) }
if ((!strpos($s, '/profile/')) && (!$force)) {
return $s; return $s;
$achar = strpos($s,'?') ? '&' : '?'; }
$achar = strpos($s, '?') ? '&' : '?';
$mine = get_my_url(); $mine = get_my_url();
if($mine and ! link_compare($mine,$s)) if ($mine and ! link_compare($mine, $s)) {
return $s . $achar . 'zrl=' . urlencode($mine); return $s . $achar . 'zrl=' . urlencode($mine);
}
return $s; return $s;
} }
if(! function_exists('link_compare')) { if (!function_exists('link_compare')) {
function link_compare($a,$b) { function link_compare($a, $b)
if(strcasecmp(normalise_link($a),normalise_link($b)) === 0) {
if (strcasecmp(normalise_link($a), normalise_link($b)) === 0) {
return true; return true;
}
return false; return false;
}} }
}
if(! function_exists('normalise_link')) { if (!function_exists('normalise_link')) {
function normalise_link($url) { function normalise_link($url)
$ret = str_replace(array('https:','//www.'), array('http:','//'), $url); {
return(rtrim($ret,'/')); $ret = str_replace(array('https:', '//www.'), array('http:', '//'), $url);
}} return(rtrim($ret, '/'));
}
}

11
composer.json Normal file
View file

@ -0,0 +1,11 @@
{
"name": "friendica/dir",
"description": "The internet is our social network",
"license": "AGPL3",
"autoload": {
"psr-4": {"Friendica\\Directory\\": "src"}
},
"require": {
"php": ">=5.3"
}
}

View file

@ -1,18 +1,7 @@
-- phpMyAdmin SQL Dump -- Generation Time: Apr 21, 2017 at 03:58 AM
-- version 3.3.10.4
-- http://www.phpmyadmin.net
--
-- Generation Time: May 15, 2012 at 11:03 PM
-- Server version: 5.1.53
-- PHP Version: 5.3.5
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
-- --
-- --
@ -24,11 +13,10 @@ SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
-- --
CREATE TABLE IF NOT EXISTS `flag` ( CREATE TABLE IF NOT EXISTS `flag` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL,
`pid` int(11) NOT NULL, `pid` int(11) NOT NULL,
`reason` int(11) NOT NULL, `reason` int(11) NOT NULL,
`total` int(11) NOT NULL DEFAULT '0', `total` int(11) NOT NULL DEFAULT '0'
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -38,12 +26,11 @@ CREATE TABLE IF NOT EXISTS `flag` (
-- --
CREATE TABLE IF NOT EXISTS `photo` ( CREATE TABLE IF NOT EXISTS `photo` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL,
`profile-id` int(11) NOT NULL, `profile-id` int(11) NOT NULL,
`data` mediumblob NOT NULL, `data` mediumblob NOT NULL,
`score` float NOT NULL DEFAULT '0', `score` float NOT NULL DEFAULT '0'
PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -52,7 +39,7 @@ CREATE TABLE IF NOT EXISTS `photo` (
-- --
CREATE TABLE IF NOT EXISTS `profile` ( CREATE TABLE IF NOT EXISTS `profile` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL,
`name` char(255) NOT NULL, `name` char(255) NOT NULL,
`nurl` char(255) NOT NULL, `nurl` char(255) NOT NULL,
`comm` tinyint(1) NOT NULL DEFAULT '0', `comm` tinyint(1) NOT NULL DEFAULT '0',
@ -61,25 +48,13 @@ CREATE TABLE IF NOT EXISTS `profile` (
`region` char(255) NOT NULL, `region` char(255) NOT NULL,
`postal-code` char(32) NOT NULL, `postal-code` char(32) NOT NULL,
`country-name` char(255) NOT NULL, `country-name` char(255) NOT NULL,
`gender` char(32) NOT NULL,
`marital` char(255) NOT NULL,
`homepage` char(255) NOT NULL, `homepage` char(255) NOT NULL,
`photo` char(255) NOT NULL, `photo` char(255) NOT NULL,
`tags` mediumtext NOT NULL, `tags` mediumtext NOT NULL,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`censored` tinyint(4) NOT NULL DEFAULT '0', `censored` tinyint(4) NOT NULL DEFAULT '0'
PRIMARY KEY (`id`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `name` (`name`),
KEY `nurl` (`nurl`),
KEY `comm` (`comm`),
KEY `pdesc` (`pdesc`),
KEY `locality` (`locality`),
KEY `region` (`region`),
KEY `country-name` (`country-name`),
KEY `homepage` (`homepage`),
FULLTEXT KEY `tags` (`tags`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -88,14 +63,11 @@ CREATE TABLE IF NOT EXISTS `profile` (
-- --
CREATE TABLE IF NOT EXISTS `session` ( CREATE TABLE IF NOT EXISTS `session` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `id` bigint(20) unsigned NOT NULL,
`sid` char(255) NOT NULL, `sid` char(255) NOT NULL,
`data` text NOT NULL, `data` text NOT NULL,
`expire` int(10) unsigned NOT NULL, `expire` int(10) unsigned NOT NULL
PRIMARY KEY (`id`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `sid` (`sid`),
KEY `expire` (`expire`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -104,7 +76,7 @@ CREATE TABLE IF NOT EXISTS `session` (
-- --
CREATE TABLE IF NOT EXISTS `site` ( CREATE TABLE IF NOT EXISTS `site` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL,
`name` char(255) NOT NULL, `name` char(255) NOT NULL,
`url` char(255) NOT NULL, `url` char(255) NOT NULL,
`version` char(16) NOT NULL, `version` char(16) NOT NULL,
@ -113,37 +85,8 @@ CREATE TABLE IF NOT EXISTS `site` (
`info` text NOT NULL, `info` text NOT NULL,
`admin_name` char(255) NOT NULL, `admin_name` char(255) NOT NULL,
`admin_profile` char(255) NOT NULL, `admin_profile` char(255) NOT NULL,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- --------------------------------------------------------
--
-- Table structure for table `tag`
--
CREATE TABLE IF NOT EXISTS `tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`term` char(255) NOT NULL,
`nurl` char(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `term` (`term`),
KEY `nurl` (`nurl`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- --------------------------------------------------------
--
-- Table structure for table `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`email` char(255) NOT NULL,
`password` char(255) NOT NULL,
PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- -------------------------------------------------------- -- --------------------------------------------------------
@ -152,76 +95,262 @@ CREATE TABLE IF NOT EXISTS `user` (
-- --
CREATE TABLE IF NOT EXISTS `site-health` ( CREATE TABLE IF NOT EXISTS `site-health` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL,
`base_url` varchar(255) NOT NULL, `base_url` varchar(255) NOT NULL,
`health_score` int(11) NOT NULL DEFAULT 0, `effective_base_url` varchar(255) DEFAULT NULL,
`no_scrape_url` varchar(255) NULL DEFAULT NULL, `health_score` int(11) NOT NULL DEFAULT '0',
`no_scrape_url` varchar(255) DEFAULT NULL,
`dt_first_noticed` datetime NOT NULL, `dt_first_noticed` datetime NOT NULL,
`dt_last_seen` datetime NULL DEFAULT NULL, `dt_last_seen` datetime DEFAULT NULL,
`dt_last_probed` datetime NULL DEFAULT NULL, `dt_last_probed` datetime DEFAULT NULL,
`dt_last_heartbeat` datetime NULL DEFAULT NULL, `dt_last_heartbeat` datetime DEFAULT NULL,
`name` varchar(255) NULL DEFAULT NULL, `name` varchar(255) DEFAULT NULL,
`version` varchar(255) NULL DEFAULT NULL, `version` varchar(255) DEFAULT NULL,
`plugins` text NULL DEFAULT NULL, `plugins` text,
`reg_policy` char(32) NULL DEFAULT NULL, `reg_policy` char(32) DEFAULT NULL,
`info` text NULL DEFAULT NULL, `info` text,
`admin_name` varchar(255) NULL DEFAULT NULL, `admin_name` varchar(255) DEFAULT NULL,
`admin_profile` varchar(255) NULL DEFAULT NULL, `admin_profile` varchar(255) DEFAULT NULL,
`ssl_state` bit(1) NULL DEFAULT NULL, `ssl_state` bit(1) DEFAULT NULL,
PRIMARY KEY (`id`), `ssl_grade` varchar(3) DEFAULT NULL
KEY `base_url` (`base_url`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `health_score` (`health_score`),
KEY `dt_last_seen` (`dt_last_seen`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- --------------------------------------------------------
--
-- Table structure for table `site-probe`
--
CREATE TABLE IF NOT EXISTS `site-probe` ( CREATE TABLE IF NOT EXISTS `site-probe` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL,
`site_health_id` int(10) unsigned NOT NULL, `site_health_id` int(10) unsigned NOT NULL,
`dt_performed` datetime NOT NULL, `dt_performed` datetime NOT NULL,
`request_time` int(10) unsigned NOT NULL, `request_time` int(10) unsigned NOT NULL
PRIMARY KEY (`id`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `site_health_id` (`site_health_id`),
KEY `dt_performed` (`dt_performed`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
-- --------------------------------------------------------
--
-- Table structure for table `site-scrape`
--
CREATE TABLE IF NOT EXISTS `site-scrape` ( CREATE TABLE IF NOT EXISTS `site-scrape` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL,
`site_health_id` int(10) unsigned NOT NULL, `site_health_id` int(10) unsigned NOT NULL,
`dt_performed` datetime NOT NULL, `dt_performed` datetime NOT NULL,
`request_time` int(10) unsigned NOT NULL, `request_time` int(10) unsigned NOT NULL,
`scrape_time` int(10) unsigned NOT NULL, `scrape_time` int(10) unsigned NOT NULL,
`photo_time` int(10) unsigned NOT NULL, `photo_time` int(10) unsigned NOT NULL,
`total_time` int(10) unsigned NOT NULL, `total_time` int(10) unsigned NOT NULL
PRIMARY KEY (`id`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `site_health_id` (`site_health_id`),
KEY `dt_performed` (`dt_performed`) -- --------------------------------------------------------
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
--
-- Table structure for table `sync-pull-queue`
--
CREATE TABLE IF NOT EXISTS `sync-pull-queue` (
`url` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `sync-push-queue`
--
CREATE TABLE IF NOT EXISTS `sync-push-queue` (
`url` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `sync-targets`
--
CREATE TABLE IF NOT EXISTS `sync-targets` ( CREATE TABLE IF NOT EXISTS `sync-targets` (
`base_url` varchar(255) NOT NULL, `base_url` varchar(255) NOT NULL,
`pull` bit(1) NOT NULL DEFAULT b'0', `pull` bit(1) NOT NULL DEFAULT b'0',
`push` bit(1) NOT NULL DEFAULT b'1', `push` bit(1) NOT NULL DEFAULT b'1',
`dt_last_pull` bigint unsigned NULL DEFAULT NULL, `dt_last_pull` bigint(20) unsigned DEFAULT NULL
PRIMARY KEY (`base_url`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `push` (`push`),
KEY `pull` (`pull`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `sync-push-queue` ( -- --------------------------------------------------------
`url` varchar(255) NOT NULL,
PRIMARY KEY (`url`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `sync-pull-queue` ( --
`url` varchar(255) NOT NULL, -- Table structure for table `sync-timestamps`
PRIMARY KEY (`url`) --
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `sync-timestamps` ( CREATE TABLE IF NOT EXISTS `sync-timestamps` (
`url` varchar(255) NOT NULL, `url` varchar(255) NOT NULL,
`modified` datetime NOT NULL, `modified` datetime NOT NULL
PRIMARY KEY (`url`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
KEY `modified` (`modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; -- --------------------------------------------------------
--
-- Table structure for table `tag`
--
CREATE TABLE IF NOT EXISTS `tag` (
`id` int(11) NOT NULL,
`term` char(255) NOT NULL,
`nurl` char(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`uid` int(11) NOT NULL,
`email` char(255) NOT NULL,
`password` char(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `flag`
--
ALTER TABLE `flag`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `photo`
--
ALTER TABLE `photo`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `profile`
--
ALTER TABLE `profile`
ADD PRIMARY KEY (`id`), ADD KEY `name` (`name`), ADD KEY `nurl` (`nurl`), ADD KEY `comm` (`comm`), ADD KEY `pdesc` (`pdesc`), ADD KEY `locality` (`locality`), ADD KEY `region` (`region`), ADD KEY `country-name` (`country-name`), ADD KEY `homepage` (`homepage`), ADD FULLTEXT KEY `tags` (`tags`), ADD FULLTEXT KEY `profile-ft` (`name`,`pdesc`,`homepage`,`locality`,`region`,`country-name`,`tags`);
--
-- Indexes for table `session`
--
ALTER TABLE `session`
ADD PRIMARY KEY (`id`), ADD KEY `sid` (`sid`), ADD KEY `expire` (`expire`);
--
-- Indexes for table `site`
--
ALTER TABLE `site`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `site-health`
--
ALTER TABLE `site-health`
ADD PRIMARY KEY (`id`), ADD KEY `base_url` (`base_url`), ADD KEY `health_score` (`health_score`), ADD KEY `dt_last_seen` (`dt_last_seen`);
--
-- Indexes for table `site-probe`
--
ALTER TABLE `site-probe`
ADD PRIMARY KEY (`id`), ADD KEY `site_health_id` (`site_health_id`), ADD KEY `dt_performed` (`dt_performed`);
--
-- Indexes for table `site-scrape`
--
ALTER TABLE `site-scrape`
ADD PRIMARY KEY (`id`), ADD KEY `site_health_id` (`site_health_id`), ADD KEY `dt_performed` (`dt_performed`);
--
-- Indexes for table `sync-pull-queue`
--
ALTER TABLE `sync-pull-queue`
ADD PRIMARY KEY (`url`);
--
-- Indexes for table `sync-push-queue`
--
ALTER TABLE `sync-push-queue`
ADD PRIMARY KEY (`url`);
--
-- Indexes for table `sync-targets`
--
ALTER TABLE `sync-targets`
ADD PRIMARY KEY (`base_url`), ADD KEY `push` (`push`), ADD KEY `pull` (`pull`);
--
-- Indexes for table `sync-timestamps`
--
ALTER TABLE `sync-timestamps`
ADD PRIMARY KEY (`url`), ADD KEY `modified` (`modified`);
--
-- Indexes for table `tag`
--
ALTER TABLE `tag`
ADD PRIMARY KEY (`id`), ADD KEY `term` (`term`), ADD KEY `nurl` (`nurl`);
--
-- Indexes for table `user`
--
ALTER TABLE `user`
ADD PRIMARY KEY (`uid`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `flag`
--
ALTER TABLE `flag`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=6;
--
-- AUTO_INCREMENT for table `photo`
--
ALTER TABLE `photo`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1486;
--
-- AUTO_INCREMENT for table `profile`
--
ALTER TABLE `profile`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1488;
--
-- AUTO_INCREMENT for table `session`
--
ALTER TABLE `session`
MODIFY `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=104;
--
-- AUTO_INCREMENT for table `site`
--
ALTER TABLE `site`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `site-health`
--
ALTER TABLE `site-health`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1513;
--
-- AUTO_INCREMENT for table `site-probe`
--
ALTER TABLE `site-probe`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=6651;
--
-- AUTO_INCREMENT for table `site-scrape`
--
ALTER TABLE `site-scrape`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=21048;
--
-- AUTO_INCREMENT for table `tag`
--
ALTER TABLE `tag`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2322;
--
-- AUTO_INCREMENT for table `user`
--
ALTER TABLE `user`
MODIFY `uid` int(11) NOT NULL AUTO_INCREMENT;

14
example.php Normal file
View file

@ -0,0 +1,14 @@
<?php
//Add the auto loader. This makes sure that we can find the files we need for a class.
require_once('vendor/autoload.php');
//This says, we want Hello to mean Friendica\Directory\Example\Hello.
//It's a shortcut.
use Friendica\Directory\Example\Hello;
//Here we use the shortcut and create a new Hello object.
$instance = new Hello();
//Let the Hello object call
echo $instance->sayHello();

91
htconfig.php Normal file
View file

@ -0,0 +1,91 @@
<?php
/**
* This is the default config file. Copy it to ".htconfig.php" and make your
* local changes there.
*/
//MySQL host.
$db_host = 'localhost';
$db_user = 'root';
$db_pass = 'root';
$db_data = 'friendica_dir';
// Choose a legal default timezone. If you are unsure, use "America/Los_Angeles".
// It can be changed later and only applies to timestamps for anonymous viewers.
$default_timezone = 'Europe/Amsterdam';
// What is your site name?
$a->config['sitename'] = "EXPERIMENTAL Friendica public directory";
//Statistic display settings.
$a->config['stats'] = array(
//For site health, the max age for which to display data.
'maxDataAge' => 3600*24*30*4 //120 days = ~4 months
);
//Settings related to the syncing feature.
$a->config['syncing'] = array(
//Pulling may be quite intensive at first when it has to do a full sync and your directory is empty.
//This timeout should be shorter than your cronjob interval. Preferably with a little breathing room.
'timeout' => 3*60, //3 minutes
//Push new submits to the `sync-target` entries?
'enable_pushing' => true,
//Maximum amount of items per batch per target to push to other sync-targets.
//For example: 3 targets x20 items = 60 requests.
'max_push_items' => 10,
//Pull updates from the `sync-target` entries?
'enable_pulling' => true,
//This is your normal amount of threads for pulling.
//With regular intervals, there's no need to give this a high value.
//But when your server is brand new, you may want to keep this high for the first day or two.
'pulling_threads' => 25,
//How many items should we crawl per sync?
'max_pull_items' => 250
);
//Things related to site-health monitoring.
$a->config['site-health'] = array(
//Wait for at least ... before probing a site again.
//The longer this value, the more "stable" site-healths will be over time.
//Note: If a bad (negative) health site submits something, a probe will be performed regardless.
'min_probe_delay' => 24*3600, // 1 day
//Probes get a simple /friendica/json file from the server.
//Feel free to set this timeout to a very tight value.
'probe_timeout' => 5, // seconds
//Imports should be fast. Feel free to prioritize healthy sites.
'skip_import_threshold' => -20
);
//Things related to the maintenance cronjob.
$a->config['maintenance'] = array(
//This is to prevent I/O blocking. Will cost you some RAM overhead though.
//A good server should handle much more than this default, so you can tweak this.
'threads' => 10,
//Limit the amount of scrapes per execution of the maintainer.
//This will depend a lot on the frequency with which you call the maintainer.
//If you have 10 threads and 80 max_scrapes, that means each thread will handle 8 scrapes.
'max_scrapes' => 80,
//Wait for at least ... before scraping a profile again.
'min_scrape_delay' => 3*24*3600, // 3 days
//At which health value should we start removing profiles?
'remove_profile_health_threshold' => -60
);

0
images/b_block.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 83 B

After

Width:  |  Height:  |  Size: 83 B

0
images/b_drop.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 138 B

After

Width:  |  Height:  |  Size: 138 B

0
images/b_drop.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 311 B

0
images/b_drophide.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 111 B

After

Width:  |  Height:  |  Size: 111 B

0
images/b_dropshow.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 138 B

After

Width:  |  Height:  |  Size: 138 B

0
images/b_edit.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 311 B

0
images/b_edit.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 451 B

0
images/blue_flag_16.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1,003 B

After

Width:  |  Height:  |  Size: 1,003 B

0
images/camera-icon.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1,015 B

After

Width:  |  Height:  |  Size: 1,015 B

0
images/default-profile-sm.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 346 B

After

Width:  |  Height:  |  Size: 346 B

0
images/default-profile.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 490 B

0
images/dfrn.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 109 B

After

Width:  |  Height:  |  Size: 109 B

0
images/dislike.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 133 B

0
images/friendica-32.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

185
images/friendica.svg Normal file
View file

@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="100"
height="100"
id="svg2">
<defs
id="defs4">
<linearGradient
id="highlightgradient">
<stop
id="stop3833"
style="stop-color:#ffffff;stop-opacity:0.74374998"
offset="0" />
<stop
id="stop3829"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="shadowgradient">
<stop
id="stop3833-5"
style="stop-color:#000000;stop-opacity:0.5"
offset="0" />
<stop
id="stop3829-9"
style="stop-color:#818080;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
x1="44.948269"
y1="0"
x2="54.103466"
y2="46.797421"
id="linearGradient4011"
xlink:href="#highlightgradient"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(1,0.54545455)" />
<linearGradient
x1="52.016712"
y1="96"
x2="42.867535"
y2="41.837971"
id="linearGradient4021"
xlink:href="#shadowgradient"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.5,0,48)" />
<filter
x="-0.029999999"
y="-0.12"
width="1.0599999"
height="1.24"
color-interpolation-filters="sRGB"
id="filter4055">
<feGaussianBlur
id="feGaussianBlur4057"
stdDeviation="1.2" />
</filter>
<filter
x="-0.029877551"
y="-0.122"
width="1.0597551"
height="1.244"
color-interpolation-filters="sRGB"
id="filter4059">
<feGaussianBlur
id="feGaussianBlur4061"
stdDeviation="1.22" />
</filter>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-952.3622)"
id="layer1"
style="display:inline">
<path
d="m 18,954.3622 c -8.9908981,0.0431 -16,7.05218 -16,16 0,0 0,41.4991 0,64 0,9.1201 7.0091019,16 16,16 l 16,0 0,-26 32,0 -0.08398,-23.9316 -31.91602,0.1679 0,-20.2363 32,0 0,-26 c 0,0 -40,0 -48,0 z"
id="rect2993"
style="fill:#ffc019;fill-opacity:1;stroke:none" />
<path
d="m 82,1050.3622 c 8.990898,0 16.086165,-6.966 16,-16 0,0 0,-41.4991 0,-64 0.07767,-9.01639 -7.067354,-16 -16,-16 l -16,0 0,26 -32,0 0,22 32,0 0,22 -32,0 0,26 c 0,0 32,0 48,0 z"
id="rect2993-6"
style="fill:#1872a2;fill-opacity:1;stroke:none" />
</g>
<g
transform="translate(0,4)"
id="g3997"
style="display:inline">
<path
d="m 66,-2 0,26 -32,0 0,22 m 32,0 0,22 -32,0 0,26"
id="path3999"
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
width="96"
height="96"
rx="16"
ry="16"
x="2"
y="-2"
id="rect4001"
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<g
transform="translate(0,4)"
id="layer3"
style="display:none">
<path
d="m 64,0 0,26 -32,0 0,22 32,0 0,22 -32,0 0,26"
id="path3926"
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
width="96"
height="96"
rx="16"
ry="16"
x="0"
y="0"
id="rect3928"
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<g
transform="translate(0,4)"
id="layer2"
style="display:inline">
<rect
width="96"
height="48.04369"
rx="15.214664"
ry="15.215644"
x="2"
y="-2"
id="rect3823"
style="fill:url(#linearGradient3930);fill-opacity:1;stroke:none" />
<rect
width="96"
height="47.86721"
rx="15.214664"
ry="15.159752"
x="2"
y="-94"
transform="scale(1,-1)"
id="rect3823-8"
style="fill:url(#linearGradient3904);fill-opacity:1;stroke:none" />
<rect
width="98"
height="24"
rx="15.214664"
ry="8.2994423"
x="0"
y="0"
transform="matrix(1.0296115,0,0,1.1963836,-0.901924,-6.713207)"
id="rect4003"
style="fill:url(#linearGradient4011);fill-opacity:1;stroke:none;filter:url(#filter4059)" />
<rect
width="96"
height="24"
rx="14.008356"
ry="12"
x="0"
y="72"
transform="matrix(0.9768331,0,0,0.91974646,3.1649641,6.098115)"
id="rect4013"
style="opacity:0.5674603;fill:url(#linearGradient4021);fill-opacity:1;stroke:none;filter:url(#filter4055)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

0
images/friendika-128.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

0
images/friendika-128.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

0
images/friendika-16.ico Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

0
images/friendika-16.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 659 B

After

Width:  |  Height:  |  Size: 659 B

0
images/friendika-16.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 699 B

After

Width:  |  Height:  |  Size: 699 B

0
images/friendika-1600.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 280 KiB

0
images/friendika-256.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

0
images/friendika-256.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
images/friendika-32.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

0
images/friendika-32.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

0
images/friendika-64.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
images/friendika-64.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

0
images/friendika.svg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

0
images/larrow.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 212 B

0
images/larrw.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1,004 B

After

Width:  |  Height:  |  Size: 1,004 B

0
images/like.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

0
images/link-icon.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 145 B

After

Width:  |  Height:  |  Size: 145 B

0
images/lock_icon.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 932 B

After

Width:  |  Height:  |  Size: 932 B

0
images/lrarrow.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 236 B

After

Width:  |  Height:  |  Size: 236 B

0
images/no.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 631 B

After

Width:  |  Height:  |  Size: 631 B

0
images/pen.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 252 B

0
images/penhover.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 270 B

0
images/rarrow.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 212 B

0
images/rarrw.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 999 B

After

Width:  |  Height:  |  Size: 999 B

0
images/rotator.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 826 B

After

Width:  |  Height:  |  Size: 826 B

0
images/shield_2_16.png Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 974 B

After

Width:  |  Height:  |  Size: 974 B

0
images/star.jpg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 608 B

After

Width:  |  Height:  |  Size: 608 B

0
images/unlock_icon.gif Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 938 B

After

Width:  |  Height:  |  Size: 938 B

View file

@ -1,166 +0,0 @@
<?php
require_once("boot.php");
$a = new App;
@include(".htconfig.php");
require_once("dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
unset($db_host, $db_user, $db_pass, $db_data);
ruire_once("esession.php");
require_once("datetime.php");
$a->set_baseurl(get_config('system','url'));
$u = q("SELECT * FROM `user` WHERE 1 LIMIT 1");
if(! count($u))
killme();
$uid = $u[0]['uid'];
$nickname = $u[0]['nickname'];
$intros = q("SELECT `intro`.*, `intro`.`id` AS `intro_id`, `contact`.*
FROM `intro` LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id`
WHERE `intro`.`blocked` = 0 AND `intro`.`ignore` = 0");
if(! count($intros))
return;
foreach($intros as $intro) {
$intro_id = intval($intro['intro_id']);
$dfrn_id = $intro['issued-id'];
$contact_id = $intro['contact-id'];
$relation = $intro['rel'];
$site_pubkey = $intro['site-pubkey'];
$dfrn_confirm = $intro['confirm'];
$aes_allow = $intro['aes_allow'];
$res=openssl_pkey_new(array(
'digest_alg' => 'whirlpool',
'private_key_bits' => 4096,
'encrypt_key' => false ));
$private_key = '';
openssl_pkey_export($res, $private_key);
$pubkey = openssl_pkey_get_details($res);
$public_key = $pubkey["key"];
$r = q("UPDATE `contact` SET `issued-pubkey` = '%s', `prvkey` = '%s' WHERE `id` = %d LIMIT 1",
dbesc($public_key),
dbesc($private_key),
intval($contact_id)
);
$params = array();
$src_aes_key = random_string();
$result = "";
openssl_private_encrypt($dfrn_id,$result,$u[0]['prvkey']);
$params['dfrn_id'] = $result;
$params['public_key'] = $public_key;
$my_url = $a->get_baseurl() . '/profile/' . $nickname ;
openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
if($aes_allow && function_exists('openssl_encrypt')) {
openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
$params['public_key'] = openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key);
}
$res = post_url($dfrn_confirm,$params);
$xml = simplexml_load_string($res);
$status = (int) $xml->status;
switch($status) {
case 0:
break;
case 1:
// birthday paradox - generate new dfrn-id and fall through.
$new_dfrn_id = random_string();
$r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d LIMIT 1",
dbesc($new_dfrn_id),
intval($contact_id)
);
case 2:
break;
case 3:
default:
break;
}
if(($status == 0 || $status == 3) && ($intro_id)) {
// delete the notification
$r = q("DELETE FROM `intro` WHERE `id` = %d LIMIT 1",
intval($intro_id)
);
}
if($status != 0)
killme();
require_once("Photo.php");
$photo_failure = false;
$filename = basename($intro['photo']);
$img_str = fetch_url($intro['photo'],true);
$img = new Photo($img_str);
if($img) {
$img->scaleImageSquare(175);
$hash = hash('md5',uniqid(mt_rand(),true));
$r = $img->store($contact_id, $hash, $filename, t('Contact Photos'), 4 );
if($r === false)
$photo_failure = true;
$img->scaleImage(80);
$r = $img->store($contact_id, $hash, $filename, t('Contact Photos'), 5 );
if($r === false)
$photo_failure = true;
$photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
$thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
}
else
$photo_failure = true;
if($photo_failure) {
$photo = $a->get_baseurl() . '/images/default-profile.jpg';
$thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
}
$r = q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `rel` = %d,
`name-date` = '%s', `uri-date` = '%s', `avatar-date` = '%s',
`readonly` = %d, `profile-id` = %d, `blocked` = 0, `pending` = 0,
`network` = 'dfrn' WHERE `id` = %d LIMIT 1",
dbesc($photo),
dbesc($thumb),
intval(($relation == DIRECTION_OUT) ? DIRECTION_BOTH : DIRECTION_IN),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval((x($a->config,'rockstar-readonly')) ? $a->config['rockstar-readonly'] : 0),
intval((x($a->config,'rockstar-profile')) ? $a->config['rockstar-profile'] : 0),
intval($contact_id)
);
}
killme();

2
include/Photo.php Executable file → Normal file
View file

@ -186,5 +186,3 @@ class Photo {
} }
} }
}} }}

11
include/Scrape.php Executable file → Normal file
View file

@ -103,7 +103,7 @@ function scrape_dfrn($url, $max_nodes=3500) {
$nodes_left = max(intval($max_nodes), $minNodes); $nodes_left = max(intval($max_nodes), $minNodes);
$items = $dom->getElementsByTagName('*'); $items = $dom->getElementsByTagName('*');
$targets = array('fn', 'pdesc', 'photo', 'key', 'locality', 'region', 'postal-code', 'country-name', 'gender', 'marital'); $targets = array('fn', 'pdesc', 'photo', 'key', 'locality', 'region', 'postal-code', 'country-name');
$targets_left = count($targets); $targets_left = count($targets);
foreach($items as $item) { foreach($items as $item) {
if(attribute_contains($item->getAttribute('class'), 'vcard')) { if(attribute_contains($item->getAttribute('class'), 'vcard')) {
@ -141,15 +141,7 @@ function scrape_dfrn($url, $max_nodes=3500) {
$ret['country-name'] = $x->textContent; $ret['country-name'] = $x->textContent;
$targets_left = pop_scrape_target($targets, 'country-name'); $targets_left = pop_scrape_target($targets, 'country-name');
} }
if(attribute_contains($x->getAttribute('class'),'x-gender')){
$ret['gender'] = $x->textContent;
$targets_left = pop_scrape_target($targets, 'gender');
} }
}
}
if(attribute_contains($item->getAttribute('class'),'marital-text')){
$ret['marital'] = $item->textContent;
$targets_left = pop_scrape_target($targets, 'marital');
} }
$nodes_left--; $nodes_left--;
if($nodes_left <= 0 || $targets_left <= 0) break; if($nodes_left <= 0 || $targets_left <= 0) break;
@ -191,4 +183,3 @@ function pop_scrape_target(&$array, $name) {
unset($array[$at]); unset($array[$at]);
return count($array); return count($array);
}} }}

2
include/auth.php Executable file → Normal file
View file

@ -72,5 +72,3 @@ function init_groups_visitor($contact_id) {
} }
return $groups; return $groups;
}} }}

0
include/bbcode.php Executable file → Normal file
View file

View file

@ -1,76 +1,89 @@
<?php <?php
// Debug stuff. //Startup.
// ini_set('display_errors', 1); require_once 'boot.php';
// ini_set('log_errors','0');
error_reporting(E_ALL^E_NOTICE);
$start_maintain = time(); use Friendica\Directory\App;
$verbose = $argv[1] === 'verbose'; // Debug stuff.
// ini_set('display_errors', 1);
// ini_set('log_errors','0');
error_reporting(E_ALL ^ E_NOTICE);
//Startup. $start_maintain = time();
require_once('boot.php');
$a = new App;
//Config and DB. $verbose = $argv[1] === 'verbose';
require_once(".htconfig.php");
require_once("dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
//Get our set of items. Youngest items first, after the threshold. $a = new App;
//This may be counter-intuitive, but is to prevent items that fail to update from blocking the rest.
$res = q( //Config and DB.
"SELECT `id`, `homepage`, `censored` FROM `profile` WHERE `updated` < '%s' ORDER BY `updated` DESC LIMIT %u", require_once '.htconfig.php';
dbesc(date('Y-m-d H:i:s', time()-$a->config['maintenance']['min_scrape_delay'])), require_once 'dba.php';
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
//Get our set of items. Youngest items first, after the threshold.
//This may be counter-intuitive, but is to prevent items that fail to update from blocking the rest.
$res = q("SELECT `id`, `homepage`, `censored`
FROM `profile`
WHERE `updated` < '%s'
ORDER BY `updated` DESC
LIMIT %u",
dbesc(date('Y-m-d H:i:s', time() - $a->config['maintenance']['min_scrape_delay'])),
intval($a->config['maintenance']['max_scrapes']) intval($a->config['maintenance']['max_scrapes'])
); );
//Nothing to do. //Nothing to do.
if(!$res || !count($res)){ if (!$res || !count($res)) {
exit; exit;
} }
//Close DB here. Threads need their private connection. //Close DB here. Threads need their private connection.
$db->getdb()->close(); $db->getdb()->close();
//We need the scraper. //We need the scraper.
require_once('include/submit.php'); require_once 'include/submit.php';
//POSIX threads only. //POSIX threads only.
if(!function_exists('pcntl_fork')){ if (!function_exists('pcntl_fork')) {
logger('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.'); logger('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.');
die('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.'); die('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.');
} }
//Create the threads we need. //Create the threads we need.
$items = count($res); $items = count($res);
$threadc = min($a->config['maintenance']['threads'], $items); //Don't need more threads than items. $threadc = min($a->config['maintenance']['threads'], $items); //Don't need more threads than items.
$threads = array(); $threads = array();
//Debug... //Debug...
if($verbose) echo("Creating $threadc maintainer threads for $items profiles.".PHP_EOL); if ($verbose) {
logger("Creating $threadc maintainer threads for $items profiles."); echo "Creating $threadc maintainer threads for $items profiles." . PHP_EOL;
}
logger("Creating $threadc maintainer threads for $items profiles.");
for($i = 0; $i < $threadc; $i++){ for ($i = 0; $i < $threadc; $i++) {
$pid = pcntl_fork(); $pid = pcntl_fork();
if($pid === -1){ if ($pid === -1) {
if($verbose) echo('Error: something went wrong with the fork. '.pcntl_strerror()); if ($verbose) {
logger('Error: something went wrong with the fork. '.pcntl_strerror()); echo('Error: something went wrong with the fork. ' . pcntl_strerror());
die('Error: something went wrong with the fork. '.pcntl_strerror()); }
logger('Error: something went wrong with the fork. ' . pcntl_strerror());
die('Error: something went wrong with the fork. ' . pcntl_strerror());
} }
//You're a child, go do some labor! //You're a child, go do some labor!
if($pid === 0) break; if ($pid === 0) {
break;
//Store the list of PID's.
if($pid > 0) $threads[] = $pid;
} }
//The work for child processes. //Store the list of PID's.
if($pid === 0){ if ($pid > 0) {
$threads[] = $pid;
}
}
//The work for child processes.
if ($pid === 0) {
//Lets be nice, we're only doing maintenance here... //Lets be nice, we're only doing maintenance here...
pcntl_setpriority(5); pcntl_setpriority(5);
@ -79,36 +92,39 @@
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install); $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
//Get our (round-robin) workload from the DB results. //Get our (round-robin) workload from the DB results.
$myIndex = $i+1; $myIndex = $i + 1;
$workload = array(); $workload = array();
while(isset($res[$i])){ while (isset($res[$i])) {
$entry = $res[$i]; $entry = $res[$i];
$workload[] = $entry; $workload[] = $entry;
$ids[] = $entry['id']; $ids[] = $entry['id'];
$i+=$threadc; $i += $threadc;
} }
while(count($workload)){ while (count($workload)) {
$entry = array_pop($workload); $entry = array_pop($workload);
set_time_limit(20); //This should work for 1 submit. set_time_limit(20); //This should work for 1 submit.
if($verbose) echo "Submitting ".$entry['homepage'].PHP_EOL; if ($verbose) {
echo "Submitting " . $entry['homepage'] . PHP_EOL;
}
run_submit($entry['homepage']); run_submit($entry['homepage']);
} }
exit; exit;
} else {
}
//The main process. //The main process.
else{ foreach ($threads as $pid) {
foreach($threads as $pid){
pcntl_waitpid($pid, $status); pcntl_waitpid($pid, $status);
if($status !== 0){ if ($status !== 0) {
if($verbose) echo "Bad process return value $pid:$status".PHP_EOL; if ($verbose) {
echo "Bad process return value $pid:$status" . PHP_EOL;
}
logger("Bad process return value $pid:$status"); logger("Bad process return value $pid:$status");
} }
} }
$time = time() - $start_maintain; $time = time() - $start_maintain;
if($verbose) echo("Maintenance completed. Took $time seconds.".PHP_EOL); if ($verbose) {
logger("Maintenance completed. Took $time seconds."); echo("Maintenance completed. Took $time seconds." . PHP_EOL);
} }
logger("Maintenance completed. Took $time seconds.");
}

View file

@ -38,39 +38,47 @@
* Decide if cron_sync.php should be split into push pull and pull-all commands. * Decide if cron_sync.php should be split into push pull and pull-all commands.
*/ */
//Startup.
require_once 'boot.php';
use Friendica\Directory\App;
// Debug stuff. // Debug stuff.
ini_set('display_errors', 1); ini_set('display_errors', 1);
ini_set('log_errors','0'); ini_set('log_errors', '0');
error_reporting(E_ALL^E_NOTICE); error_reporting(E_ALL ^ E_NOTICE);
$start_syncing = time(); $start_syncing = time();
//Startup.
require_once('boot.php');
$a = new App; $a = new App;
//Create a simple log function for CLI use. //Create a simple log function for CLI use.
global $verbose; global $verbose;
$verbose = $argv[1] === 'verbose'; $verbose = $argv[1] === 'verbose';
function msg($message, $fatal=false){ function msg($message, $fatal = false)
{
global $verbose; global $verbose;
if($verbose || $fatal) echo($message.PHP_EOL); if ($verbose || $fatal)
echo($message . PHP_EOL);
logger($message); logger($message);
if($fatal) exit(1); if ($fatal) {
}; exit(1);
}
}
//Config. //Config.
require_once(".htconfig.php"); require_once '.htconfig.php';
//Connect the DB. //Connect the DB.
require_once("dba.php"); require_once 'dba.php';
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install); $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
//Import syncing functions. //Import syncing functions.
require_once('sync.php'); require_once 'sync.php';
//Get work for pulling. //Get work for pulling.
$pull_batch = get_pulling_job($a); $pull_batch = get_pulling_job($a);
@ -81,12 +89,14 @@ list($push_targets, $push_batch) = get_pushing_job($a);
//Close the connection for now. Process forking and DB connections are not the best of friends. //Close the connection for now. Process forking and DB connections are not the best of friends.
$db->getdb()->close(); $db->getdb()->close();
if(count($pull_batch)) if (count($pull_batch)) {
run_pulling_job($a, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install); run_pulling_job($a, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install);
}
//Do our multi-fork job, if we have a batch and targets. //Do our multi-fork job, if we have a batch and targets.
if(count($push_targets) && count($push_batch)) if (count($push_targets) && count($push_batch)) {
run_pushing_job($push_targets, $push_batch, $db_host, $db_user, $db_pass, $db_data, $install); run_pushing_job($push_targets, $push_batch, $db_host, $db_user, $db_pass, $db_data, $install);
}
//Log the time it took. //Log the time it took.
$time = time() - $start_syncing; $time = time() - $start_syncing;

0
include/datetime.php Executable file → Normal file
View file

View file

@ -8,47 +8,52 @@
// x = 3: display full queries using echo; which will mess up display // x = 3: display full queries using echo; which will mess up display
// really bad but will return output in stubborn cases. // really bad but will return output in stubborn cases.
if(! class_exists('dba')) { class dba
class dba { {
private $debug = 0; private $debug = 0;
public $db; public $db;
function __construct($server,$user,$pass,$db,$install = false) { public function __construct($server, $user, $pass, $db, $install = false)
$this->db = @new mysqli($server,$user,$pass,$db); {
if((mysqli_connect_errno()) && (! install)) $this->db = @new mysqli($server, $user, $pass, $db);
if ((mysqli_connect_errno()) && (! install)) {
system_unavailable(); system_unavailable();
} }
}
public function getdb() { public function getdb()
{
return $this->db; return $this->db;
} }
public function q($sql) { public function q($sql)
{
global $debug_text; global $debug_text;
if(! $this->db ) if (! $this->db) {
return false; return false;
}
$result = @$this->db->query($sql); $result = @$this->db->query($sql);
if($this->debug) { if ($this->debug) {
$mesg = ''; $mesg = '';
if($this->db->mysqli->errno) if ($this->db->mysqli->errno) {
$debug_text .= $this->db->mysqli->error . EOL; $debug_text .= $this->db->mysqli->error . EOL;
}
if($result === false) if ($result === false) {
$mesg = 'false'; $mesg = 'false';
elseif($result === true) } elseif ($result === true) {
$mesg = 'true'; $mesg = 'true';
else } else {
$mesg = $result->num_rows.' results' . EOL; $mesg = $result->num_rows.' results' . EOL;
}
$str = 'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg . EOL; $str = 'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg . EOL;
switch($this->debug) { switch ($this->debug) {
case 3: case 3:
echo $str; echo $str;
break; break;
@ -58,60 +63,74 @@ class dba {
} }
} }
if(($result === true) || ($result === false)) if (($result === true) || ($result === false)) {
return $result; return $result;
}
$r = array(); $r = array();
if($result->num_rows) { if ($result->num_rows) {
while($x = $result->fetch_array(MYSQL_ASSOC)) while ($x = $result->fetch_array(MYSQL_ASSOC)) {
$r[] = $x; $r[] = $x;
}
$result->free_result(); $result->free_result();
} }
if($this->debug == 2) if ($this->debug == 2) {
$debug_text .= printable(print_r($r, true). EOL); $debug_text .= printable(print_r($r, true). EOL);
elseif($this->debug == 3) } elseif ($this->debug == 3) {
echo printable(print_r($r, true) . EOL) ; echo printable(print_r($r, true) . EOL) ;
return($r);
} }
public function dbg($dbg) { return $r;
}
public function dbg($dbg)
{
$this->debug = $dbg; $this->debug = $dbg;
} }
public function escape($str) { public function escape($str)
{
return @$this->db->real_escape_string($str); return @$this->db->real_escape_string($str);
} }
function __destruct() { public function __destruct()
{
@$this->db->close(); @$this->db->close();
} }
}} }
if(! function_exists('printable')) { if (! function_exists('printable')) {
function printable($s) { function printable($s)
$s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s); {
$s = str_replace("\x00",'.',$s); $s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~", ".", $s);
if(x($_SERVER,'SERVER_NAME')) $s = str_replace("\x00", '.', $s);
if (x($_SERVER, 'SERVER_NAME')) {
$s = escape_tags($s); $s = escape_tags($s);
}
return $s; return $s;
}} }
}
// Procedural functions // Procedural functions
if(! function_exists('dbg')) { if (! function_exists('dbg')) {
function dbg($state) { function dbg($state)
{
global $db; global $db;
$db->dbg($state); $db->dbg($state);
}} }
}
if(! function_exists('dbesc')) { if (! function_exists('dbesc')) {
function dbesc($str) { function dbesc($str)
{
global $db; global $db;
if($db) if ($db) {
return($db->escape($str)); return($db->escape($str));
}} }
}
}
// Function: q($sql,$args); // Function: q($sql,$args);
@ -119,20 +138,23 @@ function dbesc($str) {
// Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d", // Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
// 'user', 1); // 'user', 1);
if(! function_exists('q')) { if (! function_exists('q')) {
function q($sql) { function q($sql)
{
global $db; global $db;
$args = func_get_args(); $args = func_get_args();
unset($args[0]); unset($args[0]);
if($db) if ($db) {
$ret = $db->q(vsprintf($sql,$args)); $ret = $db->q(vsprintf($sql, $args));
if($db->db->errno) }
if ($db->db->errno) {
logger('dba: ' . $db->db->error); logger('dba: ' . $db->db->error);
}
return $ret; return $ret;
}} }
}
// Caller is responsible for ensuring that any integer arguments to // Caller is responsible for ensuring that any integer arguments to
@ -141,24 +163,30 @@ function q($sql) {
// cast to int to avoid trouble. // cast to int to avoid trouble.
if(! function_exists('dbesc_array_cb')) { if (! function_exists('dbesc_array_cb')) {
function dbesc_array_cb(&$item, $key) { function dbesc_array_cb(&$item, $key)
if(is_string($item)) {
if (is_string($item)) {
$item = dbesc($item); $item = dbesc($item);
}}
if(! function_exists('dbesc_array')) {
function dbesc_array(&$arr) {
if(is_array($arr) && count($arr)) {
array_walk($arr,'dbesc_array_cb');
} }
}} }
}
if(! function_exists('closedb')) { if (! function_exists('dbesc_array')) {
function closedb() { function dbesc_array(&$arr)
{
if (is_array($arr) && count($arr)) {
array_walk($arr, 'dbesc_array_cb');
}
}
}
if (! function_exists('closedb')) {
function closedb()
{
global $db; global $db;
// $db->close(); // $db->close();
}} }
}

34
include/directory.php Executable file → Normal file
View file

@ -1,28 +1,34 @@
<?php <?php
require_once("boot.php"); //Startup.
require_once 'boot.php';
$a = new App; use Friendica\Directory\App;
@include(".htconfig.php"); $a = new App;
require_once("dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
@include '.htconfig.php';
if($argc != 2) require_once 'dba.php';
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
if ($argc != 2) {
exit; exit;
}
load_config('system'); load_config('system');
$a->set_baseurl(get_config('system','url')); $a->set_baseurl(get_config('system', 'url'));
$dir = get_config('system','directory_submit_url'); $dir = get_config('system', 'directory_submit_url');
if(! strlen($dir)) if (!strlen($dir)) {
exit; exit;
}
fetch_url($dir . '?url=' . bin2hex($argv[1])); fetch_url($dir . '?url=' . bin2hex($argv[1]));
exit;
exit;

0
include/group.php Executable file → Normal file
View file

0
include/hostxrd.php Executable file → Normal file
View file

1
include/items.php Executable file → Normal file
View file

@ -241,4 +241,3 @@ function post_remote($a,$arr) {
return $current_post; return $current_post;
} }

View file

@ -1,154 +0,0 @@
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

View file

@ -1,33 +0,0 @@
function openClose(theID) {
if(document.getElementById(theID).style.display == "block") {
document.getElementById(theID).style.display = "none"
}
else {
document.getElementById(theID).style.display = "block"
}
}
function openMenu(theID) {
document.getElementById(theID).style.display = "block"
}
function closeMenu(theID) {
document.getElementById(theID).style.display = "none"
}
function commentOpen(obj,id) {
if(obj.value == 'Comment') {
obj.value = '';
obj.className = "comment-edit-text-full";
openMenu("comment-edit-submit-wrapper-" + id);
}
}
function commentClose(obj,id) {
if(obj.value == '') {
obj.value = 'Comment';
obj.className="comment-edit-text-empty";
closeMenu("comment-edit-submit-wrapper-" + id);
}
}

0
include/nav.php Executable file → Normal file
View file

248
include/notifier.php Executable file → Normal file
View file

@ -1,87 +1,88 @@
<?php <?php
//Startup.
require_once 'boot.php';
require_once("boot.php"); use Friendica\Directory\App;
$a = new App; $a = new App;
@include(".htconfig.php"); @include '.htconfig.php';
require_once("dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
require_once("session.php"); require_once 'dba.php';
require_once("datetime.php");
if($argc < 3) $db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
require_once 'session.php';
require_once 'datetime.php';
if ($argc < 3) {
exit; exit;
}
$a->set_baseurl(get_config('system','url')); $a->set_baseurl(get_config('system', 'url'));
$cmd = $argv[1]; $cmd = $argv[1];
switch($cmd) { switch ($cmd) {
case 'mail': case 'mail':
default: default:
$item_id = intval($argv[2]); $item_id = intval($argv[2]);
if(! $item_id) if (!$item_id) {
killme(); killme();
break;
} }
break;
}
$recipients = array();
$recipients = array(); if ($cmd == 'mail') {
if($cmd == 'mail') { $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1", intval($item_id));
if (!count($message)) {
$message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
if(! count($message))
killme(); killme();
}
$recipients[] = $message[0]['contact-id']; $recipients[] = $message[0]['contact-id'];
$item = $message[0]; $item = $message[0];
} else {
}
else {
// find ancestors // find ancestors
$r = q("SELECT `parent`, `edited` FROM `item` WHERE `id` = %d LIMIT 1", $r = q("SELECT `parent`, `edited` FROM `item` WHERE `id` = %d LIMIT 1", intval($item_id));
intval($item_id) if (!count($r)) {
);
if(! count($r))
killme(); killme();
}
$parent = $r[0]['parent']; $parent = $r[0]['parent'];
$updated = $r[0]['edited']; $updated = $r[0]['edited'];
$items = q("SELECT * FROM `item` WHERE `parent` = %d ORDER BY `id` ASC", $items = q("SELECT * FROM `item` WHERE `parent` = %d ORDER BY `id` ASC", intval($parent));
intval($parent)
);
if(! count($items)) if (!count($items)) {
killme(); killme();
} }
}
$r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1"); $r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1");
if(count($r)) if (count($r)) {
$owner = $r[0]; $owner = $r[0];
else } else {
killme(); killme();
}
if($cmd != 'mail') { if ($cmd != 'mail') {
require_once('include/group.php'); require_once 'include/group.php';
$parent = $items[0]; $parent = $items[0];
if($parent['type'] == 'remote') { if ($parent['type'] == 'remote') {
// local followup to remote post // local followup to remote post
$followup = true; $followup = true;
$conversant_str = dbesc($parent['contact-id']); $conversant_str = dbesc($parent['contact-id']);
} } else {
else {
$followup = false; $followup = false;
$allow_people = expand_acl($parent['allow_cid']); $allow_people = expand_acl($parent['allow_cid']);
@ -91,102 +92,91 @@
$conversants = array(); $conversants = array();
foreach($items as $item) { foreach ($items as $item) {
$recipients[] = $item['contact-id']; $recipients[] = $item['contact-id'];
$conversants[] = $item['contact-id']; $conversants[] = $item['contact-id'];
} }
$conversants = array_unique($conversants,SORT_NUMERIC); $conversants = array_unique($conversants, SORT_NUMERIC);
$recipients = array_unique(array_merge($recipients, $allow_people, $allow_groups), SORT_NUMERIC);
$deny = array_unique(array_merge($deny_people, $deny_groups), SORT_NUMERIC);
$recipients = array_diff($recipients, $deny);
$recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups),SORT_NUMERIC); $conversant_str = dbesc(implode(', ', $conversants));
$deny = array_unique(array_merge($deny_people,$deny_groups),SORT_NUMERIC);
$recipients = array_diff($recipients,$deny);
$conversant_str = dbesc(implode(', ',$conversants));
} }
$r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0"); $r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0");
if( ! count($r)) if (!count($r)) {
killme(); killme();
}
$contacts = $r; $contacts = $r;
$tomb_template = file_get_contents('view/atom_tomb.tpl'); $tomb_template = file_get_contents('view/atom_tomb.tpl');
$item_template = file_get_contents('view/atom_item.tpl'); $item_template = file_get_contents('view/atom_item.tpl');
$cmnt_template = file_get_contents('view/atom_cmnt.tpl'); $cmnt_template = file_get_contents('view/atom_cmnt.tpl');
} }
$feed_template = file_get_contents('view/atom_feed.tpl'); $feed_template = file_get_contents('view/atom_feed.tpl');
$mail_template = file_get_contents('view/atom_mail.tpl'); $mail_template = file_get_contents('view/atom_mail.tpl');
$atom = ''; $atom = '';
$atom .= replace_macros($feed_template, array(
$atom .= replace_macros($feed_template, array(
'$feed_id' => xmlify($a->get_baseurl()), '$feed_id' => xmlify($a->get_baseurl()),
'$feed_title' => xmlify($owner['name']), '$feed_title' => xmlify($owner['name']),
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00', 'Y-m-d\TH:i:s\Z')),
$updated . '+00:00' , 'Y-m-d\TH:i:s\Z')) ,
'$name' => xmlify($owner['name']), '$name' => xmlify($owner['name']),
'$profile_page' => xmlify($owner['url']), '$profile_page' => xmlify($owner['url']),
'$photo' => xmlify($owner['photo']), '$photo' => xmlify($owner['photo']),
'$thumb' => xmlify($owner['thumb']), '$thumb' => xmlify($owner['thumb']),
'$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , 'Y-m-d\TH:i:s\Z')) , '$picdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['avatar-date'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
'$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , 'Y-m-d\TH:i:s\Z')) , '$uridate' => xmlify(datetime_convert('UTC', 'UTC', $owner['uri-date'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
'$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , 'Y-m-d\TH:i:s\Z')) '$namdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['name-date'] . '+00:00', 'Y-m-d\TH:i:s\Z'))
)); ));
if($cmd == 'mail') { if ($cmd == 'mail') {
$atom .= replace_macros($mail_template, array( $atom .= replace_macros($mail_template, array(
'$name' => xmlify($owner['name']), '$name' => xmlify($owner['name']),
'$profile_page' => xmlify($owner['url']), '$profile_page' => xmlify($owner['url']),
'$thumb' => xmlify($owner['thumb']), '$thumb' => xmlify($owner['thumb']),
'$item_id' => xmlify($item['uri']), '$item_id' => xmlify($item['uri']),
'$subject' => xmlify($item['title']), '$subject' => xmlify($item['title']),
'$created' => xmlify(datetime_convert('UTC', 'UTC', '$created' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
$item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')), '$content' => xmlify($item['body']),
'$content' =>xmlify($item['body']),
'$parent_id' => xmlify($item['parent-uri']) '$parent_id' => xmlify($item['parent-uri'])
)); ));
} } else {
else { if ($followup) {
foreach ($items as $item) {
if($followup) { if ($item['id'] == $item_id) {
foreach($items as $item) {
if($item['id'] == $item_id) {
$atom .= replace_macros($cmnt_template, array( $atom .= replace_macros($cmnt_template, array(
'$name' => xmlify($owner['name']), '$name' => xmlify($owner['name']),
'$profile_page' => xmlify($owner['url']), '$profile_page' => xmlify($owner['url']),
'$thumb' => xmlify($owner['thumb']), '$thumb' => xmlify($owner['thumb']),
'$item_id' => xmlify($item['uri']), '$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']), '$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
$item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')), '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', '$content' => xmlify($item['body']),
$item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
'$content' =>xmlify($item['body']),
'$parent_id' => xmlify($item['parent-uri']), '$parent_id' => xmlify($item['parent-uri']),
'$comment_allow' => 0 '$comment_allow' => 0
)); ));
} }
} }
} } else {
else { foreach ($items as $item) {
foreach($items as $item) { if ($item['deleted']) {
if($item['deleted']) {
$atom .= replace_macros($tomb_template, array( $atom .= replace_macros($tomb_template, array(
'$id' => xmlify($item['uri']), '$id' => xmlify($item['uri']),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\TH:i:s\Z'))
$item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z'))
)); ));
} } else {
else { foreach ($contacts as $contact) {
foreach($contacts as $contact) { if ($item['contact-id'] == $contact['id']) {
if($item['contact-id'] == $contact['id']) { if ($item['parent'] == $item['id']) {
if($item['parent'] == $item['id']) {
$atom .= replace_macros($item_template, array( $atom .= replace_macros($item_template, array(
'$name' => xmlify($contact['name']), '$name' => xmlify($contact['name']),
'$profile_page' => xmlify($contact['url']), '$profile_page' => xmlify($contact['url']),
@ -196,26 +186,21 @@
'$owner_thumb' => xmlify($item['owner-avatar']), '$owner_thumb' => xmlify($item['owner-avatar']),
'$item_id' => xmlify($item['uri']), '$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']), '$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
$item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')), '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', '$content' => xmlify($item['body']),
$item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
'$content' =>xmlify($item['body']),
'$comment_allow' => (($item['last-child'] && strlen($contact['dfrn-id'])) ? 1 : 0) '$comment_allow' => (($item['last-child'] && strlen($contact['dfrn-id'])) ? 1 : 0)
)); ));
} } else {
else {
$atom .= replace_macros($cmnt_template, array( $atom .= replace_macros($cmnt_template, array(
'$name' => xmlify($contact['name']), '$name' => xmlify($contact['name']),
'$profile_page' => xmlify($contact['url']), '$profile_page' => xmlify($contact['url']),
'$thumb' => xmlify($contact['thumb']), '$thumb' => xmlify($contact['thumb']),
'$item_id' => xmlify($item['uri']), '$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']), '$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
$item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')), '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\TH:i:s\Z')),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', '$content' => xmlify($item['body']),
$item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
'$content' =>xmlify($item['body']),
'$parent_id' => xmlify($item['parent-uri']), '$parent_id' => xmlify($item['parent-uri']),
'$comment_allow' => (($item['last-child']) ? 1 : 0) '$comment_allow' => (($item['last-child']) ? 1 : 0)
)); ));
@ -225,54 +210,57 @@
} }
} }
} }
} }
$atom .= "</feed>\r\n"; $atom .= "</feed>\r\n";
// create a clone of this feed but with comments disabled to send to those who can't respond. // create a clone of this feed but with comments disabled to send to those who can't respond.
$atom_nowrite = str_replace('<dfrn:comment-allow>1','<dfrn:comment-allow>0',$atom); $atom_nowrite = str_replace('<dfrn:comment-allow>1', '<dfrn:comment-allow>0', $atom);
if($followup) if ($followup) {
$recip_str = $parent['contact-id']; $recip_str = $parent['contact-id'];
else } else {
$recip_str = implode(', ', $recipients); $recip_str = implode(', ', $recipients);
}
$r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) ", $r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) ", dbesc($recip_str));
dbesc($recip_str) if (!count($r)) {
);
if(! count($r))
killme(); killme();
}
// delivery loop // delivery loop
foreach($r as $rr) { foreach ($r as $rr) {
if($rr['self']) if ($rr['self']) {
continue; continue;
}
if(! strlen($rr['dfrn-id'])) if (!strlen($rr['dfrn-id'])) {
continue; continue;
}
$url = $rr['notify'] . '?dfrn_id=' . $rr['dfrn-id']; $url = $rr['notify'] . '?dfrn_id=' . $rr['dfrn-id'];
$xml = fetch_url($url); $xml = fetch_url($url);
if(! $xml) if (!$xml) {
continue; continue;
}
$res = simplexml_load_string($xml); $res = simplexml_load_string($xml);
if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) if ((intval($res->status) != 0) || (!strlen($res->challenge)) || (!strlen($res->dfrn_id))) {
continue; continue;
}
$postvars = array(); $postvars = array();
$sent_dfrn_id = hex2bin($res->dfrn_id); $sent_dfrn_id = hex2bin($res->dfrn_id);
$final_dfrn_id = ''; $final_dfrn_id = '';
openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$rr['pubkey']); openssl_public_decrypt($sent_dfrn_id, $final_dfrn_id, $rr['pubkey']);
$final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
if($final_dfrn_id != $rr['dfrn-id']) { if ($final_dfrn_id != $rr['dfrn-id']) {
// did not decode properly - cannot trust this site // did not decode properly - cannot trust this site
continue; continue;
} }
@ -281,32 +269,26 @@
$challenge = hex2bin($res->challenge); $challenge = hex2bin($res->challenge);
openssl_public_decrypt($challenge,$postvars['challenge'],$rr['pubkey']); openssl_public_decrypt($challenge, $postvars['challenge'], $rr['pubkey']);
if($cmd == 'mail') { if ($cmd == 'mail') {
$postvars['data'] = $atom; $postvars['data'] = $atom;
} } elseif (strlen($rr['dfrn-id']) && (!($rr['blocked']) || ($rr['readonly']))) {
elseif(strlen($rr['dfrn-id']) && (! ($rr['blocked']) || ($rr['readonly']))) {
$postvars['data'] = $atom; $postvars['data'] = $atom;
} } else {
else {
$postvars['data'] = $atom_nowrite; $postvars['data'] = $atom_nowrite;
} }
$xml = post_url($rr['notify'],$postvars); $xml = post_url($rr['notify'], $postvars);
$res = simplexml_load_string($xml); $res = simplexml_load_string($xml);
// Currently there is no retry attempt for failed mail delivery. // Currently there is no retry attempt for failed mail delivery.
// We need to handle this in the UI, report the non-deliverables and try again // We need to handle this in the UI, report the non-deliverables and try again
if(($cmd == 'mail') && (intval($res->status) == 0)) { if (($cmd == 'mail') && (intval($res->status) == 0)) {
$r = q("UPDATE `mail` SET `delivered` = 1 WHERE `id` = %d LIMIT 1", intval($item_id));
$r = q("UPDATE `mail` SET `delivered` = 1 WHERE `id` = %d LIMIT 1",
intval($item_id)
);
}
} }
}
killme(); killme();

202
include/poller.php Executable file → Normal file
View file

@ -1,93 +1,98 @@
<?php <?php
//Startup.
require_once 'boot.php';
require_once('boot.php'); use Friendica\Directory\App;
$a = new App; $a = new App;
@include('.htconfig.php'); @include('.htconfig.php');
require_once('dba.php');
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
require_once('session.php'); require_once 'dba.php';
require_once('datetime.php');
require_once('simplepie/simplepie.inc');
require_once('include/items.php');
$a->set_baseurl(get_config('system','url')); $db = new dba($db_host, $db_user, $db_pass, $db_data);
$contacts = q("SELECT * FROM `contact` unset($db_host, $db_user, $db_pass, $db_data);
require_once 'session.php';
require_once 'datetime.php';
require_once 'simplepie/simplepie.inc';
require_once 'include/items.php';
$a->set_baseurl(get_config('system', 'url'));
$contacts = q("SELECT * FROM `contact`
WHERE `dfrn-id` != '' AND `self` = 0 AND `blocked` = 0 WHERE `dfrn-id` != '' AND `self` = 0 AND `blocked` = 0
AND `readonly` = 0 ORDER BY RAND()"); AND `readonly` = 0 ORDER BY RAND()");
if(! count($contacts)) if (!count($contacts)) {
killme(); killme();
}
foreach($contacts as $contact) { foreach ($contacts as $contact) {
if ($contact['priority']) {
if($contact['priority']) {
$update = false; $update = false;
$t = $contact['last-update']; $t = $contact['last-update'];
switch ($contact['priority']) { switch ($contact['priority']) {
case 5: case 5:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', t . " + 1 month")) if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', t . " + 1 month"))
$update = true; $update = true;
break; break;
case 4: case 4:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', t . " + 1 week")) if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', t . " + 1 week"))
$update = true; $update = true;
break; break;
case 3: case 3:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', t . " + 1 day")) if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', t . " + 1 day"))
$update = true; $update = true;
break; break;
case 2: case 2:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', t . " + 12 hour")) if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', t . " + 12 hour"))
$update = true; $update = true;
break; break;
case 1: case 1:
default: default:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', t . " + 1 hour")) if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', t . " + 1 hour"))
$update = true; $update = true;
break; break;
} }
if(! $update) if (!$update) {
continue;
}
}
$r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1");
if (!count($r)) {
continue; continue;
} }
$r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1");
if(! count($r))
continue;
$importer = $r[0]; $importer = $r[0];
$last_update = (($contact['last-update'] == '0000-00-00 00:00:00') $last_update = (($contact['last-update'] == '0000-00-00 00:00:00') ? datetime_convert('UTC', 'UTC', 'now - 30 days', 'Y-m-d\TH:i:s\Z') : datetime_convert('UTC', 'UTC', $contact['last-update'], 'Y-m-d\TH:i:s\Z'));
? datetime_convert('UTC','UTC','now - 30 days','Y-m-d\TH:i:s\Z')
: datetime_convert('UTC','UTC',$contact['last-update'],'Y-m-d\TH:i:s\Z'));
$url = $contact['poll'] . '?dfrn_id=' . $contact['dfrn-id'] . '&type=data&last_update=' . $last_update ; $url = $contact['poll'] . '?dfrn_id=' . $contact['dfrn-id'] . '&type=data&last_update=' . $last_update;
$xml = fetch_url($url); $xml = fetch_url($url);
if(! $xml) if (!$xml) {
continue; continue;
}
$res = simplexml_load_string($xml); $res = simplexml_load_string($xml);
if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) if ((intval($res->status) != 0) || (!strlen($res->challenge)) || (!strlen($res->dfrn_id))) {
continue; continue;
}
$postvars = array(); $postvars = array();
$sent_dfrn_id = hex2bin($res->dfrn_id); $sent_dfrn_id = hex2bin($res->dfrn_id);
$final_dfrn_id = ''; $final_dfrn_id = '';
openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']); openssl_public_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['pubkey']);
$final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
if($final_dfrn_id != $contact['dfrn-id']) { if ($final_dfrn_id != $contact['dfrn-id']) {
// did not decode properly - cannot trust this site // did not decode properly - cannot trust this site
continue; continue;
} }
@ -95,13 +100,14 @@
$postvars['dfrn_id'] = $contact['dfrn-id']; $postvars['dfrn_id'] = $contact['dfrn-id'];
$challenge = hex2bin($res->challenge); $challenge = hex2bin($res->challenge);
openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']); openssl_public_decrypt($challenge, $postvars['challenge'], $contact['pubkey']);
$xml = post_url($contact['poll'],$postvars); $xml = post_url($contact['poll'], $postvars);
if(! strlen($xml)) { if (!strlen($xml)) {
// an empty response may mean there's nothing new - record the fact that we checked // an empty response may mean there's nothing new - record the fact that we checked
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", $r = q(
"UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1",
dbesc(datetime_convert()), dbesc(datetime_convert()),
intval($contact['id']) intval($contact['id'])
); );
@ -113,24 +119,25 @@
$feed->enable_order_by_date(false); $feed->enable_order_by_date(false);
$feed->init(); $feed->init();
$photo_rawupdate = $feed->get_feed_tags(NAMESPACE_DFRN,'icon-updated'); $photo_rawupdate = $feed->get_feed_tags(NAMESPACE_DFRN, 'icon-updated');
if($photo_rawupdate) {
$photo_timestamp = datetime_convert('UTC','UTC',$photo_rawupdate[0]['data']);
$photo_url = $feed->get_image_url();
if(strlen($photo_url) && $photo_timestamp > $contact['avatar-date']) {
require_once("Photo.php"); if ($photo_rawupdate) {
$photo_timestamp = datetime_convert('UTC', 'UTC', $photo_rawupdate[0]['data']);
$photo_url = $feed->get_image_url();
if (strlen($photo_url) && $photo_timestamp > $contact['avatar-date']) {
require_once 'Photo.php';
$photo_failure = false; $photo_failure = false;
$r = q("SELECT `resource-id` FROM `photo` WHERE `contact-id` = %d LIMIT 1", $r = q("SELECT `resource-id` FROM `photo` WHERE `contact-id` = %d LIMIT 1", intval($contact['id']));
intval($contact['id'])
); if (count($r)) {
if(count($r)) {
$resource_id = $r[0]['resource-id']; $resource_id = $r[0]['resource-id'];
$img_str = fetch_url($photo_url,true); $img_str = fetch_url($photo_url, true);
$img = new Photo($img_str); $img = new Photo($img_str);
if($img) {
if ($img) {
q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND contact-id` = %d ", q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND contact-id` = %d ",
dbesc($resource_id), dbesc($resource_id),
intval($contact['id']) intval($contact['id'])
@ -140,11 +147,11 @@
$hash = $resource_id; $hash = $resource_id;
$r = $img->store($contact['id'], $hash, basename($photo_url), t('Contact Photos') , 4); $r = $img->store($contact['id'], $hash, basename($photo_url), t('Contact Photos'), 4);
$img->scaleImage(80); $img->scaleImage(80);
$r = $img->store($contact['id'], $hash, basename($photo_url), t('Contact Photos') , 5); $r = $img->store($contact['id'], $hash, basename($photo_url), t('Contact Photos'), 5);
if($r) if ($r) {
q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `id` = %d LIMIT 1", q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `id` = %d LIMIT 1",
dbesc(datetime_convert()), dbesc(datetime_convert()),
intval($contact['id']) intval($contact['id'])
@ -153,37 +160,36 @@
} }
} }
} }
}
foreach ($feed->get_items() as $item) {
foreach($feed->get_items() as $item) {
$deleted = false; $deleted = false;
$rawdelete = $item->get_item_tags("http://purl.org/atompub/tombstones/1.0", 'deleted-entry'); $rawdelete = $item->get_item_tags("http://purl.org/atompub/tombstones/1.0", 'deleted-entry');
if(isset($rawdelete[0]['attribs']['']['ref'])) {
if (isset($rawdelete[0]['attribs']['']['ref'])) {
$uri = $rawthread[0]['attribs']['']['ref']; $uri = $rawthread[0]['attribs']['']['ref'];
$deleted = true; $deleted = true;
if(isset($rawdelete[0]['attribs']['']['when'])) {
if (isset($rawdelete[0]['attribs']['']['when'])) {
$when = $rawthread[0]['attribs']['']['when']; $when = $rawthread[0]['attribs']['']['when'];
$when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s'); $when = datetime_convert('UTC', 'UTC', $when, 'Y-m-d H:i:s');
} else {
$when = datetime_convert('UTC', 'UTC', 'now', 'Y-m-d H:i:s');
} }
else
$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
} }
if($deleted) {
$r = q("SELECT * FROM `item` WHERE `uri` = '%s' LIMIT 1", if ($deleted) {
dbesc($uri) $r = q("SELECT * FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($uri));
); if (count($r)) {
if(count($r)) { if ($r[0]['uri'] == $r[0]['parent-uri']) {
if($r[0]['uri'] == $r[0]['parent-uri']) {
$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s',
`body` = '', `title` = '' `body` = '', `title` = ''
WHERE `parent-uri` = '%s'", WHERE `parent-uri` = '%s'",
dbesc($when), dbesc($when),
dbesc($r[0]['uri']) dbesc($r[0]['uri'])
); );
} } else {
else {
$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s',
`body` = '', `title` = '' `body` = '', `title` = ''
WHERE `uri` = '%s' LIMIT 1", WHERE `uri` = '%s' LIMIT 1",
@ -195,29 +201,25 @@
continue; continue;
} }
$is_reply = false; $is_reply = false;
$item_id = $item->get_id(); $item_id = $item->get_id();
$rawthread = $item->get_item_tags("http://purl.org/syndication/thread/1.0",'in-reply-to'); $rawthread = $item->get_item_tags("http://purl.org/syndication/thread/1.0", 'in-reply-to');
if(isset($rawthread[0]['attribs']['']['ref'])) {
if (isset($rawthread[0]['attribs']['']['ref'])) {
$is_reply = true; $is_reply = true;
$parent_uri = $rawthread[0]['attribs']['']['ref']; $parent_uri = $rawthread[0]['attribs']['']['ref'];
} }
if ($is_reply) {
if($is_reply) {
// Have we seen it? If not, import it. // Have we seen it? If not, import it.
$item_id = $item->get_id(); $item_id = $item->get_id();
$r = q("SELECT `last-child`, `edited` FROM `item` WHERE `uri` = '%s' LIMIT 1", $r = q("SELECT `last-child`, `edited` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($item_id));
dbesc($item_id)
);
// FIXME update content if 'updated' changes // FIXME update content if 'updated' changes
if(count($r)) { if (count($r)) {
$allow = $item->get_item_tags( NAMESPACE_DFRN , 'comment-allow'); $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow');
if($allow && $allow[0]['data'] != $r[0]['last-child']) { if ($allow && $allow[0]['data'] != $r[0]['last-child']) {
$r = q("UPDATE `item` SET `last-child` = %d WHERE `uri` = '%s' LIMIT 1", $r = q("UPDATE `item` SET `last-child` = %d WHERE `uri` = '%s' LIMIT 1",
intval($allow[0]['data']), intval($allow[0]['data']),
dbesc($item_id) dbesc($item_id)
@ -225,23 +227,22 @@
} }
continue; continue;
} }
$datarray = get_atom_elements($item); $datarray = get_atom_elements($item);
$datarray['parent-uri'] = $parent_uri; $datarray['parent-uri'] = $parent_uri;
$datarray['contact-id'] = $contact['id']; $datarray['contact-id'] = $contact['id'];
$r = post_remote($a,$datarray); $r = post_remote($a, $datarray);
continue;
}
else { continue;
} else {
// Head post of a conversation. Have we seen it? If not, import it. // Head post of a conversation. Have we seen it? If not, import it.
$item_id = $item->get_id(); $item_id = $item->get_id();
$r = q("SELECT `last-child`, `edited` FROM `item` WHERE `uri` = '%s' LIMIT 1", $r = q("SELECT `last-child`, `edited` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($item_id));
dbesc($item_id)
); if (count($r)) {
if(count($r)) { $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow');
$allow = $item->get_item_tags( NAMESPACE_DFRN ,'comment-allow'); if ($allow && $allow[0]['data'] != $r[0]['last-child']) {
if($allow && $allow[0]['data'] != $r[0]['last-child']) {
$r = q("UPDATE `item` SET `last-child` = %d WHERE `uri` = '%s' LIMIT 1", $r = q("UPDATE `item` SET `last-child` = %d WHERE `uri` = '%s' LIMIT 1",
intval($allow[0]['data']), intval($allow[0]['data']),
dbesc($item_id) dbesc($item_id)
@ -253,21 +254,16 @@
$datarray = get_atom_elements($item); $datarray = get_atom_elements($item);
$datarray['parent-uri'] = $item_id; $datarray['parent-uri'] = $item_id;
$datarray['contact-id'] = $contact['id']; $datarray['contact-id'] = $contact['id'];
$r = post_remote($a,$datarray); $r = post_remote($a, $datarray);
continue; continue;
} }
} }
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1", $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1",
dbesc(datetime_convert()), dbesc(datetime_convert()),
intval($contact['id']) intval($contact['id'])
); );
}
} killme();
killme();

108
include/rockstar.php Executable file → Normal file
View file

@ -1,36 +1,42 @@
<?php <?php
require_once("boot.php"); //Startup.
require_once 'boot.php';
$a = new App; use Friendica\Directory\App;
@include(".htconfig.php"); $a = new App;
require_once("dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
unset($db_host, $db_user, $db_pass, $db_data);
require_once("session.php"); @include(".htconfig.php");
require_once("datetime.php"); require_once 'dba.php';
$a->set_baseurl(get_config('system','url')); $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
$u = q("SELECT * FROM `user` WHERE 1 LIMIT 1"); unset($db_host, $db_user, $db_pass, $db_data);
if(! count($u))
require_once 'session.php';
require_once 'datetime.php';
$a->set_baseurl(get_config('system', 'url'));
$u = q("SELECT * FROM `user` WHERE 1 LIMIT 1");
if (!count($u)) {
killme(); killme();
}
$uid = $u[0]['uid']; $uid = $u[0]['uid'];
$nickname = $u[0]['nickname']; $nickname = $u[0]['nickname'];
$intros = q("SELECT `intro`.*, `intro`.`id` AS `intro_id`, `contact`.* $intros = q("SELECT `intro`.*, `intro`.`id` AS `intro_id`, `contact`.*
FROM `intro` LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id` FROM `intro` LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id`
WHERE `intro`.`blocked` = 0 AND `intro`.`ignore` = 0"); WHERE `intro`.`blocked` = 0 AND `intro`.`ignore` = 0");
if(! count($intros)) if (!count($intros)) {
return; return;
}
foreach ($intros as $intro) {
foreach($intros as $intro) {
$intro_id = intval($intro['intro_id']); $intro_id = intval($intro['intro_id']);
$dfrn_id = $intro['issued-id']; $dfrn_id = $intro['issued-id'];
@ -40,10 +46,10 @@
$dfrn_confirm = $intro['confirm']; $dfrn_confirm = $intro['confirm'];
$aes_allow = $intro['aes_allow']; $aes_allow = $intro['aes_allow'];
$res=openssl_pkey_new(array( $res = openssl_pkey_new(array(
'digest_alg' => 'whirlpool', 'digest_alg' => 'whirlpool',
'private_key_bits' => 4096, 'private_key_bits' => 4096,
'encrypt_key' => false )); 'encrypt_key' => false));
$private_key = ''; $private_key = '';
@ -63,30 +69,29 @@
$src_aes_key = random_string(); $src_aes_key = random_string();
$result = ""; $result = "";
openssl_private_encrypt($dfrn_id,$result,$u[0]['prvkey']); openssl_private_encrypt($dfrn_id, $result, $u[0]['prvkey']);
$params['dfrn_id'] = $result; $params['dfrn_id'] = $result;
$params['public_key'] = $public_key; $params['public_key'] = $public_key;
$my_url = $a->get_baseurl() . '/profile/' . $nickname ; $my_url = $a->get_baseurl() . '/profile/' . $nickname;
openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey); openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
if($aes_allow && function_exists('openssl_encrypt')) { if ($aes_allow && function_exists('openssl_encrypt')) {
openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey); openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
$params['public_key'] = openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key); $params['public_key'] = openssl_encrypt($public_key, 'AES-256-CBC', $src_aes_key);
} }
$res = post_url($dfrn_confirm,$params); $res = post_url($dfrn_confirm, $params);
$xml = simplexml_load_string($res); $xml = simplexml_load_string($res);
$status = (int) $xml->status; $status = (int) $xml->status;
switch($status) { switch ($status) {
case 0: case 0:
break; break;
case 1: case 1:
// birthday paradox - generate new dfrn-id and fall through. // birthday paradox - generate new dfrn-id and fall through.
$new_dfrn_id = random_string(); $new_dfrn_id = random_string();
$r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d LIMIT 1", $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d LIMIT 1",
dbesc($new_dfrn_id), dbesc($new_dfrn_id),
@ -100,48 +105,47 @@
break; break;
} }
if(($status == 0 || $status == 3) && ($intro_id)) { if (($status == 0 || $status == 3) && ($intro_id)) {
// delete the notification // delete the notification
$r = q("DELETE FROM `intro` WHERE `id` = %d LIMIT 1", intval($intro_id));
$r = q("DELETE FROM `intro` WHERE `id` = %d LIMIT 1",
intval($intro_id)
);
} }
if($status != 0)
killme();
require_once("Photo.php"); if ($status != 0) {
killme();
}
require_once 'Photo.php';
$photo_failure = false; $photo_failure = false;
$filename = basename($intro['photo']); $filename = basename($intro['photo']);
$img_str = fetch_url($intro['photo'],true); $img_str = fetch_url($intro['photo'], true);
$img = new Photo($img_str); $img = new Photo($img_str);
if($img) {
if ($img) {
$img->scaleImageSquare(175); $img->scaleImageSquare(175);
$hash = hash('md5',uniqid(mt_rand(),true)); $hash = hash('md5', uniqid(mt_rand(), true));
$r = $img->store($contact_id, $hash, $filename, t('Contact Photos'), 4 ); $r = $img->store($contact_id, $hash, $filename, t('Contact Photos'), 4);
if($r === false) if ($r === false) {
$photo_failure = true; $photo_failure = true;
}
$img->scaleImage(80); $img->scaleImage(80);
$r = $img->store($contact_id, $hash, $filename, t('Contact Photos'), 5 ); $r = $img->store($contact_id, $hash, $filename, t('Contact Photos'), 5);
if($r === false) if ($r === false) {
$photo_failure = true; $photo_failure = true;
}
$photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg'; $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
$thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg'; $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
} } else {
else
$photo_failure = true; $photo_failure = true;
}
if($photo_failure) { if ($photo_failure) {
$photo = $a->get_baseurl() . '/images/default-profile.jpg'; $photo = $a->get_baseurl() . '/images/default-profile.jpg';
$thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg'; $thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
} }
@ -156,11 +160,9 @@
dbesc(datetime_convert()), dbesc(datetime_convert()),
dbesc(datetime_convert()), dbesc(datetime_convert()),
dbesc(datetime_convert()), dbesc(datetime_convert()),
intval((x($a->config,'rockstar-readonly')) ? $a->config['rockstar-readonly'] : 0), intval((x($a->config, 'rockstar-readonly')) ? $a->config['rockstar-readonly'] : 0),
intval((x($a->config,'rockstar-profile')) ? $a->config['rockstar-profile'] : 0), intval((x($a->config, 'rockstar-profile')) ? $a->config['rockstar-profile'] : 0),
intval($contact_id) intval($contact_id)
); );
}
} killme();
killme();

0
include/security.php Executable file → Normal file
View file

0
include/session.php Executable file → Normal file
View file

View file

@ -29,7 +29,7 @@ function notice_site($url, $check_health=false)
$entry = $result[0]; $entry = $result[0];
//If we are allowed to do health checks... //If we are allowed to do health checks...
if(!!$check_health){ if($check_health){
annando commented 2017-05-06 07:12:18 +02:00 (Migrated from github.com)
Review

There are some standards "violations" in the text. Do we want to ignore them just because of the huge amount of changes?

There are some standards "violations" in the text. Do we want to ignore them just because of the huge amount of changes?
MrPetovan commented 2017-05-06 07:16:07 +02:00 (Migrated from github.com)
Review

Yes, I didn't personally touch this file, and neither did @Quix0r apparently. I'll do a sitewide pass right after master is up-to-date.

Yes, I didn't personally touch this file, and neither did @Quix0r apparently. I'll do a sitewide pass right after master is up-to-date.
//And the site is in bad health currently, do a check now. //And the site is in bad health currently, do a check now.
//This is because you have a high certainty the site may perform better now. //This is because you have a high certainty the site may perform better now.
@ -57,7 +57,7 @@ function notice_site($url, $check_health=false)
); );
//And in case we should probe now, do so. //And in case we should probe now, do so.
if(!!$check_health){ if($check_health){
$result = q( $result = q(
"SELECT * FROM `site-health` WHERE `base_url`= '%s' ORDER BY `id` ASC LIMIT 1", "SELECT * FROM `site-health` WHERE `base_url`= '%s' ORDER BY `id` ASC LIMIT 1",
@ -91,7 +91,13 @@ function parse_site_from_url($url)
//Performs a ping to the given site ID //Performs a ping to the given site ID
//You may need to notice the site first before you know it's ID. //You may need to notice the site first before you know it's ID.
if(! function_exists('run_site_ping')){ //TODO: Probe server location using IP address or using the info the friendica server provides (preferred).
// If IP needs to be used only provide country information.
//TODO: Check SSLLabs Grade
// Check needs to be asynchronous, meaning that the check at SSLLabs will be initiated in one run while
// the results must be fetched later. It might be good to mark sites, where a check has been inititated
// f.e. using the ssl_grade field. In the next run, results of these sites could be fetched.
if(! function_exists('run_site_probe')){
function run_site_probe($id, &$entry_out) function run_site_probe($id, &$entry_out)
{ {
@ -134,7 +140,7 @@ function run_site_probe($id, &$entry_out)
CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS, CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
//Basic request //Basic request
CURLOPT_USERAGENT => 'friendica-directory-probe-0.1', CURLOPT_USERAGENT => 'friendica-directory-probe-1.0',
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $probe_location CURLOPT_URL => $probe_location
@ -159,7 +165,7 @@ function run_site_probe($id, &$entry_out)
//Probe again, without strict SSL. //Probe again, without strict SSL.
$options[CURLOPT_SSL_VERIFYPEER] = false; $options[CURLOPT_SSL_VERIFYPEER] = false;
//Replace the handler. //Replace the handle.
curl_close($handle); curl_close($handle);
$handle = curl_init(); $handle = curl_init();
curl_setopt_array($handle, $options); curl_setopt_array($handle, $options);
@ -178,13 +184,14 @@ function run_site_probe($id, &$entry_out)
$time = round(($probe_end - $probe_start) * 1000); $time = round(($probe_end - $probe_start) * 1000);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE); $status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
$type = curl_getinfo($handle, CURLINFO_CONTENT_TYPE); $type = curl_getinfo($handle, CURLINFO_CONTENT_TYPE);
$effective_url = curl_getinfo($handle, CURLINFO_EFFECTIVE_URL); $info = curl_getinfo($handle);
//Done with CURL now. //Done with CURL now.
curl_close($handle); curl_close($handle);
#TODO: if the site redirects elsewhere, notice this site and record an issue. #TODO: if the site redirects elsewhere, notice this site and record an issue.
$wrong_base_url = parse_site_from_url($effective_url) !== $entry['base_url']; $effective_base_url = parse_site_from_url($info['url']);
$wrong_base_url = $effective_base_url !== $entry['base_url'];
try{ try{
$data = json_decode($probe_data); $data = json_decode($probe_data);
@ -195,6 +202,18 @@ function run_site_probe($id, &$entry_out)
$parse_failed = !$data; $parse_failed = !$data;
$parsedDataQuery = ''; $parsedDataQuery = '';
logger('Effective Base URL: ' . $effective_base_url);
if($wrong_base_url){
$parsedDataQuery .= sprintf(
"`effective_base_url` = '%s',",
dbesc($effective_base_url)
);
}else{
$parsedDataQuery .= "`effective_base_url` = NULL,";
}
if(!$parse_failed){ if(!$parse_failed){
$given_base_url_match = $data->url == $base_url; $given_base_url_match = $data->url == $base_url;
@ -208,7 +227,7 @@ function run_site_probe($id, &$entry_out)
); );
//Update any health calculations or otherwise processed data. //Update any health calculations or otherwise processed data.
$parsedDataQuery = sprintf( $parsedDataQuery .= sprintf(
"`dt_last_seen` = NOW(), "`dt_last_seen` = NOW(),
`name` = '%s', `name` = '%s',
`version` = '%s', `version` = '%s',
@ -307,8 +326,8 @@ function health_score_after_probe($current, $probe_success, $time=null, $version
$current = min($current, 30); $current = min($current, 30);
} }
//Older than 3.2.x? //Older than 3.3.x?
elseif(intval($versionParts[1] < 2)){ elseif(intval($versionParts[1] < 3)){
$current -= 5; //Somewhat outdated. $current -= 5; //Somewhat outdated.
} }

81
include/smoothing.js Normal file
View file

@ -0,0 +1,81 @@
(function(){
window.Smoothing = {
/**
* Applies both a moving average bracket and and exponential smoothing.
* @param {array} raw The raw Y values.
* @param {float} factor The exponential smoothing factor to apply (between o and 1).
* @param {int} bracket The amount of datapoints to add to the backet on each side! (2 = 5 data points)
* @return {array} The smoothed Y values.
*/
exponentialMovingAverage: function(raw, factor, bracket){
var output = [];
var smoother = new ExponentialSmoother(factor);
//Transform each data point with the smoother.
for (var i = 0; i < raw.length; i++){
var input = raw[i];
//See if we should bracket.
if(bracket > 0){
//Cap our start and end so it doesn't go out of bounds.
var start = Math.max(i-bracket, 0);
var end = Math.min(i+bracket, raw.length);
//Push the range to our input.
input = [];
for(var j = start; j < end; j++){
input.push(raw[j]);
}
}
output.push(
smoother.transform(input)
);
};
return output;
}
};
// Exponential Smoother class.
var ExponentialSmoother = function(factor){
this.currentValue = null;
this.smoothingFactor = factor || 1;
};
ExponentialSmoother.prototype.transform = function(input){
// In case our input is a bracket, first average it.
if(input.length){
var len = input.length;
var sum = 0;
for (var i = input.length - 1; i >= 0; i--)
sum += input[i]
input = sum/len;
}
// Start with our initial value.
if(this.currentValue === null){
this.currentValue = input;
}
// Our output is basically an updated value.
return this.currentValue =
// Weigh our current value with the smoothing factor.
(this.currentValue * this.smoothingFactor) +
// Add the input to it with the inverse value of the smoothing factor.
( (1-this.smoothingFactor) * input );
};
})();

View file

@ -114,8 +114,6 @@ function run_submit($url) {
`region` = '%s', `region` = '%s',
`postal-code` = '%s', `postal-code` = '%s',
`country-name` = '%s', `country-name` = '%s',
`gender` = '%s',
`marital` = '%s',
`homepage` = '%s', `homepage` = '%s',
`nurl` = '%s', `nurl` = '%s',
`comm` = %d, `comm` = %d,
@ -129,8 +127,6 @@ function run_submit($url) {
$parms['region'], $parms['region'],
$parms['postal-code'], $parms['postal-code'],
$parms['country-name'], $parms['country-name'],
$parms['gender'],
$parms['marital'],
dbesc($url), dbesc($url),
dbesc($nurl), dbesc($nurl),
intval($parms['comm']), intval($parms['comm']),
@ -142,7 +138,7 @@ function run_submit($url) {
} }
else { else {
$r = q("INSERT INTO `profile` ( `name`, `pdesc`, `locality`, `region`, `postal-code`, `country-name`, `gender`, `marital`, `homepage`, `nurl`, `comm`, `tags`, `created`, `updated` ) $r = q("INSERT INTO `profile` ( `name`, `pdesc`, `locality`, `region`, `postal-code`, `country-name`, `homepage`, `nurl`, `comm`, `tags`, `created`, `updated` )
VALUES ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s' )", VALUES ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s' )",
$parms['fn'], $parms['fn'],
$parms['pdesc'], $parms['pdesc'],
@ -150,8 +146,6 @@ function run_submit($url) {
$parms['region'], $parms['region'],
$parms['postal-code'], $parms['postal-code'],
$parms['country-name'], $parms['country-name'],
$parms['gender'],
$parms['marital'],
dbesc($url), dbesc($url),
dbesc($nurl), dbesc($nurl),
intval($parms['comm']), intval($parms['comm']),

View file

@ -1,5 +1,7 @@
<?php <?php
use Friendica\Directory\App;
/** /**
* Pull this URL to our pulling queue. * Pull this URL to our pulling queue.
* @param string $url * @param string $url
@ -7,14 +9,12 @@
*/ */
function sync_pull($url) function sync_pull($url)
{ {
global $a; global $a;
//If we support it that is. //If we support it that is.
if($a->config['syncing']['enable_pulling']){ if ($a->config['syncing']['enable_pulling']) {
q("INSERT INTO `sync-pull-queue` (`url`) VALUES ('%s')", dbesc($url)); q("INSERT INTO `sync-pull-queue` (`url`) VALUES ('%s')", dbesc($url));
} }
} }
/** /**
@ -24,16 +24,14 @@ function sync_pull($url)
*/ */
function sync_push($url) function sync_push($url)
{ {
global $a; global $a;
//If we support it that is. //If we support it that is.
if($a->config['syncing']['enable_pushing']){ if ($a->config['syncing']['enable_pushing']) {
q("INSERT INTO `sync-push-queue` (`url`) VALUES ('%s')", dbesc($url)); q("INSERT INTO `sync-push-queue` (`url`) VALUES ('%s')", dbesc($url));
} }
sync_mark($url); sync_mark($url);
} }
/** /**
@ -44,21 +42,20 @@ function sync_push($url)
*/ */
function sync_mark($url) function sync_mark($url)
{ {
global $a; global $a;
//If we support it that is. //If we support it that is.
if(!$a->config['syncing']['enable_pulling']){ if (!$a->config['syncing']['enable_pulling']) {
return; return;
} }
$exists = count(q("SELECT * FROM `sync-timestamps` WHERE `url`='%s'", dbesc($url))); $exists = count(q("SELECT * FROM `sync-timestamps` WHERE `url`='%s'", dbesc($url)));
if(!$exists) if (!$exists) {
q("INSERT INTO `sync-timestamps` (`url`, `modified`) VALUES ('%s', NOW())", dbesc($url)); q("INSERT INTO `sync-timestamps` (`url`, `modified`) VALUES ('%s', NOW())", dbesc($url));
else } else {
q("UPDATE `sync-timestamps` SET `modified`=NOW() WHERE `url`='%s'", dbesc($url)); q("UPDATE `sync-timestamps` SET `modified`=NOW() WHERE `url`='%s'", dbesc($url));
}
} }
/** /**
@ -70,26 +67,25 @@ function sync_mark($url)
*/ */
function push_worker($target, $batch) function push_worker($target, $batch)
{ {
//Lets be nice, we're only doing a background job here... //Lets be nice, we're only doing a background job here...
pcntl_setpriority(5); pcntl_setpriority(5);
//Find our target's submit URL. //Find our target's submit URL.
$submit = $target['base_url'].'/submit'; $submit = $target['base_url'] . '/submit';
foreach($batch as $item){ foreach ($batch as $item) {
set_time_limit(30); //This should work for 1 submit. set_time_limit(30); //This should work for 1 submit.
msg("Submitting {$item['url']} to $submit"); msg("Submitting {$item['url']} to $submit");
fetch_url($submit.'?url='.bin2hex($item['url'])); fetch_url($submit . '?url=' . bin2hex($item['url']));
} }
} }
/** /**
* Gets an array of push targets. * Gets an array of push targets.
* @return array Push targets. * @return array Push targets.
*/ */
function get_push_targets(){ function get_push_targets()
{
return q("SELECT * FROM `sync-targets` WHERE `push`=b'1'"); return q("SELECT * FROM `sync-targets` WHERE `push`=b'1'");
} }
@ -98,7 +94,8 @@ function get_push_targets(){
* @param object $a The App instance. * @param object $a The App instance.
* @return array Batch of URL's. * @return array Batch of URL's.
*/ */
function get_push_batch($a){ function get_push_batch(App $a)
{
return q("SELECT * FROM `sync-push-queue` LIMIT %u", intval($a->config['syncing']['max_push_items'])); return q("SELECT * FROM `sync-push-queue` LIMIT %u", intval($a->config['syncing']['max_push_items']));
} }
@ -107,37 +104,33 @@ function get_push_batch($a){
* @param object $a The App instance. * @param object $a The App instance.
* @return list($targets, $batch) A list of both the targets array and batch array. * @return list($targets, $batch) A list of both the targets array and batch array.
*/ */
function get_pushing_job($a) function get_pushing_job(App $a)
{ {
//When pushing is requested... //When pushing is requested...
if(!!$a->config['syncing']['enable_pushing']){ if (!!$a->config['syncing']['enable_pushing']) {
//Find our targets. //Find our targets.
$targets = get_push_targets(); $targets = get_push_targets();
//No targets? //No targets?
if(!count($targets)){ if (!count($targets)) {
msg('Pushing enabled, but no push targets.'); msg('Pushing enabled, but no push targets.');
$batch = array(); $batch = array();
} }
//If we have targets, get our batch. //If we have targets, get our batch.
else{ else {
$batch = get_push_batch($a); $batch = get_push_batch($a);
if(!count($batch)) msg('Empty pushing queue.'); //No batch, means no work. if (!count($batch))
msg('Empty pushing queue.'); //No batch, means no work.
} }
} else {
}
//No pushing if it's disabled. //No pushing if it's disabled.
else{
$targets = array(); $targets = array();
$batch = array(); $batch = array();
} }
return array($targets, $batch); return array($targets, $batch);
} }
/** /**
@ -153,23 +146,20 @@ function get_pushing_job($a)
*/ */
function run_pushing_job($targets, $batch, $db_host, $db_user, $db_pass, $db_data, $install) function run_pushing_job($targets, $batch, $db_host, $db_user, $db_pass, $db_data, $install)
{ {
//Create a thread for each target we want to serve push messages to. //Create a thread for each target we want to serve push messages to.
//Not good creating more, because it would stress their server too much. //Not good creating more, because it would stress their server too much.
$threadc = count($targets); $threadc = count($targets);
$threads = array(); $threads = array();
//Do we only have 1 target? No need for threads. //Do we only have 1 target? No need for threads.
if($threadc === 1){ if ($threadc === 1) {
msg('No threads needed. Only one pushing target.'); msg('No threads needed. Only one pushing target.');
push_worker($targets[0], $batch); push_worker($targets[0], $batch);
} } elseif ($threadc > 1) {
//When we need threads. //When we need threads.
elseif($threadc > 1){
//POSIX threads only. //POSIX threads only.
if(!function_exists('pcntl_fork')){ if (!function_exists('pcntl_fork')) {
msg('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.', true); msg('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.', true);
} }
@ -178,49 +168,54 @@ function run_pushing_job($targets, $batch, $db_host, $db_user, $db_pass, $db_dat
msg("Creating $threadc push threads for $items items."); msg("Creating $threadc push threads for $items items.");
//Loop while we need more threads. //Loop while we need more threads.
for($i = 0; $i < $threadc; $i++){ for ($i = 0; $i < $threadc; $i++) {
$pid = pcntl_fork(); $pid = pcntl_fork();
if($pid === -1) msg('Error: something went wrong with the fork. '.pcntl_strerror(), true); if ($pid === -1)
msg('Error: something went wrong with the fork. ' . pcntl_strerror(), true);
//You're a child, go do some labor! //You're a child, go do some labor!
if($pid === 0){push_worker($targets[$i], $batch); exit;} if ($pid === 0) {
push_worker($targets[$i], $batch);
//Store the list of PID's. exit;
if($pid > 0) $threads[] = $pid;
} }
//Store the list of PID's.
if ($pid > 0) {
$threads[] = $pid;
}
}
} }
//Wait for all child processes. //Wait for all child processes.
$theading_problems = false; $theading_problems = false;
foreach($threads as $pid){
foreach ($threads as $pid) {
pcntl_waitpid($pid, $status); pcntl_waitpid($pid, $status);
if($status !== 0){
if ($status !== 0) {
$theading_problems = true; $theading_problems = true;
msg("Bad process return value $pid:$status"); msg("Bad process return value $pid:$status");
} }
} }
//If we did not have any "threading" problems. //If we did not have any "threading" problems.
if(!$theading_problems){ if (!$theading_problems) {
//Reconnect //Reconnect
global $db; global $db;
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install); $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
//Create a query for deleting this queue. //Create a query for deleting this queue.
$where = array(); $where = array();
foreach($batch as $item) $where[] = dbesc($item['url']); foreach ($batch as $item) {
$where = "WHERE `url` IN ('".implode("', '", $where)."')"; $where[] = dbesc($item['url']);
}
$where = "WHERE `url` IN ('" . implode("', '", $where) . "')";
//Remove the items from queue. //Remove the items from queue.
q("DELETE FROM `sync-push-queue` $where LIMIT %u", count($batch)); q("DELETE FROM `sync-push-queue` $where LIMIT %u", count($batch));
msg('Removed items from push queue.'); msg('Removed items from push queue.');
} }
} }
/** /**
@ -228,7 +223,8 @@ function run_pushing_job($targets, $batch, $db_host, $db_user, $db_pass, $db_dat
* @param object $a The App instance. * @param object $a The App instance.
* @return array Batch of URL's. * @return array Batch of URL's.
*/ */
function get_queued_pull_batch($a){ function get_queued_pull_batch(App $a)
{
//Randomize this, to prevent scraping the same servers too much or dead URL's. //Randomize this, to prevent scraping the same servers too much or dead URL's.
$batch = q("SELECT * FROM `sync-pull-queue` ORDER BY RAND() LIMIT %u", intval($a->config['syncing']['max_pull_items'])); $batch = q("SELECT * FROM `sync-pull-queue` ORDER BY RAND() LIMIT %u", intval($a->config['syncing']['max_pull_items']));
msg(sprintf('Pulling %u items from queue.', count($batch))); msg(sprintf('Pulling %u items from queue.', count($batch)));
@ -239,7 +235,8 @@ function get_queued_pull_batch($a){
* Gets an array of pull targets. * Gets an array of pull targets.
* @return array Pull targets. * @return array Pull targets.
*/ */
function get_pull_targets(){ function get_pull_targets()
{
return q("SELECT * FROM `sync-targets` WHERE `pull`=b'1'"); return q("SELECT * FROM `sync-targets` WHERE `pull`=b'1'");
} }
@ -248,59 +245,61 @@ function get_pull_targets(){
* @param object $a The App instance. * @param object $a The App instance.
* @return array Batch of URL's. * @return array Batch of URL's.
*/ */
function get_remote_pull_batch($a) function get_remote_pull_batch(App $a)
{ {
//Find our targets. //Find our targets.
$targets = get_pull_targets(); $targets = get_pull_targets();
msg(sprintf('Pulling from %u remote targets.', count($targets))); msg(sprintf('Pulling from %u remote targets.', count($targets)));
//No targets, means no batch. //No targets, means no batch.
if(!count($targets)) if (!count($targets)) {
return array(); return array();
}
//Pull a list of URL's from each target. //Pull a list of URL's from each target.
$urls = array(); $urls = array();
foreach($targets as $i => $target){
foreach ($targets as $i => $target) {
//First pull, or an update? //First pull, or an update?
if(!$target['dt_last_pull']) if (!$target['dt_last_pull']) {
$url = $target['base_url'].'/sync/pull/all'; $url = $target['base_url'] . '/sync/pull/all';
else } else {
$url = $target['base_url'].'/sync/pull/since/'.intval($target['dt_last_pull']); $url = $target['base_url'] . '/sync/pull/since/' . intval($target['dt_last_pull']);
}
//Go for it :D //Go for it :D
$targets[$i]['pull_data'] = json_decode(fetch_url($url), true); $targets[$i]['pull_data'] = json_decode(fetch_url($url), true);
//If we didn't get any JSON. //If we didn't get any JSON.
if(!$targets[$i]['pull_data']){ if (!$targets[$i]['pull_data']) {
msg(sprintf('Failed to pull from "%s".', $url)); msg(sprintf('Failed to pull from "%s".', $url));
continue; continue;
} }
//Add all entries as keys, to remove duplicates. //Add all entries as keys, to remove duplicates.
foreach($targets[$i]['pull_data']['results'] as $url) foreach ($targets[$i]['pull_data']['results'] as $url) {
$urls[$url]=true; $urls[$url] = true;
}
} }
//Now that we have our URL's. Store them in the queue. //Now that we have our URL's. Store them in the queue.
foreach($urls as $url=>$bool){ foreach ($urls as $url => $bool) {
if($url) sync_pull($url); if ($url) {
sync_pull($url);
}
} }
//Since this all worked out, mark each source with the timestamp of pulling. //Since this all worked out, mark each source with the timestamp of pulling.
foreach($targets as $target){ foreach ($targets as $target) {
if($target['pull_data'] && $target['pull_data']['now']){ if ($target['pull_data'] && $target['pull_data']['now']) {
msg('New pull timestamp '.$target['pull_data']['now'].' for '.$target['base_url']); msg('New pull timestamp ' . $target['pull_data']['now'] . ' for ' . $target['base_url']);
q("UPDATE `sync-targets` SET `dt_last_pull`=%u WHERE `base_url`='%s'", $target['pull_data']['now'], dbesc($target['base_url'])); q("UPDATE `sync-targets` SET `dt_last_pull`=%u WHERE `base_url`='%s'", $target['pull_data']['now'], dbesc($target['base_url']));
} }
} }
//Finally, return a batch of this. //Finally, return a batch of this.
return get_queued_pull_batch($a); return get_queued_pull_batch($a);
} }
/** /**
@ -308,21 +307,24 @@ function get_remote_pull_batch($a)
* @param object $a The App instance. * @param object $a The App instance.
* @return array URL's to scrape. * @return array URL's to scrape.
*/ */
function get_pulling_job($a) function get_pulling_job(App $a)
{ {
//No pulling today... //No pulling today...
if(!$a->config['syncing']['enable_pulling']) if (!$a->config['syncing']['enable_pulling']) {
return array(); return array();
}
//Firstly, finish the items from our queue. //Firstly, finish the items from our queue.
$batch = get_queued_pull_batch($a); $batch = get_queued_pull_batch($a);
if(count($batch)) return $batch; if (count($batch)) {
return $batch;
}
//If that is empty, fill the queue with remote items and return a batch of that. //If that is empty, fill the queue with remote items and return a batch of that.
$batch = get_remote_pull_batch($a); $batch = get_remote_pull_batch($a);
if(count($batch)) return $batch; if (count($batch)) {
return $batch;
}
} }
/** /**
@ -340,7 +342,6 @@ function get_pulling_job($a)
*/ */
function pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install) function pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install)
{ {
//Lets be nice, we're only doing maintenance here... //Lets be nice, we're only doing maintenance here...
pcntl_setpriority(5); pcntl_setpriority(5);
@ -350,20 +351,19 @@ function pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $d
//Get our (round-robin) workload from the batch. //Get our (round-robin) workload from the batch.
$workload = array(); $workload = array();
while(isset($pull_batch[$i])){ while (isset($pull_batch[$i])) {
$entry = $pull_batch[$i]; $entry = $pull_batch[$i];
$workload[] = $entry; $workload[] = $entry;
$i+=$threadc; $i += $threadc;
} }
//While we've got work to do. //While we've got work to do.
while(count($workload)){ while (count($workload)) {
$entry = array_pop($workload); $entry = array_pop($workload);
set_time_limit(20); //This should work for 1 submit. set_time_limit(20); //This should work for 1 submit.
msg("Submitting ".$entry['url']); msg("Submitting " . $entry['url']);
run_submit($entry['url']); run_submit($entry['url']);
} }
} }
/** /**
@ -377,14 +377,13 @@ function pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $d
* @param mixed $install Maybe a boolean. * @param mixed $install Maybe a boolean.
* @return void * @return void
*/ */
function run_pulling_job($a, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install) function run_pulling_job(App $a, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install)
{ {
//We need the scraper. //We need the scraper.
require_once('include/submit.php'); require_once 'include/submit.php';
//POSIX threads only. //POSIX threads only.
if(!function_exists('pcntl_fork')){ if (!function_exists('pcntl_fork')) {
msg('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.', true); msg('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.', true);
} }
@ -396,45 +395,50 @@ function run_pulling_job($a, $pull_batch, $db_host, $db_user, $db_pass, $db_data
msg("Creating $threadc pulling threads for $items profiles."); msg("Creating $threadc pulling threads for $items profiles.");
//Build the threads. //Build the threads.
for($i = 0; $i < $threadc; $i++){ for ($i = 0; $i < $threadc; $i++) {
$pid = pcntl_fork(); $pid = pcntl_fork();
if($pid === -1) msg('Error: something went wrong with the fork. '.pcntl_strerror(), true); if ($pid === -1) {
msg('Error: something went wrong with the fork. ' . pcntl_strerror(), true);
}
//You're a child, go do some labor! //You're a child, go do some labor!
if($pid === 0){pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install); exit;} if ($pid === 0) {
pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install);
exit;
}
//Store the list of PID's. //Store the list of PID's.
if($pid > 0) $threads[] = $pid; if ($pid > 0) {
$threads[] = $pid;
}
} }
//Wait for all child processes. //Wait for all child processes.
$theading_problems = false; $theading_problems = false;
foreach($threads as $pid){ foreach ($threads as $pid) {
pcntl_waitpid($pid, $status); pcntl_waitpid($pid, $status);
if($status !== 0){ if ($status !== 0) {
$theading_problems = true; $theading_problems = true;
msg("Bad process return value $pid:$status"); msg("Bad process return value $pid:$status");
} }
} }
//If we did not have any "threading" problems. //If we did not have any "threading" problems.
if(!$theading_problems){ if (!$theading_problems) {
//Reconnect //Reconnect
global $db; global $db;
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install); $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
//Create a query for deleting this queue. //Create a query for deleting this queue.
$where = array(); $where = array();
foreach($pull_batch as $item) $where[] = dbesc($item['url']); foreach ($pull_batch as $item) {
$where = "WHERE `url` IN ('".implode("', '", $where)."')"; $where[] = dbesc($item['url']);
}
$where = "WHERE `url` IN ('" . implode("', '", $where) . "')";
//Remove the items from queue. //Remove the items from queue.
q("DELETE FROM `sync-pull-queue` $where LIMIT %u", count($pull_batch)); q("DELETE FROM `sync-pull-queue` $where LIMIT %u", count($pull_batch));
msg('Removed items from pull queue.'); msg('Removed items from pull queue.');
} }
} }

0
include/system_unavailable.php Executable file → Normal file
View file

View file

@ -1,41 +1,47 @@
<?php <?php
function tags_widget()
function tags_widget() { {
$o = ''; $o = '';
$r = q("select distinct(term), count(term) as total from tag group by term order by count(term) desc limit 20"); $r = q("SELECT `term`, COUNT(`term`) AS `total` FROM `tag` GROUP BY `term` ORDER BY COUNT(`term`) DESC LIMIT 20");
if(count($r)) { if (count($r)) {
$o .= '<div class="widget">'; $o .= '<div class="widget">';
$o .= '<h3>' . t('Trending Interests') . '</h3>'; $o .= '<h3>' . t('Trending Interests') . '</h3>';
$o .= '<ul>'; $o .= '<ul>';
foreach($r as $rr) { foreach ($r as $rr) {
$o .= '<li><a href="directory?search=' . $rr['term'] . '" >' . $rr['term'] . '</a></li>'; $o .= '<li><a href="search?query=' . $rr['term'] . '" >' . $rr['term'] . '</a> (' . $rr['total'] . ')</li>';
} }
$o .= '</ul></div>'; $o .= '</ul></div>';
} }
return $o; return $o;
} }
function country_widget() { function country_widget()
{
$o = ''; $o = '';
$r = q("select distinct(`country-name`), count(`country-name`) as total from profile where `country-name` != '' group by `country-name` order by count(`country-name`) desc limit 20"); $r = q("SELECT `country-name`, COUNT(`country-name`) AS `total`"
if(count($r)) { . " FROM `profile`"
. " WHERE `country-name` != ''"
. " GROUP BY `country-name`"
. " ORDER BY COUNT(`country-name`) DESC"
. " LIMIT 20");
if (count($r)) {
$o .= '<div class="widget">'; $o .= '<div class="widget">';
$o .= '<h3>' . t('Locations') . '</h3>'; $o .= '<h3>' . t('Locations') . '</h3>';
$o .= '<ul>'; $o .= '<ul>';
foreach($r as $rr) { foreach ($r as $rr) {
$o .= '<li><a href="directory?search=' . $rr['country-name'] . '" >' . $rr['country-name'] . '</a></li>'; $o .= '<li><a href="search?query=' . $rr['country-name'] . '" >' . $rr['country-name'] . '</a> (' . $rr['total'] . ')</li>';
} }
$o .= '</ul></div>'; $o .= '</ul></div>';
} }
return $o; return $o;
} }
function get_taglist($limit = 50)
function get_taglist($limit = 50) { {
$r = q("select distinct(term), count(term) as total from tag group by term order by count(term) desc limit %d", $r = q("SELECT DISTINCT(`term`), COUNT(`term`) AS `total` FROM `tag` GROUP BY `term` ORDER BY COUNT(`term`) DESC LIMIT %d",
intval($limit) intval($limit)
); );

99
index.php Executable file → Normal file
View file

@ -1,93 +1,95 @@
<?php <?php
require_once('boot.php'); require_once 'boot.php';
use Friendica\Directory\App;
$a = new App; $a = new App;
error_reporting(E_ERROR | E_WARNING | E_PARSE ); error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set('error_log','php.out'); error_reporting(E_ALL);
ini_set('log_errors','1'); ini_set('error_log', 'php.out');
ini_set('log_errors', '1');
ini_set('display_errors', '0'); ini_set('display_errors', '0');
$debug_text = ''; $debug_text = '';
require_once('.htconfig.php'); require_once '.htconfig.php';
require_once("dba.php"); require_once 'dba.php';
$db = new dba($db_host, $db_user, $db_pass, $db_data); $db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data); unset($db_host, $db_user, $db_pass, $db_data);
$a->init_pagehead(); $a->init_pagehead();
$a->page['aside'] .= '<div id="logo"><img src="images/friendica-32.png" alt="friendica logo" /> <a href="http://friendica.com">Friendica</a></div><div id="slogan">Your friends. Your web.</div>'; $a->page['aside'] = '<div id="logo"><img src="images/friendica-32.png" alt="friendica logo" /> <a href="http://friendica.com">Friendica</a></div><div id="slogan">Your friends. Your web.</div>';
require_once("session.php");
require_once 'session.php';
session_start(); session_start();
if ((x($_SESSION, 'authenticated')) || (x($_POST, 'auth-params')) || ($a->module === 'login')) {
if((x($_SESSION,'authenticated')) || (x($_POST,'auth-params')) || ($a->module === 'login')) require 'auth.php';
require("auth.php"); }
$dreamhost_error_hack = 1; $dreamhost_error_hack = 1;
if (x($_GET, 'zrl')) {
if(x($_GET,'zrl')) {
$_SESSION['my_url'] = $_GET['zrl']; $_SESSION['my_url'] = $_GET['zrl'];
$a->query_string = preg_replace('/[\?&]*zrl=(.*?)([\?&]|$)/is','',$a->query_string); $a->query_string = preg_replace('/[\?&]*zrl=(.*?)([\?&]|$)/is', '', $a->query_string);
} }
if(strlen($a->module)) { if (strlen($a->module)) {
if(file_exists("mod/{$a->module}.php")) { if (file_exists("mod/{$a->module}.php")) {
include("mod/{$a->module}.php"); include("mod/{$a->module}.php");
$a->module_loaded = true; $a->module_loaded = true;
} }
if(! $a->module_loaded) {
if((x($_SERVER,'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) { if (!$a->module_loaded) {
if ((x($_SERVER, 'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
goaway($a->get_baseurl() . $_SERVER['REQUEST_URI']); goaway($a->get_baseurl() . $_SERVER['REQUEST_URI']);
} }
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found')); header($_SERVER['SERVER_PROTOCOL'] . ' 404 ' . t('Not Found'));
notice( t('Page not found' ) . EOL); notice(t('Page not found') . EOL);
} }
} }
if($a->module_loaded) { if ($a->module_loaded) {
$a->page['page_title'] = $a->module; $a->page['page_title'] = $a->module;
if(function_exists($a->module . '_init')) {
if (function_exists($a->module . '_init')) {
$func = $a->module . '_init'; $func = $a->module . '_init';
$func($a); $func($a);
} }
if(($_SERVER['REQUEST_METHOD'] == 'POST') && (! $a->error) if (($_SERVER['REQUEST_METHOD'] == 'POST') && (!$a->error) && (function_exists($a->module . '_post')) && (!x($_POST, 'auth-params'))) {
&& (function_exists($a->module . '_post'))
&& (! x($_POST,'auth-params'))) {
$func = $a->module . '_post'; $func = $a->module . '_post';
$func($a); $func($a);
} }
if((! $a->error) && (function_exists($a->module . '_afterpost'))) { if ((!$a->error) && (function_exists($a->module . '_afterpost'))) {
$func = $a->module . '_afterpost'; $func = $a->module . '_afterpost';
$func($a); $func($a);
} }
if((! $a->error) && (function_exists($a->module . '_content'))) { if ((!$a->error) && (function_exists($a->module . '_content'))) {
$func = $a->module . '_content'; $func = $a->module . '_content';
$a->page['content'] .= $func($a); $a->page['content'] = $func($a);
} }
}
if(stristr($_SESSION['sysmsg'], t('Permission denied'))) {
header($_SERVER["SERVER_PROTOCOL"] . ' 403 ' . t('Permission denied.'));
} }
// report anything important happening // report anything important happening
if(x($_SESSION,'sysmsg')) { if (x($_SESSION, 'sysmsg')) {
$a->page['content'] = '<div id="sysmsg" class="error-message">' . $_SESSION['sysmsg'] . '</div>' . "\r\n" if (stristr($_SESSION['sysmsg'], t('Permission denied'))) {
header($_SERVER['SERVER_PROTOCOL'] . ' 403 ' . t('Permission denied.'));
}
if (!isset($a->page['content'])) {
$a->page['content'] = '';
}
$a->page['content'] = '<div id="sysmsg" class="error-message">' . $_SESSION['sysmsg'] . '</div>' . PHP_EOL
. $a->page['content']; . $a->page['content'];
unset($_SESSION['sysmsg']); unset($_SESSION['sysmsg']);
} }
@ -96,20 +98,23 @@ if(x($_SESSION,'sysmsg')) {
$a->page['htmlhead'] = replace_macros($a->page['htmlhead'], array( $a->page['htmlhead'] = replace_macros($a->page['htmlhead'], array(
'$stylesheet' => $a->get_baseurl() . '/view/theme/' '$stylesheet' => $a->get_baseurl() . '/view/theme/'
. ((x($_SESSION,'theme')) ? $_SESSION['theme'] : 'default') . ((x($_SESSION, 'theme')) ? $_SESSION['theme'] : 'default')
. '/style.css' . '/style.css'
)); ));
$page = $a->page; $page = $a->page;
$profile = $a->profile; $profile = $a->profile;
header("Content-type: text/html; charset=utf-8"); header('Content-type: text/html; charset=utf-8');
$template = "view/"
. ((x($a->page,'template')) ? $a->page['template'] : 'default' ) $template = 'view/'
. ".php"; . ((x($a->page, 'template')) ? $a->page['template'] : 'default' )
. '.php';
require_once $template;
require_once($template);
session_write_close(); session_write_close();
closedb(); closedb();
exit; exit;

0
include/ajaxupload.js → js/ajaxupload.js Executable file → Normal file
View file

0
include/country.js → js/country.js Executable file → Normal file
View file

0
include/jquery.js → js/jquery.js vendored Executable file → Normal file
View file

32
js/main.js Normal file
View file

@ -0,0 +1,32 @@
function openClose(theID) {
if (document.getElementById(theID).style.display == "block") {
document.getElementById(theID).style.display = "none"
} else {
document.getElementById(theID).style.display = "block"
}
}
function openMenu(theID) {
document.getElementById(theID).style.display = "block"
}
function closeMenu(theID) {
document.getElementById(theID).style.display = "none"
}
function commentOpen(obj,id) {
if (obj.value == 'Comment') {
obj.value = '';
obj.className = "comment-edit-text-full";
openMenu("comment-edit-submit-wrapper-" + id);
}
}
function commentClose(obj,id) {
if (obj.value == '') {
obj.value = 'Comment';
obj.className="comment-edit-text-empty";
closeMenu("comment-edit-submit-wrapper-" + id);
}
}

0
library/HTML5/Data.php Executable file → Normal file
View file

0
library/HTML5/InputStream.php Executable file → Normal file
View file

0
library/HTML5/Parser.php Executable file → Normal file
View file

0
library/HTML5/Tokenizer.php Executable file → Normal file
View file

0
library/HTML5/TreeBuilder.php Executable file → Normal file
View file

0
library/HTML5/named-character-references.ser Executable file → Normal file
View file

View file

@ -0,0 +1,237 @@
# PHP-SSLLabs-API
This PHP library provides basic access to the SSL Labs API.
It's build upon the official API documentation at https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md
```PHP
<?php
require_once 'sslLabsApi.php';
//Return API response as JSON string
$api = new sslLabsApi();
//Return API response as JSON object
//$api = new sslLabsApi(true);
//Set content-type header for JSON output
header('Content-Type: application/json');
//get API information
var_dump($api->fetchApiInfo());
?>
```
## Methods
### fetchApiInfo()
No parameters needed
Returns an Info object (see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#info).
### fetchStatusCodes()
No parameters needed
Returns a StatusCodes instance (see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#statuscodes).
### fetchHostInformation()
See https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#invoke-assessment-and-check-progress for parameter description.
| Parameter | Type | Default value | |
|---------------------|---------|---------------|----------|
| **host** | string | | Required |
| **publish** | boolean | false | |
| **startNew** | boolean | false | |
| **fromCache** | boolean | false | |
| **maxAge** | int | null | |
| **all** | string | null | |
| **ignoreMismatch** | boolean | false | |
Returns a Host object (see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#host).
Make sure to check the 'status' attribute inside Host object.
### fetchHostInformationCached()
You can also use fetchHostInformation() with the proper parameters, this is just a helper function.
| Parameter | Type | Default value | |
|---------------------|---------|---------------|----------|
| **host** | string | | Required |
| **maxAge** | int | null | |
| **publish** | boolean | false | |
| **ignoreMismatch** | boolean | false | |
Returns a Host object (see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#host).
Also make sure to check the 'status' attribute inside Host object.
### fetchEndpointData()
See https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#retrieve-detailed-endpoint-information for parameter description.
| Parameter | Type | Default value | |
|----------------|---------|---------------|----------|
| **host** | string | | Required |
| **s** | string | | Required |
| **fromCache** | boolean | false | |
Returns an Endpoint object (see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md#endpoint).
### Custom API calls
Use sendApiRequest() method to create custom API calls.
| Parameter | Type | Default value | |
|-----------------|--------|---------------|----------|
| **apiCall** | string | | Required |
| **parameters** | array | | |
```PHP
$api->sendApiRequest('apiCallName', array('p1' => 'p1_value', 'p2' => 'p2_value'));
```
### getReturnJsonObjects()
Getter for returnJsonObjects
### setReturnJsonObjects()
Setter for returnJsonObjects
| Parameter | Type | Default value | |
|-----------------------|---------|---------------|----------|
| **returnJsonObjects** | boolean | | Required |
## Example output (as JSON strings)
### Get API information
```PHP
$api->fetchApiInfo();
```
```JSON
{
"engineVersion": "1.15.1",
"criteriaVersion": "2009i",
"clientMaxAssessments": 25,
"maxAssessments": 25,
"currentAssessments": 0,
"messages": [
"This assessment service is provided free of charge by Qualys SSL Labs, subject to our terms and conditions: https://www.ssllabs.com/about/terms.html"
]
}
```
### Get host information
```PHP
$api->fetchHostInformation('https://www.google.de');
```
```JSON
{
"host": "https://www.google.de",
"port": 443,
"protocol": "HTTP",
"isPublic": false,
"status": "READY",
"startTime": 1427195976527,
"testTime": 1427196284525,
"engineVersion": "1.15.1",
"criteriaVersion": "2009i",
"endpoints": [
{
"ipAddress": "74.125.239.119",
"serverName": "nuq05s01-in-f23.1e100.net",
"statusMessage": "Ready",
"grade": "B",
"hasWarnings": false,
"isExceptional": false,
"progress": 100,
"duration": 77376,
"eta": 1610,
"delegation": 3
},
{
"ipAddress": "74.125.239.120",
"serverName": "nuq05s01-in-f24.1e100.net",
"statusMessage": "Ready",
"grade": "B",
"hasWarnings": false,
"isExceptional": false,
"progress": 100,
"duration": 76386,
"eta": 1609,
"delegation": 3
},
{
"ipAddress": "74.125.239.127",
"serverName": "nuq05s01-in-f31.1e100.net",
"statusMessage": "Ready",
"grade": "B",
"hasWarnings": false,
"isExceptional": false,
"progress": 100,
"duration": 76937,
"eta": 1608,
"delegation": 3
},
{
"ipAddress": "74.125.239.111",
"serverName": "nuq05s01-in-f15.1e100.net",
"statusMessage": "Ready",
"grade": "B",
"hasWarnings": false,
"isExceptional": false,
"progress": 100,
"duration": 77171,
"eta": 1606,
"delegation": 3
}
]
}
```
### Get endpoint information
```PHP
$api->fetchEndpointData('https://www.google.de', '74.125.239.111');
```
(just an except of the entire JSON output)
```JSON
{
"ipAddress": "74.125.239.111",
"serverName": "nuq05s01-in-f15.1e100.net",
"statusMessage": "Ready",
"grade": "B",
"hasWarnings": false,
"isExceptional": false,
"progress": 100,
"duration": 77171,
"eta": 1609,
"delegation": 3,
"details": {
"hostStartTime": 1427195976527,
"key": {},
"cert": {},
"chain": {},
"protocols": [],
"suites": {},
"serverSignature": "gws",
"prefixDelegation": true,
"nonPrefixDelegation": true,
"vulnBeast": false,
"renegSupport": 2,
"sessionResumption": 1,
"compressionMethods": 0,
"supportsNpn": true,
"npnProtocols": "h2-15 h2-14 spdy/3.1 spdy/3 http/1.1",
"sessionTickets": 1,
"ocspStapling": false,
"sniRequired": false,
"httpStatusCode": 200,
"supportsRc4": true,
"forwardSecrecy": 2,
"rc4WithModern": true,
"sims": {},
"heartbleed": false,
"heartbeat": false,
"openSslCcs": 1,
"poodleTls": 1,
"fallbackScsv": true
}
}
```
# Terms and Conditions
As this is just a PHP library for SSL Labs API please refer to SSL Labs terms and conditions at https://www.ssllabs.com/about/terms.html

View file

@ -0,0 +1,216 @@
<?php
/**
* PHP-SSLLabs-API
*
* This PHP library provides basic access to the SSL Labs API
* and is build upon the official API documentation at
* https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md
*
* @author Björn Roland <https://github.com/bjoernr-de>
* @license GNU GENERAL PUBLIC LICENSE v3
*/
class sslLabsApi
{
CONST API_URL = "https://api.ssllabs.com/api/v2";
private $returnJsonObjects;
/**
* sslLabsApi::__construct()
*/
public function __construct($returnJsonObjects = false)
{
$this->returnJsonObjects = (boolean) $returnJsonObjects;
}
/**
* sslLabsApi::fetchApiInfo()
*
* API Call: info
* @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md
*/
public function fetchApiInfo()
{
return ($this->sendApiRequest('info'));
}
/**
* sslLabsApi::fetchHostInformation()
*
* API Call: analyze
* @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md
*
* @param string $host Hostname to analyze
* @param boolean $publish
* @param boolean $startNew
* @param boolean $fromCache
* @param int $maxAge
* @param string $all
* @param boolean $ignoreMismatch
*/
public function fetchHostInformation($host, $publish = false, $startNew = false, $fromCache = false, $maxAge = NULL, $all = NULL, $ignoreMismatch = false)
{
$apiRequest = $this->sendApiRequest
(
'analyze',
array
(
'host' => $host,
'publish' => $publish,
'startNew' => $startNew,
'fromCache' => $fromCache,
'maxAge' => $maxAge,
'all' => $all,
'ignoreMismatch' => $ignoreMismatch
)
);
return ($apiRequest);
}
/**
* sslLabsApi::fetchHostInformationCached()
*
* API Call: analyze
* Same as fetchHostInformation() but prefer to receive cached information
*
* @param string $host
* @param int $maxAge
* @param string $publish
* @param string $ignoreMismatch
*/
public function fetchHostInformationCached($host, $maxAge, $publish = false, $ignoreMismatch = false)
{
return($this->fetchHostInformation($host, $publish, false, true, $maxAge, 'done', $ignoreMismatch));
}
/**
* sslLabsApi::fetchEndpointData()
*
* API Call: getEndpointData
* @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md
*
* @param string $host
* @param string $s
* @param string $fromCache
* @return string
*/
public function fetchEndpointData($host, $s, $fromCache = false)
{
$apiRequest = $this->sendApiRequest
(
'getEndpointData',
array
(
'host' => $host,
's' => $s,
'fromCache' => $fromCache
)
);
return ($apiRequest);
}
/**
* sslLabsApi::fetchStatusCodes()
*
* API Call: getStatusCodes
*/
public function fetchStatusCodes()
{
return ($this->sendApiRequest('getStatusCodes'));
}
/**
* sslLabsApi::sendApiRequest()
*
* Send API request
*
* @param string $apiCall
* @param array $parameters
* @return string JSON from API
*/
public function sendApiRequest($apiCall, $parameters = array())
{
//we also want content from failed api responses
$context = stream_context_create
(
array
(
'http' => array
(
'ignore_errors' => true
)
)
);
$apiResponse = file_get_contents(self::API_URL . '/' . $apiCall . $this->buildGetParameterString($parameters), false, $context);
if($this->returnJsonObjects)
{
return (json_decode($apiResponse));
}
return ($apiResponse);
}
/**
* sslLabsApi::setReturnJsonObjects()
*
* Setter for returnJsonObjects
* Set true to return all API responses as JSON object, false returns it as simple JSON strings (default)
*
* @param boolean $returnJsonObjects
*/
public function setReturnJsonObjects($returnJsonObjects)
{
$this->returnJsonObjects = (boolean) $returnJsonObjects;
}
/**
* sslLabsApi::getReturnJsonObjects()
*
* Getter for returnJsonObjects
*
* @return boolean true returns all API responses as JSON object, false returns it as simple JSON string
*/
public function getReturnJsonObjects()
{
return ($this->returnJsonObjects);
}
/**
* sslLabsApi::buildGetParameterString()
*
* Helper function to build get parameter string for URL
*
* @param array $parameters
* @return string
*/
private function buildGetParameterString($parameters)
{
$string = '';
$counter = 0;
foreach($parameters as $name => $value)
{
if(!is_string($name) || (!is_string($value) && !is_bool($value) && !is_int($value)))
{
continue;
}
if(is_bool($value))
{
$value = ($value) ? 'on' : 'off';
}
$string .= ($counter == 0) ? '?' : '&';
$string .= urlencode($name) . '=' . urlencode($value);
$counter++;
}
return ($string);
}
}

0
mod/admin.php Executable file → Normal file
View file

136
mod/directory.php Executable file → Normal file
View file

@ -1,126 +1,82 @@
<?php <?php
require_once('include/widget.php'); use Friendica\Directory\App;
use Friendica\Directory\Rendering\View;
use Friendica\Directory\Helper\Search as SearchHelper;
use Friendica\Directory\Helper\Profile as ProfileHelper;
function directory_init(&$a) { require_once 'include/widget.php';
$a->set_pager_itemspage(80);
function directory_init(App $a)
{
$a->set_pager_itemspage(30);
$a->page['aside'] .= tags_widget(); $a->page['aside'] .= tags_widget();
$a->page['aside'] .= country_widget(); $a->page['aside'] .= country_widget();
} }
function directory_content(&$a) { function directory_content(App $a)
{
$forums = false; $forums = false;
if($a->argc == 2 && $a->argv[1] === 'forum') if ($a->argc == 2 && $a->argv[1] === 'forum') {
$forums = true; $forums = true;
$alpha = false;
if($_GET['alpha'] == 1)
$alpha = true;
$search = ((x($_GET,'search')) ? notags(trim($_GET['search'])) : '');
if($_GET['submit'] === t('Clear')) {
goaway($a->get_baseurl());
} }
if($search) $alpha = false;
if (isset($_GET['alpha']) && $_GET['alpha'] == 1) {
$alpha = true; $alpha = true;
}
$tpl = file_get_contents('view/directory_header.tpl');
$tpl .= file_get_contents('view/directory_header.tpl'); $o = replace_macros($tpl, array(
$o .= replace_macros($tpl, array(
'$search' => $search,
'$header' => t('Global Directory'), '$header' => t('Global Directory'),
'$submit' => t('Find'), '$submit' => t('Find'),
'$clear' => t('Clear'), '$forum' => $a->get_baseurl() . (($forums) ? '' : '/directory/forum'),
'$forum' => $a->get_baseurl() . (($forums) ? '' : '/directory/forum' ),
'$toggle' => (($forums) ? t('Show People') : t('Show Community Forums')), '$toggle' => (($forums) ? t('Show People') : t('Show Community Forums')),
'$alpha' => (($alpha) ? t('Updated order') : t('Alphabetic order')), '$alpha' => (($alpha) ? t('Updated order') : t('Alphabetic order')),
'$alink' => (($alpha) ? str_replace('&alpha=1','',$a->query_string) : $a->query_string . "&alpha=1"), '$alink' => (($alpha) ? str_replace('&alpha=1', '', $a->query_string) : $a->query_string . "&alpha=1"),
'$args' => (($forums) ? '/forum' : ''), '$args' => (($forums) ? '/forum' : ''),
'$finding' => (strlen($search) ? '<h4>' . t('Search for: ') . "'" . $search . "'" . '</h4>' : "")
)); ));
if($search) $sql_extra = '';
$search = dbesc($search . '*'); if ($forums) {
$sql_extra = ((strlen($search)) ? " AND MATCH (`name`, `pdesc`, `homepage`, `locality`, `region`, `country-name`, `gender`, `marital`, `tags` ) $sql_extra .= ' AND `comm` = 1 ';
AGAINST ('$search' IN BOOLEAN MODE) " : ""); }
if($forums) $sql_extra = str_replace('%', '%%', $sql_extra);
$sql_extra .= " and comm = 1 ";
$sql_extra = str_replace('%','%%',$sql_extra);
$r = q("SELECT COUNT(*) AS `total` FROM `profile` WHERE `censored` = 0 $sql_extra "); $r = q("SELECT COUNT(*) AS `total` FROM `profile` WHERE `censored` = 0 $sql_extra ");
if(count($r)) if (count($r)) {
$a->set_pager_total($r[0]['total']); $total = $r[0]['total'];
$a->set_pager_total($total);
if($alpha) }
$order = " order by name asc ";
else
$order = " order by updated desc, id desc ";
if ($alpha) {
$order = ' ORDER BY `name` ASC ';
} else {
$order = ' ORDER BY `updated` DESC, `id` DESC ';
}
$r = q("SELECT * FROM `profile` WHERE `censored` = 0 $sql_extra $order LIMIT %d , %d ", $r = q("SELECT * FROM `profile` WHERE `censored` = 0 $sql_extra $order LIMIT %d , %d ",
intval($a->pager['start']), intval($a->pager['start']),
intval($a->pager['itemspage']) intval($a->pager['itemspage'])
); );
if(count($r)) { //Show results.
$view = new View('directory');
$tpl = file_get_contents('view/directory_item.tpl');
foreach($r as $rr) {
$pdesc = (($rr['pdesc']) ? $rr['pdesc'] . '<br />' : '');
$details = '';
if(strlen($rr['locality']))
$details .= $rr['locality'];
if(strlen($rr['region'])) {
if(strlen($rr['locality']))
$details .= ', ';
$details .= $rr['region'];
}
if(strlen($rr['country-name'])) {
if(strlen($details))
$details .= ', ';
$details .= $rr['country-name'];
}
if(strlen($rr['gender']))
$details .= '<br />' . t('Gender: ') . $rr['gender'] ;
$o .= replace_macros($tpl,array(
'$id' => $rr['id'],
'$mod' => '<div class="moderate"><a href="flag/' . $rr['id'] . '" title="' . t('Flag this entry') . '" ><img src="images/shield_2_16.png" alt="' . t('Flag this entry') . '" title="' . t('Flag this entry') . '"></a></div>',
'$star' => (($rr['tags']) ? '<div class="star" title="' . strip_tags($rr['tags']) . '"></div>' : ''),
'$profile-link' => zrl($rr['homepage']),
'$photo' => $a->get_baseurl() . '/photo/' . $rr['id'],
// '$photo' => (($rr['photo']) ? $rr['photo'] : $a->get_baseurl() . '/photo/' . $rr['id']),
'$alt-text' => $rr['name'] . ' ' . '(' . $rr['homepage'] . ')',
'$name' => $rr['name'],
'$pclass' => (($rr['comm']) ? ' group' : ''),
'$pgroup' => (($rr['comm']) ? '<div class="directory-group">' . t('[Public Group]') . '</div>' : ''),
'$details' => $pdesc . $details,
'$marital' => ((strlen($rr['marital'])) ? '<div class="marital"><span class="marital-label"><span class="heart">&hearts;</span> ' . t('Status:') . ' </span><span class="marital-text">' . $rr['marital'] . '</span></div>' : '')
$view->addHelper('paginate', function() use ($a) {
return paginate($a);
});
$view->addHelper('photoUrl', ProfileHelper::get('photoUrl'));
$view->addHelper('filterAllUrl', SearchHelper::get('filterAllUrl'));
$view->addHelper('filterPeopleUrl', SearchHelper::get('filterPeopleUrl'));
$view->addHelper('filterForumsUrl', SearchHelper::get('filterForumsUrl'));
$view->output(array(
'total' => number_format($total),
'results' => $r,
'filter' => $forums ? 'forums' : '',
)); ));
}
$o .= "<div class=\"directory-end\" ></div>\r\n";
$o .= paginate($a);
}
else
notice( t('No matching entries.') . EOL);
return $o;
} }

Some files were not shown because too many files have changed in this diff Show more