]> _ Git - cubeextranet.git/commitdiff
#2687
authorvincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Tue, 7 May 2019 14:32:25 +0000 (14:32 +0000)
committervincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Tue, 7 May 2019 14:32:25 +0000 (14:32 +0000)
inc/ws/Controlleur/class.ws.url.php
inc/ws/Metier/class.ws.book.parametres.php

index f19b1c8be702d68f89d32f00a5add607086b746a..09bd52dc5a3dff2e87c7f26dfc57d6a61261f2fc 100644 (file)
 class wsUrl
 {
 
-       public static function publications($args)
-       {
-               global $core;
-
-               if (isset($args[1])) {
-                       $_SESSION['q'] = $args[1];
-               }
-
-               $settings = $core->user->getSettings('books');
-
-               $shortcuts = array();
-               if (wsDroits::creation()) {
-                       $shortcuts[] = '<a href="#" class="popup" rel="newBookForm">' . $core->typo->Ajouter(__('Créer une nouvelle publication')) . '</a>';
-               }
-
-               $filtres = array();
-               if (wsDroits::revendeur(false)) {
-                       $filtres[] = new commonFiltre(__('Status'), 'status_book', $settings['filtres']);
-               }
-               if (wsDroits::admin()) {
-                       $filtres[] = new commonFiltre(__('Administrateur'), 'admin_book', $settings['filtres']);
-                       $filtres[] = new commonFiltre(__('Revendeur'), 'revendeur_book', $settings['filtres']);
-               }
-               $res = commonPage::barre($filtres, 'filtreBooks', 'books', $shortcuts, wsDroits::creation());
-               $res .= commonPage::tMain(null, wsDroits::creation());
-               $res .= commonPage::bh();
-               $res .= '<div id="listeBooks">';
-               $res .= self::listeBooks();
-               $res .= '</div>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-               return $res;
-       }
-
-       public static function listeBooks($dashboard = null, $settings = null)
-       {
-               global $core;
-               cubePage::truePopup();
-               cubePage::autocomplete();
-               cubePage::contextMenu();
-
-               $droits = wsDroits::getDroits();
-
-               commonDroits::min(1);
-               $settings = is_null($settings) ? $core->user->getSettings('books') : $settings;
-               $change = is_null($dashboard) ? 'Books' : 'Dashboard/' . $dashboard;
-               $dao = new wsDAOBook($core->con);
-               $context_download_id = is_null($dashboard) ? 'contextDownloadBook' : 'contextDashboard_Download' . $dashboard;
-               $context_status_id = is_null($dashboard) ? 'contextStatusBook' : 'contextDashboard_Status' . $dashboard;
-               $context_view_id = is_null($dashboard) ? 'contextViewBook' : 'contextView_Status' . $dashboard;
-
-               if (isset($settings['search']) && !is_null($settings['search'])) {
-                       $dao->setSearch($settings['search']);
-               }
-               $dao->setFiltres($settings['filtres']);
-               $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user);
-
-               $res = '';
-
-
-               $res .= self::contextBookStatus($context_status_id);
-               $res .= self::contextBookView($context_view_id);
-
-               $res .= '<table class="liste">';
-               $res .= '<tr><th>' . commonUrl::orderby('#', 'book_id', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Titre de la publication'), 'nom', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Date'), 'date', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__(''), 'lang', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . __('Pages') . '</th>';
-               if ($droits->admin) {
-                       $res .= '<th>' . commonUrl::orderby('C', 'demo_counter', $settings, 'sort' . $change, __('Compteur de démos')) . '</th>';
-               }
-               if ($droits->revendeur) {
-                       $res .= '<th>' . commonUrl::orderby(__('Proprietaire'), 'proprietaire_nom', $settings, 'sort' . $change) . '</th>';
-               } else {
-                       $res .= '<th>' . commonUrl::orderby(__('Proprietaire'), 'proprietaire_utilisateur', $settings, 'sort' . $change) . '</th>';
-               }
-               if ($droits->admin) {
-                       $res .= '<th>' . commonUrl::orderby(__('Facturation'), 'facturable', $settings, 'sort' . $change) . '</th>';
-               }
-               if ($droits->revendeur) {
-                       $res .= '<th>' . commonUrl::orderby(__('Status'), 'status', $settings, 'sort' . $change) . '</th>';
-                       $res .= '<th>' . __('V') . '</th>';
-               }
-               $res .= str_repeat('<th class="min"></th>', 5);
-               $res .= '</tr>';
-               $i = 0;
-
-               $btVoir = '<div></div><span>' . __('voir') . '</span>';
-               $btEdit = '<div></div><span>' . __('éditer') . '</span>';
-               $btStats = '<div></div><span>' . __('stats') . '</span>';
-               $btDownload = '<div></div><span>' . __('télécharger') . '</span>';
-               if ($droits->creation) {
-                       $btDel = '<div></div><span>' . __('suppr.') . '</span>';
-               }
-
-               foreach ($liste as $id => $book) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '>';
-                       $res .= '<td>' . $book->book_id . '</td>';
-                       $res .= '<td>' . html::escapeHTML($book->nom) . '</td>';
-                       $res .= '<td>' . date('Y-m-d', $book->date) . '</td>';
-                       $res .= '<td>' . mb_strtoupper($book->lang) . '</td>';
-                       $res .= '<td>' . $book->parametres->pages . '</td>';
-                       if ($droits->admin) {
-                               $res .= '<td>' . $book->demo_counter . '</td>';
-                       }
-
-                       if ($droits->revendeur) {
-                               $p = str_replace(" (", '<br /><em>', html::escapeHTML($book->proprietaire));
-                               $p = str_replace(')', '</em>', $p);
-                               $res .= '<td><a href="#" class="popup" rel="formChangeBookProprietaire/' . $book->book_id . '" title="' . __('Modifier le proprietaire') . '">' . $p . '</a></td>';
-                       } else {
-                               $res .= '<td>' . html::escapeHTML($book->proprietaire_utilisateur) . '</td>';
-                       }
-                       if ($droits->admin) {
-                               $res .= '<td>' . html::escapeHTML($book->facturable) . '</td>';
-                       }
-                       if ($droits->revendeur) {
-                               if ($droits->admin || $book->status < 1) {
-                                       $p = '';
-                                       if (!is_null($book->projet)) {
-                                               $p = ' <a href="' . EXTRANET_URL . '/projet/' . $book->projet . '" title="' . __('Voir les détails du projet') . '" class="blank icon">' . cubeMedia::silk('arrow_right.png') . '</a>';
-                                       }
-                                       $res .= '<td><a href="#" class="openContextMenu" rel="' . $context_status_id . '" rev="' . $book->book_id . '">' . $core->books_status[$book->status] . '</a>' . $p . '</td>';
-                               } else {
-                                       $res .= '<td>' . $core->books_status[1] . '</td>';
-                               }
-                               $res .= '<td>' . $book->version . '</td>';
-                       }
-                       if ($book->version > 1 || $droits->admin) {
-                               $types = [];
-                               if (!$book->parametres->alwaysHTML5) {
-                                       $types[] = 'flash';
-                                       $defaultPlayer = 'viewer';
-                               } else {
-                                       $defaultPlayer = 'viewerh';
-                               }
-                               if ($book->parametres->mobileVersion != 'pdf') {
-                                       $types[] = 'html5';
-                               }
-                               if ($book->parametres->scorm_enable) {
-                                       $types[] = 'scorm';
-                               }
-
-
-                               $res .= '<td class="bouton"><a href="/' . $defaultPlayer . '/' . $book->book_id . '_' . $book->hash . '/" class="openContextMenu voir btbook" data-type="' . implode(',', $types) . '" rel="' . $context_view_id . '" rev="' . $book->book_id . '§' . $book->hash . '§' . TIME . '">' . $btVoir . '</a></td>';
-                               $res .= '<td class="bouton"><a class="popupFSBar edit btbook" rel="toolbar=yes" rev="editor_' . $book->book_id . '" href="' . SITE_PATH . 'editor/' . $book->book_id . '_' . $book->hash . '">' . $btEdit . '</a></td>';
-                       } else {
-                               $res .= '<td></td><td></td>';
-                       }
-                       $res .= '<td class="bouton"><a href="' . SITE_PATH . 'stats/' . $book->book_id . '_' . $book->hash . '" class="normallink stats btbook">' . $btStats . '</a></td>';
-                       if ($book->version > 1) {
-                               if ($droits->admin) {
-                                       $res .= '<td class="bouton"><a href="#" rel="exportbook/' . $book->book_id . '" class="popup download btbook">' . $btDownload . '</a></td>';
-                               } else {
-                                       $res .= self::contextBookDownload($context_download_id, $droits, $book);
-                                       $res .= '<td class="bouton"><a href="#" class="openContextMenu download btbook" rel="' . $context_download_id . '_' . $book->book_id . '" rev="' . $book->book_id . '">' . $btDownload . '</a></td>';
-                               }
-                       } else {
-                               $res .= '<td></td>';
-                       }
-                       if ($droits->creation && $book->status < 0) {
-                               $res .= '<td class="bouton"><a href="#" rel="supprimeBook/' . $book->book_id . '" class="ajax suppr btbook" title="' . __('Êtes-vous certain de vouloir supprimer cette publication ?') . '">' . $btDel . '</a></td>';
-                       } else {
-                               $res .= '<td></td>';
-                       }
-                       $res .= '</tr>';
-                       $i++;
-               }
-
-               if (!isset($settings['search']) || is_null($settings['search'])) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '><td colspan="15">';
-                       $res .= commonPage::pager($settings['page'], $dao->count($core->user), $settings['par_page'], 'page' . $change . '/%d');
-                       $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('publications'), false);
-                       $res .= '</td></tr>';
-               }
-               $res .= '</table>';
-               return $res;
-       }
-
-       public static function collections()
-       {
-               global $core;
-
-               if (isset($args[1])) {
-                       $_SESSION['q'] = $args[1];
-               }
-
-               $settings = $core->user->getSettings('collections');
-               $shortcuts = array();
-               if (wsDroits::creation()) {
-                       $shortcuts[] = '<a href="#" class="popup" rel="newCollectionForm">' . $core->typo->Ajouter(__('Créer une nouvelle collection')) . '</a>';
-               }
-
-               $filtres = array();
-
-               $res = commonPage::barre($filtres, 'filtreCollections', 'collections', $shortcuts);
-               $res .= commonPage::tMain(null);
-               $res .= commonPage::bh();
-               $res .= '<div id="listeCollections">';
-               $res .= self::listeCollections();
-               $res .= '</div>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-               return $res;
-       }
-
-       public static function collection($args)
-       {
-               global $core;
-               commonDroits::min(1);
-               cubePage::ui('Sortable');
-               cubePage::autocomplete();
-
-               $dao = new wsDAOCollection($core->con);
-               $collection = $dao->selectById($args[1]);
-
-               $shortcuts = array();
-
-               $res = commonPage::barre(null, null, null, $shortcuts);
-               $res .= commonPage::tMain();
-               $res .= commonPage::bh();
-               $res .= '<div id="collection">';
-               $res .= self::collectionEdit($collection);
-               $res .= '</div>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-               return $res;
-       }
-
-       public static function collectionEdit($collection)
-       {
-               global $core;
-
-               $res = '<h1>Gestion de la collection &laquo; ' . $collection->nom . ' &raquo; <em># ' . $collection->collection_id . '</em></h1>';
-               $res .= '<form method="post" action="saveCollectionComposition" enctype="multipart/form-data">';
-               $res .= '<table class="max">';
-               $res .= '<tr><td class="min nowrap">#</td><td>' . form::hidden('collection_id', $collection->collection_id) . $collection->collection_id . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Nom de la collection') . '</td><td>' . form::field('nom', 20, 64, $collection->nom) . '</td></tr>';
-               $res .= '</table>';
-               $res .= '<h3>' . __('Composition') . '</h3>';
-               $res .= '<a href="#" id="newGroup">' . $core->typo->Ajouter(__('Nouveau groupe')) . '</a><br /><br />';
-               $res .= '<ul>';
-
-               $dao = new wsDAOCollection($core->con);
-               $books = $dao->getPublications($collection->collection_id);
-
-               $datas = $collection->datas;
-               $datas['new_'] = $dao->_emptyGroup();
-
-               $langs = array();
-
-               foreach ($datas as $gid => $group) {
-                       $class = 'group';
-                       if ($gid && $gid == 'new_') {
-                               $class .= ' empty';
-                       }
-                       $res .= '<li class="' . $class . '" data-group="' . $gid . '">';
-                       $res .= '<div class="g">';
-                       $res .= '<a href="#" class="move"></a>';
-                       $g = 'group[' . $gid . ']';
-                       $res .= __('Nom du groupe') . ' ' . form::field(array($g . '[label]'), 20, 64, $group['label']);
-                       $res .= '<a href="#" class="delete"></a>';
-                       $res .= '</div>';
-                       $res .= '<ul>';
-                       $res .= '<li style="height:2px;"></li>';
-
-                       $publications = array_values($group['publications']);
-                       foreach ($publications as $pid => $publication) {
-                               if ($gid && $gid == 'new_') {
-                                       $pid = 'pnew_';
-                               }
-                               $p = $g . '[publications][' . $pid . ']';
-                               $res .= '<li class="publication" data-publication="' . $pid . '"><div>';
-                               if (isset($books[$publication['id']])) {
-                                       $book = $books[$publication['id']];
-                                       $completeLang = $book->lang;
-                                       if ($book->parametres->country) {
-                                               $completeLang .= '_' . mb_strtoupper($book->parametres->country);
-                                       }
-                                       $langs[] = $completeLang;
-                               } else {
-                                       $book = new stdClass();
-                                       $book->lang = '';
-                                       $book->nom = '';
-                               }
-
-
-                               $res .= '<a href="#" class="move"></a>';
-                               $res .= '<span class="lang">' . mb_strtoupper($completeLang) . '</span>';
-                               $res .= '<span class="id"># ' . form::field(array($p . '[s]'), 64, 256, trim($publication['id'] . ' - ' . $book->nom, ' -'), 'publication_id') . form::hidden(array($p . '[id]'), $publication['id']) . '</span>';
-                               $res .= '<span class="label">' . __('Label') . ' ' . form::field(array($p . '[label]'), 20, 64, $publication['label']) . '</span>';
-                               $res .= '<a href="#" class="delete"></a>';
-                               $res .= '<a href="#" class="add"></a>';
-                               $res .= '<span class="online">' . form::checkbox(array($p . '[online]'), '1', $publication['online']) . '</span>';
-                               $res .= '</div></li>';
-                       }
-                       $res .= '</ul>';
-                       $res .= '</li>';
-               }
-
-               $langs = array_unique($langs);
-
-               $res .= '</ul>';
-
-               $contents = $collection->contents;
-               $theme = $collection->theme;
-
-               foreach ($langs as $l) {
-                       $e = explode('_', $l);
-                       $slang = $e[0];
-                       if (!isset($contents[$l]) && isset($contents[$slang])) {
-                               $contents[$l] = $contents[$slang];
-                       }
-
-                       $files = ['splash', 'ad'];
-                       foreach ($files as $file) {
-                               if (!isset($theme[$file . '_' . $l]) && isset($theme[$file . '_' . $slang])) {
-                                       $theme[$file . '_' . $l] = $theme[$file . '_' . $slang];
-                               }
-                       }
-
-                       $res .= '<h3>' . __('Contenus') . ' [' . $l . ']</h3>';
-                       $res .= '<table class="max">';
-                       $res .= '<tr><td class="min nowrap">' . __('Titre') . '</td><td>' . form::field(array('contents[' . $l . '][titre]', 'contents_' . $l . '_titre'), 64, 64, $contents[$l]['titre']) . '</td></tr>';
-                       $res .= '<tr><td class="min nowrap">' . __("Titre sur l'écran d'accueil") . '</td><td>' . form::field(array('contents[' . $l . '][titrehome]', 'contents_' . $l . '_titrehome'), 64, 64, $contents[$l]['titrehome']) . '</td></tr>';
-                       $res .= '<tr><td class="min nowrap">' . __('A propos') . '</td><td>' . form::textarea(array('contents[' . $l . '][apropos]', 'contents_' . $l . '_apropos'), 60, 10, $contents[$l]['apropos']) . '</td></tr>';
-                       //'splash' =>
-                       $res .= '<tr><td class="min nowrap">' . __('Ecran de lancement') . ' (2048x2048px)</td><td><input type="file" name="splash_' . $l . '" />' . form::hidden(array('theme[splash_' . $l . ']', 'splash_' . $l), $theme['splash_' . $l]) . self::viewCollectionFile($theme['splash_' . $l], $collection->collection_id) . '</td></tr>';
-                       $res .= '<tr><td class="min nowrap">' . __('Panneau publicité') . '</td><td><input type="file" name="ad_' . $l . '" />' . form::hidden(array('theme[ad_' . $l . ']', 'ad_' . $l), $theme['ad_' . $l]) . self::viewCollectionFile($theme['ad_' . $l], $collection->collection_id) . '</td></tr>';
-                       $res .= '<tr><td class="min nowrap">' . __('Lien publicité') . '</td><td>' . form::field(array('contents[' . $l . '][adlink]', 'adlink_' . $l), 64, 64, $contents[$l]['adlink']) . '</td></tr>';
-                       $res .= '</table>';
-               }
-
-               $res .= '<h3>' . __('Paramètres avancés') . '</h3>';
-               $res .= '<table class="max">';
-               $res .= '<tr><td class="min nowrap">' . __('Activity') . '</td><td>' . form::field(array('settings[activity]', 'activity'), 20, 64, $collection->settings['activity']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Build') . '</td><td>' . form::field(array('settings[build]', 'build'), 10, 64, $collection->settings['build']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Android License Key') . '</td><td>' . form::textArea(array('settings[license_key]', 'license_key'), 50, 3, $collection->settings['license_key']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Version') . '</td><td>' . form::field(array('settings[version]', 'version'), 10, 64, $collection->settings['version']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Orientation') . '</td><td>' . form::combo(array('settings[orientation]', 'orientation'), array(__('Portrait et Paysage') => 'unspecified', __('Portrait') => 'portrait', __('Paysage') => 'landscape'), $collection->settings['orientation']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Full offline') . '</td><td>' . form::checkbox(array('settings[offline]', 'offline'), 1, $collection->settings['offline']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Stockage publications') . ' (Android)</td><td>' . form::combo(array('settings[android_storage]', 'android_storage'), array(__('Fichier expansion (.obb)') => 'expansion', __('Application (.apk)') => 'apk'), $collection->settings['android_storage']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Identifiant de l\'application') . '</td><td>' . form::field(array('settings[namespace]', 'namespace'), 64, 64, $collection->settings['namespace']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Certificat APNS') . ' Dev (' . __('Fichier .pem') . ')</td><td><input type="file" name="apns_dev" /></td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Certificat APNS') . ' Prod (' . __('Fichier .pem') . ')</td><td><input type="file" name="apns_prod" /></td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Versions iOS') . '</td><td>' . form::field(array('settings[v_ios]', 'namespace'), 64, 256, $collection->settings['v_ios']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Versions Android') . '</td><td>' . form::field(array('settings[v_android]', 'namespace'), 64, 256, $collection->settings['v_android']) . '</td></tr>';
-               $res .= '</table>';
-
-               $res .= '<h3>' . __('Applications offline') . '</h3>';
-               $res .= '<table class="max">';
-               $res .= '<tr><td class="min nowrap">' . __("Filtres d'exclusion") . '</td><td>' . form::textarea(array('settings[offline_exclude]', 'offline_exclude'), 30, 3, $collection->settings['offline_exclude']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __("Synchronisations supplémentaires") . '</td><td>' . form::textarea(array('settings[offline_syncs]', 'offline_syncs'), 30, 3, $collection->settings['offline_syncs']) . '</td></tr>';
-               $res .= '</table>';
-
-
-               if (!isset($collection->settings['perline']) || !$collection->settings['perline']) {
-                       $collection->settings['perline'] = 3;
-               }
-               $res .= '<h3>' . __('Thème') . '</h3>';
-               $res .= '<table class="max">';
-               $images = array('back' => __('Image de fond'), 'etagere' => __("Image de l'étagère"), 'icon' => __("Icône de l'application") . ' (1024x1024px)');
-               foreach ($images as $i => $label) {
-                       $res .= '<tr><td class="min nowrap">' . $label . '</td><td><input type="file" name="' . $i . '" />' . form::hidden(array('theme[' . $i . ']', 'theme_' . $i), $collection->theme[$i]) . self::viewCollectionFile($collection->theme[$i], $collection->collection_id) . '</td></tr>';
-               }
-               $res .= '<tr><td class="min nowrap">' . __('Couleur principale') . '</td><td>#' . form::field(array('settings[couleurA]', 'couleurA'), 6, 6, $collection->settings['couleurA']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Couleur secondaire') . '</td><td>#' . form::field(array('settings[couleurB]', 'couleurB'), 6, 6, $collection->settings['couleurB']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Couleur des textes') . '</td><td>#' . form::field(array('settings[couleurC]', 'couleurC'), 6, 6, $collection->settings['couleurC']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Couleur des titres de publication') . '</td><td>#' . form::field(array('settings[couleurE]', 'couleurC'), 6, 6, $collection->settings['couleurE']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Couleur de fond') . '</td><td>#' . form::field(array('settings[couleurD]', 'couleurD'), 6, 6, $collection->settings['couleurD']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Nombre de publication par ligne') . '</td><td>' . form::field(array('settings[perline]', 'perline'), 1, 1, $collection->settings['perline']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Contenu HTML alternatif') . '</td><td>' . form::textArea(array('settings[htmlalt]', 'htmlalt'), 100, 30, $collection->settings['htmlalt']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('HTML Head') . '</td><td>' . form::textArea(array('settings[htmlhead]', 'htmlhead'), 100, 6, $collection->settings['htmlhead']) . '</td></tr>';
-               $res .= '<tr><td class="min nowrap">' . __('Fichiers pour le contenu alternatif') . '</td><td><input type="file" name="filesalt" />' . form::hidden(array('theme[filesalt]', 'theme_' . $i), $collection->theme['filesalt']) . self::viewCollectionFile($collection->theme['filesalt'], $collection->collection_id) . '</td></tr>';
-
-               $res .= '</table>';
-
-               $res .= '<a href="#" class="submit right">' . $core->typo->Ajouter(__('Enregistrer')) . '</a>';
-               $res .= '</form>';
-               $res .= '<p class="clear"></p>';
-               $res .= '<h3>' . __('Versions') . '</h3>';
-               $res .= '<form action="collectionVersionPublish/' . $collection->collection_id . '" method="post">';
-               $res .= '<a href="#" class="ajax" rel="collectionVersionCreate/' . $collection->collection_id . '">' . $core->typo->Ajouter(__('Créer une version')) . '</a><br /><br />';
-               $r = $core->con->select('SELECT * FROM book_collection_compile WHERE collection_id=\'' . $collection->collection_id . '\' ORDER BY compile_date DESC');
-
-               $v_ios = self::getSelectVersions($collection->settings['v_ios']);
-               $v_android = self::getSelectVersions($collection->settings['v_android']);
-
-
-               if (!$r->count()) {
-                       $res .= __('Aucune version de la collection n\'a été crée');
-               } else {
-                       $res .= '<table class="max">';
-                       $res .= '<tr><th class="left">' . __('Date') . '</th><th class="left">iOS</th><th class="left">Android</th><th class="min nowrap"></th></tr>';
-                       while ($r->fetch()) {
-
-                               if ($r->online_ios || $r->online_android) {
-                                       $del = '';
-                               } else {
-                                       $del = '<a class="ajax suppr btbook" rel="collectionVersionDelete/' . $r->collection_id . '/' . $r->compile_date . '" href="#" title="' . __('Êtes-vous certain de vouloir supprimer cette version ?') . '"><div></div><span>' . __('Effacer') . '</span></a>';
-                               }
-
-                               $pub_ios = form::combo('version[' . $r->compile_date . '][ios]', $v_ios, $r->online_ios);
-                               $pub_android = form::combo('version[' . $r->compile_date . '][android]', $v_android, $r->online_android);
-
-                               $res .= '<tr><td>' . date('Y-m-d H:i:s', $r->compile_date) . '</td><td>' . $pub_ios . '</td><td>' . $pub_android . '</td><td class="min nowrap">' . $del . '</td></tr>';
-                       }
-                       $res .= '</table>';
-               }
-               $res .= '<a href="#" class="submit right">' . $core->typo->Ajouter(__('Enregistrer')) . '</a>';
-               $res .= '</form>';
-               $res .= '<p class="clear"></p>';
-               $res .= '<h3>' . __('Notifications') . '</h3>';
-               $res .= '<p>' . __('Indiquez le texte de la notification à envoyer aux utilisateurs') . ' (' . __('Max 200 caractères') . ').<br />' . __('Laissez vide si vous souhaitez simplement afficher un badge') . '</p>';
-               $res .= '<form method="post" action="publishCollection">';
-               $res .= form::hidden('collection', $collection->collection_id);
-               $res .= '<table class="max">';
-               foreach ($langs as $lang) {
-                       $res .= '<tr><td class="min nowrap">' . __('Notification') . '[' . $lang . ']</td><td class="pad">' . form::textArea(array('notification[' . $lang . ']'), 60, 3) . '</td></tr>';
-               }
-               $res .= '<tr><td colspan="2" class="right"></td><a href="#" class="submit">' . $core->typo->Ajouter(__('Publier et notifier les utilisateurs')) . '</a></tr>';
-               $res .= '</table>';
-               $res .= '</form>';
-               $res .= '<h3>' . __('Export') . '</h3>';
-               $res .= '<a href="#" class="right ajax" rel="exportCollection/' . $collection->collection_id . '/android">' . $core->typo->Ajouter(__('Exporter pour Android')) . '</a> <a href="#" class="right ajax" rel="exportCollection/' . $collection->collection_id . '/ios">' . $core->typo->Ajouter(__('Exporter pour iOS')) . '</a>';
-
-               return $res;
-       }
-
-       public static function viewCollectionFile($file, $collection_id)
-       {
-               $res = '<a href="/fluidbook/collections/working/' . $collection_id . '/' . $file . '" target="_blank">';
-               $res .= cubeMedia::tango('actions/document-save.png');
-               $res .= '</a>';
-               return $res;
-       }
-
-       public static function getSelectVersions($versions)
-       {
-               fb($versions);
-               $res = array('-----' => '');
-               $e = explode(',', $versions);
-
-               foreach ($e as $ee) {
-                       $ee = trim($ee);
-                       $res[$ee] = $ee;
-               }
-               return $res;
-       }
-
-       public static function listeCollections($dashboard = null, $settings = null)
-       {
-               global $core;
-
-               cubePage::truePopup();
-
-               $droits = wsDroits::getDroits();
-
-               commonDroits::min(3);
-               $settings = is_null($settings) ? $core->user->getSettings('collections') : $settings;
-               $change = is_null($dashboard) ? 'Collections' : 'Dashboard/' . $dashboard;
-               $dao = new wsDAOCollection($core->con);
-               if (isset($settings['search']) && !is_null($settings['search'])) {
-                       $dao->setSearch($settings['search']);
-               }
-               $dao->setFiltres($settings['filtres']);
-               $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user);
-
-               $btVoir = '<div></div><span>' . __('voir') . '</span>';
-               $btEdit = '<div></div><span>' . __('éditer') . '</span>';
-               $btStats = '<div></div><span>' . __('stats') . '</span>';
-               $btDownload = '<div></div><span>' . __('télécharger') . '</span>';
-               if ($droits->creation) {
-                       $btDel = '<div></div><span>' . __('suppr.') . '</span>';
-               }
-
-
-               $res = '<table class="liste">';
-               $res .= '<tr><th>' . commonUrl::orderby('#', 'collection_id', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Nom de la collection'), 'nom', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Propriétaire'), 'proprietaire_nom', $settings, 'sort' . $change) . '</th>';
-               $res .= str_repeat('<th class="min"></th>', 4);
-               $res .= '</tr>';
-
-               $i = 0;
-               foreach ($liste as $collection) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr>';
-                       $res .= '<td>' . $collection->collection_id . '</td>';
-                       $res .= '<td>' . $collection->nom . '</td>';
-                       if ($droits->revendeur) {
-                               $p = str_replace(" (", '<br /><em>', html::escapeHTML($collection->proprietaire_nom));
-                               $p = str_replace(')', '</em>', $p);
-                               $res .= '<td><a href="#" class="popup" rel="formChangeCollectionProprietaire/' . $collection->collection_id . '" title="' . __('Modifier le proprietaire') . '">' . $p . '</a></td>';
-                       } else {
-                               $res .= '<td>' . html::escapeHTML($collection->proprietaire_utilisateur) . '</td>';
-                       }
-
-                       $res .= '<td class="bouton"><!--<a href="#" class="normallink voir btbook">' . $btVoir . '</a>--></td>';
-                       $res .= '<td class="bouton"><a href="/collection/' . $collection->collection_id . '" class="normallink edit btbook">' . $btEdit . '</a></td>';
-                       $res .= '<td class="bouton"><!--<a href="#" class="normallink download btbook">' . $btDownload . '</a>--></td>';
-                       $res .= '<td class="bouton"><!--<a href="#" class="normallink suppr btbook">' . $btDel . '</a>--></td>';
-
-                       $res .= '</tr>';
-
-                       $i++;
-               }
-
-               if (!isset($settings['search']) || is_null($settings['search'])) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '><td colspan="7">';
-                       $res .= commonPage::pager($settings['page'], $dao->count($core->user), $settings['par_page'], 'page' . $change . '/%d');
-                       $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('collections'), false);
-                       $res .= '</td></tr>';
-               }
-               $res .= '</table>';
-
-               return $res;
-       }
-
-       public static function getFluidbookVersions($select = false)
-       {
-               $droits = wsDroits::getDroits();
-
-               $chooseVersion = wsDroits::admin();
-
-               if ($chooseVersion) {
-                       $default = ' - ' . __('Version par défaut');
-               } else {
-                       $default = '';
-               }
-
-               $versions = array();
-               $versions['online'] = array('title' => __('Version online') . $default, 'icon' => cubeMedia::silk('page_world.png'));
-               $versions['scorm'] = array('title' => __('Version SCORM') . $default, 'icon' => cubeMedia::silk('page_world.png'));
-               if ($chooseVersion) {
-                       $versions['v1'] = array('title' => __('Version online') . ' - V1', 'icon' => cubeMedia::silk('page_white_world.png'));
-                       $versions['v2'] = array('title' => __('Version online') . ' - V2', 'icon' => cubeMedia::silk('page_white_world.png'));
-               }
-               $versions['win-exe'] = array('title' => __('Version offline') . ' - ' . __('Executable Windows') . ' (Flash)', 'icon' => cubeMedia::silk('application_view_tile.png'));
-               $versions['win-inss-html'] = array('title' => __('Version offline') . ' - ' . __('Executable Windows') . ' (HTML5)', 'icon' => cubeMedia::silk('application_view_tile.png'));
-               $versions['win-ins'] = array('title' => __('Version offline') . ' - ' . __('Installeur Auto-executable Windows') . ' (Flash)', 'icon' => cubeMedia::silk('application_view_tile.png'));
-               $versions['win-ins-html'] = array('title' => __('Version offline') . ' - ' . __('Installeur Auto-executable Windows') . ' (HTML5)', 'icon' => cubeMedia::silk('application_view_tile.png'));
-               $versions['mac-exe'] = array('title' => __('Version offline') . ' - ' . __('Exécutable Mac OS X') . ' (Flash)', 'icon' => cubeMedia::image(IMG . '/macos.png'));
-               $versions['mac-exe-html'] = array('title' => __('Version offline') . ' - ' . __('Exécutable Mac OS X') . ' (HTML)', 'icon' => cubeMedia::image(IMG . '/macos.png'));
-               $versions['win-cd'] = array('title' => __('Version offline') . ' - ' . __('CD-ROM') . ' / ' . __('Clé USB') . ' (Flash)', 'icon' => cubeMedia::silk('cd.png'));
-               $versions['win-cd-html'] = array('title' => __('Version offline') . ' - ' . __('CD-ROM') . ' / ' . __('Clé USB') . ' (HTML)', 'icon' => cubeMedia::silk('cd.png'));
-
-               $versions['win-html'] = array('title' => __('Version offline') . ' - ' . __('HTML') . ' (' . __('Non adaptée à l\'installation sur un serveur web') . ')', 'icon' => cubeMedia::silk('cd.png'));
-               if ($droits->admin) {
-                       $versions['phonegap'] = array('title' => __('Version offline') . ' - ' . __('Application mobile'), 'icon' => cubeMedia::image(IMG . '/phonegap.png'));
-               }
-
-               if (!$select) {
-                       return $versions;
-               }
-
-               $res = array();
-               foreach ($versions as $id => $d) {
-                       $t = explode('-', $d['title'], 2);
-                       $meta = trim($t[0]);
-                       if (isset($t[1])) {
-                               $title = trim($t[1]);
-                       } else {
-                               $title = $meta;
-                       }
-
-                       if (!isset($res[$meta])) {
-                               $res[$meta] = array();
-                       }
-                       $res[$meta][$title] = $id;
-               }
-               return $res;
-       }
-
-       public static function contextBookDownload($id, $droits, $book = null)
-       {
-               global $core;
-
-               $versions = self::getFluidbookVersions();
-
-               if (null !== $book) {
-                       $id .= '_' . $book->book_id;
-               }
-
-               $res = '<div class="contextMenu downbookContextMenu" id="' . $id . '">';
-               $res .= '<ul>';
-               $res .= '<li class="head">' . __("Sélectionnez une version") . '</li>';
-               foreach ($versions as $k => $v) {
-                       $disabled = '';
-                       if (null !== $book) {
-                               if ($k == 'scorm' && !$book->parametres->scorm_enable) {
-                                       continue;
-                               }
-                               $tk = 'download_' . $k;
-                               if (!$book->parametres->{$tk} && $k !== 'scorm') {
-                                       if ($core->user->rs == 'Kadreo' || $core->user->rs == 'STUDIOFRANCE') {
-                                               $disabled = ' class="disabled"';
-                                       } else {
-                                               continue;
-                                       }
-
-                               }
-                       }
-                       $res .= '<li' . $disabled . '><a href="#" rel="downbook/$1/' . $k . '" class="ajax">' . $v['icon'] . $v['title'] . '</a></li>';
-               }
-               if ($droits->admin) {
-                       $res .= '<li class="head">' . __("Installer sur ...") . '</li>';
-                       $versions = array();
-                       $versions['hosting'] = array('title' => __("Le serveur d'hébergement"), 'icon' => cubeMedia::silk('server_go.png'));
-                       $versions['references'] = array('title' => __("L'espace références"), 'icon' => cubeMedia::silk('server_add.png'));
-                       $versions['external'] = array('title' => __("Serveur FTP"), 'icon' => cubeMedia::silk('server_add.png'));
-                       $versions['macbook_phonegap_ios'] = array('title' => __("Projet Phonegap IOS"), 'icon' => cubeMedia::image(IMG . '/ios.png'));
-                       $versions['phonegap_android'] = array('title' => __("Projet Phonegap Android"), 'icon' => cubeMedia::image(IMG . '/android.png'));
-
-                       foreach ($versions as $k => $v) {
-                               $res .= '<li><a href="#" rel="instbook/$1/' . $k . '" class="ajax">' . $v['icon'] . $v['title'] . '</a></li>';
-                       }
-               }
-               $res .= '</ul></div>';
-               return $res;
-       }
-
-       public static function contextBookStatus($id)
-       {
-               global $core;
-
-               if (wsDroits::admin()) {
-                       $status = $core->books_status;
-                       $status[2] = __('Facturé (associé à un projet)');
-               } else {
-                       $status = array();
-                       $status[-1] = $core->books_status[-1];
-                       $status[0] = $core->books_status[0];
-               }
-
-               $res = '<div class="contextMenu statusbookContextMenu" id="' . $id . '">';
-               $res .= '<ul>';
-               $res .= '<li class="head">' . __("Changer le status de la publication") . '</li>';
-               foreach ($status as $s => $title) {
-                       $res .= '<li><a href="#" rel="statusBook/$1/' . $s . '" class="ajax">' . $title . '</a></li>';
-               }
-               $res .= '</ul></div>';
-               return $res;
-       }
-
-       public static function contextBookView($id)
-       {
-               global $core;
-
-               $viewers = array(array('type' => 'flash', 'version' => 'viewer', 'title' => __('Version Flash'), 'icon' => cubeMedia::image(IMG . '/flash.png')),
-                       array('type' => 'html5', 'version' => 'viewerh', 'title' => __('Version HTML5'), 'icon' => cubeMedia::image(IMG . '/html5.png')),
-                       array('type' => 'scorm', 'version' => 'viewers', 'title' => __('Version SCORM'), 'icon' => cubeMedia::image(IMG . '/html5.png')),
-               );
-
-               $res = '<div class="contextMenu viewbookContextMenu" id="' . $id . '">';
-               $res .= '<ul>';
-               $res .= '<li class="head">' . __("Sélectionnez la version") . '</li>';
-               if (isset($viewers)) {
-                       foreach ($viewers as $infos) {
-                               if (!isset($infos['file'])) {
-                                       $infos['file'] = '';
-                               }
-                               if (!isset($infos['pattern'])) {
-                                       $infos['pattern'] = '$1_$2';
-                               }
-                               $res .= '<li data-type="' . $infos['type'] . '"><a target="_blank" href="' . SITE_PATH . $infos['version'] . '/' . $infos['pattern'] . '/' . $infos['file'] . '">' . $infos['icon'] . $infos['title'] . '</a></li>';
-                       }
-               }
-               $res .= '</ul></div>';
-               return $res;
-       }
-
-       public static function traductions($args)
-       {
-               global $core;
-
-               commonDroits::min(5);
-
-               if (count($args) < 2) {
-                       $args[1] = 'fr';
-               }
-
-               $allLangs = cubeLang::getCodes($core->user->lang);
-               $allLangs['es-pr'] = 'Espagnol, Porto Rico';
-               $existingLangs = array();
-
-               $dao = new wsDAOLang($core->con);
-               $langs = $dao->selectAll();
-               foreach ($langs as $lang) {
-                       if (!isset($allLangs[$lang->lang_id])) {
-                               continue;
-                       }
-                       $existingLangs[$lang->lang_id] = $allLangs[$lang->lang_id];
-
-                       unset($allLangs[$lang->lang_id]);
-               }
-
-               $langs = array(__('Langues configurées') => array_flip($existingLangs), __('Autres langues') => array_flip($allLangs));
-
-               $res = commonPage::barre();
-               $res .= commonPage::tMain(null, false);
-
-               $res .= commonPage::bh();
-               $res .= '<form action="changeLang" method="post" class="submitonchange">';
-               $res .= '<table class="liste">';
-               $res .= '<tr><td class="center">' . __('Sélectionnez la langue à configurer') . ' : ' . form::combo('lang', $langs, $args[1]) . ' </td></tr>';
-               $res .= '</table>';
-               $res .= '</form>';
-               $res .= commonPage::bf();
-
-               $res .= '<div id="formLang">';
-               $res .= self::formLang($args[1]);
-               $res .= '</div>';
-               $res .= commonPage::bMain(true);
-
-               return $res;
-       }
-
-       public static function formLang($lang_id)
-       {
-               commonDroits::min(5);
-               global $core;
-               $dao = new wsDAOLang($core->con);
-               $lang = $dao->selectById($lang_id);
-
-               $res = commonPage::bh();
-               $res .= '<table class="liste">';
-               $res .= '<tr><td><a href="' . SITE_PATH . 'exportLangAsExcel/' . $lang_id . '">' . __('Exporter au format Excel') . '</a>';
-               $res .= ' | <a href="' . SITE_PATH . 'exportAllLangsAsExcel/' . $lang_id . '">' . __('Exporter toutes les langues au format Excel') . '</a>';
-               $res .= '</td></tr>';
-               $res .= '</table>';
-               $res .= commonPage::bf();
-
-               $res .= '<form action="saveLang" method="post">';
-
-               $res .= commonPage::bh();
-               $res .= '<table class="liste">';
-               $res .= '<tr><td>' . __('Police de caractères') . ' : </td><td>' . form::hidden('lang', $lang_id) . form::combo('font', self::getFonts(), $lang->font) . '</td></tr>';
-               $res .= '<tr class="odd"><td>' . __('Jeux de caractères') . ' : </td><td>' . form::combo('charset', self::getCharsets(), $lang->charset) . '</td></tr>';
-               $res .= '<tr><td>' . __("Langue de l'installeur") . ' : </td><td>' . form::combo('nsis', self::getNSISLangs(), $lang->nsis) . '</td></tr>';
-               $res .= '<tr><td colspan="2" class="right odd"><a href="#" class="submit">' . $core->typo->Ajouter('Valider') . '</a></td></tr>';
-               $res .= '</table>';
-               $res .= commonPage::bf();
-
-               $res .= commonPage::bh();
-               $res .= cubeLang::translationForm(self::getTranslationSources(), $lang_id, null, 'liste', array(), '<a href="#" class="submit">' . $core->typo->Ajouter(__('Enregistrer')) . '</a>', $lang->traductions);
-               $res .= commonPage::bf();
-               $res .= '</form>';
-               return $res;
-       }
-
-       public static function getTranslationSources()
-       {
-               return array(__('Version Flash') => PLAYER_SOURCES, __('Version HTML5') => WS_COMPILE_ASSETS . '/player/local', __('Compilateur HTML5') => ROOT . '/inc/ws/Util/html5', __('Application') => WS_COMPILE_ASSETS . '/_html5app');
-       }
-
-       public static function exportLangAsExcel($args)
-       {
-               global $core;
-
-               $lang_id = $args[1];
-
-               $xls = new PHPExcel();
-               $s = $xls->setActiveSheetIndex(0);
-
-               $lang_name = self::exportLangAsSheet($s, $lang_id, 'en');
-
-               $xls->setActiveSheetIndex(0);
-
-               ob_end_clean();
-               files::registerMimeTypes(array('xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'));
-               cubeHTTP::forceDownload('Fluidbook_' . $lang_name . '.xlsx', false);
-
-               $writer = new PHPExcel_Writer_Excel2007($xls);
-               $writer->save('php://output');
-
-               exit;
-       }
-
-       public static function exportAllLangsAsExcel($args)
-       {
-               global $core;
-
-               $xls = new PHPExcel();
-
-               $dao = new wsDAOLang($core->con);
-               $all = $dao->selectAll();
-
-               $i = 0;
-               foreach ($all as $l) {
-                       try {
-                               $s = $xls->getSheet($i);
-                       } catch (Exception $e) {
-                               $s = $xls->createSheet($i);
-                       }
-                       self::exportLangAsSheet($s, $l->lang_id, 'en');
-                       $i++;
-               }
-
-               $xls->setActiveSheetIndex(0);
-
-               ob_end_clean();
-               files::registerMimeTypes(array('xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'));
-               cubeHTTP::forceDownload('Fluidbook_All_Languages.xlsx', false);
-
-               $writer = new PHPExcel_Writer_Excel2007($xls);
-               $writer->save('php://output');
-               exit;
-       }
-
-       public static function exportLangAsSheet($s, $lang_id, $ref_id = 'en')
-       {
-               global $core;
-               $dao = new wsDAOLang($core->con);
-
-
-               $lang = $dao->selectById($lang_id);
-               $ref = $dao->selectById($ref_id);
-
-               $lang_name = cubeLang::getNameByCode($lang_id, 'en');
-               $ref_name = cubeLang::getNameByCode($ref_id, 'en');
-
-               $s->setTitle(cubeText::str2URL($lang_name));
-
-               $sources = [];
-               $ts = self::getTranslationSources();
-               foreach ($ts as $item) {
-                       $sources = array_merge($sources, $item);
-               }
-
-               $tab = cubeLang::getTranslationsList(self::getTranslationSources(), array('php', 'as', 'js'), array(), $lang->traductions);
-
-               $s->setCellValueByColumnAndRow(0, 1, 'ID', true);
-               $s->setCellValueByColumnAndRow(1, 1, $ref_name, true);
-               $s->setCellValueByColumnAndRow(2, 1, $lang_name, true);
-
-               $j = 2;
-               foreach ($tab as $msgid => $msgstr) {
-                       $s->setCellValueByColumnAndRow(0, $j, $msgid);
-                       $s->setCellValueByColumnAndRow(1, $j, $ref->traductions[$msgid]);
-                       $s->setCellValueByColumnAndRow(2, $j, $msgstr);
-
-                       if ($msgstr == '') {
-                               $s->getStyleByColumnAndRow(2, $j)->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
-                               $s->getStyleByColumnAndRow(2, $j)->getFill()->getStartColor()->setARGB('FFFFFF00');
-                       }
-                       $j++;
-               }
-
-               $s->getColumnDimensionByColumn(0)->setAutoSize(true);
-               $s->getColumnDimensionByColumn(1)->setAutoSize(true);
-               $s->getColumnDimensionByColumn(2)->setAutoSize(true);
-
-               return $lang_name;
-       }
-
-       public static function getFonts()
-       {
-               $formats = array('ttf', 'otf', 'TTF', 'OTF');
-
-               $dr = opendir(FONT_PATH);
-               $fonts = array('Arial (police système)' => "system");
-               while ($file = readdir($dr)) {
-                       if ($file == '.' || $file == '..' || !in_array(files::getExtension($file), $formats)) {
-                               continue;
-                       }
-                       $fonts[$file] = $file;
-               }
-               return $fonts;
-       }
-
-       protected static function getCharsets()
-       {
-               $sets = cubeFlexFontAsset::getSets();
-               $res = array();
-               foreach ($sets as $k => $v) {
-                       $res[$k] = $k;
-               }
-               return $res;
-       }
-
-       protected static function getNSISLangs()
-       {
-               $res = array();
-               $dir = WS_FILES . '/nsislangs';
-               $dr = opendir($dir);
-               while ($file = readdir($dr)) {
-                       if ($file == '.' || $file == '..') {
-                               continue;
-                       }
-                       $e = explode('.', $file);
-                       $res[$e[0]] = $e[0];
-               }
-
-               ksort($res);
-               return $res;
-       }
-
-       public static function editor($args)
-       {
-               commonDroits::min(1);
-
-               global $core;
-
-               $args = cubePage::getArgs($args);
-               $e = explode('_', $args[0]);
-               $book_id = $e[0];
-               $hash = isset($e[1]) ? $e[1] : '';
-
-
-               self::checkDocumentVersionOfBook($book_id);
-
-               if ($book_id == 'new') {
-                       $dao = new wsDAOBook($core->con);
-                       $book = $dao->creeEmpty($core->user->utilisateur_id, $core->user->lang);
-                       http::redirect(SITE_PATH . 'editor/' . $book->book_id . '_' . $book->hash);
-               }
-
-               $res = '<html><head><style type="text/css">';
-               $res .= '#composerSwf{width:100%;height:100%;margin:0 auto;}
+    public static function publications($args)
+    {
+        global $core;
+
+        if (isset($args[1])) {
+            $_SESSION['q'] = $args[1];
+        }
+
+        $settings = $core->user->getSettings('books');
+
+        $shortcuts = array();
+        if (wsDroits::creation()) {
+            $shortcuts[] = '<a href="#" class="popup" rel="newBookForm">' . $core->typo->Ajouter(__('Créer une nouvelle publication')) . '</a>';
+        }
+
+        $filtres = array();
+        if (wsDroits::revendeur(false)) {
+            $filtres[] = new commonFiltre(__('Status'), 'status_book', $settings['filtres']);
+        }
+        if (wsDroits::admin()) {
+            $filtres[] = new commonFiltre(__('Administrateur'), 'admin_book', $settings['filtres']);
+            $filtres[] = new commonFiltre(__('Revendeur'), 'revendeur_book', $settings['filtres']);
+        }
+        $res = commonPage::barre($filtres, 'filtreBooks', 'books', $shortcuts, wsDroits::creation());
+        $res .= commonPage::tMain(null, wsDroits::creation());
+        $res .= commonPage::bh();
+        $res .= '<div id="listeBooks">';
+        $res .= self::listeBooks();
+        $res .= '</div>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+        return $res;
+    }
+
+    public static function listeBooks($dashboard = null, $settings = null)
+    {
+        global $core;
+        cubePage::truePopup();
+        cubePage::autocomplete();
+        cubePage::contextMenu();
+
+        $droits = wsDroits::getDroits();
+
+        commonDroits::min(1);
+        $settings = is_null($settings) ? $core->user->getSettings('books') : $settings;
+        $change = is_null($dashboard) ? 'Books' : 'Dashboard/' . $dashboard;
+        $dao = new wsDAOBook($core->con);
+        $context_download_id = is_null($dashboard) ? 'contextDownloadBook' : 'contextDashboard_Download' . $dashboard;
+        $context_status_id = is_null($dashboard) ? 'contextStatusBook' : 'contextDashboard_Status' . $dashboard;
+        $context_view_id = is_null($dashboard) ? 'contextViewBook' : 'contextView_Status' . $dashboard;
+
+        if (isset($settings['search']) && !is_null($settings['search'])) {
+            $dao->setSearch($settings['search']);
+        }
+        $dao->setFiltres($settings['filtres']);
+        $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user);
+
+        $res = '';
+
+
+        $res .= self::contextBookStatus($context_status_id);
+        $res .= self::contextBookView($context_view_id);
+
+        $res .= '<table class="liste">';
+        $res .= '<tr><th>' . commonUrl::orderby('#', 'book_id', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Titre de la publication'), 'nom', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Date'), 'date', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__(''), 'lang', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . __('Pages') . '</th>';
+        if ($droits->admin) {
+            $res .= '<th>' . commonUrl::orderby('C', 'demo_counter', $settings, 'sort' . $change, __('Compteur de démos')) . '</th>';
+        }
+        if ($droits->revendeur) {
+            $res .= '<th>' . commonUrl::orderby(__('Proprietaire'), 'proprietaire_nom', $settings, 'sort' . $change) . '</th>';
+        } else {
+            $res .= '<th>' . commonUrl::orderby(__('Proprietaire'), 'proprietaire_utilisateur', $settings, 'sort' . $change) . '</th>';
+        }
+        if ($droits->admin) {
+            $res .= '<th>' . commonUrl::orderby(__('Facturation'), 'facturable', $settings, 'sort' . $change) . '</th>';
+        }
+        if ($droits->revendeur) {
+            $res .= '<th>' . commonUrl::orderby(__('Status'), 'status', $settings, 'sort' . $change) . '</th>';
+            $res .= '<th>' . __('V') . '</th>';
+        }
+        $res .= str_repeat('<th class="min"></th>', 5);
+        $res .= '</tr>';
+        $i = 0;
+
+        $btVoir = '<div></div><span>' . __('voir') . '</span>';
+        $btEdit = '<div></div><span>' . __('éditer') . '</span>';
+        $btStats = '<div></div><span>' . __('stats') . '</span>';
+        $btDownload = '<div></div><span>' . __('télécharger') . '</span>';
+        if ($droits->creation) {
+            $btDel = '<div></div><span>' . __('suppr.') . '</span>';
+        }
+
+        foreach ($liste as $id => $book) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '>';
+            $res .= '<td>' . $book->book_id . '</td>';
+            $res .= '<td>' . html::escapeHTML($book->nom) . '</td>';
+            $res .= '<td>' . date('Y-m-d', $book->date) . '</td>';
+            $res .= '<td>' . mb_strtoupper($book->lang) . '</td>';
+            $res .= '<td>' . $book->parametres->pages . '</td>';
+            if ($droits->admin) {
+                $res .= '<td>' . $book->demo_counter . '</td>';
+            }
+
+            if ($droits->revendeur) {
+                $p = str_replace(" (", '<br /><em>', html::escapeHTML($book->proprietaire));
+                $p = str_replace(')', '</em>', $p);
+                $res .= '<td><a href="#" class="popup" rel="formChangeBookProprietaire/' . $book->book_id . '" title="' . __('Modifier le proprietaire') . '">' . $p . '</a></td>';
+            } else {
+                $res .= '<td>' . html::escapeHTML($book->proprietaire_utilisateur) . '</td>';
+            }
+            if ($droits->admin) {
+                $res .= '<td>' . html::escapeHTML($book->facturable) . '</td>';
+            }
+            if ($droits->revendeur) {
+                if ($droits->admin || $book->status < 1) {
+                    $p = '';
+                    if (!is_null($book->projet)) {
+                        $p = ' <a href="' . EXTRANET_URL . '/projet/' . $book->projet . '" title="' . __('Voir les détails du projet') . '" class="blank icon">' . cubeMedia::silk('arrow_right.png') . '</a>';
+                    }
+                    $res .= '<td><a href="#" class="openContextMenu" rel="' . $context_status_id . '" rev="' . $book->book_id . '">' . $core->books_status[$book->status] . '</a>' . $p . '</td>';
+                } else {
+                    $res .= '<td>' . $core->books_status[1] . '</td>';
+                }
+                $res .= '<td>' . $book->version . '</td>';
+            }
+            if ($book->version > 1 || $droits->admin) {
+                $types = [];
+                if (!$book->parametres->alwaysHTML5) {
+                    $types[] = 'flash';
+                    $defaultPlayer = 'viewer';
+                } else {
+                    $defaultPlayer = 'viewerh';
+                }
+                if ($book->parametres->mobileVersion != 'pdf') {
+                    $types[] = 'html5';
+                }
+                if ($book->parametres->scorm_enable) {
+                    $types[] = 'scorm';
+                }
+
+
+                $res .= '<td class="bouton"><a href="/' . $defaultPlayer . '/' . $book->book_id . '_' . $book->hash . '/" class="openContextMenu voir btbook" data-type="' . implode(',', $types) . '" rel="' . $context_view_id . '" rev="' . $book->book_id . '§' . $book->hash . '§' . TIME . '">' . $btVoir . '</a></td>';
+                $res .= '<td class="bouton"><a class="popupFSBar edit btbook" rel="toolbar=yes" rev="editor_' . $book->book_id . '" href="' . SITE_PATH . 'editor/' . $book->book_id . '_' . $book->hash . '">' . $btEdit . '</a></td>';
+            } else {
+                $res .= '<td></td><td></td>';
+            }
+            $res .= '<td class="bouton"><a href="' . SITE_PATH . 'stats/' . $book->book_id . '_' . $book->hash . '" class="normallink stats btbook">' . $btStats . '</a></td>';
+            if ($book->version > 1) {
+                if ($droits->admin) {
+                    $res .= '<td class="bouton"><a href="#" rel="exportbook/' . $book->book_id . '" class="popup download btbook">' . $btDownload . '</a></td>';
+                } else {
+                    $res .= self::contextBookDownload($context_download_id, $droits, $book);
+                    $res .= '<td class="bouton"><a href="#" class="openContextMenu download btbook" rel="' . $context_download_id . '_' . $book->book_id . '" rev="' . $book->book_id . '">' . $btDownload . '</a></td>';
+                }
+            } else {
+                $res .= '<td></td>';
+            }
+            if ($droits->creation && $book->status < 0) {
+                $res .= '<td class="bouton"><a href="#" rel="supprimeBook/' . $book->book_id . '" class="ajax suppr btbook" title="' . __('Êtes-vous certain de vouloir supprimer cette publication ?') . '">' . $btDel . '</a></td>';
+            } else {
+                $res .= '<td></td>';
+            }
+            $res .= '</tr>';
+            $i++;
+        }
+
+        if (!isset($settings['search']) || is_null($settings['search'])) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '><td colspan="15">';
+            $res .= commonPage::pager($settings['page'], $dao->count($core->user), $settings['par_page'], 'page' . $change . '/%d');
+            $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('publications'), false);
+            $res .= '</td></tr>';
+        }
+        $res .= '</table>';
+        return $res;
+    }
+
+    public static function collections()
+    {
+        global $core;
+
+        if (isset($args[1])) {
+            $_SESSION['q'] = $args[1];
+        }
+
+        $settings = $core->user->getSettings('collections');
+        $shortcuts = array();
+        if (wsDroits::creation()) {
+            $shortcuts[] = '<a href="#" class="popup" rel="newCollectionForm">' . $core->typo->Ajouter(__('Créer une nouvelle collection')) . '</a>';
+        }
+
+        $filtres = array();
+
+        $res = commonPage::barre($filtres, 'filtreCollections', 'collections', $shortcuts);
+        $res .= commonPage::tMain(null);
+        $res .= commonPage::bh();
+        $res .= '<div id="listeCollections">';
+        $res .= self::listeCollections();
+        $res .= '</div>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+        return $res;
+    }
+
+    public static function collection($args)
+    {
+        global $core;
+        commonDroits::min(1);
+        cubePage::ui('Sortable');
+        cubePage::autocomplete();
+
+        $dao = new wsDAOCollection($core->con);
+        $collection = $dao->selectById($args[1]);
+
+        $shortcuts = array();
+
+        $res = commonPage::barre(null, null, null, $shortcuts);
+        $res .= commonPage::tMain();
+        $res .= commonPage::bh();
+        $res .= '<div id="collection">';
+        $res .= self::collectionEdit($collection);
+        $res .= '</div>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+        return $res;
+    }
+
+    public static function collectionEdit($collection)
+    {
+        global $core;
+
+        $res = '<h1>Gestion de la collection &laquo; ' . $collection->nom . ' &raquo; <em># ' . $collection->collection_id . '</em></h1>';
+        $res .= '<form method="post" action="saveCollectionComposition" enctype="multipart/form-data">';
+        $res .= '<table class="max">';
+        $res .= '<tr><td class="min nowrap">#</td><td>' . form::hidden('collection_id', $collection->collection_id) . $collection->collection_id . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Nom de la collection') . '</td><td>' . form::field('nom', 20, 64, $collection->nom) . '</td></tr>';
+        $res .= '</table>';
+        $res .= '<h3>' . __('Composition') . '</h3>';
+        $res .= '<a href="#" id="newGroup">' . $core->typo->Ajouter(__('Nouveau groupe')) . '</a><br /><br />';
+        $res .= '<ul>';
+
+        $dao = new wsDAOCollection($core->con);
+        $books = $dao->getPublications($collection->collection_id);
+
+        $datas = $collection->datas;
+        $datas['new_'] = $dao->_emptyGroup();
+
+        $langs = array();
+
+        foreach ($datas as $gid => $group) {
+            $class = 'group';
+            if ($gid && $gid == 'new_') {
+                $class .= ' empty';
+            }
+            $res .= '<li class="' . $class . '" data-group="' . $gid . '">';
+            $res .= '<div class="g">';
+            $res .= '<a href="#" class="move"></a>';
+            $g = 'group[' . $gid . ']';
+            $res .= __('Nom du groupe') . ' ' . form::field(array($g . '[label]'), 20, 64, $group['label']);
+            $res .= '<a href="#" class="delete"></a>';
+            $res .= '</div>';
+            $res .= '<ul>';
+            $res .= '<li style="height:2px;"></li>';
+
+            $publications = array_values($group['publications']);
+            foreach ($publications as $pid => $publication) {
+                if ($gid && $gid == 'new_') {
+                    $pid = 'pnew_';
+                }
+                $p = $g . '[publications][' . $pid . ']';
+                $res .= '<li class="publication" data-publication="' . $pid . '"><div>';
+                if (isset($books[$publication['id']])) {
+                    $book = $books[$publication['id']];
+                    $completeLang = $book->lang;
+                    if ($book->parametres->country) {
+                        $completeLang .= '_' . mb_strtoupper($book->parametres->country);
+                    }
+                    $langs[] = $completeLang;
+                } else {
+                    $book = new stdClass();
+                    $book->lang = '';
+                    $book->nom = '';
+                }
+
+
+                $res .= '<a href="#" class="move"></a>';
+                $res .= '<span class="lang">' . mb_strtoupper($completeLang) . '</span>';
+                $res .= '<span class="id"># ' . form::field(array($p . '[s]'), 64, 256, trim($publication['id'] . ' - ' . $book->nom, ' -'), 'publication_id') . form::hidden(array($p . '[id]'), $publication['id']) . '</span>';
+                $res .= '<span class="label">' . __('Label') . ' ' . form::field(array($p . '[label]'), 20, 64, $publication['label']) . '</span>';
+                $res .= '<a href="#" class="delete"></a>';
+                $res .= '<a href="#" class="add"></a>';
+                $res .= '<span class="online">' . form::checkbox(array($p . '[online]'), '1', $publication['online']) . '</span>';
+                $res .= '</div></li>';
+            }
+            $res .= '</ul>';
+            $res .= '</li>';
+        }
+
+        $langs = array_unique($langs);
+
+        $res .= '</ul>';
+
+        $contents = $collection->contents;
+        $theme = $collection->theme;
+
+        foreach ($langs as $l) {
+            $e = explode('_', $l);
+            $slang = $e[0];
+            if (!isset($contents[$l]) && isset($contents[$slang])) {
+                $contents[$l] = $contents[$slang];
+            }
+
+            $files = ['splash', 'ad'];
+            foreach ($files as $file) {
+                if (!isset($theme[$file . '_' . $l]) && isset($theme[$file . '_' . $slang])) {
+                    $theme[$file . '_' . $l] = $theme[$file . '_' . $slang];
+                }
+            }
+
+            $res .= '<h3>' . __('Contenus') . ' [' . $l . ']</h3>';
+            $res .= '<table class="max">';
+            $res .= '<tr><td class="min nowrap">' . __('Titre') . '</td><td>' . form::field(array('contents[' . $l . '][titre]', 'contents_' . $l . '_titre'), 64, 64, $contents[$l]['titre']) . '</td></tr>';
+            $res .= '<tr><td class="min nowrap">' . __("Titre sur l'écran d'accueil") . '</td><td>' . form::field(array('contents[' . $l . '][titrehome]', 'contents_' . $l . '_titrehome'), 64, 64, $contents[$l]['titrehome']) . '</td></tr>';
+            $res .= '<tr><td class="min nowrap">' . __('A propos') . '</td><td>' . form::textarea(array('contents[' . $l . '][apropos]', 'contents_' . $l . '_apropos'), 60, 10, $contents[$l]['apropos']) . '</td></tr>';
+            //'splash' =>
+            $res .= '<tr><td class="min nowrap">' . __('Ecran de lancement') . ' (2048x2048px)</td><td><input type="file" name="splash_' . $l . '" />' . form::hidden(array('theme[splash_' . $l . ']', 'splash_' . $l), $theme['splash_' . $l]) . self::viewCollectionFile($theme['splash_' . $l], $collection->collection_id) . '</td></tr>';
+            $res .= '<tr><td class="min nowrap">' . __('Panneau publicité') . '</td><td><input type="file" name="ad_' . $l . '" />' . form::hidden(array('theme[ad_' . $l . ']', 'ad_' . $l), $theme['ad_' . $l]) . self::viewCollectionFile($theme['ad_' . $l], $collection->collection_id) . '</td></tr>';
+            $res .= '<tr><td class="min nowrap">' . __('Lien publicité') . '</td><td>' . form::field(array('contents[' . $l . '][adlink]', 'adlink_' . $l), 64, 64, $contents[$l]['adlink']) . '</td></tr>';
+            $res .= '</table>';
+        }
+
+        $res .= '<h3>' . __('Paramètres avancés') . '</h3>';
+        $res .= '<table class="max">';
+        $res .= '<tr><td class="min nowrap">' . __('Activity') . '</td><td>' . form::field(array('settings[activity]', 'activity'), 20, 64, $collection->settings['activity']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Build') . '</td><td>' . form::field(array('settings[build]', 'build'), 10, 64, $collection->settings['build']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Android License Key') . '</td><td>' . form::textArea(array('settings[license_key]', 'license_key'), 50, 3, $collection->settings['license_key']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Version') . '</td><td>' . form::field(array('settings[version]', 'version'), 10, 64, $collection->settings['version']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Orientation') . '</td><td>' . form::combo(array('settings[orientation]', 'orientation'), array(__('Portrait et Paysage') => 'unspecified', __('Portrait') => 'portrait', __('Paysage') => 'landscape'), $collection->settings['orientation']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Full offline') . '</td><td>' . form::checkbox(array('settings[offline]', 'offline'), 1, $collection->settings['offline']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Stockage publications') . ' (Android)</td><td>' . form::combo(array('settings[android_storage]', 'android_storage'), array(__('Fichier expansion (.obb)') => 'expansion', __('Application (.apk)') => 'apk'), $collection->settings['android_storage']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Identifiant de l\'application') . '</td><td>' . form::field(array('settings[namespace]', 'namespace'), 64, 64, $collection->settings['namespace']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Certificat APNS') . ' Dev (' . __('Fichier .pem') . ')</td><td><input type="file" name="apns_dev" /></td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Certificat APNS') . ' Prod (' . __('Fichier .pem') . ')</td><td><input type="file" name="apns_prod" /></td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Versions iOS') . '</td><td>' . form::field(array('settings[v_ios]', 'namespace'), 64, 256, $collection->settings['v_ios']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Versions Android') . '</td><td>' . form::field(array('settings[v_android]', 'namespace'), 64, 256, $collection->settings['v_android']) . '</td></tr>';
+        $res .= '</table>';
+
+        $res .= '<h3>' . __('Applications offline') . '</h3>';
+        $res .= '<table class="max">';
+        $res .= '<tr><td class="min nowrap">' . __("Filtres d'exclusion") . '</td><td>' . form::textarea(array('settings[offline_exclude]', 'offline_exclude'), 30, 3, $collection->settings['offline_exclude']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __("Synchronisations supplémentaires") . '</td><td>' . form::textarea(array('settings[offline_syncs]', 'offline_syncs'), 30, 3, $collection->settings['offline_syncs']) . '</td></tr>';
+        $res .= '</table>';
+
+
+        if (!isset($collection->settings['perline']) || !$collection->settings['perline']) {
+            $collection->settings['perline'] = 3;
+        }
+        $res .= '<h3>' . __('Thème') . '</h3>';
+        $res .= '<table class="max">';
+        $images = array('back' => __('Image de fond'), 'etagere' => __("Image de l'étagère"), 'icon' => __("Icône de l'application") . ' (1024x1024px)');
+        foreach ($images as $i => $label) {
+            $res .= '<tr><td class="min nowrap">' . $label . '</td><td><input type="file" name="' . $i . '" />' . form::hidden(array('theme[' . $i . ']', 'theme_' . $i), $collection->theme[$i]) . self::viewCollectionFile($collection->theme[$i], $collection->collection_id) . '</td></tr>';
+        }
+        $res .= '<tr><td class="min nowrap">' . __('Couleur principale') . '</td><td>#' . form::field(array('settings[couleurA]', 'couleurA'), 6, 6, $collection->settings['couleurA']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Couleur secondaire') . '</td><td>#' . form::field(array('settings[couleurB]', 'couleurB'), 6, 6, $collection->settings['couleurB']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Couleur des textes') . '</td><td>#' . form::field(array('settings[couleurC]', 'couleurC'), 6, 6, $collection->settings['couleurC']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Couleur des titres de publication') . '</td><td>#' . form::field(array('settings[couleurE]', 'couleurC'), 6, 6, $collection->settings['couleurE']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Couleur de fond') . '</td><td>#' . form::field(array('settings[couleurD]', 'couleurD'), 6, 6, $collection->settings['couleurD']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Nombre de publication par ligne') . '</td><td>' . form::field(array('settings[perline]', 'perline'), 1, 1, $collection->settings['perline']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Contenu HTML alternatif') . '</td><td>' . form::textArea(array('settings[htmlalt]', 'htmlalt'), 100, 30, $collection->settings['htmlalt']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('HTML Head') . '</td><td>' . form::textArea(array('settings[htmlhead]', 'htmlhead'), 100, 6, $collection->settings['htmlhead']) . '</td></tr>';
+        $res .= '<tr><td class="min nowrap">' . __('Fichiers pour le contenu alternatif') . '</td><td><input type="file" name="filesalt" />' . form::hidden(array('theme[filesalt]', 'theme_' . $i), $collection->theme['filesalt']) . self::viewCollectionFile($collection->theme['filesalt'], $collection->collection_id) . '</td></tr>';
+
+        $res .= '</table>';
+
+        $res .= '<a href="#" class="submit right">' . $core->typo->Ajouter(__('Enregistrer')) . '</a>';
+        $res .= '</form>';
+        $res .= '<p class="clear"></p>';
+        $res .= '<h3>' . __('Versions') . '</h3>';
+        $res .= '<form action="collectionVersionPublish/' . $collection->collection_id . '" method="post">';
+        $res .= '<a href="#" class="ajax" rel="collectionVersionCreate/' . $collection->collection_id . '">' . $core->typo->Ajouter(__('Créer une version')) . '</a><br /><br />';
+        $r = $core->con->select('SELECT * FROM book_collection_compile WHERE collection_id=\'' . $collection->collection_id . '\' ORDER BY compile_date DESC');
+
+        $v_ios = self::getSelectVersions($collection->settings['v_ios']);
+        $v_android = self::getSelectVersions($collection->settings['v_android']);
+
+
+        if (!$r->count()) {
+            $res .= __('Aucune version de la collection n\'a été crée');
+        } else {
+            $res .= '<table class="max">';
+            $res .= '<tr><th class="left">' . __('Date') . '</th><th class="left">iOS</th><th class="left">Android</th><th class="min nowrap"></th></tr>';
+            while ($r->fetch()) {
+
+                if ($r->online_ios || $r->online_android) {
+                    $del = '';
+                } else {
+                    $del = '<a class="ajax suppr btbook" rel="collectionVersionDelete/' . $r->collection_id . '/' . $r->compile_date . '" href="#" title="' . __('Êtes-vous certain de vouloir supprimer cette version ?') . '"><div></div><span>' . __('Effacer') . '</span></a>';
+                }
+
+                $pub_ios = form::combo('version[' . $r->compile_date . '][ios]', $v_ios, $r->online_ios);
+                $pub_android = form::combo('version[' . $r->compile_date . '][android]', $v_android, $r->online_android);
+
+                $res .= '<tr><td>' . date('Y-m-d H:i:s', $r->compile_date) . '</td><td>' . $pub_ios . '</td><td>' . $pub_android . '</td><td class="min nowrap">' . $del . '</td></tr>';
+            }
+            $res .= '</table>';
+        }
+        $res .= '<a href="#" class="submit right">' . $core->typo->Ajouter(__('Enregistrer')) . '</a>';
+        $res .= '</form>';
+        $res .= '<p class="clear"></p>';
+        $res .= '<h3>' . __('Notifications') . '</h3>';
+        $res .= '<p>' . __('Indiquez le texte de la notification à envoyer aux utilisateurs') . ' (' . __('Max 200 caractères') . ').<br />' . __('Laissez vide si vous souhaitez simplement afficher un badge') . '</p>';
+        $res .= '<form method="post" action="publishCollection">';
+        $res .= form::hidden('collection', $collection->collection_id);
+        $res .= '<table class="max">';
+        foreach ($langs as $lang) {
+            $res .= '<tr><td class="min nowrap">' . __('Notification') . '[' . $lang . ']</td><td class="pad">' . form::textArea(array('notification[' . $lang . ']'), 60, 3) . '</td></tr>';
+        }
+        $res .= '<tr><td colspan="2" class="right"></td><a href="#" class="submit">' . $core->typo->Ajouter(__('Publier et notifier les utilisateurs')) . '</a></tr>';
+        $res .= '</table>';
+        $res .= '</form>';
+        $res .= '<h3>' . __('Export') . '</h3>';
+        $res .= '<a href="#" class="right ajax" rel="exportCollection/' . $collection->collection_id . '/android">' . $core->typo->Ajouter(__('Exporter pour Android')) . '</a> <a href="#" class="right ajax" rel="exportCollection/' . $collection->collection_id . '/ios">' . $core->typo->Ajouter(__('Exporter pour iOS')) . '</a>';
+
+        return $res;
+    }
+
+    public static function viewCollectionFile($file, $collection_id)
+    {
+        $res = '<a href="/fluidbook/collections/working/' . $collection_id . '/' . $file . '" target="_blank">';
+        $res .= cubeMedia::tango('actions/document-save.png');
+        $res .= '</a>';
+        return $res;
+    }
+
+    public static function getSelectVersions($versions)
+    {
+        fb($versions);
+        $res = array('-----' => '');
+        $e = explode(',', $versions);
+
+        foreach ($e as $ee) {
+            $ee = trim($ee);
+            $res[$ee] = $ee;
+        }
+        return $res;
+    }
+
+    public static function listeCollections($dashboard = null, $settings = null)
+    {
+        global $core;
+
+        cubePage::truePopup();
+
+        $droits = wsDroits::getDroits();
+
+        commonDroits::min(3);
+        $settings = is_null($settings) ? $core->user->getSettings('collections') : $settings;
+        $change = is_null($dashboard) ? 'Collections' : 'Dashboard/' . $dashboard;
+        $dao = new wsDAOCollection($core->con);
+        if (isset($settings['search']) && !is_null($settings['search'])) {
+            $dao->setSearch($settings['search']);
+        }
+        $dao->setFiltres($settings['filtres']);
+        $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user);
+
+        $btVoir = '<div></div><span>' . __('voir') . '</span>';
+        $btEdit = '<div></div><span>' . __('éditer') . '</span>';
+        $btStats = '<div></div><span>' . __('stats') . '</span>';
+        $btDownload = '<div></div><span>' . __('télécharger') . '</span>';
+        if ($droits->creation) {
+            $btDel = '<div></div><span>' . __('suppr.') . '</span>';
+        }
+
+
+        $res = '<table class="liste">';
+        $res .= '<tr><th>' . commonUrl::orderby('#', 'collection_id', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Nom de la collection'), 'nom', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Propriétaire'), 'proprietaire_nom', $settings, 'sort' . $change) . '</th>';
+        $res .= str_repeat('<th class="min"></th>', 4);
+        $res .= '</tr>';
+
+        $i = 0;
+        foreach ($liste as $collection) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr>';
+            $res .= '<td>' . $collection->collection_id . '</td>';
+            $res .= '<td>' . $collection->nom . '</td>';
+            if ($droits->revendeur) {
+                $p = str_replace(" (", '<br /><em>', html::escapeHTML($collection->proprietaire_nom));
+                $p = str_replace(')', '</em>', $p);
+                $res .= '<td><a href="#" class="popup" rel="formChangeCollectionProprietaire/' . $collection->collection_id . '" title="' . __('Modifier le proprietaire') . '">' . $p . '</a></td>';
+            } else {
+                $res .= '<td>' . html::escapeHTML($collection->proprietaire_utilisateur) . '</td>';
+            }
+
+            $res .= '<td class="bouton"><!--<a href="#" class="normallink voir btbook">' . $btVoir . '</a>--></td>';
+            $res .= '<td class="bouton"><a href="/collection/' . $collection->collection_id . '" class="normallink edit btbook">' . $btEdit . '</a></td>';
+            $res .= '<td class="bouton"><!--<a href="#" class="normallink download btbook">' . $btDownload . '</a>--></td>';
+            $res .= '<td class="bouton"><!--<a href="#" class="normallink suppr btbook">' . $btDel . '</a>--></td>';
+
+            $res .= '</tr>';
+
+            $i++;
+        }
+
+        if (!isset($settings['search']) || is_null($settings['search'])) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '><td colspan="7">';
+            $res .= commonPage::pager($settings['page'], $dao->count($core->user), $settings['par_page'], 'page' . $change . '/%d');
+            $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('collections'), false);
+            $res .= '</td></tr>';
+        }
+        $res .= '</table>';
+
+        return $res;
+    }
+
+    public static function getFluidbookVersions($select = false)
+    {
+        $droits = wsDroits::getDroits();
+
+        $chooseVersion = wsDroits::admin();
+
+        if ($chooseVersion) {
+            $default = ' - ' . __('Version par défaut');
+        } else {
+            $default = '';
+        }
+
+        $versions = array();
+        $versions['online'] = array('title' => __('Version online') . $default, 'icon' => cubeMedia::silk('page_world.png'));
+        $versions['scorm'] = array('title' => __('Version SCORM') . $default, 'icon' => cubeMedia::silk('page_world.png'));
+        if ($chooseVersion) {
+            $versions['v1'] = array('title' => __('Version online') . ' - V1', 'icon' => cubeMedia::silk('page_white_world.png'));
+            $versions['v2'] = array('title' => __('Version online') . ' - V2', 'icon' => cubeMedia::silk('page_white_world.png'));
+        }
+        $versions['win-exe'] = array('title' => __('Version offline') . ' - ' . __('Executable Windows') . ' (Flash)', 'icon' => cubeMedia::silk('application_view_tile.png'));
+        $versions['win-inss-html'] = array('title' => __('Version offline') . ' - ' . __('Executable Windows') . ' (HTML5)', 'icon' => cubeMedia::silk('application_view_tile.png'));
+        $versions['win-ins'] = array('title' => __('Version offline') . ' - ' . __('Installeur Auto-executable Windows') . ' (Flash)', 'icon' => cubeMedia::silk('application_view_tile.png'));
+        $versions['win-ins-html'] = array('title' => __('Version offline') . ' - ' . __('Installeur Auto-executable Windows') . ' (HTML5)', 'icon' => cubeMedia::silk('application_view_tile.png'));
+        $versions['mac-exe'] = array('title' => __('Version offline') . ' - ' . __('Exécutable Mac OS X') . ' (Flash)', 'icon' => cubeMedia::image(IMG . '/macos.png'));
+        $versions['mac-exe-html'] = array('title' => __('Version offline') . ' - ' . __('Exécutable Mac OS X') . ' (HTML)', 'icon' => cubeMedia::image(IMG . '/macos.png'));
+        $versions['win-cd'] = array('title' => __('Version offline') . ' - ' . __('CD-ROM') . ' / ' . __('Clé USB') . ' (Flash)', 'icon' => cubeMedia::silk('cd.png'));
+        $versions['win-cd-html'] = array('title' => __('Version offline') . ' - ' . __('CD-ROM') . ' / ' . __('Clé USB') . ' (HTML)', 'icon' => cubeMedia::silk('cd.png'));
+
+        $versions['win-html'] = array('title' => __('Version offline') . ' - ' . __('HTML') . ' (' . __('Non adaptée à l\'installation sur un serveur web') . ')', 'icon' => cubeMedia::silk('cd.png'));
+        if ($droits->admin) {
+            $versions['phonegap'] = array('title' => __('Version offline') . ' - ' . __('Application mobile'), 'icon' => cubeMedia::image(IMG . '/phonegap.png'));
+        }
+
+        if (!$select) {
+            return $versions;
+        }
+
+        $res = array();
+        foreach ($versions as $id => $d) {
+            $t = explode('-', $d['title'], 2);
+            $meta = trim($t[0]);
+            if (isset($t[1])) {
+                $title = trim($t[1]);
+            } else {
+                $title = $meta;
+            }
+
+            if (!isset($res[$meta])) {
+                $res[$meta] = array();
+            }
+            $res[$meta][$title] = $id;
+        }
+        return $res;
+    }
+
+    public static function contextBookDownload($id, $droits, $book = null)
+    {
+        global $core;
+
+        $versions = self::getFluidbookVersions();
+
+        if (null !== $book) {
+            $id .= '_' . $book->book_id;
+        }
+
+        $res = '<div class="contextMenu downbookContextMenu" id="' . $id . '">';
+        $res .= '<ul>';
+        $res .= '<li class="head">' . __("Sélectionnez une version") . '</li>';
+        foreach ($versions as $k => $v) {
+            $disabled = '';
+            if (null !== $book) {
+                if ($k == 'scorm' && !$book->parametres->scorm_enable) {
+                    continue;
+                }
+                $tk = 'download_' . $k;
+                if (!$book->parametres->{$tk} && $k !== 'scorm') {
+                    if ($core->user->rs == 'Kadreo' || $core->user->rs == 'STUDIOFRANCE') {
+                        $disabled = ' class="disabled"';
+                    } else {
+                        continue;
+                    }
+
+                }
+            }
+            $res .= '<li' . $disabled . '><a href="#" rel="downbook/$1/' . $k . '" class="ajax">' . $v['icon'] . $v['title'] . '</a></li>';
+        }
+        if ($droits->admin) {
+            $res .= '<li class="head">' . __("Installer sur ...") . '</li>';
+            $versions = array();
+            $versions['hosting'] = array('title' => __("Le serveur d'hébergement"), 'icon' => cubeMedia::silk('server_go.png'));
+            $versions['references'] = array('title' => __("L'espace références"), 'icon' => cubeMedia::silk('server_add.png'));
+            $versions['external'] = array('title' => __("Serveur FTP"), 'icon' => cubeMedia::silk('server_add.png'));
+            $versions['macbook_phonegap_ios'] = array('title' => __("Projet Phonegap IOS"), 'icon' => cubeMedia::image(IMG . '/ios.png'));
+            $versions['phonegap_android'] = array('title' => __("Projet Phonegap Android"), 'icon' => cubeMedia::image(IMG . '/android.png'));
+
+            foreach ($versions as $k => $v) {
+                $res .= '<li><a href="#" rel="instbook/$1/' . $k . '" class="ajax">' . $v['icon'] . $v['title'] . '</a></li>';
+            }
+        }
+        $res .= '</ul></div>';
+        return $res;
+    }
+
+    public static function contextBookStatus($id)
+    {
+        global $core;
+
+        if (wsDroits::admin()) {
+            $status = $core->books_status;
+            $status[2] = __('Facturé (associé à un projet)');
+        } else {
+            $status = array();
+            $status[-1] = $core->books_status[-1];
+            $status[0] = $core->books_status[0];
+        }
+
+        $res = '<div class="contextMenu statusbookContextMenu" id="' . $id . '">';
+        $res .= '<ul>';
+        $res .= '<li class="head">' . __("Changer le status de la publication") . '</li>';
+        foreach ($status as $s => $title) {
+            $res .= '<li><a href="#" rel="statusBook/$1/' . $s . '" class="ajax">' . $title . '</a></li>';
+        }
+        $res .= '</ul></div>';
+        return $res;
+    }
+
+    public static function contextBookView($id)
+    {
+        global $core;
+
+        $viewers = array(array('type' => 'flash', 'version' => 'viewer', 'title' => __('Version Flash'), 'icon' => cubeMedia::image(IMG . '/flash.png')),
+            array('type' => 'html5', 'version' => 'viewerh', 'title' => __('Version HTML5'), 'icon' => cubeMedia::image(IMG . '/html5.png')),
+            array('type' => 'scorm', 'version' => 'viewers', 'title' => __('Version SCORM'), 'icon' => cubeMedia::image(IMG . '/html5.png')),
+        );
+
+        $res = '<div class="contextMenu viewbookContextMenu" id="' . $id . '">';
+        $res .= '<ul>';
+        $res .= '<li class="head">' . __("Sélectionnez la version") . '</li>';
+        if (isset($viewers)) {
+            foreach ($viewers as $infos) {
+                if (!isset($infos['file'])) {
+                    $infos['file'] = '';
+                }
+                if (!isset($infos['pattern'])) {
+                    $infos['pattern'] = '$1_$2';
+                }
+                $res .= '<li data-type="' . $infos['type'] . '"><a target="_blank" href="' . SITE_PATH . $infos['version'] . '/' . $infos['pattern'] . '/' . $infos['file'] . '">' . $infos['icon'] . $infos['title'] . '</a></li>';
+            }
+        }
+        $res .= '</ul></div>';
+        return $res;
+    }
+
+    public static function traductions($args)
+    {
+        global $core;
+
+        commonDroits::min(5);
+
+        if (count($args) < 2) {
+            $args[1] = 'fr';
+        }
+
+        $allLangs = cubeLang::getCodes($core->user->lang);
+        $allLangs['es-pr'] = 'Espagnol, Porto Rico';
+        $existingLangs = array();
+
+        $dao = new wsDAOLang($core->con);
+        $langs = $dao->selectAll();
+        foreach ($langs as $lang) {
+            if (!isset($allLangs[$lang->lang_id])) {
+                continue;
+            }
+            $existingLangs[$lang->lang_id] = $allLangs[$lang->lang_id];
+
+            unset($allLangs[$lang->lang_id]);
+        }
+
+        $langs = array(__('Langues configurées') => array_flip($existingLangs), __('Autres langues') => array_flip($allLangs));
+
+        $res = commonPage::barre();
+        $res .= commonPage::tMain(null, false);
+
+        $res .= commonPage::bh();
+        $res .= '<form action="changeLang" method="post" class="submitonchange">';
+        $res .= '<table class="liste">';
+        $res .= '<tr><td class="center">' . __('Sélectionnez la langue à configurer') . ' : ' . form::combo('lang', $langs, $args[1]) . ' </td></tr>';
+        $res .= '</table>';
+        $res .= '</form>';
+        $res .= commonPage::bf();
+
+        $res .= '<div id="formLang">';
+        $res .= self::formLang($args[1]);
+        $res .= '</div>';
+        $res .= commonPage::bMain(true);
+
+        return $res;
+    }
+
+    public static function formLang($lang_id)
+    {
+        commonDroits::min(5);
+        global $core;
+        $dao = new wsDAOLang($core->con);
+        $lang = $dao->selectById($lang_id);
+
+        $res = commonPage::bh();
+        $res .= '<table class="liste">';
+        $res .= '<tr><td><a href="' . SITE_PATH . 'exportLangAsExcel/' . $lang_id . '">' . __('Exporter au format Excel') . '</a>';
+        $res .= ' | <a href="' . SITE_PATH . 'exportAllLangsAsExcel/' . $lang_id . '">' . __('Exporter toutes les langues au format Excel') . '</a>';
+        $res .= '</td></tr>';
+        $res .= '</table>';
+        $res .= commonPage::bf();
+
+        $res .= '<form action="saveLang" method="post">';
+
+        $res .= commonPage::bh();
+        $res .= '<table class="liste">';
+        $res .= '<tr><td>' . __('Police de caractères') . ' : </td><td>' . form::hidden('lang', $lang_id) . form::combo('font', self::getFonts(), $lang->font) . '</td></tr>';
+        $res .= '<tr class="odd"><td>' . __('Jeux de caractères') . ' : </td><td>' . form::combo('charset', self::getCharsets(), $lang->charset) . '</td></tr>';
+        $res .= '<tr><td>' . __("Langue de l'installeur") . ' : </td><td>' . form::combo('nsis', self::getNSISLangs(), $lang->nsis) . '</td></tr>';
+        $res .= '<tr><td colspan="2" class="right odd"><a href="#" class="submit">' . $core->typo->Ajouter('Valider') . '</a></td></tr>';
+        $res .= '</table>';
+        $res .= commonPage::bf();
+
+        $res .= commonPage::bh();
+        $res .= cubeLang::translationForm(self::getTranslationSources(), $lang_id, null, 'liste', array(), '<a href="#" class="submit">' . $core->typo->Ajouter(__('Enregistrer')) . '</a>', $lang->traductions);
+        $res .= commonPage::bf();
+        $res .= '</form>';
+        return $res;
+    }
+
+    public static function getTranslationSources()
+    {
+        return array(__('Version Flash') => PLAYER_SOURCES, __('Version HTML5') => WS_COMPILE_ASSETS . '/player/local', __('Compilateur HTML5') => ROOT . '/inc/ws/Util/html5', __('Application') => WS_COMPILE_ASSETS . '/_html5app');
+    }
+
+    public static function exportLangAsExcel($args)
+    {
+        global $core;
+
+        $lang_id = $args[1];
+
+        $xls = new PHPExcel();
+        $s = $xls->setActiveSheetIndex(0);
+
+        $lang_name = self::exportLangAsSheet($s, $lang_id, 'en');
+
+        $xls->setActiveSheetIndex(0);
+
+        ob_end_clean();
+        files::registerMimeTypes(array('xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'));
+        cubeHTTP::forceDownload('Fluidbook_' . $lang_name . '.xlsx', false);
+
+        $writer = new PHPExcel_Writer_Excel2007($xls);
+        $writer->save('php://output');
+
+        exit;
+    }
+
+    public static function exportAllLangsAsExcel($args)
+    {
+        global $core;
+
+        $xls = new PHPExcel();
+
+        $dao = new wsDAOLang($core->con);
+        $all = $dao->selectAll();
+
+        $i = 0;
+        foreach ($all as $l) {
+            try {
+                $s = $xls->getSheet($i);
+            } catch (Exception $e) {
+                $s = $xls->createSheet($i);
+            }
+            self::exportLangAsSheet($s, $l->lang_id, 'en');
+            $i++;
+        }
+
+        $xls->setActiveSheetIndex(0);
+
+        ob_end_clean();
+        files::registerMimeTypes(array('xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'));
+        cubeHTTP::forceDownload('Fluidbook_All_Languages.xlsx', false);
+
+        $writer = new PHPExcel_Writer_Excel2007($xls);
+        $writer->save('php://output');
+        exit;
+    }
+
+    public static function exportLangAsSheet($s, $lang_id, $ref_id = 'en')
+    {
+        global $core;
+        $dao = new wsDAOLang($core->con);
+
+
+        $lang = $dao->selectById($lang_id);
+        $ref = $dao->selectById($ref_id);
+
+        $lang_name = cubeLang::getNameByCode($lang_id, 'en');
+        $ref_name = cubeLang::getNameByCode($ref_id, 'en');
+
+        $s->setTitle(cubeText::str2URL($lang_name));
+
+        $sources = [];
+        $ts = self::getTranslationSources();
+        foreach ($ts as $item) {
+            $sources = array_merge($sources, $item);
+        }
+
+        $tab = cubeLang::getTranslationsList(self::getTranslationSources(), array('php', 'as', 'js'), array(), $lang->traductions);
+
+        $s->setCellValueByColumnAndRow(0, 1, 'ID', true);
+        $s->setCellValueByColumnAndRow(1, 1, $ref_name, true);
+        $s->setCellValueByColumnAndRow(2, 1, $lang_name, true);
+
+        $j = 2;
+        foreach ($tab as $msgid => $msgstr) {
+            $s->setCellValueByColumnAndRow(0, $j, $msgid);
+            $s->setCellValueByColumnAndRow(1, $j, $ref->traductions[$msgid]);
+            $s->setCellValueByColumnAndRow(2, $j, $msgstr);
+
+            if ($msgstr == '') {
+                $s->getStyleByColumnAndRow(2, $j)->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
+                $s->getStyleByColumnAndRow(2, $j)->getFill()->getStartColor()->setARGB('FFFFFF00');
+            }
+            $j++;
+        }
+
+        $s->getColumnDimensionByColumn(0)->setAutoSize(true);
+        $s->getColumnDimensionByColumn(1)->setAutoSize(true);
+        $s->getColumnDimensionByColumn(2)->setAutoSize(true);
+
+        return $lang_name;
+    }
+
+    public static function getFonts()
+    {
+        $formats = array('ttf', 'otf', 'TTF', 'OTF');
+
+        $dr = opendir(FONT_PATH);
+        $fonts = array('Arial (police système)' => "system");
+        while ($file = readdir($dr)) {
+            if ($file == '.' || $file == '..' || !in_array(files::getExtension($file), $formats)) {
+                continue;
+            }
+            $fonts[$file] = $file;
+        }
+        return $fonts;
+    }
+
+    protected static function getCharsets()
+    {
+        $sets = cubeFlexFontAsset::getSets();
+        $res = array();
+        foreach ($sets as $k => $v) {
+            $res[$k] = $k;
+        }
+        return $res;
+    }
+
+    protected static function getNSISLangs()
+    {
+        $res = array();
+        $dir = WS_FILES . '/nsislangs';
+        $dr = opendir($dir);
+        while ($file = readdir($dr)) {
+            if ($file == '.' || $file == '..') {
+                continue;
+            }
+            $e = explode('.', $file);
+            $res[$e[0]] = $e[0];
+        }
+
+        ksort($res);
+        return $res;
+    }
+
+    public static function editor($args)
+    {
+        commonDroits::min(1);
+
+        global $core;
+
+        $args = cubePage::getArgs($args);
+        $e = explode('_', $args[0]);
+        $book_id = $e[0];
+        $hash = isset($e[1]) ? $e[1] : '';
+
+
+        self::checkDocumentVersionOfBook($book_id);
+
+        if ($book_id == 'new') {
+            $dao = new wsDAOBook($core->con);
+            $book = $dao->creeEmpty($core->user->utilisateur_id, $core->user->lang);
+            http::redirect(SITE_PATH . 'editor/' . $book->book_id . '_' . $book->hash);
+        }
+
+        $res = '<html><head><style type="text/css">';
+        $res .= '#composerSwf{width:100%;height:100%;margin:0 auto;}
 body{margin:0;padding:0;height:100%;overflow:hidden;background:#d2d3c7;}
 html{height:100%}' . "\n";
-               $res .= '</style>';
-               $res .= '<title>' . __('Edition de la publication') . ' #' . $args[0] . '</title>';
-               $res .= '</head>';
-               $res .= '<body onload="this.focus();">';
-               $res .= self::editComposition($book_id, $hash);
-               $res .= '</body>';
-               $res .= '</html>';
-               echo $res;
-       }
-
-       /**
-        * wsUrl::restoreLinks()
-        *
-        * @param mixed $args
-        * @return
-        */
-       public static function restoreLinks($args)
-       {
-               commonDroits::min(1);
-
-               global $core;
-
-               $args = cubePage::getArgs($args);
-               $book_id = $args[0];
-
-
-               $dao = new wsDAODocument($core->con);
-               $updates = $dao->getLinksVersions($book_id);
-               krsort($updates);
-
-               $res = '<html><head>';
-               $res .= '<title>' . __('Restauration des liens de la publication') . ' #' . $args[0] . '</title>';
-               $res .= '</head>';
-               $res .= '<body onload="this.focus();">';
-               $res .= '<div id="restoreLinks">';
-               $res .= '<div>';
-               $res .= '<h2>' . __('Import') . '</h2>';
-               $res .= '<div class="center">';
-               $res .= '<form action="importLinksAsExcel/' . $book_id . '" method="post" enctype="multipart/form-data" class="notajax" id="importLinksAsExcel">';
-               $res .= __("Importer des liens à partir d'un fichier Excel") . ' : <input type="file" name="file" accept="*.xlsx" />';
-               $res .= '<input type="submit" value="' . __('Importer') . '" />';
-               $res .= '</form>';
-               $res .= '</div>';
-               $res .= '</div>';
-               $res .= '<hr />';
-
-               $res .= '<div id="linksOffset">';
-               $res .= '<h2>' . __('Décalage de pages') . '</h2>';
-               $res .= '<form action="offsetLinks/' . $book_id . '" method="post" id="offsetLinks">';
-               $offset = form::field('offset', 3, 5);
-               $from = form::field('from', 3, 5);
-               $res .= sprintf(__('Décaler les liens de %s pages à partir de la page %s'), $offset, $from) . '<br />';
-               $res .= '<label>' . form::checkbox('internal', 1, true) . ' ' . __('Appliquer le décalages sur les numéros de pages dans les liens internes') . '</label><br />';
-               $res .= '<input type="submit" value="' . __('Procéder au décalage') . '" />';
-               $res .= '</form>';
-               $res .= '</div>';
-               $res .= '<hr />';
-
-               $res .= '<h2>' . __('Réimporter les liens du fichier PDF') . '</h2>';
-               $res .= '<a class="restoreLink" rel="' . $book_id . '/pdf" href="#">Restaurer</a>';
-               $res .= '<hr />';
-
-               $res .= '<h2>' . __('Historique') . '</h2>';
-               $res .= '<table class="liste" style="width:100%;min-width:0;">';
-               $res .= '<tr>';
-               $res .= '<th>' . __('Date') . '</th>';
-               $res .= '<th class="center">' . __('Liens') . '</th>';
-               $res .= '<th class="center">' . __('Règles') . '</th>';
-               $res .= '<th class="center">' . __('Utilisateur') . '</th>';
-               $res .= '<th class="center">' . __('Informations') . '</th>';
-               $res .= '<th class="min"></th>';
-               $res .= '<th class="min"></th>';
-               $res .= '</tr>';
-               $i = 0;
-               foreach ($updates as $time => $infos) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '>';
-                       $res .= '<td>' . date('Y-m-d H:i:s', $time) . '</td>';
-                       $res .= '<td class="center">' . $infos['links'] . '</td>';
-                       $res .= '<td class="center">' . $infos['rulers'] . '</td>';
-                       $res .= '<td class="center">' . $infos['user'] . '</td>';
-                       $res .= '<td class="center">' . $infos['comments'] . '</td>';
-                       $res .= '<td><a href="#" rel="' . $book_id . '/' . $time . '" class="restoreLink">' . __('Restaurer') . '</a></td>';
-                       $res .= '<td><a href="' . SITE_PATH . 'exportLinksAsExcel/' . $book_id . '/' . $time . '">' . str_replace(' ', '&nbsp;', __('Export Excel')) . '</a></td>';
-                       $res .= '</tr>';
-                       $i++;
-               }
-
-               $res .= '</table>';
-               $res .= '</div>';
-               $res .= '</body>';
-               $res .= '</html>';
-
-               echo $res;
-       }
-
-       public static function exportLinksAsExcel($args)
-       {
-               global $core;
-
-               cubePHP::neverStop();
-
-               $book_id = $args[1];
-               $time = $args[2];
-
-               $dao = new wsDAODocument($core->con);
-               $dao->getLinksAndRulers($book_id, $links, $rulers, $time);
-               $xls = $dao->getLinksAsExcel($links, $rulers);
-
-               ob_end_clean();
-               files::registerMimeTypes(array('xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'));
-               cubeHTTP::forceDownload('links_' . $book_id . '_' . $time . '.xlsx', false);
-
-               $writer = new PHPExcel_Writer_Excel2007($xls);
-               $writer->save('php://output');
-
-               exit;
-       }
-
-       public static function editComposition($book_id, $hash)
-       {
-
-               $fv = array(session_name() => session_id(),
-                       'book_id' => $book_id,
-                       'hash' => $hash,
-                       'url' => '/');
-
-               $mtime = filemtime(ROOT . '/swf/composer.swf');
-               return cubeMedia::flash2(WEBROOT . '/swf/composer.swf?junk=' . $mtime, '100%', '100%', $fv, 'composerSwf', 'swfPanel', 10, '#d2d3c7', '', 'false', 'noscale', 'normal', array(), false, true, false);
-       }
-
-       public static function stats($args)
-       {
-               global $core;
-               $bid = (isset($args[1])) ? $args[1] : null;
-
-               list($bid, $hash) = explode('_', $bid);
-
-               $r = $core->con->select('SELECT * FROM books WHERE book_id=\'' . $core->con->escape($bid) . '\' AND hash=\'' . $core->con->escape($hash) . '\'');
-               if (!$r->count()) {
-                       return;
-               }
-
-               $annee = (isset($args[2])) ? $args[2] : null;
-               $mois = (isset($args[3])) ? $args[3] : null;
-               return wsStats::display($bid . '_' . $hash, $annee, $mois);
-       }
-
-       public static function viewerh($args)
-       {
-               global $core;
-
-               $args = cubePage::getArgs($args);
-
-               $e = explode('_', $args[0]);
-
-               $book_id = $e[0];
-               $hash = $e[1];
-
-               $dao = new wsDAOBook($core->con);
-
-               $book = $dao->selectById($book_id);
-               if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
-                       commonDroits::error();
-               }
-
-               if (!wsDroits::admin()) {
-                       if ($book->parametres->redirectDemo != '') {
-                               http::redirect($book->parametres->redirectDemo);
-                               exit;
-                       }
-                       if ($book->parametres->disableDemo) {
-                               commonDroits::error();
-                       }
-               }
-
-               $time = TIME;
-               if (count($e) == 2) {
-                       $e[2] = $time;
-                       http::redirect(SITE_PATH . 'viewerh/' . implode('_', $e) . '/');
-                       exit;
-               }
-
-               $dao->compile($book_id, 'html5', false, false, false, null, false);
-
-               $book_id = $e[0];
-               $hash = $e[1];
-               self::commonHTML5Viewer($book_id, $hash);
-       }
-
-
-       public static function viewers($args)
-       {
-               global $core;
-
-               $args = cubePage::getArgs($args);
-
-               $e = explode('_', $args[0]);
-
-               $book_id = $e[0];
-               $hash = $e[1];
-
-               $dao = new wsDAOBook($core->con);
-
-               $book = $dao->selectById($book_id);
-               if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
-                       commonDroits::error();
-               }
-
-               if (!wsDroits::admin()) {
-                       if ($book->parametres->redirectDemo != '') {
-                               http::redirect($book->parametres->redirectDemo);
-                               exit;
-                       }
-                       if ($book->parametres->disableDemo) {
-                               commonDroits::error();
-                       }
-               }
-
-               $dao->compile($book_id, 'html5');
-               $time = TIME;
-
-               if (count($e) == 2 || $e[2] <= $time - 10) {
-                       $e[2] = $time;
-                       http::redirect(SITE_PATH . 'viewers/' . implode('_', $e) . '/');
-                       exit;
-               }
-
-               $book_id = $e[0];
-               $hash = $e[1];
-               self::commonHTML5Viewer($book_id, $hash, '', ['<head>' => '<head><script type="text/javascript">var FORCE_SCORM=true;</script>']);
-       }
-
-       public static function commonHTML5Viewer($book_id, $hash, $version = '', $replace = [])
-       {
-               global $core;
-               self::checkDocumentVersionOfBook($book_id);
-
-               $dao = new wsDAOBook($core->con);
-               $dir = '';
-
-               $book = $dao->selectById($book_id);
-               if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
-                       commonDroits::error();
-               }
-
-               if (!wsDroits::admin()) {
-                       if ($book->parametres->redirectDemo != '') {
-                               http::redirect($book->parametres->redirectDemo);
-                               exit;
-                       }
-                       if ($book->parametres->disableDemo) {
-                               commonDroits::error();
-                       }
-               }
-
-               self::logReferer($book_id);
-               $html = file_get_contents(WS_BOOKS . '/html5' . $dir . '/' . $book_id . '/index' . $version . '.html');
-               foreach ($replace as $from => $to) {
-                       $html = str_replace($from, $to, $html);
-               }
-               echo $html;
-               exit;
-       }
-
-       public static function viewer($args)
-       {
-               $args = cubePage::getArgs($args);
-
-               $qs = '';
-               if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) {
-                       $qs = '?' . $_SERVER['QUERY_STRING'];
-               }
-
-               $e = explode('_', $args[0]);
-               $newurl = null;
-               if (count($e) == 2 || $e[2] < TIME - 10) {
-                       $e[2] = TIME;
-                       http::redirect(SITE_PATH . 'viewer/' . implode('_', $e) . '/' . $qs);
-                       exit;
-               }
-
-               $book_id = $e[0];
-
-               $wmode = (isset($wmode) && $wmode != '') ? $wmode : 'default';
-
-               self::checkDocumentVersionOfBook($book_id);
-               wsSecureSWF::checkProtectedSWF();
-
-               echo self::commonViewer($book_id, $e[1], false, $wmode, $newurl);
-       }
-
-       public static function commonViewer($book_id, $hash, $standalone = false, $wmode = 'default', $fps = false, $version = 2)
-       {
-               if (!defined('MINIMIZE_JS')) {
-                       define('MINIMIZE_JS', false);
-               }
-               if (!defined('MINIMIZE_CSS')) {
-                       define('MINIMIZE_CSS', false);
-               }
-               if (!defined('JQUERY')) {
-                       define('JQUERY', false);
-               }
-
-               global $core;
-               global $css;
-               global $js;
-               global $standard;
-               global $meta;
-               global $jsvar;
-
-               if ($version == 2) {
-                       $flashVersion = '10.0.22';
-               } else {
-                       $flashVersion = '8';
-               }
-
-               cubePage::swfobject(2);
-
-               $dao = new wsDAOBook($core->con);
-               $book = $dao->selectById($book_id);
-
-               if (!wsDroits::admin()) {
-                       if ($book->parametres->redirectDemo != '') {
-                               http::redirect($book->parametres->redirectDemo);
-                               exit;
-                       }
-                       if ($book->parametres->disableDemo) {
-                               commonDroits::error();
-                       }
-               }
-
-               if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
-                       commonDroits::error();
-               }
-
-
-               if (is_null($core->user)) {
-                       $dao->addDemoCount($book_id);
-               }
-
-               $dao->compile($book_id, (string)$version);
-
-               $daoTheme = new wsDAOTheme($core->con);
-               $theme = $daoTheme->selectById($book->theme, 'themes');
-
-               $webcompile = WEBROOT . '/fluidbook/compile/';
-
-               $standard = 'XHTML 1.0 Transitional';
-               $css = $js = array();
-               $css[] = $webcompile . 'style.css';
-               $fv = $_GET;
-               if ($standalone) {
-                       $fv['base'] = $_SERVER['REQUEST_URI'];
-               }
-               if ($fps) {
-                       $fv['monitoring'] = '1';
-               }
-
-               if ($version == 1) {
-                       $fv['id'] = $book_id;
-                       $fv['mail'] = '0';
-                       $fv['onlineFlag'] = '1';
-                       $fv['loaderColor'] = $theme->parametres->loadingBackColor;
-               }
-
-               $res = '<html>';
-               $res .= '<head>';
-               $res .= '<title>' . $book->parametres->title . '</title>';
-               $res .= '<meta name="google" value="notranslate">';
-               $res .= '<style type="text/css" media="print">*{ visibility: hidden; display: none }</style>';
-               // Entêtes Facebook
-               $meta['og:title'] = ($book->parametres->facebook_title == '') ? $book->parametres->title : $book->parametres->facebook_title;
-               if ($book->parametres->facebook_description != '') {
-                       $meta['og:description'] = $book->parametres->facebook_description;
-               }
-               $meta['og:image'] = 'https://workshop.fluidbook.com/services/facebook_thumbnail?id=' . $book->book_id . '&j=' . TIME;
-
-
-               $redirectPDF = 'window.location="data/document.pdf"';
-
-               if ($book->parametres->mobileVersion == 'pdf') {
-                       $redirectMobile = $redirectPDF;
-               } else {
-                       $redirectMobile = 'window.location="/viewerh/' . $book_id . '_' . $hash . '_' . TIME . '/";';
-               }
-
-               $alt = '<div style="width:734px;margin:100px auto;"><a href="http://get.adobe.com/flashplayer/" target="_blank">' . cubeMedia::image($webcompile . 'getflash.gif', 734, 409, '') . '</a></div>';
-
-               $res .= '</head>';
-               $res .= '<body style="background-color:#' . $theme->parametres->loadingBackColor . '" onload="this.focus();">';
-               $res .= '<div id="fluidbook"><div style="width:734px;margin:100px auto;"><a href="http://get.adobe.com/flashplayer/" target="_blank"></a></div></div>';
-               $res .= "\n" . '<script type="text/javascript">' . "\n";
-               $res .= 'if(isMobile()){' . "\n";
-               $res .= "\t" . $redirectMobile . "\n";
-               $res .= '} else if(isBadMobile()) {' . "\n";
-               $res .= "\t" . $redirectPDF . "\n";
-               $res .= '} else {' . "\n";
-               $res .= "\t" . 'swfobject.embedSWF("index.swf", "fluidbook", "100%", "100%", "' . $flashVersion . '",';
-               $res .= '"", ' . json_encode($fv) . ',';
-               $res .= '{"allowScriptAccess":"always","quality":"high","scale":"noscale","wmode":getWmode(),"allowFullScreen":"true","allowFullScreenInteractive":"true"},{"bgcolor":"#' . $theme->parametres->loadingBackColor . '"}';
-               $res .= ');' . "\n";
-               $res .= '}' . "\n";
-               $res .= '</script>';
-               $js = array('fluidbook.js');
-               $jsvar = array();
-
-               $gacodes = array(GA);
-               if ($book->parametres->googleAnalytics != '') {
-                       $gacodes[] = $book->parametres->googleAnalytics;
-               }
-               $res .= cubePage::googleAnalytics($gacodes, false);
-               $res .= '</body>';
-               $res .= '</html>';
-
-               self::logReferer($book_id);
-
-               return $res;
-       }
-
-       public static function logReferer($id)
-       {
-
-               if (!isset($_SERVER['HTTP_REFERER']) || !$_SERVER['HTTP_REFERER']) {
-                       $r = '';
-               } else {
-                       $r = $_SERVER['HTTP_REFERER'];
-               }
-
-               fb($r, $id);
-
-               global $core;
-               $rr = $core->con->select('SELECT * FROM books_referer WHERE book_id=\'' . $core->con->escape($id) . '\' AND referer=\'' . $core->con->escape($r) . '\'');
-               $c = $core->con->openCursor('books_referer');
-               if (!$rr->count()) {
-                       $c->book_id = $id;
-                       $c->referer = $r;
-                       $c->count = 1;
-                       $c->insert();
-               } else {
-                       $rr->fetch();
-                       $c->count = $rr->count + 1;
-                       $c->update('WHERE book_id=\'' . $core->con->escape($id) . '\' AND referer=\'' . $core->con->escape($r) . '\'');
-               }
-       }
-
-       public static function statsxls($args)
-       {
-               $bid = (isset($args[1])) ? $args[1] : null;
-               $annee = (isset($args[2])) ? $args[2] : null;
-               $mois = (isset($args[3])) ? $args[3] : null;
-               wsStats::exportXLS($bid, $annee, $mois);
-       }
-
-       public static function chooseExistingBook()
-       {
-               wsDroits::creation(true);
-               $res = '<tr><td colspan="2"><p style="width:600px;text-align:justify;"><em>a' . __("Si votre nouvelle publication a des paramètres en commun avec une publication existante, veuillez rechercher cette publication afin d'attribuer par défaut à votre nouvelle publication les paramètres de l'existante") . '</em></p></td></tr>';
-               $res .= '<tr><td>' . __('Rechercher une publication') . ' : </td><td>' . form::field('book_nom', 64, 1024) . form::hidden('book', '') . '</td></tr>';
-               $res .= '<tr><td>' . __('Indiquez le titre de votre nouvelle publication') . '</td><td>' . form::field('title', 64, 1024) . '</td></tr>';
-               $res .= '<tr><td colspan="2"><label>' . form::checkbox('settings', '1', true, '', '', true, '') . __('Importer les paramètres de la publication') . '</td></tr>';
-               $res .= '<tr><td colspan="2"><label>' . form::checkbox('pages', '1', false) . __('Importer les pages et les liens') . '</td></tr>';
-               return $res;
-       }
-
-       public static function changeBookProprietaire($book_id)
-       {
-               global $core;
-               commonDroits::min(3);
-
-               $dao = new wsDAOBook($core->con);
-               $book = $dao->selectById($book_id);
-
-               return self::_changeProprietaire($book->proprietaire);
-       }
-
-       public static function changeCollectionProprietaire($collection_id)
-       {
-               global $core;
-               commonDroits::min(3);
-
-               $dao = new wsDAOCollection($core->con);
-               $collection = $dao->selectById($collection_id);
-
-               return self::_changeProprietaire($collection->proprietaire_nom);
-       }
-
-       protected static function _changeProprietaire($proprietaire)
-       {
-               $res = '<tr><td>' . __('Propriétaire actuel') . ' : </td><td>' . $proprietaire . '</td></tr>';
-               $res .= '<tr><td>' . __('Rechercher un utilisateur') . ' : </td><td>' . form::field('book_proprietaire', 64, 1024) . form::hidden('proprietaire', '') . '</td></tr>';
-               return $res;
-       }
-
-       public static function chooseBookProject($book_id)
-       {
-               global $core;
-
-               wsDroits::admin(true);
-
-               $dao = new wsDAOBook($core->con);
-               $book = $dao->selectById($book_id);
-
-               $projects = array("--" => '0');
-
-               $proprietaire = 'SELECT facturable_id FROM ws_users_tree WHERE utilisateur_id=\'' . $core->con->escape($book->proprietaire_id) . '\'';
-               $entreprise = 'SELECT entreprise FROM utilisateurs WHERE utilisateur_id IN (' . $proprietaire . ')';
-               $collegues = 'SELECT utilisateur_id FROM utilisateurs WHERE entreprise IN(' . $entreprise . ')';
-
-               $r = $core->con->select('SELECT * FROM projets WHERE client IN(' . $collegues . ') ORDER BY projet_id DESC');
-               while ($r->fetch()) {
-                       $projects[$r->projet_id . ' - ' . $r->nom] = $r->projet_id;
-               }
-
-               $res = '<tr><td>' . __('Choisir un projet') . ' : </td><td>' . form::hidden('book_id', $book_id) . form::combo('book_project', $projects, $book->projet, 'hide_new_value') . '</td></tr>';
-               $res .= '<tr class="new"><td>' . __('ou créer un nouveau projet') . ' : </td><td>' . form::field('new_book_project_nom', 64, 1024, $book->nom) . '</td></tr>';
-               return $res;
-       }
-
-       public static function chooseBookTache($book_id, $projet_id)
-       {
-               global $core;
-               wsDroits::admin(true);
-
-               $dao = new wsDAOBook($core->con);
-               $book = $dao->selectById($book_id);
-
-               $taches = array("--" => '0');
-               $r = $core->con->select('SELECT * FROM taches WHERE projet=\'' . $core->con->escape($projet_id) . '\' AND categorie=8');
-               while ($r->fetch()) {
-                       $taches[$r->nom] = $r->tache_id;
-               }
-
-               $res = '';
-
-               if ($r->count() > 0) {
-                       $res .= '<tr><td>' . __('Choisir une tâche') . ' : </td><td>' . form::hidden('book_id', $book_id) . form::hidden('projet_id', $projet_id) . form::combo('tache', $taches, '0', 'hide_new_value') . '</td></tr>';
-                       $res .= '<tr class="new"><td>' . __('ou créer une nouvelle tâche') . ' : </td><td>' . form::field('nom', 32, 1024, 'Fluidbook #' . $book->book_id . ' : ' . $book->nom) . ' ' . __('ayant le budget suivant') . ' ' . form::field('budget', 6, 6) . '</td></tr>';
-               } else {
-                       $res .= '<tr><td>' . __('Créer une tâche') . ' : </td><td>'
-                               . form::hidden('book_id', $book_id)
-                               . form::hidden('projet_id', $projet_id)
-                               . form::hidden('tache', '0')
-                               . form::field('nom', 32, 1024, 'Fluidbook #' . $book->book_id . ' : ' . $book->nom)
-                               . ' ' . __('ayant le budget suivant')
-                               . ' ' . form::field('budget', 6, 6) . '</td></tr>';
-               }
-
-               return $res;
-       }
-
-       public static function valideDownload()
-       {
-               global $core;
-
-               $res = '<tr><td>' . __("Le téléchargement du fluidbook implique qu'il a été testé et définitivement validé.") . '<br />' . __("Si vous le téléchargez, il vous sera facturé selon les conditions stipulées dans votre contrat.") . '</td></tr>';
-               $res .= '<tr><td class="right"><label>' . __("Oui, ce fluidbook est validé, je souhaite le télécharger et il me sera facturé.") . ' ' . form::checkbox('valide', 1, false) . '</label></td></tr>';
-
-               return $res;
-       }
-
-       public static function formInstall($book, $server)
-       {
-               if ($server == 'references') {
-                       $s = __('Espace des références');
-                       $dir = $book->dir_references;
-               } elseif ($server == 'hosting') {
-                       $s = __("Serveur d'hébergement");
-                       $dir = $book->dir_hosting;
-               } elseif ($server == 'macbook_phonegap_ios') {
-                       $s = __("Projet Phonegap iOS");
-                       $dir = $book->dir_macbook_phonegap_ios;
-               } elseif ($server == 'phonegap_android') {
-                       $s = __("Projet Phonegap Android");
-                       $dir = $book->dir_phonegap_android;
-               } elseif ($server == 'external') {
-                       $s = __('Serveur FTP externe') . ' : ftp://';
-                       $dir = $book->dir_external;
-               }
-
-               if ($dir == '') {
-                       $dir = cubeText::str2URL($book->parametres->title);
-               }
-
-               $res = '<tr><td>' . __("Dossier d'installation") . '</td><td><em>' . $s . '</em> ' . form::field('dir', 60, 128, $dir) . '</td></tr>';
-               $res .= '<tr><td colspan="2">' . __("A l'issue de l'installation, vous serez dirigé vers le serveur sur lequel la publication a été installée") . '</td></tr>';
-               return $res;
-       }
-
-       public static function testAS($args)
-       {
-               global $core;
-               commonDroits::min(5);
-               if (!isset($args[1])) {
-                       $args[1] = 2964;
-               }
-               self::checkDocumentVersionOfBook($args[1]);
-               wsSecureSWF::checkProtectedSWF();
-               cubePHP::neverStop();
-               $dao = new wsDAOBook($core->con);
-
-               header('Content-type: text/plain');
-               ob_end_clean();
-               echo $dao->compile($args[1], 3, false, true);
-               exit;
-       }
-
-       public static function testAIR($args)
-       {
-               global $core;
-               commonDroits::min(5);
-               if (!isset($args[1])) {
-                       $args[1] = 2964;
-               }
-               self::checkDocumentVersionOfBook($args[1]);
-               cubePHP::neverStop();
-               $dao = new wsDAOBook($core->con);
-
-               header('Content-type: text/plain');
-               ob_end_clean();
-               echo $dao->compileAIR($args[1]);
-               exit;
-       }
-
-       public static function testLinksCSV($args)
-       {
-               global $core;
-               commonDroits::min(5);
-
-               $dao = new wsDAODocument($core->con);
-               header('Content-type: text/plain');
-               ob_clean();
-               echo $dao->putLinksFromCSV($args[1]);
-       }
-
-       protected static function checkDocumentVersionOfBook($book_id)
-       {
-               global $core;
-               cubePHP::neverStop();
-               $daoBook = new wsDAOBook($core->con);
-
-
-               $toUpdate = $daoBook->getDocumentsToUpdate($book_id);
-               foreach ($toUpdate as $document_id) {
-                       self::updateDocument($document_id);
-               }
-
-               if (count($toUpdate) > 0) {
-                       $daoBook->setChaptersFromOldFluidbook($book_id);
-                       $daoDoc = new wsDAODocument($core->con);
-                       $daoDoc->setLinksFromOldFluidbook($book_id);
-               }
-
-               $daoBook->setVersion($book_id, 2);
-       }
-
-       public static function testOldLink($args)
-       {
-               global $core;
-               $daoDoc = new wsDAODocument($core->con);
-               $daoDoc->setLinksFromOldFluidbook($args[1]);
-       }
-
-       protected static function updateDocument($document_id)
-       {
-               global $core;
-
-               $dao = new wsDAODocument($core->con);
-               $doc = $dao->selectById($document_id);
-
-               $doc->copyOriginalFromOlderVersion();
-               $doc->globalOperations();
-
-               for ($i = 1; $i <= $doc->generalInfos['pages']; $i++) {
-                       $doc->processOnePage($i);
-               }
-
-               $doc->version = 2;
-               $dao->updateFromObject($doc);
-       }
-
-       public static function testFontExtraction($args)
-       {
-               $documentId = $args[1];
-
-               header('Content-type: text/plain');
-               ob_clean();
-
-
-               $extractor = new wsPDFFontExtractor(WS_DOCS . '/' . $documentId);
-               $extractor->extract();
-
-               exit;
-       }
-
-       public static function getParamsHelp($args)
-       {
-               commonDroits::min(5);
-               global $core;
-
-               $res = '';
-
-               if (isset($args[1]) && $args[1] != '') {
-                       $dao = new wsDAOBook($core->con);
-                       $b = $dao->selectById($args[1]);
-
-                       $daoTheme = new wsDAOTheme($core->con);
-                       $t = $daoTheme->getThemeOfBook($args[1], true);
-
-                       $book = $b->parametres;
-                       $theme = $t->parametres;
-               } else {
-                       $theme = new wsThemeParametres(new wsTheme());
-                       $book = new wsBookParametres(new wsBook());
-               }
-
-               $res = commonPage::barre();
-               $res .= commonPage::tMain();
-               $res .= commonPage::bh();
-               $res .= '<table class="liste">';
-               $res .= self::formatHelp($theme->getHelp());
-               $res .= '</table>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bh();
-               $res .= '<table class="liste">';
-               $res .= self::formatHelp($book->getHelp());
-               $res .= '</table>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-
-               return $res;
-       }
-
-       public static function formatHelp($rubriques)
-       {
-               commonDroits::min(5);
-
-               $res = '';
-               foreach ($rubriques as $label => $fields) {
-                       $res .= '<tr class="odd"><th colspan="5">' . $label . '</th></tr>';
-                       foreach ($fields as $name => $t) {
-                               if (is_string($t) && $t == '|') {
-                                       $res .= '<tr class="odd"><th></th></tr>';
-                               } else {
-                                       $res .= '<tr>';
-                                       foreach ($t as $tt) {
-                                               $res .= '<td>' . $tt . '</td>';
-                                       }
-                                       $res .= '</tr>';
-                               }
-                       }
-               }
-               return $res;
-       }
-
-       public static function clients($args)
-       {
-               global $core;
-               cubePage::truePopup();
-               cubePage::autoComplete();
-               cubePage::emptyfield();
-               commonDroits::min(3);
-               $settings = $core->user->getSettings('clients_ws');
-
-               $shortcuts = array();
-               $shortcuts[] = '<a href="#" class="popup" rel="formClient/new">' . $core->typo->Ajouter('Créer un nouveau client') . '</a>';
-
-               $filtres = array();
-               if (wsDroits::admin()) {
-                       $filtres[] = new commonFiltre(__('Grade'), 'ws_grade', $settings['filtres']);
-                       $filtres[] = new commonFiltre(__('Administrateur'), 'admin_client', $settings['filtres']);
-               }
-
-               $res = commonPage::barre($filtres, 'filtreClients', 'clients', $shortcuts);
-               $res .= commonPage::tMain();
-               $res .= commonPage::bh();
-               $res .= '<div id="listeClients">';
-               $res .= self::listeClients();
-               $res .= '</div>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-               return $res;
-       }
-
-       public static function listeClients($dashboard = null, $settings = null)
-       {
-               global $core;
-               commonDroits::min(3);
-               $settings = is_null($settings) ? $core->user->getSettings('clients_ws') : $settings;
-               $change = is_null($dashboard) ? 'Client' : 'Dashboard/' . $dashboard;
-
-               $dao = new commonDAOEntreprise($core->con);
-               if (isset($settings['search']) && !is_null($settings['search'])) {
-                       $dao->setSearch($settings['search']);
-               }
-               $dao->setFiltres($settings['filtres']);
-
-               $admin = wsDroits::admin();
-
-               if ($admin) {
-                       $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], null, 'entreprises_ws');
-               } else {
-                       $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user, 'entreprises_ws');
-               }
-
-               $res = '<table class="liste">';
-               $res .= '<tr><th>' . commonUrl::orderby('#', 'entreprise_id', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Raison sociale'), 'nom', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . __('Contacts') . '</th>';
-               if ($admin) {
-                       $res .= '<th>' . commonUrl::orderby(__('Grade'), 'ws_grade', $settings, 'sort', $change) . '</th>';
-                       $res .= '<th>' . commonUrl::orderby(__('Revendeur'), 'revendeur', $settings, 'sort', $change) . '</th>';
-                       $res .= '<th>' . commonUrl::orderby(__('Administrateur'), 'administrateur', $settings, 'sort', $change) . '</th>';
-               }
-               $res .= '<th class="min"></th><th class="min"></th></tr>';
-               $i = 0;
-               foreach ($liste as $id => $client) {
-                       if (!is_array($client->contacts)) {
-                               $client->contacts = array();
-                       }
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '>';
-                       $res .= '<td>' . $client->entreprise_id . '</td>';
-                       $res .= '<td>' . $client->nom . '</td>';
-                       $contacts = array();
-
-                       foreach ($client->contacts as $c) {
-                               $contacts[] = '<a href="#" class="popup" rel="formContact/' . $c->utilisateur_id . '">' . $c->prenom . ' ' . $c->nom . '</a>';
-                       }
-
-                       $res .= '<td id="contacts_' . $client->entreprise_id . '">' . implode(', ', $contacts) . '</td>';
-
-                       if ($admin) {
-                               $rev = $client->ws_revendeur == '' ? '-' : $client->ws_revendeur;
-                               $adm = $client->ws_administrateur == '' ? '-' : $client->ws_administrateur;
-
-                               if ($client->ws_grade == 0) {
-                                       $rev = $adm = '-';
-                               }
-
-                               $res .= '<td>' . $core->ws_grades[$client->ws_grade] . '</td>';
-                               $res .= '<td>' . $rev . '</td>';
-                               $res .= '<td>' . $adm . '</td>';
-                       }
-
-                       $res .= '<td class="nowrap">';
-                       $res .= '</td>';
-                       $res .= '<td class="action"><a href="#" class="popup" rel="formClient/' . $client->entreprise_id . '">' . cubeMedia::image(IMG . '/edit.png') . '</a></td>';
-                       $res .= '</tr>';
-                       $i++;
-               }
-               if (!isset($settings['search']) || is_null($settings['search'])) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '><td colspan="10">';
-                       if ($admin) {
-                               $res .= commonPage::pager($settings['page'], $dao->count(null, 'entreprises_ws'), $settings['par_page'], 'page' . $change . '/%d');
-                       } else {
-                               $res .= commonPage::pager($settings['page'], $dao->count($core->user, 'entreprises_ws'), $settings['par_page'], 'page' . $change . '/%d');
-                       }
-                       $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('clients'));
-                       $res .= '</td></tr>';
-               }
-               $res .= '</table>';
-               return $res;
-       }
-
-       public static function formClient($entreprise_id = 'new')
-       {
-               global $core;
-               commonDroits::min(3);
-               $dao = new commonDAOEntreprise($core->con);
-               $daoUtilisateur = new commonDAOUtilisateur($core->con);
-               if ($entreprise_id == 'new') {
-                       $client = $dao->cree();
-               } else {
-                       $client = $dao->selectById($entreprise_id);
-               }
-
-               $res = '<tr><td>' . __('Numéro de client') . '</td><td>' . form::hidden('entreprise_id', $client->entreprise_id) . '' . $client->entreprise_id . '</td></tr>';
-               $res .= '<tr><td>' . __('Raison sociale') . '</td><td>' . form::field('nom', 30, 128, $client->nom) . '</td></tr>';
-               $res .= '<tr><td>' . __('Adresse') . '</td><td>' . form::textarea('adresse', 40, 3, $client->adresse) . '</td></tr>';
-               $res .= '<tr><td>' . __('Code postal') . '</td><td>' . form::field('code_postal', 10, 20, $client->code_postal) . '</td></tr>';
-               $res .= '<tr><td>' . __('Ville') . '</td><td>' . form::field('ville', 30, 128, $client->ville) . '</td></tr>';
-               $res .= '<tr><td>' . __('Pays') . '</td><td>' . form::combo('pays', cubeCountry::getList(), $client->pays) . '</td></tr>';
-               $res .= '<tr><td>' . __('Site internet') . '</td><td>' . form::field('site', 30, 128, $client->site) . '</td></tr>';
-               if (wsDroits::admin(false)) {
-                       $res .= '<tr><td>' . __('Adresse de facturation') . '</td><td>' . form::textarea('adresse_facturation', 40, 3, $client->adresse_facturation) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Numéro de TVA intracommunautaire') . '</td><td>' . form::field('tva_intra', 15, 64, $client->tva_intra) . '</td></tr>';
-               }
-               // Bloc Fluidbook Workshop
-               if (wsDroits::admin(false)) {
-                       $res .= '<tr class="light"><th colspan="2" class="light"><strong>' . __('Fluidbook Workshop') . '</strong></th></tr>';
-                       $res .= '<tr class="odd"><td>' . __('Grade') . '</td><td>' . form::combo('ws_grade', array_flip($core->ws_grades), $client->ws_grade) . '</td></tr>';
-                       if ($entreprise_id == 'new' || !$client->ws_admin) {
-                               $class = 'empty-field';
-                               $default_id = '';
-                               $default = __("Entrez le nom du revendeur ou de l'administrateur");
-                       } else {
-                               $class = '';
-                               $default_id = $client->ws_admin;
-                               $wsa = $daoUtilisateur->selectById($client->ws_admin, 'utilisateurs_entreprise');
-                               $default = $wsa->utilisateur_id . ' - ' . $wsa->rs . ' (' . $wsa->prenom . ' ' . $wsa->nom . ')';
-                       }
-
-                       $d = $dao->getWSDatas($entreprise_id);
-
-                       $res .= '<tr class="odd"><td>' . __('Revendeur / Administrateur') . '</td><td>' . form::field('ws_admin_nom', 60, 128, $default, $class) . form::hidden('ws_admin', $default_id) . '</td></tr>';
-                       if (!is_null($d)) {
-                               $res .= '<tr class="odd"><td>' . __('Entité facturable') . '</td><td>' . $d->facturable->prenom . ' ' . $d->facturable->nom . ' (' . $d->facturable->rs . ')</td></tr>';
-                               $res .= '<tr class="odd"><td>' . __('Administrateur responsable') . '</td><td>' . $d->administrateur->prenom . ' ' . $d->administrateur->nom . ' (' . $d->administrateur->rs . ')</td></tr>';
-                       }
-
-                       $daoSignature = new wsDAOSignature($core->con);
-                       $signaturesList = $daoSignature->selectAll();
-
-                       $signatures = array();
-                       foreach ($signaturesList as $s) {
-                               $signatures[$s->nom] = $s->signature_id;
-                       }
-
-                       $res .= '<tr class="odd"><td>' . __('Signatures Fluidbook') . '</td><td>' . cubeForm::checkMultiple('ws_signatures', $signatures, 5, explode(',', $client->ws_signatures)) . '</td></tr>';
-               }
-               if ($entreprise_id == 'new') {
-                       $daoContact = new commonDAOClient($core->con);
-                       $contact = $daoContact->cree();
-                       $res .= '<tr><th colspan="2" class="light"><strong>' . __('Contact') . '</strong></th></tr>';
-                       $res .= '<tr><td>' . __('Adresse e-mail') . '</td><td>' . form::field(array('contact[email]'), 30, 128, $contact->email) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Mot de passe') . '</td><td>' . form::field(array('contact[password]'), 30, 128, $contact->password) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Prénom') . '</td><td>' . form::field(array('contact[prenom]'), 30, 128, $contact->prenom) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Nom') . '</td><td>' . form::field(array('contact[nom]'), 30, 128, $contact->nom) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Téléphone') . '</td><td>' . form::field(array('contact[telephone]'), 20, 128, $contact->telephone) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Mobile') . '</td><td>' . form::field(array('contact[mobile]'), 20, 128, $contact->mobile) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Fax') . '</td><td>' . form::field(array('contact[fax]'), 20, 128, $contact->fax) . '</td></tr>';
-                       $res .= '<tr><td>' . __('Langue') . '</td><td>' . form::combo(array('contact[lang]'), cubeLang::getAvailableLangs(true), $contact->lang) . '</td></tr>';
-               }
-               return $res;
-       }
-
-       public static function listeContacts($entreprise_id)
-       {
-               global $core;
-               commonDroits::min(3);
-               $dao = new commonDAOEntreprise($core->con);
-               $contacts = $dao->getContacts($entreprise_id);
-
-               $res = '<table class="liste light">';
-               $res .= '<tr class="light"><th colspan="4"><a href="" class="popup" rel="formContact/new/' . $entreprise_id . '">' . $core->typo->Contact('Ajouter un contact') . '</a></th></tr>';
-               $i = 0;
-               foreach ($contacts as $contact) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '><td>' . trim($contact->prenom . ' ' . $contact->nom) . '</td>';
-                       $res .= '<td><a href="mailto:' . trim($contact->prenom . ' ' . $contact->nom) . '<' . $contact->email . '>">' . $contact->email . '</a></td>';
-                       $res .= '<td class="min"><a href="' . SITE_PATH . 'fichiers/' . $contact->utilisateur_id . '">FTP</a></td>';
-                       //$res .= '<td><a class="ajax" href="#" rel="connectAs/' . $contact->utilisateur_id . '">Se connecter comme ...</a></td>';
-                       $res .= '<td class="right"><a href="#" rel="formContact/' . $contact->utilisateur_id . '" class="popup">' . cubeMedia::image(IMG . '/edit.png') . '</a></td></tr>';
-                       $i++;
-               }
-               $res .= '</table>';
-               return $res;
-       }
-
-       public static function formCollection($collection_id = 'new')
-       {
-               global $core;
-               commonDroits::min(3);
-               $dao = new wsDAOCollection($core->con);
-               if ($collection_id != 'new') {
-                       $collection = $dao->selectById($collection_id);
-               } else {
-                       $collection = $dao->cree();
-               }
-
-               $res = '<tr><td>#</td><td>' . form::hidden('collection_id', $collection->collection_id) . $collection->collection_id . '</td></tr>';
-               $res .= '<tr><td>Nom de la collection</td><td>' . form::field('nom', 20, 64, $collection->nom) . '</td></tr>';
-               return $res;
-       }
-
-       public static function formContact($client_id = 'new', $entreprise_id = null)
-       {
-               global $core;
-               commonDroits::min(3);
-
-               $dao = new commonDAOClient($core->con);
-               if ($client_id == 'new') {
-                       $client = $dao->creeFromEntreprise($entreprise_id);
-               } else {
-                       $client = $dao->selectById($client_id);
-               }
-
-               $res = '<tr><td>' . __('Numéro de client') . '</td><td>' . form::hidden('grade', 0) . form::hidden('entreprise', $client->entreprise) . form::hidden('utilisateur_id', $client->utilisateur_id) . '' . $client->utilisateur_id . '</td></tr>';
-               $res .= '<tr><td>' . __('Login activé') . '</td><td>' . form::hidden('enabled', 0) . form::checkbox('enabled', 1, $client->enabled) . '</td></tr>';
-               $res .= '<tr><td>' . __('Adresse e-mail') . '</td><td>' . form::field('email', 30, 128, $client->email) . '</td></tr>';
-               $res .= '<tr><td>' . __('Mot de passe') . '</td><td>' . form::field('password', 30, 128, $client->password) . '</td></tr>';
-               $res .= '<tr><td>' . __('Prénom du contact') . '</td><td>' . form::field('prenom', 30, 128, $client->prenom) . '</td></tr>';
-               $res .= '<tr><td>' . __('Nom du contact') . '</td><td>' . form::field('nom', 30, 128, $client->nom) . '</td></tr>';
-               $res .= '<tr><td>' . __('Adresse') . '</td><td>' . form::textarea('adresse', 40, 3, $client->adresse) . '</td></tr>';
-               $res .= '<tr><td>' . __('Code postal') . '</td><td>' . form::field('code_postal', 10, 20, $client->code_postal) . '</td></tr>';
-               $res .= '<tr><td>' . __('Ville') . '</td><td>' . form::field('ville', 30, 128, $client->ville) . '</td></tr>';
-               $res .= '<tr><td>' . __('Pays') . '</td><td>' . form::combo('pays', cubeCountry::getList(), $client->pays) . '</td></tr>';
-               $res .= '<tr><td>' . __('Téléphone') . '</td><td>' . form::field('telephone', 20, 128, $client->telephone) . '</td></tr>';
-               $res .= '<tr><td>' . __('Mobile') . '</td><td>' . form::field('mobile', 20, 128, $client->mobile) . '</td></tr>';
-               $res .= '<tr><td>' . __('Fax') . '</td><td>' . form::field('fax', 20, 128, $client->fax) . '</td></tr>';
-               $res .= '<tr><td>' . __('Langue') . '</td><td>' . form::combo('lang', cubeLang::getAvailableLangs(true), $client->lang) . '</td></tr>';
-               if ($client_id != 'new') {
-                       $res .= '<tr><td colspan="2">' . cubeMedia::spacer(10, 10) . '</td></tr>';
-                       $res .= '<tr><td></td><td><a href="' . SITE_PATH . 'fichiers/' . $client->utilisateur_id . '">' . __('FTP') . '</a></td></tr>';
-                       //$res .= '<tr><td></td><td><a href="#" class="ajax" rel="connectAs/' . $client->utilisateur_id . '">' . __('Se connecter comme ...') . '</a></td></tr>';
-                       $res .= '<tr><td>' . __("Paramètres de connexion au Fluidbook Workshop") . '</td><td>' . __('Adresse') . ' : https://' . $_SERVER['HTTP_HOST'] . '/<br />' . __("Nom d'utilisateur") . ' : ' . $client->email . '<br />' . __('Mot de passe') . ' : ' . $client->password . '</td></tr>';
-                       $res .= '<tr><td colspan="2">' . cubeMedia::spacer(10, 10) . '</td></tr>';
-               }
-               return $res;
-       }
-
-       public static function demandes()
-       {
-               global $core;
-               cubePage::truePopup();
-               cubePage::autoComplete();
-               cubePage::emptyfield();
-               commonDroits::min(5);
-               $settings = $core->user->getSettings('demandes');
-
-               $shortcuts = array();
-
-               $filtres = array();
-               $filtres[] = new commonFiltre(__('Statut'), 'status_demande', $settings['filtres']);
-               $filtres[] = new commonFiltre(__('Confiées à'), 'demande_moi', $settings['filtres']);
-
-               $res = commonPage::barre($filtres, 'filtreDemandes', 'demandes', $shortcuts);
-               $res .= commonPage::tMain();
-               $res .= commonPage::bh();
-               $res .= '<div id="listeDemandes">';
-               $res .= self::listeDemandes();
-               $res .= '</div>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-               return $res;
-       }
-
-       public static function listeDemandes($dashboard = null, $settings = null)
-       {
-               global $core;
-               commonDroits::min(5);
-               $settings = is_null($settings) ? $core->user->getSettings('demandes') : $settings;
-               $change = is_null($dashboard) ? 'Demandes' : 'Dashboard/' . $dashboard;
-               $dao = new wsDAODemande($core->con);
-               if (isset($settings['search']) && !is_null($settings['search'])) {
-                       $dao->setSearch($settings['search']);
-               }
-               $dao->setFiltres($settings['filtres']);
-               $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user);
-
-               $res = '<table class="liste">';
-               $res .= '<tr><th>' . commonUrl::orderby('#', 'demande_id', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Date'), 'date', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Type'), 'type', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Prospect') . '/' . __('Client'), 'utilisateur_nom', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Confiée à'), 'revendeur_nom', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Gérée par'), 'administrateur_nom', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th>' . commonUrl::orderby(__('Statut'), 'status', $settings, 'sort' . $change) . '</th>';
-               $res .= '<th class="min"></th><th class="min"></th></tr>';
-               $i = 0;
-               foreach ($liste as $id => $demande) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '>';
-                       $res .= '<td>' . $demande->demande_id . '</td>';
-                       $res .= '<td>' . date(__('d/m/Y H:i'), $demande->date) . '</td>';
-                       $res .= '<td>' . $core->demandes_type[$demande->type] . '</td>';
-                       $res .= '<td><a href="#" class="popup" rel="formClient/' . $demande->entreprise . '">' . $demande->utilisateur_nom . '</a></td>';
-                       $revendeur = $demande->revendeur == 0 ? '-' : $demande->revendeur_nom;
-                       $res .= '<td>' . $revendeur . '</td>';
-                       $administrateur = $demande->administrateur == 0 ? '-' : $demande->administrateur_nom;
-                       $res .= '<td>' . $administrateur . '</td>';
-                       // Affichage du status
-                       // Si non traitée ou traitée, pas la possibilité de changer le status
-                       if ($demande->status == 0 || $demande->status == 2) {
-                               $res .= '<td>' . $core->demandes_status[$demande->status] . '</td>';
-                       } else if ($demande->status == 1) {
-                               if ($demande->revendeur == $core->user->utilisateur_id) {
-                                       $res .= '<td><a href="#" class="ajax" rel="reponseDemande/' . $demande->demande_id . '/' . $demande->revendeur . '/1/1">' . __('Je me suis chargé de cette demande') . '</a></td>';
-                               } else {
-                                       $res .= '<td>' . $core->demandes_status[$demande->status] . ' (<a href="#" class="ajax" rel="resetDemande/' . $demande->demande_id . '" title="' . __('Réinitialiser la demande') . '">x</a>)</td>';
-                               }
-                       }
-                       // On ne peut éditer que si la facture est non traitée et qu'elle n'a pas commencé à être éditée par un autre administrateur
-                       if (($demande->administrateur == 0 || $demande->administrateur == $core->user->utilisateur_id) && $demande->status == 0) {
-                               $res .= '<td class="action"><a href="#" class="popup" rel="formDemande/' . $demande->demande_id . '">' . cubeMedia::image(IMG . '/edit.png') . '</a></td>';
-                       } else {
-                               $res .= '<td></td>';
-                       }
-                       // On n'affiche le bouton "Supprimer" que si la demande est non-traitée
-                       if (($demande->administrateur == 0 || $demande->administrateur == $core->user->utilisateur_id) && $demande->status == 0) {
-                               $res .= '<td class="action"><a href="#" class="ajax" rel="supprimeDemande/' . $demande->demande_id . '" title="' . __('Êtes-vous certain de vouloir supprimer cette demande ?') . '">' . cubeMedia::image(IMG . '/delete.png') . '</a></td>';
-                       } else {
-                               $res .= '<td></td>';
-                       }
-                       $res .= '</tr>';
-                       $i++;
-               }
-               if (!isset($settings['search']) || is_null($settings['search'])) {
-                       $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
-                       $res .= '<tr' . $odd . '><td colspan="10">';
-                       $res .= commonPage::pager($settings['page'], $dao->count($core->user), $settings['par_page'], 'page' . $change . '/%d');
-                       $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('demandes'));
-                       $res .= '</td></tr>';
-               }
-               $res .= '</table>';
-               return $res;
-       }
-
-       public static function formDemande($demande_id = 'new')
-       {
-               global $core;
-               commonDroits::min(5);
-               $dao = new wsDAODemande($core->con);
-               $demande = $dao->selectById($demande_id);
-
-               if ($demande->administrateur != 0 && $demande->administrateur != $core->user->utilisateur_id) {
-                       $action = __("Cette demande est actuellement en cours d'édition par un autre administrateur");
-               } elseif ($demande->status > 1) {
-                       $action = __("Cette demande est actuellement en cours de traitement");
-               } else {
-                       $action = '<a href="#" rel="lockDemande/' . $demande->demande_id . '" class="ajax">' . __("Cliquez-ici pour effectuer une action") . '</a>';
-               }
-
-
-               $res = '<tr><td>' . __('Numéro de demande') . '</td><td>' . form::hidden('demande_id', $demande->demande_id) . '' . $demande->demande_id . '</td></tr>';
-               $res .= '<tr><td>' . __('Date de la demande') . '</td><td>' . date(__('d/m/Y H:i'), $demande->date) . '</td></tr>';
-               $res .= '<tr><td>' . __('Emetteur de la demande') . '</td><td><a href="#" class="popup" rel="formClient/' . $demande->entreprise . '">' . $demande->utilisateur_nom . '</a></td></tr>';
-               $res .= '<tr><td>' . __('Nombre de pages') . '</td><td>' . $demande->pages . '</td></tr>';
-               $res .= '<tr><td>' . __('Nombre de liens') . '</td><td>' . $demande->liens . '</td></tr>';
-               $res .= '<tr><td>' . __('Nombre de langues') . '</td><td>' . $demande->langues . '</td></tr>';
-               $res .= '<tr><td>' . __('Détails') . '</td><td>' . $demande->details . '</td></tr>';
-               $res .= '<tr><td>' . __('Action') . '</td><td><div id="actionDemande">' . $action . '</div></td></tr>';
-               $res .= '<tr><td></td></tr>';
-
-               return $res;
-       }
-
-       public static function reponseDemande($args)
-       {
-               global $core;
-
-               commonDroits::min(3);
-
-
-               $demande_id = $args[1];
-               $revendeur_id = $args[2];
-
-               $dao = new wsDAODemande($core->con);
-               $demande = $dao->selectById($demande_id);
-
-               $res = commonPage::barre();
-               $res .= commonPage::tMain();
-               $res .= commonPage::bh();
-               $res .= '<div id="accepteDemandes">';
-               $res .= '<h1>' . __('Prendre en charge une demande de devis') . '</h1>';
-               $res .= '<br /><br />';
-
-               if ($demande->revendeur != $revendeur_id || $demande->revendeur != $core->user->utilisateur_id || $demande->status == 0) {
-                       $res .= '<p class="center">' . __('Cette demande de devis ne vous est pas adressée.') . '</p>';
-               } else if ($demande->status == 2) {
-                       $res .= '<p class="center">' . __('Merci ! Nous avons bien pris en compte votre réponse.') . '<br /><br />';
-                       $res .= '<a href="' . $dao->getMailto($demande_id) . '">' . __("Ouvrir l'email de réponse") . '</a>';
-                       $res .= '</p>';
-               } else {
-                       $res .= '<p>' . __('Si vous acceptez de traiter la demande suivante, veuillez cliquer sur le bouton "Accepter la demande" situé à droite de la description.');
-                       $res .= ' ' . __('Vous avez également la possibilité de décliner la demande en cliquant sur le bouton "Décliner la demande"') . "</p>";
-                       $res .= '<br /><br />';
-
-                       $res .= '<table>';
-                       $res .= '<tr><th class="left" colspan="2">' . __("Détails de la demande") . '</th><th class="left" style="width:40%">' . __('Votre action') . '</th></tr>';
-                       $res .= '<tr><td>' . __('Numéro de demande') . '</td><td>' . $demande->demande_id . '</td>';
-                       $res .= '<td>' . '<a href="#" class="ajax download btbook" rel="reponseDemande/' . $demande_id . '/' . $revendeur_id . '/1" ><div></div><span>' . __('Accepter la demande') . '</span></a>' . '</td></tr>';
-                       $res .= '<tr><td>' . __('Date de la demande') . '</td><td>' . date(__('d/m/Y H:i'), $demande->date) . '</td></tr>';
-                       $res .= '</tr>';
-                       $res .= '<tr><td>' . __('Client') . ' / ' . __('Prospect') . '</td><td><a href="#" class="popup" rel="formClient/' . $demande->entreprise . '">' . $demande->utilisateur_nom . '</a></td></tr>';
-                       $res .= '<tr><td>' . __('Nombre de pages') . '</td><td>' . $demande->pages . '</td>';
-                       $res .= '<td>' . '<a href="#" class="ajax suppr btbook" rel="reponseDemande/' . $demande_id . '/' . $revendeur_id . '/0"><div></div><span>' . __('Décliner la demande') . '</span></a>' . '</td>';
-                       $res .= '</tr>';
-                       $res .= '<tr><td>' . __('Nombre de liens') . '</td><td>' . $demande->liens . '</td></tr>';
-                       $res .= '<tr><td>' . __('Nombre de langues') . '</td><td>' . $demande->langues . '</td></tr>';
-                       $res .= '<tr><td>' . __('Détails') . '</td><td>' . $demande->details . '</td></tr>';
-                       $res .= '</table>';
-               }
-
-               $res .= '</div>';
-               $res .= commonPage::bf();
-               $res .= commonPage::bMain();
-               return $res;
-       }
-
-       public static function orpiref($args)
-       {
-               $ref = $args[1];
-
-
-               try {
-                       $adapter = new Zend_Http_Client_Adapter_Socket();
-                       $streamOpts = array(
-                               'ssl' => array(
-                                       'verify_peer' => false,
-                                       'allow_self_signed' => true
-                               )
-                       );
-                       $adapter->setStreamContext($streamOpts);
-                       $client = new Zend_Http_Client();
-                       $client->setAdapter($adapter);
-                       $client->setEncType(Zend_Http_Client::ENC_FORMDATA);
-                       $client->setMethod(Zend_Http_Client::POST);
-                       $client->setParameterPost(array('reference' => $ref));
-                       $client->setUri('https://www.orpi.com/recherche/search_by_reference');
-                       $client->setHeaders(['X-Requested-With' => 'XMLHttpRequest',
-                               'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0',
-                               'Origin' => 'https://www.orpi.com',
-                               'Referer' => 'https://www.orpi.com/',
-                               'Pragma' => 'no-cache',
-                               'DNT' => '1']);
-                       $response = $client->request();
-                       $json = $response->getBody();
-                       $res = 'https://www.orpi.com';
-                       if ($json === false) {
-                               header('Location: ' . $res);
-                               exit;
-                       }
-                       $r = json_decode($json);
-                       if ($r === false) {
-                               header('Location: ' . $res);
-                               exit;
-                       }
-
-                       if (isset($r->success) && $r->success && isset($r->location)) {
-                               header('Location: ' . $res . $r->location);
-                               exit;
-                       }
-
-                       header('Location: ' . $res);
-               } catch (Exception $e) {
-                       ob_end_clean();
-                       echo $e->getMessage();
-               }
-
-               header('Location: https://www.orpi.com/');
-       }
+        $res .= '</style>';
+        $res .= '<title>' . __('Edition de la publication') . ' #' . $args[0] . '</title>';
+        $res .= '</head>';
+        $res .= '<body onload="this.focus();">';
+        $res .= self::editComposition($book_id, $hash);
+        $res .= '</body>';
+        $res .= '</html>';
+        echo $res;
+    }
+
+    /**
+     * wsUrl::restoreLinks()
+     *
+     * @param mixed $args
+     * @return
+     */
+    public static function restoreLinks($args)
+    {
+        commonDroits::min(1);
+
+        global $core;
+
+        $args = cubePage::getArgs($args);
+        $book_id = $args[0];
+
+
+        $dao = new wsDAODocument($core->con);
+        $updates = $dao->getLinksVersions($book_id);
+        krsort($updates);
+
+        $res = '<html><head>';
+        $res .= '<title>' . __('Restauration des liens de la publication') . ' #' . $args[0] . '</title>';
+        $res .= '</head>';
+        $res .= '<body onload="this.focus();">';
+        $res .= '<div id="restoreLinks">';
+        $res .= '<div>';
+        $res .= '<h2>' . __('Import') . '</h2>';
+        $res .= '<div class="center">';
+        $res .= '<form action="importLinksAsExcel/' . $book_id . '" method="post" enctype="multipart/form-data" class="notajax" id="importLinksAsExcel">';
+        $res .= __("Importer des liens à partir d'un fichier Excel") . ' : <input type="file" name="file" accept="*.xlsx" />';
+        $res .= '<input type="submit" value="' . __('Importer') . '" />';
+        $res .= '</form>';
+        $res .= '</div>';
+        $res .= '</div>';
+        $res .= '<hr />';
+
+        $res .= '<div id="linksOffset">';
+        $res .= '<h2>' . __('Décalage de pages') . '</h2>';
+        $res .= '<form action="offsetLinks/' . $book_id . '" method="post" id="offsetLinks">';
+        $offset = form::field('offset', 3, 5);
+        $from = form::field('from', 3, 5);
+        $res .= sprintf(__('Décaler les liens de %s pages à partir de la page %s'), $offset, $from) . '<br />';
+        $res .= '<label>' . form::checkbox('internal', 1, true) . ' ' . __('Appliquer le décalages sur les numéros de pages dans les liens internes') . '</label><br />';
+        $res .= '<input type="submit" value="' . __('Procéder au décalage') . '" />';
+        $res .= '</form>';
+        $res .= '</div>';
+        $res .= '<hr />';
+
+        $res .= '<h2>' . __('Réimporter les liens du fichier PDF') . '</h2>';
+        $res .= '<a class="restoreLink" rel="' . $book_id . '/pdf" href="#">Restaurer</a>';
+        $res .= '<hr />';
+
+        $res .= '<h2>' . __('Historique') . '</h2>';
+        $res .= '<table class="liste" style="width:100%;min-width:0;">';
+        $res .= '<tr>';
+        $res .= '<th>' . __('Date') . '</th>';
+        $res .= '<th class="center">' . __('Liens') . '</th>';
+        $res .= '<th class="center">' . __('Règles') . '</th>';
+        $res .= '<th class="center">' . __('Utilisateur') . '</th>';
+        $res .= '<th class="center">' . __('Informations') . '</th>';
+        $res .= '<th class="min"></th>';
+        $res .= '<th class="min"></th>';
+        $res .= '</tr>';
+        $i = 0;
+        foreach ($updates as $time => $infos) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '>';
+            $res .= '<td>' . date('Y-m-d H:i:s', $time) . '</td>';
+            $res .= '<td class="center">' . $infos['links'] . '</td>';
+            $res .= '<td class="center">' . $infos['rulers'] . '</td>';
+            $res .= '<td class="center">' . $infos['user'] . '</td>';
+            $res .= '<td class="center">' . $infos['comments'] . '</td>';
+            $res .= '<td><a href="#" rel="' . $book_id . '/' . $time . '" class="restoreLink">' . __('Restaurer') . '</a></td>';
+            $res .= '<td><a href="' . SITE_PATH . 'exportLinksAsExcel/' . $book_id . '/' . $time . '">' . str_replace(' ', '&nbsp;', __('Export Excel')) . '</a></td>';
+            $res .= '</tr>';
+            $i++;
+        }
+
+        $res .= '</table>';
+        $res .= '</div>';
+        $res .= '</body>';
+        $res .= '</html>';
+
+        echo $res;
+    }
+
+    public static function exportLinksAsExcel($args)
+    {
+        global $core;
+
+        cubePHP::neverStop();
+
+        $book_id = $args[1];
+        $time = $args[2];
+
+        $dao = new wsDAODocument($core->con);
+        $dao->getLinksAndRulers($book_id, $links, $rulers, $time);
+        $xls = $dao->getLinksAsExcel($links, $rulers);
+
+        ob_end_clean();
+        files::registerMimeTypes(array('xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'));
+        cubeHTTP::forceDownload('links_' . $book_id . '_' . $time . '.xlsx', false);
+
+        $writer = new PHPExcel_Writer_Excel2007($xls);
+        $writer->save('php://output');
+
+        exit;
+    }
+
+    public static function editComposition($book_id, $hash)
+    {
+
+        $fv = array(session_name() => session_id(),
+            'book_id' => $book_id,
+            'hash' => $hash,
+            'url' => '/');
+
+        $mtime = filemtime(ROOT . '/swf/composer.swf');
+        return cubeMedia::flash2(WEBROOT . '/swf/composer.swf?junk=' . $mtime, '100%', '100%', $fv, 'composerSwf', 'swfPanel', 10, '#d2d3c7', '', 'false', 'noscale', 'normal', array(), false, true, false);
+    }
+
+    public static function stats($args)
+    {
+        global $core;
+        $bid = (isset($args[1])) ? $args[1] : null;
+
+        list($bid, $hash) = explode('_', $bid);
+
+        $r = $core->con->select('SELECT * FROM books WHERE book_id=\'' . $core->con->escape($bid) . '\' AND hash=\'' . $core->con->escape($hash) . '\'');
+        if (!$r->count()) {
+            return;
+        }
+
+        $annee = (isset($args[2])) ? $args[2] : null;
+        $mois = (isset($args[3])) ? $args[3] : null;
+        return wsStats::display($bid . '_' . $hash, $annee, $mois);
+    }
+
+    public static function viewerh($args)
+    {
+        global $core;
+
+        $args = cubePage::getArgs($args);
+
+        $e = explode('_', $args[0]);
+
+        $book_id = $e[0];
+        $hash = $e[1];
+
+        $dao = new wsDAOBook($core->con);
+
+        $book = $dao->selectById($book_id);
+        if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
+            commonDroits::error();
+        }
+
+        if (!wsDroits::admin()) {
+            if ($book->parametres->redirectDemo != '') {
+                http::redirect($book->parametres->redirectDemo);
+                exit;
+            }
+            if ($book->parametres->disableDemo) {
+                commonDroits::error();
+            }
+        }
+
+        $time = TIME;
+        $q = $_SERVER['QUERY_STRING'];
+        if ($q != '') {
+            $q = '?' . $q;
+        }
+        if (count($e) == 2) {
+            $e[2] = $time;
+            http::redirect(SITE_PATH . 'viewerh/' . implode('_', $e) . '/' . $q);
+            exit;
+        }
+
+        $dao->compile($book_id, 'html5', false, false, false, null, false);
+
+        $book_id = $e[0];
+        $hash = $e[1];
+        self::commonHTML5Viewer($book_id, $hash);
+    }
+
+
+    public static function viewers($args)
+    {
+        global $core;
+
+        $args = cubePage::getArgs($args);
+
+        $e = explode('_', $args[0]);
+
+        $book_id = $e[0];
+        $hash = $e[1];
+
+        $dao = new wsDAOBook($core->con);
+
+        $book = $dao->selectById($book_id);
+        if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
+            commonDroits::error();
+        }
+
+        if (!wsDroits::admin()) {
+            if ($book->parametres->redirectDemo != '') {
+                http::redirect($book->parametres->redirectDemo);
+                exit;
+            }
+            if ($book->parametres->disableDemo) {
+                commonDroits::error();
+            }
+        }
+
+        $dao->compile($book_id, 'html5');
+        $time = TIME;
+
+        if (count($e) == 2 || $e[2] <= $time - 10) {
+            $e[2] = $time;
+            http::redirect(SITE_PATH . 'viewers/' . implode('_', $e) . '/');
+            exit;
+        }
+
+        $book_id = $e[0];
+        $hash = $e[1];
+        self::commonHTML5Viewer($book_id, $hash, '', ['<head>' => '<head><script type="text/javascript">var FORCE_SCORM=true;</script>']);
+    }
+
+    public static function commonHTML5Viewer($book_id, $hash, $version = '', $replace = [])
+    {
+        global $core;
+        self::checkDocumentVersionOfBook($book_id);
+
+        $dao = new wsDAOBook($core->con);
+        $dir = '';
+
+        $book = $dao->selectById($book_id);
+        if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
+            commonDroits::error();
+        }
+
+        if (!wsDroits::admin()) {
+            if ($book->parametres->redirectDemo != '') {
+                http::redirect($book->parametres->redirectDemo);
+                exit;
+            }
+            if ($book->parametres->disableDemo) {
+                commonDroits::error();
+            }
+        }
+
+        self::logReferer($book_id);
+        $html = file_get_contents(WS_BOOKS . '/html5' . $dir . '/' . $book_id . '/index' . $version . '.html');
+        foreach ($replace as $from => $to) {
+            $html = str_replace($from, $to, $html);
+        }
+        echo $html;
+        exit;
+    }
+
+    public static function viewer($args)
+    {
+        $args = cubePage::getArgs($args);
+
+        $qs = '';
+        if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) {
+            $qs = '?' . $_SERVER['QUERY_STRING'];
+        }
+
+        $e = explode('_', $args[0]);
+        $newurl = null;
+        if (count($e) == 2 || $e[2] < TIME - 10) {
+            $e[2] = TIME;
+            http::redirect(SITE_PATH . 'viewer/' . implode('_', $e) . '/' . $qs);
+            exit;
+        }
+
+        $book_id = $e[0];
+
+        $wmode = (isset($wmode) && $wmode != '') ? $wmode : 'default';
+
+        self::checkDocumentVersionOfBook($book_id);
+        wsSecureSWF::checkProtectedSWF();
+
+        echo self::commonViewer($book_id, $e[1], false, $wmode, $newurl);
+    }
+
+    public static function commonViewer($book_id, $hash, $standalone = false, $wmode = 'default', $fps = false, $version = 2)
+    {
+        if (!defined('MINIMIZE_JS')) {
+            define('MINIMIZE_JS', false);
+        }
+        if (!defined('MINIMIZE_CSS')) {
+            define('MINIMIZE_CSS', false);
+        }
+        if (!defined('JQUERY')) {
+            define('JQUERY', false);
+        }
+
+        global $core;
+        global $css;
+        global $js;
+        global $standard;
+        global $meta;
+        global $jsvar;
+
+        if ($version == 2) {
+            $flashVersion = '10.0.22';
+        } else {
+            $flashVersion = '8';
+        }
+
+        cubePage::swfobject(2);
+
+        $dao = new wsDAOBook($core->con);
+        $book = $dao->selectById($book_id);
+
+        if (!wsDroits::admin()) {
+            if ($book->parametres->redirectDemo != '') {
+                http::redirect($book->parametres->redirectDemo);
+                exit;
+            }
+            if ($book->parametres->disableDemo) {
+                commonDroits::error();
+            }
+        }
+
+        if ($hash != 'bcf26f9cf4a795ec00b9a44f42750d58' && $book->hash != $hash) {
+            commonDroits::error();
+        }
+
+
+        if (is_null($core->user)) {
+            $dao->addDemoCount($book_id);
+        }
+
+        $dao->compile($book_id, (string)$version);
+
+        $daoTheme = new wsDAOTheme($core->con);
+        $theme = $daoTheme->selectById($book->theme, 'themes');
+
+        $webcompile = WEBROOT . '/fluidbook/compile/';
+
+        $standard = 'XHTML 1.0 Transitional';
+        $css = $js = array();
+        $css[] = $webcompile . 'style.css';
+        $fv = $_GET;
+        if ($standalone) {
+            $fv['base'] = $_SERVER['REQUEST_URI'];
+        }
+        if ($fps) {
+            $fv['monitoring'] = '1';
+        }
+
+        if ($version == 1) {
+            $fv['id'] = $book_id;
+            $fv['mail'] = '0';
+            $fv['onlineFlag'] = '1';
+            $fv['loaderColor'] = $theme->parametres->loadingBackColor;
+        }
+
+        $res = '<html>';
+        $res .= '<head>';
+        $res .= '<title>' . $book->parametres->title . '</title>';
+        $res .= '<meta name="google" value="notranslate">';
+        $res .= '<style type="text/css" media="print">*{ visibility: hidden; display: none }</style>';
+        // Entêtes Facebook
+        $meta['og:title'] = ($book->parametres->facebook_title == '') ? $book->parametres->title : $book->parametres->facebook_title;
+        if ($book->parametres->facebook_description != '') {
+            $meta['og:description'] = $book->parametres->facebook_description;
+        }
+        $meta['og:image'] = 'https://workshop.fluidbook.com/services/facebook_thumbnail?id=' . $book->book_id . '&j=' . TIME;
+
+
+        $redirectPDF = 'window.location="data/document.pdf"';
+
+        if ($book->parametres->mobileVersion == 'pdf') {
+            $redirectMobile = $redirectPDF;
+        } else {
+            $redirectMobile = 'window.location="/viewerh/' . $book_id . '_' . $hash . '_' . TIME . '/";';
+        }
+
+        $alt = '<div style="width:734px;margin:100px auto;"><a href="http://get.adobe.com/flashplayer/" target="_blank">' . cubeMedia::image($webcompile . 'getflash.gif', 734, 409, '') . '</a></div>';
+
+        $res .= '</head>';
+        $res .= '<body style="background-color:#' . $theme->parametres->loadingBackColor . '" onload="this.focus();">';
+        $res .= '<div id="fluidbook"><div style="width:734px;margin:100px auto;"><a href="http://get.adobe.com/flashplayer/" target="_blank"></a></div></div>';
+        $res .= "\n" . '<script type="text/javascript">' . "\n";
+        $res .= 'if(isMobile()){' . "\n";
+        $res .= "\t" . $redirectMobile . "\n";
+        $res .= '} else if(isBadMobile()) {' . "\n";
+        $res .= "\t" . $redirectPDF . "\n";
+        $res .= '} else {' . "\n";
+        $res .= "\t" . 'swfobject.embedSWF("index.swf", "fluidbook", "100%", "100%", "' . $flashVersion . '",';
+        $res .= '"", ' . json_encode($fv) . ',';
+        $res .= '{"allowScriptAccess":"always","quality":"high","scale":"noscale","wmode":getWmode(),"allowFullScreen":"true","allowFullScreenInteractive":"true"},{"bgcolor":"#' . $theme->parametres->loadingBackColor . '"}';
+        $res .= ');' . "\n";
+        $res .= '}' . "\n";
+        $res .= '</script>';
+        $js = array('fluidbook.js');
+        $jsvar = array();
+
+        $gacodes = array(GA);
+        if ($book->parametres->googleAnalytics != '') {
+            $gacodes[] = $book->parametres->googleAnalytics;
+        }
+        $res .= cubePage::googleAnalytics($gacodes, false);
+        $res .= '</body>';
+        $res .= '</html>';
+
+        self::logReferer($book_id);
+
+        return $res;
+    }
+
+    public static function logReferer($id)
+    {
+
+        if (!isset($_SERVER['HTTP_REFERER']) || !$_SERVER['HTTP_REFERER']) {
+            $r = '';
+        } else {
+            $r = $_SERVER['HTTP_REFERER'];
+        }
+
+        fb($r, $id);
+
+        global $core;
+        $rr = $core->con->select('SELECT * FROM books_referer WHERE book_id=\'' . $core->con->escape($id) . '\' AND referer=\'' . $core->con->escape($r) . '\'');
+        $c = $core->con->openCursor('books_referer');
+        if (!$rr->count()) {
+            $c->book_id = $id;
+            $c->referer = $r;
+            $c->count = 1;
+            $c->insert();
+        } else {
+            $rr->fetch();
+            $c->count = $rr->count + 1;
+            $c->update('WHERE book_id=\'' . $core->con->escape($id) . '\' AND referer=\'' . $core->con->escape($r) . '\'');
+        }
+    }
+
+    public static function statsxls($args)
+    {
+        $bid = (isset($args[1])) ? $args[1] : null;
+        $annee = (isset($args[2])) ? $args[2] : null;
+        $mois = (isset($args[3])) ? $args[3] : null;
+        wsStats::exportXLS($bid, $annee, $mois);
+    }
+
+    public static function chooseExistingBook()
+    {
+        wsDroits::creation(true);
+        $res = '<tr><td colspan="2"><p style="width:600px;text-align:justify;"><em>a' . __("Si votre nouvelle publication a des paramètres en commun avec une publication existante, veuillez rechercher cette publication afin d'attribuer par défaut à votre nouvelle publication les paramètres de l'existante") . '</em></p></td></tr>';
+        $res .= '<tr><td>' . __('Rechercher une publication') . ' : </td><td>' . form::field('book_nom', 64, 1024) . form::hidden('book', '') . '</td></tr>';
+        $res .= '<tr><td>' . __('Indiquez le titre de votre nouvelle publication') . '</td><td>' . form::field('title', 64, 1024) . '</td></tr>';
+        $res .= '<tr><td colspan="2"><label>' . form::checkbox('settings', '1', true, '', '', true, '') . __('Importer les paramètres de la publication') . '</td></tr>';
+        $res .= '<tr><td colspan="2"><label>' . form::checkbox('pages', '1', false) . __('Importer les pages et les liens') . '</td></tr>';
+        return $res;
+    }
+
+    public static function changeBookProprietaire($book_id)
+    {
+        global $core;
+        commonDroits::min(3);
+
+        $dao = new wsDAOBook($core->con);
+        $book = $dao->selectById($book_id);
+
+        return self::_changeProprietaire($book->proprietaire);
+    }
+
+    public static function changeCollectionProprietaire($collection_id)
+    {
+        global $core;
+        commonDroits::min(3);
+
+        $dao = new wsDAOCollection($core->con);
+        $collection = $dao->selectById($collection_id);
+
+        return self::_changeProprietaire($collection->proprietaire_nom);
+    }
+
+    protected static function _changeProprietaire($proprietaire)
+    {
+        $res = '<tr><td>' . __('Propriétaire actuel') . ' : </td><td>' . $proprietaire . '</td></tr>';
+        $res .= '<tr><td>' . __('Rechercher un utilisateur') . ' : </td><td>' . form::field('book_proprietaire', 64, 1024) . form::hidden('proprietaire', '') . '</td></tr>';
+        return $res;
+    }
+
+    public static function chooseBookProject($book_id)
+    {
+        global $core;
+
+        wsDroits::admin(true);
+
+        $dao = new wsDAOBook($core->con);
+        $book = $dao->selectById($book_id);
+
+        $projects = array("--" => '0');
+
+        $proprietaire = 'SELECT facturable_id FROM ws_users_tree WHERE utilisateur_id=\'' . $core->con->escape($book->proprietaire_id) . '\'';
+        $entreprise = 'SELECT entreprise FROM utilisateurs WHERE utilisateur_id IN (' . $proprietaire . ')';
+        $collegues = 'SELECT utilisateur_id FROM utilisateurs WHERE entreprise IN(' . $entreprise . ')';
+
+        $r = $core->con->select('SELECT * FROM projets WHERE client IN(' . $collegues . ') ORDER BY projet_id DESC');
+        while ($r->fetch()) {
+            $projects[$r->projet_id . ' - ' . $r->nom] = $r->projet_id;
+        }
+
+        $res = '<tr><td>' . __('Choisir un projet') . ' : </td><td>' . form::hidden('book_id', $book_id) . form::combo('book_project', $projects, $book->projet, 'hide_new_value') . '</td></tr>';
+        $res .= '<tr class="new"><td>' . __('ou créer un nouveau projet') . ' : </td><td>' . form::field('new_book_project_nom', 64, 1024, $book->nom) . '</td></tr>';
+        return $res;
+    }
+
+    public static function chooseBookTache($book_id, $projet_id)
+    {
+        global $core;
+        wsDroits::admin(true);
+
+        $dao = new wsDAOBook($core->con);
+        $book = $dao->selectById($book_id);
+
+        $taches = array("--" => '0');
+        $r = $core->con->select('SELECT * FROM taches WHERE projet=\'' . $core->con->escape($projet_id) . '\' AND categorie=8');
+        while ($r->fetch()) {
+            $taches[$r->nom] = $r->tache_id;
+        }
+
+        $res = '';
+
+        if ($r->count() > 0) {
+            $res .= '<tr><td>' . __('Choisir une tâche') . ' : </td><td>' . form::hidden('book_id', $book_id) . form::hidden('projet_id', $projet_id) . form::combo('tache', $taches, '0', 'hide_new_value') . '</td></tr>';
+            $res .= '<tr class="new"><td>' . __('ou créer une nouvelle tâche') . ' : </td><td>' . form::field('nom', 32, 1024, 'Fluidbook #' . $book->book_id . ' : ' . $book->nom) . ' ' . __('ayant le budget suivant') . ' ' . form::field('budget', 6, 6) . '</td></tr>';
+        } else {
+            $res .= '<tr><td>' . __('Créer une tâche') . ' : </td><td>'
+                . form::hidden('book_id', $book_id)
+                . form::hidden('projet_id', $projet_id)
+                . form::hidden('tache', '0')
+                . form::field('nom', 32, 1024, 'Fluidbook #' . $book->book_id . ' : ' . $book->nom)
+                . ' ' . __('ayant le budget suivant')
+                . ' ' . form::field('budget', 6, 6) . '</td></tr>';
+        }
+
+        return $res;
+    }
+
+    public static function valideDownload()
+    {
+        global $core;
+
+        $res = '<tr><td>' . __("Le téléchargement du fluidbook implique qu'il a été testé et définitivement validé.") . '<br />' . __("Si vous le téléchargez, il vous sera facturé selon les conditions stipulées dans votre contrat.") . '</td></tr>';
+        $res .= '<tr><td class="right"><label>' . __("Oui, ce fluidbook est validé, je souhaite le télécharger et il me sera facturé.") . ' ' . form::checkbox('valide', 1, false) . '</label></td></tr>';
+
+        return $res;
+    }
+
+    public static function formInstall($book, $server)
+    {
+        if ($server == 'references') {
+            $s = __('Espace des références');
+            $dir = $book->dir_references;
+        } elseif ($server == 'hosting') {
+            $s = __("Serveur d'hébergement");
+            $dir = $book->dir_hosting;
+        } elseif ($server == 'macbook_phonegap_ios') {
+            $s = __("Projet Phonegap iOS");
+            $dir = $book->dir_macbook_phonegap_ios;
+        } elseif ($server == 'phonegap_android') {
+            $s = __("Projet Phonegap Android");
+            $dir = $book->dir_phonegap_android;
+        } elseif ($server == 'external') {
+            $s = __('Serveur FTP externe') . ' : ftp://';
+            $dir = $book->dir_external;
+        }
+
+        if ($dir == '') {
+            $dir = cubeText::str2URL($book->parametres->title);
+        }
+
+        $res = '<tr><td>' . __("Dossier d'installation") . '</td><td><em>' . $s . '</em> ' . form::field('dir', 60, 128, $dir) . '</td></tr>';
+        $res .= '<tr><td colspan="2">' . __("A l'issue de l'installation, vous serez dirigé vers le serveur sur lequel la publication a été installée") . '</td></tr>';
+        return $res;
+    }
+
+    public static function testAS($args)
+    {
+        global $core;
+        commonDroits::min(5);
+        if (!isset($args[1])) {
+            $args[1] = 2964;
+        }
+        self::checkDocumentVersionOfBook($args[1]);
+        wsSecureSWF::checkProtectedSWF();
+        cubePHP::neverStop();
+        $dao = new wsDAOBook($core->con);
+
+        header('Content-type: text/plain');
+        ob_end_clean();
+        echo $dao->compile($args[1], 3, false, true);
+        exit;
+    }
+
+    public static function testAIR($args)
+    {
+        global $core;
+        commonDroits::min(5);
+        if (!isset($args[1])) {
+            $args[1] = 2964;
+        }
+        self::checkDocumentVersionOfBook($args[1]);
+        cubePHP::neverStop();
+        $dao = new wsDAOBook($core->con);
+
+        header('Content-type: text/plain');
+        ob_end_clean();
+        echo $dao->compileAIR($args[1]);
+        exit;
+    }
+
+    public static function testLinksCSV($args)
+    {
+        global $core;
+        commonDroits::min(5);
+
+        $dao = new wsDAODocument($core->con);
+        header('Content-type: text/plain');
+        ob_clean();
+        echo $dao->putLinksFromCSV($args[1]);
+    }
+
+    protected static function checkDocumentVersionOfBook($book_id)
+    {
+        global $core;
+        cubePHP::neverStop();
+        $daoBook = new wsDAOBook($core->con);
+
+
+        $toUpdate = $daoBook->getDocumentsToUpdate($book_id);
+        foreach ($toUpdate as $document_id) {
+            self::updateDocument($document_id);
+        }
+
+        if (count($toUpdate) > 0) {
+            $daoBook->setChaptersFromOldFluidbook($book_id);
+            $daoDoc = new wsDAODocument($core->con);
+            $daoDoc->setLinksFromOldFluidbook($book_id);
+        }
+
+        $daoBook->setVersion($book_id, 2);
+    }
+
+    public static function testOldLink($args)
+    {
+        global $core;
+        $daoDoc = new wsDAODocument($core->con);
+        $daoDoc->setLinksFromOldFluidbook($args[1]);
+    }
+
+    protected static function updateDocument($document_id)
+    {
+        global $core;
+
+        $dao = new wsDAODocument($core->con);
+        $doc = $dao->selectById($document_id);
+
+        $doc->copyOriginalFromOlderVersion();
+        $doc->globalOperations();
+
+        for ($i = 1; $i <= $doc->generalInfos['pages']; $i++) {
+            $doc->processOnePage($i);
+        }
+
+        $doc->version = 2;
+        $dao->updateFromObject($doc);
+    }
+
+    public static function testFontExtraction($args)
+    {
+        $documentId = $args[1];
+
+        header('Content-type: text/plain');
+        ob_clean();
+
+
+        $extractor = new wsPDFFontExtractor(WS_DOCS . '/' . $documentId);
+        $extractor->extract();
+
+        exit;
+    }
+
+    public static function getParamsHelp($args)
+    {
+        commonDroits::min(5);
+        global $core;
+
+        $res = '';
+
+        if (isset($args[1]) && $args[1] != '') {
+            $dao = new wsDAOBook($core->con);
+            $b = $dao->selectById($args[1]);
+
+            $daoTheme = new wsDAOTheme($core->con);
+            $t = $daoTheme->getThemeOfBook($args[1], true);
+
+            $book = $b->parametres;
+            $theme = $t->parametres;
+        } else {
+            $theme = new wsThemeParametres(new wsTheme());
+            $book = new wsBookParametres(new wsBook());
+        }
+
+        $res = commonPage::barre();
+        $res .= commonPage::tMain();
+        $res .= commonPage::bh();
+        $res .= '<table class="liste">';
+        $res .= self::formatHelp($theme->getHelp());
+        $res .= '</table>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bh();
+        $res .= '<table class="liste">';
+        $res .= self::formatHelp($book->getHelp());
+        $res .= '</table>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+
+        return $res;
+    }
+
+    public static function formatHelp($rubriques)
+    {
+        commonDroits::min(5);
+
+        $res = '';
+        foreach ($rubriques as $label => $fields) {
+            $res .= '<tr class="odd"><th colspan="5">' . $label . '</th></tr>';
+            foreach ($fields as $name => $t) {
+                if (is_string($t) && $t == '|') {
+                    $res .= '<tr class="odd"><th></th></tr>';
+                } else {
+                    $res .= '<tr>';
+                    foreach ($t as $tt) {
+                        $res .= '<td>' . $tt . '</td>';
+                    }
+                    $res .= '</tr>';
+                }
+            }
+        }
+        return $res;
+    }
+
+    public static function clients($args)
+    {
+        global $core;
+        cubePage::truePopup();
+        cubePage::autoComplete();
+        cubePage::emptyfield();
+        commonDroits::min(3);
+        $settings = $core->user->getSettings('clients_ws');
+
+        $shortcuts = array();
+        $shortcuts[] = '<a href="#" class="popup" rel="formClient/new">' . $core->typo->Ajouter('Créer un nouveau client') . '</a>';
+
+        $filtres = array();
+        if (wsDroits::admin()) {
+            $filtres[] = new commonFiltre(__('Grade'), 'ws_grade', $settings['filtres']);
+            $filtres[] = new commonFiltre(__('Administrateur'), 'admin_client', $settings['filtres']);
+        }
+
+        $res = commonPage::barre($filtres, 'filtreClients', 'clients', $shortcuts);
+        $res .= commonPage::tMain();
+        $res .= commonPage::bh();
+        $res .= '<div id="listeClients">';
+        $res .= self::listeClients();
+        $res .= '</div>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+        return $res;
+    }
+
+    public static function listeClients($dashboard = null, $settings = null)
+    {
+        global $core;
+        commonDroits::min(3);
+        $settings = is_null($settings) ? $core->user->getSettings('clients_ws') : $settings;
+        $change = is_null($dashboard) ? 'Client' : 'Dashboard/' . $dashboard;
+
+        $dao = new commonDAOEntreprise($core->con);
+        if (isset($settings['search']) && !is_null($settings['search'])) {
+            $dao->setSearch($settings['search']);
+        }
+        $dao->setFiltres($settings['filtres']);
+
+        $admin = wsDroits::admin();
+
+        if ($admin) {
+            $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], null, 'entreprises_ws');
+        } else {
+            $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user, 'entreprises_ws');
+        }
+
+        $res = '<table class="liste">';
+        $res .= '<tr><th>' . commonUrl::orderby('#', 'entreprise_id', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Raison sociale'), 'nom', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . __('Contacts') . '</th>';
+        if ($admin) {
+            $res .= '<th>' . commonUrl::orderby(__('Grade'), 'ws_grade', $settings, 'sort', $change) . '</th>';
+            $res .= '<th>' . commonUrl::orderby(__('Revendeur'), 'revendeur', $settings, 'sort', $change) . '</th>';
+            $res .= '<th>' . commonUrl::orderby(__('Administrateur'), 'administrateur', $settings, 'sort', $change) . '</th>';
+        }
+        $res .= '<th class="min"></th><th class="min"></th></tr>';
+        $i = 0;
+        foreach ($liste as $id => $client) {
+            if (!is_array($client->contacts)) {
+                $client->contacts = array();
+            }
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '>';
+            $res .= '<td>' . $client->entreprise_id . '</td>';
+            $res .= '<td>' . $client->nom . '</td>';
+            $contacts = array();
+
+            foreach ($client->contacts as $c) {
+                $contacts[] = '<a href="#" class="popup" rel="formContact/' . $c->utilisateur_id . '">' . $c->prenom . ' ' . $c->nom . '</a>';
+            }
+
+            $res .= '<td id="contacts_' . $client->entreprise_id . '">' . implode(', ', $contacts) . '</td>';
+
+            if ($admin) {
+                $rev = $client->ws_revendeur == '' ? '-' : $client->ws_revendeur;
+                $adm = $client->ws_administrateur == '' ? '-' : $client->ws_administrateur;
+
+                if ($client->ws_grade == 0) {
+                    $rev = $adm = '-';
+                }
+
+                $res .= '<td>' . $core->ws_grades[$client->ws_grade] . '</td>';
+                $res .= '<td>' . $rev . '</td>';
+                $res .= '<td>' . $adm . '</td>';
+            }
+
+            $res .= '<td class="nowrap">';
+            $res .= '</td>';
+            $res .= '<td class="action"><a href="#" class="popup" rel="formClient/' . $client->entreprise_id . '">' . cubeMedia::image(IMG . '/edit.png') . '</a></td>';
+            $res .= '</tr>';
+            $i++;
+        }
+        if (!isset($settings['search']) || is_null($settings['search'])) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '><td colspan="10">';
+            if ($admin) {
+                $res .= commonPage::pager($settings['page'], $dao->count(null, 'entreprises_ws'), $settings['par_page'], 'page' . $change . '/%d');
+            } else {
+                $res .= commonPage::pager($settings['page'], $dao->count($core->user, 'entreprises_ws'), $settings['par_page'], 'page' . $change . '/%d');
+            }
+            $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('clients'));
+            $res .= '</td></tr>';
+        }
+        $res .= '</table>';
+        return $res;
+    }
+
+    public static function formClient($entreprise_id = 'new')
+    {
+        global $core;
+        commonDroits::min(3);
+        $dao = new commonDAOEntreprise($core->con);
+        $daoUtilisateur = new commonDAOUtilisateur($core->con);
+        if ($entreprise_id == 'new') {
+            $client = $dao->cree();
+        } else {
+            $client = $dao->selectById($entreprise_id);
+        }
+
+        $res = '<tr><td>' . __('Numéro de client') . '</td><td>' . form::hidden('entreprise_id', $client->entreprise_id) . '' . $client->entreprise_id . '</td></tr>';
+        $res .= '<tr><td>' . __('Raison sociale') . '</td><td>' . form::field('nom', 30, 128, $client->nom) . '</td></tr>';
+        $res .= '<tr><td>' . __('Adresse') . '</td><td>' . form::textarea('adresse', 40, 3, $client->adresse) . '</td></tr>';
+        $res .= '<tr><td>' . __('Code postal') . '</td><td>' . form::field('code_postal', 10, 20, $client->code_postal) . '</td></tr>';
+        $res .= '<tr><td>' . __('Ville') . '</td><td>' . form::field('ville', 30, 128, $client->ville) . '</td></tr>';
+        $res .= '<tr><td>' . __('Pays') . '</td><td>' . form::combo('pays', cubeCountry::getList(), $client->pays) . '</td></tr>';
+        $res .= '<tr><td>' . __('Site internet') . '</td><td>' . form::field('site', 30, 128, $client->site) . '</td></tr>';
+        if (wsDroits::admin(false)) {
+            $res .= '<tr><td>' . __('Adresse de facturation') . '</td><td>' . form::textarea('adresse_facturation', 40, 3, $client->adresse_facturation) . '</td></tr>';
+            $res .= '<tr><td>' . __('Numéro de TVA intracommunautaire') . '</td><td>' . form::field('tva_intra', 15, 64, $client->tva_intra) . '</td></tr>';
+        }
+        // Bloc Fluidbook Workshop
+        if (wsDroits::admin(false)) {
+            $res .= '<tr class="light"><th colspan="2" class="light"><strong>' . __('Fluidbook Workshop') . '</strong></th></tr>';
+            $res .= '<tr class="odd"><td>' . __('Grade') . '</td><td>' . form::combo('ws_grade', array_flip($core->ws_grades), $client->ws_grade) . '</td></tr>';
+            if ($entreprise_id == 'new' || !$client->ws_admin) {
+                $class = 'empty-field';
+                $default_id = '';
+                $default = __("Entrez le nom du revendeur ou de l'administrateur");
+            } else {
+                $class = '';
+                $default_id = $client->ws_admin;
+                $wsa = $daoUtilisateur->selectById($client->ws_admin, 'utilisateurs_entreprise');
+                $default = $wsa->utilisateur_id . ' - ' . $wsa->rs . ' (' . $wsa->prenom . ' ' . $wsa->nom . ')';
+            }
+
+            $d = $dao->getWSDatas($entreprise_id);
+
+            $res .= '<tr class="odd"><td>' . __('Revendeur / Administrateur') . '</td><td>' . form::field('ws_admin_nom', 60, 128, $default, $class) . form::hidden('ws_admin', $default_id) . '</td></tr>';
+            if (!is_null($d)) {
+                $res .= '<tr class="odd"><td>' . __('Entité facturable') . '</td><td>' . $d->facturable->prenom . ' ' . $d->facturable->nom . ' (' . $d->facturable->rs . ')</td></tr>';
+                $res .= '<tr class="odd"><td>' . __('Administrateur responsable') . '</td><td>' . $d->administrateur->prenom . ' ' . $d->administrateur->nom . ' (' . $d->administrateur->rs . ')</td></tr>';
+            }
+
+            $daoSignature = new wsDAOSignature($core->con);
+            $signaturesList = $daoSignature->selectAll();
+
+            $signatures = array();
+            foreach ($signaturesList as $s) {
+                $signatures[$s->nom] = $s->signature_id;
+            }
+
+            $res .= '<tr class="odd"><td>' . __('Signatures Fluidbook') . '</td><td>' . cubeForm::checkMultiple('ws_signatures', $signatures, 5, explode(',', $client->ws_signatures)) . '</td></tr>';
+        }
+        if ($entreprise_id == 'new') {
+            $daoContact = new commonDAOClient($core->con);
+            $contact = $daoContact->cree();
+            $res .= '<tr><th colspan="2" class="light"><strong>' . __('Contact') . '</strong></th></tr>';
+            $res .= '<tr><td>' . __('Adresse e-mail') . '</td><td>' . form::field(array('contact[email]'), 30, 128, $contact->email) . '</td></tr>';
+            $res .= '<tr><td>' . __('Mot de passe') . '</td><td>' . form::field(array('contact[password]'), 30, 128, $contact->password) . '</td></tr>';
+            $res .= '<tr><td>' . __('Prénom') . '</td><td>' . form::field(array('contact[prenom]'), 30, 128, $contact->prenom) . '</td></tr>';
+            $res .= '<tr><td>' . __('Nom') . '</td><td>' . form::field(array('contact[nom]'), 30, 128, $contact->nom) . '</td></tr>';
+            $res .= '<tr><td>' . __('Téléphone') . '</td><td>' . form::field(array('contact[telephone]'), 20, 128, $contact->telephone) . '</td></tr>';
+            $res .= '<tr><td>' . __('Mobile') . '</td><td>' . form::field(array('contact[mobile]'), 20, 128, $contact->mobile) . '</td></tr>';
+            $res .= '<tr><td>' . __('Fax') . '</td><td>' . form::field(array('contact[fax]'), 20, 128, $contact->fax) . '</td></tr>';
+            $res .= '<tr><td>' . __('Langue') . '</td><td>' . form::combo(array('contact[lang]'), cubeLang::getAvailableLangs(true), $contact->lang) . '</td></tr>';
+        }
+        return $res;
+    }
+
+    public static function listeContacts($entreprise_id)
+    {
+        global $core;
+        commonDroits::min(3);
+        $dao = new commonDAOEntreprise($core->con);
+        $contacts = $dao->getContacts($entreprise_id);
+
+        $res = '<table class="liste light">';
+        $res .= '<tr class="light"><th colspan="4"><a href="" class="popup" rel="formContact/new/' . $entreprise_id . '">' . $core->typo->Contact('Ajouter un contact') . '</a></th></tr>';
+        $i = 0;
+        foreach ($contacts as $contact) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '><td>' . trim($contact->prenom . ' ' . $contact->nom) . '</td>';
+            $res .= '<td><a href="mailto:' . trim($contact->prenom . ' ' . $contact->nom) . '<' . $contact->email . '>">' . $contact->email . '</a></td>';
+            $res .= '<td class="min"><a href="' . SITE_PATH . 'fichiers/' . $contact->utilisateur_id . '">FTP</a></td>';
+            //$res .= '<td><a class="ajax" href="#" rel="connectAs/' . $contact->utilisateur_id . '">Se connecter comme ...</a></td>';
+            $res .= '<td class="right"><a href="#" rel="formContact/' . $contact->utilisateur_id . '" class="popup">' . cubeMedia::image(IMG . '/edit.png') . '</a></td></tr>';
+            $i++;
+        }
+        $res .= '</table>';
+        return $res;
+    }
+
+    public static function formCollection($collection_id = 'new')
+    {
+        global $core;
+        commonDroits::min(3);
+        $dao = new wsDAOCollection($core->con);
+        if ($collection_id != 'new') {
+            $collection = $dao->selectById($collection_id);
+        } else {
+            $collection = $dao->cree();
+        }
+
+        $res = '<tr><td>#</td><td>' . form::hidden('collection_id', $collection->collection_id) . $collection->collection_id . '</td></tr>';
+        $res .= '<tr><td>Nom de la collection</td><td>' . form::field('nom', 20, 64, $collection->nom) . '</td></tr>';
+        return $res;
+    }
+
+    public static function formContact($client_id = 'new', $entreprise_id = null)
+    {
+        global $core;
+        commonDroits::min(3);
+
+        $dao = new commonDAOClient($core->con);
+        if ($client_id == 'new') {
+            $client = $dao->creeFromEntreprise($entreprise_id);
+        } else {
+            $client = $dao->selectById($client_id);
+        }
+
+        $res = '<tr><td>' . __('Numéro de client') . '</td><td>' . form::hidden('grade', 0) . form::hidden('entreprise', $client->entreprise) . form::hidden('utilisateur_id', $client->utilisateur_id) . '' . $client->utilisateur_id . '</td></tr>';
+        $res .= '<tr><td>' . __('Login activé') . '</td><td>' . form::hidden('enabled', 0) . form::checkbox('enabled', 1, $client->enabled) . '</td></tr>';
+        $res .= '<tr><td>' . __('Adresse e-mail') . '</td><td>' . form::field('email', 30, 128, $client->email) . '</td></tr>';
+        $res .= '<tr><td>' . __('Mot de passe') . '</td><td>' . form::field('password', 30, 128, $client->password) . '</td></tr>';
+        $res .= '<tr><td>' . __('Prénom du contact') . '</td><td>' . form::field('prenom', 30, 128, $client->prenom) . '</td></tr>';
+        $res .= '<tr><td>' . __('Nom du contact') . '</td><td>' . form::field('nom', 30, 128, $client->nom) . '</td></tr>';
+        $res .= '<tr><td>' . __('Adresse') . '</td><td>' . form::textarea('adresse', 40, 3, $client->adresse) . '</td></tr>';
+        $res .= '<tr><td>' . __('Code postal') . '</td><td>' . form::field('code_postal', 10, 20, $client->code_postal) . '</td></tr>';
+        $res .= '<tr><td>' . __('Ville') . '</td><td>' . form::field('ville', 30, 128, $client->ville) . '</td></tr>';
+        $res .= '<tr><td>' . __('Pays') . '</td><td>' . form::combo('pays', cubeCountry::getList(), $client->pays) . '</td></tr>';
+        $res .= '<tr><td>' . __('Téléphone') . '</td><td>' . form::field('telephone', 20, 128, $client->telephone) . '</td></tr>';
+        $res .= '<tr><td>' . __('Mobile') . '</td><td>' . form::field('mobile', 20, 128, $client->mobile) . '</td></tr>';
+        $res .= '<tr><td>' . __('Fax') . '</td><td>' . form::field('fax', 20, 128, $client->fax) . '</td></tr>';
+        $res .= '<tr><td>' . __('Langue') . '</td><td>' . form::combo('lang', cubeLang::getAvailableLangs(true), $client->lang) . '</td></tr>';
+        if ($client_id != 'new') {
+            $res .= '<tr><td colspan="2">' . cubeMedia::spacer(10, 10) . '</td></tr>';
+            $res .= '<tr><td></td><td><a href="' . SITE_PATH . 'fichiers/' . $client->utilisateur_id . '">' . __('FTP') . '</a></td></tr>';
+            //$res .= '<tr><td></td><td><a href="#" class="ajax" rel="connectAs/' . $client->utilisateur_id . '">' . __('Se connecter comme ...') . '</a></td></tr>';
+            $res .= '<tr><td>' . __("Paramètres de connexion au Fluidbook Workshop") . '</td><td>' . __('Adresse') . ' : https://' . $_SERVER['HTTP_HOST'] . '/<br />' . __("Nom d'utilisateur") . ' : ' . $client->email . '<br />' . __('Mot de passe') . ' : ' . $client->password . '</td></tr>';
+            $res .= '<tr><td colspan="2">' . cubeMedia::spacer(10, 10) . '</td></tr>';
+        }
+        return $res;
+    }
+
+    public static function demandes()
+    {
+        global $core;
+        cubePage::truePopup();
+        cubePage::autoComplete();
+        cubePage::emptyfield();
+        commonDroits::min(5);
+        $settings = $core->user->getSettings('demandes');
+
+        $shortcuts = array();
+
+        $filtres = array();
+        $filtres[] = new commonFiltre(__('Statut'), 'status_demande', $settings['filtres']);
+        $filtres[] = new commonFiltre(__('Confiées à'), 'demande_moi', $settings['filtres']);
+
+        $res = commonPage::barre($filtres, 'filtreDemandes', 'demandes', $shortcuts);
+        $res .= commonPage::tMain();
+        $res .= commonPage::bh();
+        $res .= '<div id="listeDemandes">';
+        $res .= self::listeDemandes();
+        $res .= '</div>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+        return $res;
+    }
+
+    public static function listeDemandes($dashboard = null, $settings = null)
+    {
+        global $core;
+        commonDroits::min(5);
+        $settings = is_null($settings) ? $core->user->getSettings('demandes') : $settings;
+        $change = is_null($dashboard) ? 'Demandes' : 'Dashboard/' . $dashboard;
+        $dao = new wsDAODemande($core->con);
+        if (isset($settings['search']) && !is_null($settings['search'])) {
+            $dao->setSearch($settings['search']);
+        }
+        $dao->setFiltres($settings['filtres']);
+        $liste = $dao->getListe($settings['orderby'], $settings['sens'], $settings['limit'], $core->user);
+
+        $res = '<table class="liste">';
+        $res .= '<tr><th>' . commonUrl::orderby('#', 'demande_id', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Date'), 'date', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Type'), 'type', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Prospect') . '/' . __('Client'), 'utilisateur_nom', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Confiée à'), 'revendeur_nom', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Gérée par'), 'administrateur_nom', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th>' . commonUrl::orderby(__('Statut'), 'status', $settings, 'sort' . $change) . '</th>';
+        $res .= '<th class="min"></th><th class="min"></th></tr>';
+        $i = 0;
+        foreach ($liste as $id => $demande) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '>';
+            $res .= '<td>' . $demande->demande_id . '</td>';
+            $res .= '<td>' . date(__('d/m/Y H:i'), $demande->date) . '</td>';
+            $res .= '<td>' . $core->demandes_type[$demande->type] . '</td>';
+            $res .= '<td><a href="#" class="popup" rel="formClient/' . $demande->entreprise . '">' . $demande->utilisateur_nom . '</a></td>';
+            $revendeur = $demande->revendeur == 0 ? '-' : $demande->revendeur_nom;
+            $res .= '<td>' . $revendeur . '</td>';
+            $administrateur = $demande->administrateur == 0 ? '-' : $demande->administrateur_nom;
+            $res .= '<td>' . $administrateur . '</td>';
+            // Affichage du status
+            // Si non traitée ou traitée, pas la possibilité de changer le status
+            if ($demande->status == 0 || $demande->status == 2) {
+                $res .= '<td>' . $core->demandes_status[$demande->status] . '</td>';
+            } else if ($demande->status == 1) {
+                if ($demande->revendeur == $core->user->utilisateur_id) {
+                    $res .= '<td><a href="#" class="ajax" rel="reponseDemande/' . $demande->demande_id . '/' . $demande->revendeur . '/1/1">' . __('Je me suis chargé de cette demande') . '</a></td>';
+                } else {
+                    $res .= '<td>' . $core->demandes_status[$demande->status] . ' (<a href="#" class="ajax" rel="resetDemande/' . $demande->demande_id . '" title="' . __('Réinitialiser la demande') . '">x</a>)</td>';
+                }
+            }
+            // On ne peut éditer que si la facture est non traitée et qu'elle n'a pas commencé à être éditée par un autre administrateur
+            if (($demande->administrateur == 0 || $demande->administrateur == $core->user->utilisateur_id) && $demande->status == 0) {
+                $res .= '<td class="action"><a href="#" class="popup" rel="formDemande/' . $demande->demande_id . '">' . cubeMedia::image(IMG . '/edit.png') . '</a></td>';
+            } else {
+                $res .= '<td></td>';
+            }
+            // On n'affiche le bouton "Supprimer" que si la demande est non-traitée
+            if (($demande->administrateur == 0 || $demande->administrateur == $core->user->utilisateur_id) && $demande->status == 0) {
+                $res .= '<td class="action"><a href="#" class="ajax" rel="supprimeDemande/' . $demande->demande_id . '" title="' . __('Êtes-vous certain de vouloir supprimer cette demande ?') . '">' . cubeMedia::image(IMG . '/delete.png') . '</a></td>';
+            } else {
+                $res .= '<td></td>';
+            }
+            $res .= '</tr>';
+            $i++;
+        }
+        if (!isset($settings['search']) || is_null($settings['search'])) {
+            $odd = cubeMath::isOdd($i) ? ' class="odd"' : '';
+            $res .= '<tr' . $odd . '><td colspan="10">';
+            $res .= commonPage::pager($settings['page'], $dao->count($core->user), $settings['par_page'], 'page' . $change . '/%d');
+            $res .= commonUrl::formParPage('parPage' . $change, $settings['par_page'], __('demandes'));
+            $res .= '</td></tr>';
+        }
+        $res .= '</table>';
+        return $res;
+    }
+
+    public static function formDemande($demande_id = 'new')
+    {
+        global $core;
+        commonDroits::min(5);
+        $dao = new wsDAODemande($core->con);
+        $demande = $dao->selectById($demande_id);
+
+        if ($demande->administrateur != 0 && $demande->administrateur != $core->user->utilisateur_id) {
+            $action = __("Cette demande est actuellement en cours d'édition par un autre administrateur");
+        } elseif ($demande->status > 1) {
+            $action = __("Cette demande est actuellement en cours de traitement");
+        } else {
+            $action = '<a href="#" rel="lockDemande/' . $demande->demande_id . '" class="ajax">' . __("Cliquez-ici pour effectuer une action") . '</a>';
+        }
+
+
+        $res = '<tr><td>' . __('Numéro de demande') . '</td><td>' . form::hidden('demande_id', $demande->demande_id) . '' . $demande->demande_id . '</td></tr>';
+        $res .= '<tr><td>' . __('Date de la demande') . '</td><td>' . date(__('d/m/Y H:i'), $demande->date) . '</td></tr>';
+        $res .= '<tr><td>' . __('Emetteur de la demande') . '</td><td><a href="#" class="popup" rel="formClient/' . $demande->entreprise . '">' . $demande->utilisateur_nom . '</a></td></tr>';
+        $res .= '<tr><td>' . __('Nombre de pages') . '</td><td>' . $demande->pages . '</td></tr>';
+        $res .= '<tr><td>' . __('Nombre de liens') . '</td><td>' . $demande->liens . '</td></tr>';
+        $res .= '<tr><td>' . __('Nombre de langues') . '</td><td>' . $demande->langues . '</td></tr>';
+        $res .= '<tr><td>' . __('Détails') . '</td><td>' . $demande->details . '</td></tr>';
+        $res .= '<tr><td>' . __('Action') . '</td><td><div id="actionDemande">' . $action . '</div></td></tr>';
+        $res .= '<tr><td></td></tr>';
+
+        return $res;
+    }
+
+    public static function reponseDemande($args)
+    {
+        global $core;
+
+        commonDroits::min(3);
+
+
+        $demande_id = $args[1];
+        $revendeur_id = $args[2];
+
+        $dao = new wsDAODemande($core->con);
+        $demande = $dao->selectById($demande_id);
+
+        $res = commonPage::barre();
+        $res .= commonPage::tMain();
+        $res .= commonPage::bh();
+        $res .= '<div id="accepteDemandes">';
+        $res .= '<h1>' . __('Prendre en charge une demande de devis') . '</h1>';
+        $res .= '<br /><br />';
+
+        if ($demande->revendeur != $revendeur_id || $demande->revendeur != $core->user->utilisateur_id || $demande->status == 0) {
+            $res .= '<p class="center">' . __('Cette demande de devis ne vous est pas adressée.') . '</p>';
+        } else if ($demande->status == 2) {
+            $res .= '<p class="center">' . __('Merci ! Nous avons bien pris en compte votre réponse.') . '<br /><br />';
+            $res .= '<a href="' . $dao->getMailto($demande_id) . '">' . __("Ouvrir l'email de réponse") . '</a>';
+            $res .= '</p>';
+        } else {
+            $res .= '<p>' . __('Si vous acceptez de traiter la demande suivante, veuillez cliquer sur le bouton "Accepter la demande" situé à droite de la description.');
+            $res .= ' ' . __('Vous avez également la possibilité de décliner la demande en cliquant sur le bouton "Décliner la demande"') . "</p>";
+            $res .= '<br /><br />';
+
+            $res .= '<table>';
+            $res .= '<tr><th class="left" colspan="2">' . __("Détails de la demande") . '</th><th class="left" style="width:40%">' . __('Votre action') . '</th></tr>';
+            $res .= '<tr><td>' . __('Numéro de demande') . '</td><td>' . $demande->demande_id . '</td>';
+            $res .= '<td>' . '<a href="#" class="ajax download btbook" rel="reponseDemande/' . $demande_id . '/' . $revendeur_id . '/1" ><div></div><span>' . __('Accepter la demande') . '</span></a>' . '</td></tr>';
+            $res .= '<tr><td>' . __('Date de la demande') . '</td><td>' . date(__('d/m/Y H:i'), $demande->date) . '</td></tr>';
+            $res .= '</tr>';
+            $res .= '<tr><td>' . __('Client') . ' / ' . __('Prospect') . '</td><td><a href="#" class="popup" rel="formClient/' . $demande->entreprise . '">' . $demande->utilisateur_nom . '</a></td></tr>';
+            $res .= '<tr><td>' . __('Nombre de pages') . '</td><td>' . $demande->pages . '</td>';
+            $res .= '<td>' . '<a href="#" class="ajax suppr btbook" rel="reponseDemande/' . $demande_id . '/' . $revendeur_id . '/0"><div></div><span>' . __('Décliner la demande') . '</span></a>' . '</td>';
+            $res .= '</tr>';
+            $res .= '<tr><td>' . __('Nombre de liens') . '</td><td>' . $demande->liens . '</td></tr>';
+            $res .= '<tr><td>' . __('Nombre de langues') . '</td><td>' . $demande->langues . '</td></tr>';
+            $res .= '<tr><td>' . __('Détails') . '</td><td>' . $demande->details . '</td></tr>';
+            $res .= '</table>';
+        }
+
+        $res .= '</div>';
+        $res .= commonPage::bf();
+        $res .= commonPage::bMain();
+        return $res;
+    }
+
+    public static function orpiref($args)
+    {
+        $ref = $args[1];
+
+
+        try {
+            $adapter = new Zend_Http_Client_Adapter_Socket();
+            $streamOpts = array(
+                'ssl' => array(
+                    'verify_peer' => false,
+                    'allow_self_signed' => true
+                )
+            );
+            $adapter->setStreamContext($streamOpts);
+            $client = new Zend_Http_Client();
+            $client->setAdapter($adapter);
+            $client->setEncType(Zend_Http_Client::ENC_FORMDATA);
+            $client->setMethod(Zend_Http_Client::POST);
+            $client->setParameterPost(array('reference' => $ref));
+            $client->setUri('https://www.orpi.com/recherche/search_by_reference');
+            $client->setHeaders(['X-Requested-With' => 'XMLHttpRequest',
+                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0',
+                'Origin' => 'https://www.orpi.com',
+                'Referer' => 'https://www.orpi.com/',
+                'Pragma' => 'no-cache',
+                'DNT' => '1']);
+            $response = $client->request();
+            $json = $response->getBody();
+            $res = 'https://www.orpi.com';
+            if ($json === false) {
+                header('Location: ' . $res);
+                exit;
+            }
+            $r = json_decode($json);
+            if ($r === false) {
+                header('Location: ' . $res);
+                exit;
+            }
+
+            if (isset($r->success) && $r->success && isset($r->location)) {
+                header('Location: ' . $res . $r->location);
+                exit;
+            }
+
+            header('Location: ' . $res);
+        } catch (Exception $e) {
+            ob_end_clean();
+            echo $e->getMessage();
+        }
+
+        header('Location: https://www.orpi.com/');
+    }
 }
index ce61aab3a8c25d5bcbea885a5897c61994803557..0e18e2b89ee4ebb942b0872573faaa330e265bef 100644 (file)
@@ -521,8 +521,12 @@ class wsBookParametres extends wsParametres
         $this->fields['secureURL'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __('URL de sécurisation'), 'grade' => 5, 'hint' => __('URL intérrogé pour vérifier si le visiteur à les droits pour consulter la publication'));
         $this->fields['secureURLRedirect'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __('Redirection'), 'grade' => 5, 'hint' => __("Si l'authentification échoue, redirection vers cette adresse"));
         $this->fields['preventRightClick'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Essayer d'empêcher le clic droit"), 'grade' => 1);
+        $this->fields['restrictPrint'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Restreindre l'impression"), 'grade' => 5);
+        $this->fields['restrictDownload'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Restreindre l'impression"), 'grade' => 5);
+        $this->fields['restrictSendBookmark'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Restreindre l'envoi de marques-pages"), 'grade' => 5);
+        $this->fields['restrictPrintDownload'] = ['type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Paramètre de l\'url permettant de désactiver la restriction (non vide pour activer les restrictions)'), 'grade' => 5, 'hint' => __("Ne pas indiquer le ?")];
         $this->forms['secure'] = array('label' => __('Sécurisation'),
-            'fieldsnames' => array('secureURL', 'secureURLRedirect', '|', 'preventRightClick'));
+            'fieldsnames' => array('secureURL', 'secureURLRedirect', '|', 'preventRightClick', '|', 'restrictPrintDownload', 'restrictPrint', 'restrictDownload', 'restrictSendBookmark'));
 
         $this->fields['home'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Accueil de l'interface multibrochure"), 'grade' => 5);
         $this->fields['multilang'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Langues'), 'hint' => __('Code langue') . ',' . __('Code pays') . ',' . __('URL'));