From 9a831c09345fc5a212c68241c0e5e514724efe1b Mon Sep 17 00:00:00 2001 From: Ulrich Block Date: Fri, 21 Feb 2014 19:32:48 +0100 Subject: [PATCH] #340 Substitutes can maintain their own data --- web/login.php | 75 +++++++- web/stuff/functions.php | 20 ++- web/stuff/global_userdata.php | 2 + web/stuff/init_user.php | 6 +- web/stuff/jobs_user_rm.php | 2 + web/stuff/tables_add.php | 10 ++ web/stuff/tables_repair.php | 8 + web/stuff/userpanel_substitutes.php | 2 +- web/stuff/userpanel_substitutes_own.php | 169 ++++++++++++++++++ web/template/default/admin_user_own_md.tpl | 38 ++-- web/template/default/login_mutiple.tpl | 3 + web/template/default/userpanel_header.tpl | 2 - web/template/default/userpanel_user_md.tpl | 17 +- .../default/userpanel_user_substitute_md.tpl | 52 ++++++ 14 files changed, 361 insertions(+), 45 deletions(-) create mode 100644 web/stuff/userpanel_substitutes_own.php create mode 100644 web/template/default/userpanel_user_substitute_md.tpl diff --git a/web/login.php b/web/login.php index 67e7512e..80d43534 100644 --- a/web/login.php +++ b/web/login.php @@ -256,6 +256,32 @@ if ($ui->st('w', 'get') == 'lo') { unset($_SESSION['loginUserAllowed']); + } else if (isset($serviceProviderConfig['providers'][$serviceProvider]) and $ui->id('loginSubstituteId', 10, 'get')) { + + if (isset($_SESSION['loginSubstitutesAllowed'][$ui->id('loginSubstituteId', 10, 'get')])) { + + $query = $sql->prepare("SELECT * FROM `userdata_substitutes` WHERE `sID`=? LIMIT 1"); + $query->execute(array($ui->id('loginSubstituteId', 10, 'get'))); + foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { + + $mail = ''; + $externalID = 0; + $accounttype = 'v'; + + $sID = $row['sID']; + $id = $row['userID']; + $username = $row['loginName']; + $active = $row['active']; + $resellerid = $row['resellerID']; + + $passwordCorrect = true; + + } + + } + + unset($_SESSION['loginSubstitutesAllowed']); + } else if (isset($serviceProviderConfig['providers'][$serviceProvider])) { $_SERVER = $ui->server; @@ -267,6 +293,7 @@ if ($ui->st('w', 'get') == 'lo') { try{ $connectedUsers = array(); + $connectedSubstitutes = array(); // initialize Hybrid_Auth with a given file $hybridauth = new Hybrid_Auth($serviceProviderConfig); @@ -282,8 +309,17 @@ if ($ui->st('w', 'get') == 'lo') { if ((isset($user_id) or isset($admin_id)) and strlen($userProfile->identifier) > 0) { - $query = $sql->prepare("INSERT INTO `userdata_social_identities` (`userID`,`serviceProviderID`,`serviceUserID`,`resellerID`) VALUES (?,?,?,?)"); - $query->execute(array((isset($admin_id)) ? $admin_id : $user_id, $serviceProviderID, $userProfile->identifier, $reseller_id)); + if (isset($_SESSION['sID'])) { + + $query = $sql->prepare("INSERT INTO `userdata_social_identities_substitutes` (`userID`,`serviceProviderID`,`serviceUserID`,`resellerID`) VALUES (?,?,?,?)"); + $query->execute(array($_SESSION['sID'], $serviceProviderID, $userProfile->identifier, $reseller_id)); + + } else { + + $query = $sql->prepare("INSERT INTO `userdata_social_identities` (`userID`,`serviceProviderID`,`serviceUserID`,`resellerID`) VALUES (?,?,?,?)"); + $query->execute(array((isset($admin_id)) ? $admin_id : $user_id, $serviceProviderID, $userProfile->identifier, $reseller_id)); + + } $redirectURL = (isset($admin_id)) ? $pageUrl . '/admin.php?w=su&added=' . $serviceProvider . '&r=su' : $pageUrl . '/userpanel.php?w=se&added=' . $serviceProvider . '&r=se'; @@ -304,8 +340,18 @@ if ($ui->st('w', 'get') == 'lo') { $connectedUserCount = count($connectedUsers); + $query = $sql->prepare("SELECT u.`sID`,u.`loginName`,CONCAT(u.`vname`,' ',u.`name`) AS `username` FROM `userdata_social_identities_substitutes` AS s INNER JOIN `userdata_substitutes` AS u ON u.`sID`=s.`userID` WHERE s.`serviceProviderID`=? AND s.`serviceUserID`=? AND u.`active`='Y'"); + $query->execute(array($serviceProviderID, $userProfile->identifier)); + foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { + + $connectedSubstitutes[$row['sID']] = (strlen(trim($row['username'])) > 0) ? trim($row['username']) . ' (' . $row['loginName'] . ')' : $row['loginName']; + + } + + $connectedSubstituteCount = count($connectedSubstitutes); + // no user has been found. Check if registration is allowed. If yes display registration form - if ($connectedUserCount == 0) { + if ($connectedUserCount == 0 and $connectedSubstituteCount == 0) { if (isset($registration) and in_array($registration, array('A', 'M', 'D'))) { @@ -320,16 +366,17 @@ if ($ui->st('w', 'get') == 'lo') { } // multiple active users are connected, let the user pick one - } else if ($connectedUserCount > 1) { + } else if (($connectedUserCount + $connectedSubstituteCount) > 1) { $sprache->multipleHelper = str_replace('%sp%', $serviceProvider, $sprache->multipleHelper); $_SESSION['loginUserAllowed'] = $connectedUsers; + $_SESSION['loginSubstitutesAllowed'] = $connectedSubstitutes; $include = 'login_mutiple.tpl'; // exactly one user connected, login - } else { + } else if ($connectedUserCount == 1 and $connectedSubstituteCount == 0) { $query = $sql->prepare("SELECT `id`,`accounttype`,`cname`,`active`,`security`,`resellerid`,`mail`,`salt`,`externalID` FROM `userdata` WHERE `id`=? LIMIT 1"); $query->execute(array(key($connectedUsers))); @@ -346,6 +393,24 @@ if ($ui->st('w', 'get') == 'lo') { $passwordCorrect = true; } + } else if ($connectedUserCount == 0 and $connectedSubstituteCount == 1) { + + $query = $sql->prepare("SELECT * FROM `userdata_substitutes` WHERE `sID`=? LIMIT 1"); + $query->execute(array(key($connectedSubstitutes))); + foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { + + $mail = ''; + $externalID = 0; + $accounttype = 'v'; + + $sID = $row['sID']; + $id = $row['userID']; + $username = $row['loginName']; + $active = $row['active']; + $resellerid = $row['resellerID']; + + $passwordCorrect = true; + } } } } diff --git a/web/stuff/functions.php b/web/stuff/functions.php index c78f7021..40c31578 100644 --- a/web/stuff/functions.php +++ b/web/stuff/functions.php @@ -1152,22 +1152,24 @@ if (!function_exists('passwordgenerate')) { global $_SESSION; - if ($id != '' and $d != '') { - unset($_SESSION[$w][$d][$id]); + if ($w != 'sID') { + if ($id != '' and $d != '') { + unset($_SESSION[$w][$d][$id]); - } else if ($id == '' and $d != '') { - unset($_SESSION[$w][$d]); + } else if ($id == '' and $d != '') { + unset($_SESSION[$w][$d]); - } else if ($id != '' and $d == '') { - unset($_SESSION[$w][$id]); + } else if ($id != '' and $d == '') { + unset($_SESSION[$w][$id]); - } else if ($id == '' and $d == '') { - unset($_SESSION[$w]); + } else if ($id == '' and $d == '') { + unset($_SESSION[$w]); + } } foreach ($_SESSION as $k => $v) { - if (wpreg_check($k, 4) and ((isset($_SESSION[$k]['t']) and $_SESSION[$k]['d'] < strtotime('now')) or (is_array($_SESSION[$k]) and count($_SESSION[$k]) == 0))) { + if (wpreg_check($k, 4) and $k != 'sID' and ((isset($_SESSION[$k]['t']) and $_SESSION[$k]['d'] < strtotime('now')) or (is_array($_SESSION[$k]) and count($_SESSION[$k]) == 0))) { unset($_SESSION[$k]); } else if (wpreg_check($k, 4) and is_array($_SESSION[$k]) and count($_SESSION[$k]) > 0) { diff --git a/web/stuff/global_userdata.php b/web/stuff/global_userdata.php index b6fbf824..fc4b931c 100644 --- a/web/stuff/global_userdata.php +++ b/web/stuff/global_userdata.php @@ -133,9 +133,11 @@ if ($ui->st('d', 'get') == 'pw') { $template_file = $spracheResponse->error_table; } } + } else { $template_file = 'userpanel_404.tpl'; } + } else if ($ui->escaped('spUser', 'get') and $ui->id('spId', 10, 'get')) { $query = $sql->prepare("DELETE FROM `userdata_social_identities` WHERE `userID`=? AND `serviceProviderID`=? AND `serviceUserID`=? AND `resellerID`=? LIMIT 1"); diff --git a/web/stuff/init_user.php b/web/stuff/init_user.php index 83b69977..af29ac91 100644 --- a/web/stuff/init_user.php +++ b/web/stuff/init_user.php @@ -135,7 +135,7 @@ if (isset($lastlogin) and $lastlogin != null and $lastlogin != '0000-00-00 00:00 # https://github.com/easy-wi/developer/issues/61 # basic modules array. available at any time to anyone -$what_to_be_included_array = array('lo' => 'userpanel_logdata.php','ti' => 'userpanel_tickets.php'); +$what_to_be_included_array = array('lo' => 'userpanel_logdata.php', 'ti' => 'userpanel_tickets.php'); $easywiModules = array('gs' => true, 'ip' => true, 'my' => true, 'ro' => true, 'ti' => true, 'le' => true, 'vo' => true); @@ -168,7 +168,9 @@ foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { } # modules meant only for user only -if (!isset($_SESSION['sID'])) { +if (isset($_SESSION['sID'])) { + $what_to_be_included_array['se'] = 'userpanel_substitutes_own.php'; +} else { $what_to_be_included_array['su'] = 'userpanel_substitutes.php'; $what_to_be_included_array['se'] = 'global_userdata.php'; } diff --git a/web/stuff/jobs_user_rm.php b/web/stuff/jobs_user_rm.php index 3943ab53..9e606b8a 100644 --- a/web/stuff/jobs_user_rm.php +++ b/web/stuff/jobs_user_rm.php @@ -156,6 +156,8 @@ $sql->exec("DELETE p.* FROM `userpermissions` p LEFT JOIN `userdata` u ON p.`use $sql->exec("DELETE g.* FROM `userdata_groups` g LEFT JOIN `userdata` u ON g.`userID`=u.`id` WHERE u.`id` IS NULL"); $sql->exec("DELETE s.* FROM `userdata_substitutes` s LEFT JOIN `userdata` u ON s.`userID`=u.`id` WHERE u.`id` IS NULL"); $sql->exec("DELETE o.* FROM `userdata_substitutes_servers` o LEFT JOIN `userdata_substitutes` s ON o.`sID`=s.`sID` WHERE s.`sID` IS NULL"); +$sql->exec("DELETE s.* FROM `userdata_social_identities` s LEFT JOIN `userdata` u ON s.`userID`=u.`id` WHERE u.`id` IS NULL"); +$sql->exec("DELETE s.* FROM `userdata_social_identities_substitutes` s LEFT JOIN `userdata_substitutes` u ON s.`userID`=u.`sID` WHERE u.`sID` IS NULL"); $sql->exec("DELETE g.* FROM `gsswitch` g LEFT JOIN `userdata` u ON g.`userid`=u.`id` WHERE u.`id` IS NULL"); $sql->exec("DELETE s.* FROM `serverlist` s LEFT JOIN `gsswitch` g ON s.`switchID`=g.`id` WHERE g.`id` IS NULL"); $sql->exec("DELETE a.* FROM `addons_installed` a LEFT JOIN `serverlist` s ON a.`serverid`=s.`id` WHERE s.`id` IS NULL"); diff --git a/web/stuff/tables_add.php b/web/stuff/tables_add.php index 13b4e9dd..4638a6d9 100644 --- a/web/stuff/tables_add.php +++ b/web/stuff/tables_add.php @@ -1130,6 +1130,16 @@ $query = "CREATE TABLE IF NOT EXISTS `userdata_social_identities` ( $add = $sql->prepare($query); $add->execute(); +$query = "CREATE TABLE IF NOT EXISTS `userdata_social_identities_substitutes` ( + `userID` int(10) unsigned NOT NULL, + `serviceProviderID` int(10) unsigned NOT NULL, + `serviceUserID` varchar(255) DEFAULT NULL, + `resellerID` int(10) unsigned DEFAULT 0, + PRIMARY KEY (`userID`,`serviceProviderID`,`serviceUserID`),KEY(`resellerID`) +) ENGINE=InnoDB"; +$add = $sql->prepare($query); +$add->execute(); + $query = "CREATE TABLE IF NOT EXISTS `userdata_social_providers` ( `serviceProviderID` int(10) unsigned NOT NULL AUTO_INCREMENT, `active` enum('Y','N') NOT NULL DEFAULT 'Y', diff --git a/web/stuff/tables_repair.php b/web/stuff/tables_repair.php index 97772622..de1d6a4a 100644 --- a/web/stuff/tables_repair.php +++ b/web/stuff/tables_repair.php @@ -960,6 +960,14 @@ $defined['userdata_social_identities'] = array( 'resellerID' => array("Type"=>"int(10) unsigned","Null"=>"NO","Key"=>"MUL","Default"=>"0","Extra"=>"") ); +#https://github.com/easy-wi/developer/issues/1 +$defined['userdata_social_identities_substitutes'] = array( + 'userID' => array("Type"=>"int(10) unsigned","Null"=>"NO","Key"=>"PRI","Default"=>"","Extra"=>""), + 'serviceProviderID' => array("Type"=>"int(10) unsigned","Null"=>"NO","Key"=>"PRI","Default"=>"","Extra"=>""), + 'serviceUserID' => array("Type"=>"varchar(255)","Null"=>"NO","Key"=>"PRI","Default"=>"","Extra"=>""), + 'resellerID' => array("Type"=>"int(10) unsigned","Null"=>"NO","Key"=>"MUL","Default"=>"0","Extra"=>"") +); + $defined['userdata_social_providers'] = array( 'serviceProviderID' => array("Type"=>"int(10) unsigned","Null"=>"NO","Key"=>"PRI","Default"=>"","Extra"=>"auto_increment"), 'active' => array("Type"=>"enum('Y','N')","Null"=>"NO","Key"=>"","Default"=>"Y","Extra"=>""), diff --git a/web/stuff/userpanel_substitutes.php b/web/stuff/userpanel_substitutes.php index 55ca0a23..70a9f48f 100644 --- a/web/stuff/userpanel_substitutes.php +++ b/web/stuff/userpanel_substitutes.php @@ -176,7 +176,7 @@ if ($ui->w('action', 4, 'post') and !token(true)) { if ($ui->password('security',255, 'post') != '(encrypted)') { - $salt=md5(mt_rand().date('Y-m-d H:i:s:u')); + $salt = md5(mt_rand().date('Y-m-d H:i:s:u')); $query = $sql->prepare("SELECT `loginName` FROM `userdata_substitutes` WHERE `sID`=? AND `resellerID`=? LIMIT 1"); $query->execute(array($id,$reseller_id)); $loginName = $query->fetchColumn(); diff --git a/web/stuff/userpanel_substitutes_own.php b/web/stuff/userpanel_substitutes_own.php new file mode 100644 index 00000000..9dcaaf8e --- /dev/null +++ b/web/stuff/userpanel_substitutes_own.php @@ -0,0 +1,169 @@ + + * + * This file is part of Easy-WI. + * + * Easy-WI is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Easy-WI is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Easy-WI. If not, see . + * + * Diese Datei ist Teil von Easy-WI. + * + * Easy-WI ist Freie Software: Sie koennen es unter den Bedingungen + * der GNU General Public License, wie von der Free Software Foundation, + * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder spaeteren + * veroeffentlichten Version, weiterverbreiten und/oder modifizieren. + * + * Easy-WI wird in der Hoffnung, dass es nuetzlich sein wird, aber + * OHNE JEDE GEWAEHELEISTUNG, bereitgestellt; sogar ohne die implizite + * Gewaehrleistung der MARKTFAEHIGKEIT oder EIGNUNG FUER EINEN BESTIMMTEN ZWECK. + * Siehe die GNU General Public License fuer weitere Details. + * + * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem + * Programm erhalten haben. Wenn nicht, siehe . + */ + +include(EASYWIDIR . '/stuff/keyphrasefile.php'); +include(EASYWIDIR . '/third_party/password_compat/password.php'); + +$sprache = getlanguagefile('user', $user_language, $reseller_id); + +if ($ui->st('d', 'get') == 'pw') { + + if (!$ui->smallletters('action', 2, 'post')) { + + $template_file = 'userpanel_pass.tpl'; + + } else if ($ui->smallletters('action', 2, 'post') == 'md'){ + $errors = array(); + + if (!$ui->password('password', 255, 'post')) { + $errors[] = $sprache->error_pass; + } + + if (!$ui->password('pass2', 255, 'post')) { + $errors[] = $sprache->error_pas; + } + + if ($ui->password('password', 255, 'post') != $ui->password('pass2', 255, 'post')) { + $errors[] = $sprache->error_passw_succ; + } + + if (!token(true)) { + $errors[] = $spracheResponse->token; + } + + if (count($errors)>0) { + + $template_file = implode('
', $errors); + + } else { + + $salt = md5(mt_rand() . date('Y-m-d H:i:s:u')); + $query = $sql->prepare("SELECT `loginName` FROM `userdata_substitutes` WHERE `sID`=? AND `resellerID`=? LIMIT 1"); + $query->execute(array($_SESSION['sID'], $reseller_id)); + $loginName = $query->fetchColumn(); + + if (strlen($loginName) > 0 and $ui->password('password', 255, 'post')) { + + $newHash = passwordCreate($loginName, (string) $ui->password('password', 255, 'post')); + + if (is_array($newHash)) { + $query = $sql->prepare("UPDATE `userdata_substitutes` SET `passwordHashed`=?,`salt`=? WHERE `sID`=? AND `resellerID`=? LIMIT 1"); + $query->execute(array($newHash['hash'], $newHash['salt'], $_SESSION['sID'], $reseller_id)); + + } else { + $query = $sql->prepare("UPDATE `userdata_substitutes` SET `passwordHashed`=? WHERE `sID`=? AND `resellerID`=? LIMIT 1"); + $query->execute(array($newHash, $_SESSION['sID'], $reseller_id)); + } + + if ($query->rowCount() > 0) { + $template_file = $spracheResponse->table_add; + } else { + $template_file = $spracheResponse->error_table; + } + } else { + $template_file = 'userpanel_404.tpl'; + } + } + + } else { + $template_file = 'userpanel_404.tpl'; + } + +} else if ($ui->escaped('spUser', 'get') and $ui->id('spId', 10, 'get')) { + + $query = $sql->prepare("DELETE FROM `userdata_social_identities_substitutes` WHERE `userID`=? AND `serviceProviderID`=? AND `serviceUserID`=? AND `resellerID`=? LIMIT 1"); + $query->execute(array($_SESSION['sID'], $ui->id('spId', 10, 'get'), $ui->escaped('spUser', 'get'), $reseller_id)); + + if ($query->rowCount() > 0) { + $template_file = $spracheResponse->table_del; + } else { + $template_file = $spracheResponse->error_table; + } + +} else { + + if ($ui->smallletters('action', 2, 'post') != 'md' and $ui->w('added', 255, 'get')) { + + $template_file = $spracheResponse->table_add; + + } else if ($ui->smallletters('action', 2, 'post') != 'md') { + + $serviceProviders = array(); + + $htmlExtraInformation['css'][] = ''; + + $query = $sql->prepare("SELECT `serviceProviderID`,`filename` FROM `userdata_social_providers` WHERE `resellerID`=0 AND `active`='Y'"); + $query2 = $sql->prepare("SELECT `serviceUserID` FROM `userdata_social_identities_substitutes` WHERE `serviceProviderID`=? AND `userID`=? LIMIT 1"); + + + $query->execute(); + foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { + + $query2->execute(array($row['serviceProviderID'], $_SESSION['sID'])); + + $serviceProviders[] = array( + 'spId' => $row['serviceProviderID'], + 'sp' => $row['filename'], + 'spUserId' => urlencode($query2->fetchColumn()) + ); + } + + $query = $sql->prepare("SELECT `name`,`vname` FROM `userdata_substitutes` WHERE `sID`=? AND `resellerID`=? LIMIT 1"); + $query->execute(array($_SESSION['sID'], $reseller_id)); + foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { + $name = $row['name']; + $vname = $row['vname']; + } + + $template_file = 'userpanel_user_substitute_md.tpl'; + + } else if ($ui->smallletters('action', 2, 'post') == 'md' and token(true)) { + + $query = $sql->prepare("UPDATE `userdata_substitutes` SET `name`=?,`vname`=? WHERE `sID`=? AND `resellerID`=? LIMIT 1"); + $query->execute(array($ui->names('name',255, 'post'),$ui->names('vname',255, 'post'), $_SESSION['sID'], $reseller_id)); + + if ($query->rowCount() > 0) { + $template_file = $spracheResponse->table_add; + } else { + $template_file = $spracheResponse->error_table; + } + + } + +} \ No newline at end of file diff --git a/web/template/default/admin_user_own_md.tpl b/web/template/default/admin_user_own_md.tpl index 5bb756b8..8eccb9ca 100644 --- a/web/template/default/admin_user_own_md.tpl +++ b/web/template/default/admin_user_own_md.tpl @@ -11,6 +11,24 @@
+ 0 ) echo '

Social Auth

';?> + + + + 0 ) echo '
';?>

Mails

@@ -49,25 +67,7 @@

- 0 ) echo '

Social Auth

';?> - - - - 0 ) echo '
';?> -

+

user;?>

diff --git a/web/template/default/login_mutiple.tpl b/web/template/default/login_mutiple.tpl index c361e865..cc36f3a8 100644 --- a/web/template/default/login_mutiple.tpl +++ b/web/template/default/login_mutiple.tpl @@ -35,6 +35,9 @@ $v){ ?>
  • + $v){ ?> +
  • +

    diff --git a/web/template/default/userpanel_header.tpl b/web/template/default/userpanel_header.tpl index 9fe6d14b..053e143e 100644 --- a/web/template/default/userpanel_header.tpl +++ b/web/template/default/userpanel_header.tpl @@ -65,11 +65,9 @@
  • last.'
    '.$great_last;?>
  • '.$gsprache->hotline.": ".$support_phonenumber.'
  • ';?> -
  • password." ".$gsprache->change;?>
  • settings;?>
  • -
  • About
  • Forum
  • Wiki
  • diff --git a/web/template/default/userpanel_user_md.tpl b/web/template/default/userpanel_user_md.tpl index 41c0cc3b..4a0a228c 100644 --- a/web/template/default/userpanel_user_md.tpl +++ b/web/template/default/userpanel_user_md.tpl @@ -11,13 +11,7 @@
    -
    - -
    - > -
    -
    -
    + 0 ) echo '

    Social Auth

    ';?>
    @@ -35,6 +29,13 @@
    0 ) echo '
    ';?> +

    Mail

    +
    + +
    + > +
    +
    @@ -47,6 +48,8 @@ >
    +
    +

    user;?>

    diff --git a/web/template/default/userpanel_user_substitute_md.tpl b/web/template/default/userpanel_user_substitute_md.tpl new file mode 100644 index 00000000..62947d60 --- /dev/null +++ b/web/template/default/userpanel_user_substitute_md.tpl @@ -0,0 +1,52 @@ +
    +
    + +
    +
    +
    +
    + + + + + + + 0 ) echo '
    ';?> +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    \ No newline at end of file