function handler_upload($page) { $page->assign('exception', false); $page->assign('image', false); if (FrankizUpload::has('file')) { $g = Group::from('temp')->select(GroupSelect::castes()); $temp = $g->caste(Rights::everybody()); try { $upload = FrankizUpload::v('file'); $secret = uniqid(); $i = new FrankizImage(); $i->insert(); $i->caste($temp); $i->label($secret); $i->image($upload); $page->assign('image', $i); $page->assign('secret', $secret); } catch (Exception $e) { try { if ($i) { $i->delete(); } } catch (Exception $eb) { $page->assign('exception', $eb); } $page->assign('exception', $e); if ($e instanceof ImageSizeException) { $page->assign('pixels', true); } else { if ($e instanceof UploadSizeException) { $page->assign('bytes', true); } else { if ($e instanceof ImageFormatException) { $page->assign('format', true); } } } } } if (Env::has('delete')) { $image = new FrankizImage(Env::i('iid')); $image->select(FrankizImageSelect::base()); if ($image->label() == Env::s('secret')) { $image->delete(); } } $page->addCssLink('upload.css'); $page->changeTpl('images/upload.tpl', SIMPLE); }
public function sendmailfinal($valid) { $mail = new FrankizMailer('validate/mail.valid.qdj.tpl'); $mail->assign('valid', $valid); $mail->assign('comm', Env::s('ans', '')); if ($valid) { $mail->Subject = '[Frankiz] Ta QDJ a été acceptée'; } else { $mail->Subject = '[Frankiz] Ta QDJ a été refusée'; } $mail->setFrom($this->_mail_from_addr(), $this->_mail_from_disp()); $mail->addAddress($this->writer->bestEmail(), $this->writer->displayName()); $mail->addCC($this->_mail_from_addr(), $this->_mail_from_disp()); $mail->send(false); }
function handler_ig_search($page) { if (Env::has('quick') && Env::s('quick') != '') { global $globals; require_once 'userset.inc.php'; $view = new QuickSearchSet(); $view->addMod('gadget', 'Gadget', true); $view->apply(null, $page); $nb_tot = $view->count(); $page->assign('result_count', $nb_tot); if (!S::logged() && $nb_tot > $globals->search->public_max) { $page->assign('error', 'Votre recherche a généré trop de résultats pour un affichage public.'); } elseif ($nb_tot > $globals->search->private_max) { $page->assign('error', 'Recherche trop générale.'); } elseif (empty($nb_tot)) { $page->assign('error', 'Il n\'existe personne correspondant à ces critères dans la base !'); } else { $page->assign('error', false); } } require_once 'gadgets/gadgets.inc.php'; init_igoogle_html('gadgets/ig-search.tpl', AUTH_PUBLIC); }
function init_igoogle_html($template, $auth = AUTH_PUBLIC) { $page =& Platal::page(); $page->changeTpl('gadgets/ig-skin.tpl', NO_SKIN); $page->register_modifier('escape_html', 'escape_html'); $page->default_modifiers = array('@escape_html'); header('Accept-Charset: utf-8'); // Adds external JavaScript libraries provided by iGoogle to the page. if (Env::has('libs')) { $libs = preg_split('/,/', Env::s('libs'), -1, PREG_SPLIT_NO_EMPTY); foreach ($libs as $lib) { if (preg_match('@^[a-z0-9/._-]+$@i', $lib) && !preg_match('@([.][.])|([.]/)|(//)@', $lib)) { $page->append('gadget_js', 'https://www.google.com/ig/f/' . $lib); } } } // Redirects the user to the login pagin if required. if ($auth > S::v('auth', AUTH_PUBLIC)) { $page->assign('gadget_tpl', 'gadgets/ig-login.tpl'); return false; } $page->assign('gadget_tpl', $template); return true; }
/** * The authentication schema is based on three query parameters: * ?user=<hruid>×tamp=<timestamp>&sig=<sig> * where: * - hruid is the hruid of the querying user * - timestamp is the current UNIX timestamp, which has to be within a * given distance of the server-side UNIX timestamp * - sig is the HMAC of "<method>#<resource>#<payload>#<timestamp>" using * a known secret of the user as the key. * * At the moment, the shared secret of the user is the sha1 hash of its * password. This is temporary, though, until better support for tokens is * implemented in plat/al. * TODO(vzanotti): Switch to dedicated secrets for authentication. */ public function apiAuth($method, $resource, $payload) { // Verify that the timestamp is within acceptable bounds. $timestamp = Env::i('timestamp', 0); if (abs($timestamp - time()) > Platal::globals()->api->timestamp_tolerance) { return null; } // Retrieve the user corresponding to the forlife. Note that at the // moment, other aliases are also accepted. $user = User::getSilent(Env::s('user', '')); if (is_null($user) || !$user->isActive()) { return null; } // Determine the list of tokens associated with the user. At the moment, // this is just the sha1 of the password. $tokens = array($user->password()); // For each token, try to validate the signature. $message = implode('#', array($method, $resource, $payload, $timestamp)); $signature = Env::s('sig'); foreach ($tokens as $token) { $expected_signature = hash_hmac(Platal::globals()->api->hmac_algo, $message, $token); if ($signature == $expected_signature) { return $user; } } return null; }
function handler_add_accounts($page, $action = null, $promo = null) { require_once 'name.func.inc.php'; $page->changeTpl('admin/add_accounts.tpl'); if (Env::has('add_type') && Env::has('people')) { static $titles = array('male' => 'M', 'female' => 'MLLE'); $lines = explode("\n", Env::t('people')); $separator = Env::t('separator'); $promotion = Env::i('promotion'); if (Env::t('add_type') == 'promo') { $eduSchools = DirEnum::getOptions(DirEnum::EDUSCHOOLS); $eduSchools = array_flip($eduSchools); $eduDegrees = DirEnum::getOptions(DirEnum::EDUDEGREES); $eduDegrees = array_flip($eduDegrees); switch (Env::t('edu_type')) { case 'X': $degreeid = $eduDegrees[Profile::DEGREE_X]; $entry_year = $promotion; $grad_year = $promotion + 3; $promo = 'X' . $promotion; $hrpromo = $promotion; $type = 'x'; break; case 'M': $degreeid = $eduDegrees[Profile::DEGREE_M]; $grad_year = $promotion; $entry_year = $promotion - 2; $promo = 'M' . $promotion; $hrpromo = $promo; $type = 'master'; break; case 'D': $degreeid = $eduDegrees[Profile::DEGREE_D]; $grad_year = $promotion; $entry_year = $promotion - 3; $promo = 'D (en cours)'; $hrpromo = 'D' . $promotion; $type = 'phd'; break; default: $page->killError("La formation n'est pas reconnue : " . Env::t('edu_type') . '.'); } $best_domain = XDB::fetchOneCell('SELECT id FROM email_virtual_domains WHERE name = {?}', User::$sub_mail_domains[$type] . Platal::globals()->mail->domain); XDB::startTransaction(); foreach ($lines as $line) { if ($infos = self::formatNewUser($page, $line, $separator, $hrpromo, 6)) { $sex = self::formatSex($page, $infos[3], $line); $lastname = capitalize_name($infos[0]); $firstname = capitalize_name($infos[1]); if (!is_null($sex)) { $fullName = build_full_name($firstname, $lastname); $directoryName = build_directory_name($firstname, $lastname); $sortName = build_sort_name($firstname, $lastname); $birthDate = self::formatBirthDate($infos[2]); if ($type == 'x') { if ($promotion < 1996 && preg_match('/^[0-9]{8}$/', $infos[4])) { /* Allow using Xorg ID for old promotions, to allow fixing typos in names */ $xorgId = $infos[4]; $year = intval(substr($xorgId, 0, 4)); if ($year != $promotion) { $page->trigError("La ligne {$line} n'a pas été ajoutée car le matricule Xorg n'a pas la date correspondant à la promotion."); continue; } } else { $xorgId = Profile::getXorgId($infos[4]); } } elseif (isset($infos[4])) { $xorgId = trim($infos[4]); } else { $xorgId = 0; } if (is_null($xorgId)) { $page->trigError("La ligne {$line} n'a pas été ajoutée car le matricule École est mal renseigné."); continue; } XDB::execute('INSERT INTO profiles (hrpid, xorg_id, ax_id, birthdate_ref, sex, title) VALUES ({?}, {?}, {?}, {?}, {?}, {?})', $infos['hrid'], $xorgId, isset($infos[5]) ? $infos[5] : null, $birthDate, $sex, $titles[$sex]); $pid = XDB::insertId(); XDB::execute('INSERT INTO profile_public_names (pid, lastname_initial, lastname_main, firstname_initial, firstname_main) VALUES ({?}, {?}, {?}, {?}, {?})', $pid, $lastname, $lastname, $firstname, $firstname); XDB::execute('INSERT INTO profile_display (pid, yourself, public_name, private_name, directory_name, short_name, sort_name, promo) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $pid, $firstname, $fullName, $fullName, $directoryName, $fullName, $sortName, $promo); XDB::execute('INSERT INTO profile_education (id, pid, eduid, degreeid, entry_year, grad_year, promo_year, flags) VALUES (100, {?}, {?}, {?}, {?}, {?}, {?}, \'primary\')', $pid, $eduSchools[Profile::EDU_X], $degreeid, $entry_year, $grad_year, $promotion); XDB::execute('INSERT INTO accounts (hruid, type, is_admin, state, full_name, directory_name, sort_name, display_name, lastname, firstname, sex, best_domain) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $infos['hrid'], $type, 0, 'pending', $fullName, $directoryName, $sortName, $firstname, $lastname, $firstname, $sex, $best_domain); $uid = XDB::insertId(); XDB::execute('INSERT INTO account_profiles (uid, pid, perms) VALUES ({?}, {?}, {?})', $uid, $pid, 'owner'); Profile::rebuildSearchTokens($pid, false); } } } XDB::commit(); } else { if (Env::t('add_type') == 'account') { $type = Env::t('type'); $newAccounts = array(); foreach ($lines as $line) { if ($infos = self::formatNewUser($page, $line, $separator, $type, 4)) { $sex = self::formatSex($page, $infos[3], $line); if (!is_null($sex)) { $lastname = capitalize_name($infos[0]); $firstname = capitalize_name($infos[1]); $fullName = build_full_name($firstname, $lastname); $directoryName = build_directory_name($firstname, $lastname); $sortName = build_sort_name($firstname, $lastname); XDB::execute('INSERT INTO accounts (hruid, type, is_admin, state, email, full_name, directory_name, sort_name, display_name, lastname, firstname, sex) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $infos['hrid'], $type, 0, 'pending', $infos[2], $fullName, $directoryName, $sortName, $firstname, $lastname, $firstname, $sex); $newAccounts[$infos['hrid']] = $fullName; } } } if (!empty($newAccounts)) { $page->assign('newAccounts', $newAccounts); } } else { if (Env::t('add_type') == 'ax_id') { $type = 'x'; foreach ($lines as $line) { $infos = explode($separator, $line); if (sizeof($infos) > 3 || sizeof($infos) < 2) { $page->trigError("La ligne {$line} n'a pas été ajoutée : mauvais nombre de champs."); continue; } $infos = array_map('trim', $infos); if (sizeof($infos) == 3) { // Get human readable ID with first name and last name $hrid = User::makeHrid($infos[1], $infos[0], $promotion); $user = User::getSilent($hrid); $axid = $infos[2]; } else { // The first column is the hrid, possibly without the promotion $user = User::getSilent($infos[0] . '.' . $promotion); if (is_null($user)) { $user = User::getSilent($infos[0]); } $axid = $infos[1]; } if (!$axid) { $page->trigError("La ligne {$line} n'a pas été ajoutée : matricule AX vide."); continue; } if (is_null($user)) { $page->trigError("La ligne {$line} n'a pas été ajoutée : aucun compte trouvé."); continue; } $profile = $user->profile(); if ($profile->ax_id) { $page->trigError("Le profil " . $profile->hrpid . " a déjà l'ID AX " . $profile->ax_id); continue; } XDB::execute('UPDATE profiles SET ax_id = {?} WHERE pid = {?}', $axid, $profile->id()); } } } } $errors = $page->nb_errs(); if ($errors == 0) { $page->trigSuccess("L'opération a été effectuée avec succès."); } else { $page->trigSuccess('L\'opération a été effectuée avec succès, sauf pour ' . ($errors == 1 ? 'l\'erreur signalée' : "les {$errors} erreurs signalées") . ' ci-dessus.'); } } else { if (Env::has('add_type')) { $res = XDB::query('SELECT type FROM account_types'); $page->assign('account_types', $res->fetchColumn()); $page->assign('add_type', Env::s('add_type')); } } }
function handler_remote($page) { global $globals, $platal; if (!(Env::has('timestamp') && Env::has('site') && Env::has('hash') && Env::has('request'))) { $page->trigError("Requête non valide"); return; } // Read request $timestamp = Env::s('timestamp'); if (abs($timestamp - time()) > $globals->remote->lag) { $page->trigError("Delai d'attente dépassé"); return; } $site = Env::s('site'); $request = Env::s('request'); // Load remote information try { $remote = Remote::from(Env::s('site')); $remote->select(RemoteSelect::groups()); } catch (ItemNotFoundException $e) { $page->trigError("Ton site n'est pas renseigné dans la base de données"); return; } // Check request if (md5($timestamp . $site . $remote->privkey() . $request) != Env::s('hash')) { $page->trigError("Erreur de validation de la requête d'authentification"); return; } $request = json_decode($request, true); // Force login $user = Platal::session()->doAuthWithoutStart(AUTH_COOKIE); if (empty($user)) { $page->assign('remote_site', $remote->label()); $platal->force_login($page); return PL_FORBIDDEN; } // Build response $response = array('uid' => $user->id()); if ($remote->hasRight('names') && in_array('names', $request)) { $response['hruid'] = $user->login(); $response['firstname'] = $user->firstname(); $response['lastname'] = $user->lastname(); $response['nickname'] = $user->nickname(); } if ($remote->hasRight('email') && in_array('email', $request)) { $response['email'] = $user->email(); } if ($remote->hasRight('rights') && in_array('rights', $request)) { $r = array(); foreach ($remote->groups() as $g) { $r[$g->name()] = array_map(function ($r) { return (string) $r; }, $user->rights($g)); } if (!empty($r)) { $response['rights'] = $r; } } if ($remote->hasRight('sport') && in_array('sport', $request)) { $groups = $user->castes()->groups(); $group = $groups->filter('ns', Group::NS_SPORT)->first(); if ($group) { $response['sport'] = $group->label(); } } if ($remote->hasRight('promo') && in_array('promo', $request)) { $groups = $user->castes()->groups()->filter('ns', Group::NS_PROMO); $groups = $groups->remove(Group::from('on_platal')); // Extract promos from group labels // For backward compatibility, compute the minimal promo year $promo = 0; $promos = array(); foreach ($groups as $g) { $matches = array(); if (preg_match('/^promo_([a-z_]+)([1-9][0-9]{3})$/', $g->name(), $matches)) { $promos[] = $matches[1] . $matches[2]; $year = (int) $matches[2]; if (!$promo || $year < $promo) { $promo = $year; } } } if ($promo) { $response['promo'] = $promo; $response['promos'] = $promos; } } if ($remote->hasRight('photo') && in_array('photo', $request)) { $img = $user->photo(); if ($img === false) { $img = $user->original(); } if ($img !== false) { $response['photo'] = $globals->baseurl . '/' . $img->src('full'); } } if ($remote->hasRight('binets_admin') && in_array('binets_admin', $request)) { $gf = new GroupFilter(new PFC_And(new GFC_User($user, Rights::admin()), new GFC_Namespace('binet'))); $gs = $gf->get(); if ($gs->count() > 0) { $gs->select(GroupSelect::base()); $r = array(); foreach ($gs as $g) { $r[$g->name()] = $g->label(); } if (!empty($r)) { $response['binets_admin'] = $r; } } } // Send response $response = json_encode($response); $location = Env::s('location'); header('Location: ' . $site . '?location=' . $location . '×tamp=' . $timestamp . '&response=' . $response . '&hash=' . md5($timestamp . $remote->privkey() . $response)); }
function handler_admin($page) { $mixed = func_get_args(); array_shift($mixed); $mixed = implode('/', $mixed); if (empty($mixed)) { $wikis = Wiki::selectAll(Wiki::SELECT_BASE | Wiki::SELECT_COUNT); $page->assign('wikis', $wikis); $page->addCssLink('wiki.css'); $page->assign('title', 'Admin Wiki'); $page->changeTpl('wiki/list.tpl'); } else { if (Wiki::isId($mixed)) { $wiki = new Wiki($mixed); } else { $wiki = Wiki::from($mixed, true); // Create the Wiki if it doesn't exist } if (Env::has('newcontent')) { $wiki->update(Env::s('newcontent')); } $wiki->select(Wiki::SELECT_BASE | Wiki::SELECT_COUNT); $wiki->select(array(Wiki::SELECT_VERSION => array('versions' => array('last'), 'options' => UserSelect::base()))); $page->assign('wiki', $wiki); $page->addCssLink('wiki.css'); $page->assign('title', 'Admin Wiki: ' . $wiki->name()); $page->changeTpl('wiki/admin.tpl'); } }
public function handler_password($page) { $err = array(); $msg = array(); if (Env::has('new_passwd')) { if (Env::s('new_passwd1') != Env::s('new_passwd2')) { $err[] = 'Les mots de passe donnés sont incohérents.'; } else { if (strlen(Env::s('new_passwd1')) < 6) { $msg[] = 'Le mot de passe est trop court.'; } else { S::user()->password(Env::s('new_passwd1')); $msg[] = 'Le mot de passe a été changé avec succès.'; } } } $page->assign('err', $err); $page->assign('msg', $msg); $page->addCssLink('profile.css'); $page->assign('title', 'Modification du mot de passe'); $page->changeTpl('profile/password.tpl'); }
function handler_paypal_return($page, $uid = null) { $page->changeTpl('payment/retour_paypal.tpl'); /* reference banque (numero de transaction) */ $no_transaction = Env::s('tx'); /* token a renvoyer pour avoir plus d'information */ $clef = Env::s('sig'); /* code retour */ $status = Env::s('st'); /* raison */ $reason = $status == 'Pending' ? Env::s('pending_reason') : Env::s('reason_code'); /* reference complete de la commande */ $fullref = str_replace('%2d', '-', Env::s('cm')); /* montant de la transaction */ $montant = Env::s('amt'); /* devise */ if (Env::s('cc') != 'EUR') { cb_erreur("monnaie autre que l'euro"); } /* on extrait le code de retour */ if ($status != "Completed") { if ($status) { paypal_erreur("erreur lors du paiement : {$status} - {$reason}"); } else { paypal_erreur("Paiement annulé", false); } } /* on extrait les informations sur l'utilisateur */ $user = User::get($uid); if (!$user) { paypal_erreur("uid invalide"); } /* on extrait la reference de la commande */ if (!preg_match('/-xorg-([0-9]+)$/', $fullref, $matches)) { paypal_erreur("référence de commande invalide"); } $ref = $matches[1]; $res = XDB::query('SELECT mail, text, confirmation FROM payments WHERE id = {?}', $ref); if (!(list($conf_mail, $conf_title, $conf_text) = $res->fetchOneRow())) { paypal_erreur('référence de commande inconnue'); } /* on fait l'insertion en base de donnees */ XDB::execute("INSERT INTO payment_transactions (id, method_id, uid, ref, fullref, ts_confirmed, amount, pkey, comment, status, display)\n VALUES ({?}, 1, {?}, {?}, {?}, NOW(), {?}, {?}, {?}, 'confirmed', {?})", $no_transaction, $user->id(), $ref, $fullref, $montant, $clef, Env::v('comment'), Get::i('display')); // We check if it is an Xnet payment and then update the related ML. $res = XDB::query('SELECT eid, asso_id FROM group_events WHERE paiement_id = {?}', $ref); if ($res->numRows() == 1) { list($eid, $asso_id) = $res->fetchOneRow(); require_once dirname(__FILE__) . '/xnetevents/xnetevents.inc.php'; $evt = get_event_detail($eid, false, $asso_id); subscribe_lists_event($user->id(), $evt['short_name'], 1, $montant, true); } /* on genere le mail de confirmation */ $conf_text = str_replace(array('<prenom>', '<nom>', '<promo>', '<montant>', '<salutation>', '<cher>', '<comment>'), array($user->firstName(), $user->lastName(), $user->promo(), $montant, $user->isFemale() ? 'Chère' : 'Cher', $user->isFemale() ? 'Chère' : 'Cher', Env::v('comment')), $conf_text); global $globals; $mymail = new PlMailer(); $mymail->setFrom($conf_mail); $mymail->addCc($conf_mail); $mymail->setSubject($conf_title); $mymail->setWikiBody($conf_text); $mymail->sendTo($user); /* on envoie les details de la transaction à telepaiement@ */ $mymail = new PlMailer(); $mymail->setFrom("webmaster@" . $globals->mail->domain); $mymail->addTo($globals->money->email); $mymail->setSubject($conf_title); $msg = 'utilisateur : ' . $user->login() . ' (' . $user->id() . ')' . "\n" . 'mail : ' . $user->forlifeEmail() . "\n\n" . "paiement : {$conf_title} ({$conf_mail})\n" . "reference : {$champ200}\n" . "montant : {$montant}\n\n" . "dump de REQUEST:\n" . var_export($_REQUEST, true); $mymail->setTxtBody($msg); $mymail->send(); $page->assign('texte', $conf_text); $page->assign('erreur', $erreur); }
/** Wrappers around Env::i/s/..., to add envprefix */ public function s($key, $def = '') { if ($this->fake_env) { return $this->fake_env->s($key, $def); } else { return Env::s($this->envprefix . $key, $def); } }