Problème de renommage au moment de l'import de fichier - Composant elearning Shika

Réduire
X
 
  • Filtrer
  • Heure
  • Afficher
Tout effacer
nouveaux messages

  • Problème de renommage au moment de l'import de fichier - Composant elearning Shika

    Bonjour,

    Je rencontre un problème avec un composant d’elearning Shika.

    Avec ce composant, il est possible de créer des leçons, et pour chaque leçon d’associer un ou plusieurs fichiers (par exemple des fichiers PDF ou PPTX).
    Le problème est que les fichiers sont randomisés au moment de l’import sur le site.
    L’import se fait via le composant.
    Si mon fichier se nomme : « fichier.pdf », quand je vais sur l’interface utilisateur frontend (en tant qu'étudiant), je vois bien dans la section des fichiers à télécharger le nom correct de mon fichier, mais quand je le télécharge, il est intitulé par exemple « 2247054353.pdf ».

    Sur le FTP, le fichier se retrouve dans le répertoire / media / com_tjlms / lessons

    Je pense qu’il faudrait modifier le fichier qui traite de l’import pour agir sur ce point, car c’est au moment de l’import que le fichier est renommé. Mais je ne vois pas où chercher…

    Voici par exemple une partie du fichier fileupload.json.php qui se trouve dans les controllers du composant :

    public function addTableEntries()
    {
    $input = JFactory::getApplication()->input;
    $post = $input->post;
    $uploadPathData = $mediaData = [];

    $testData = $post->get('test', array(), 'ARRAY');
    $lessonData = $post->get('lesson', array(), 'ARRAY');
    $format = $uploadPathData['mediaformat'] = $post->get('mediaformat', '', 'STRING');
    $subformat = $uploadPathData['subformat'] = $post->get('subformat', '', 'STRING');
    $file = $post->get('fileToUpload', '', 'Array');

    JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_tjlms/models');
    $mediaModel = JModelLegacy::getInstance('Media', 'TjlmsModel');

    if (!empty($file))
    {
    $mediaData['source'] = JFile::makeSafe($file['source']);
    $mediaData['org_filename'] = JFile::makeSafe($file['name']);
    $mediaData['format'] = $format;
    $mediaData['sub_format'] = $subformat;

    // $mediaData['path'] = $this->getuploadFolder($uploadPathData);
    $mediaData['created_by'] = JFactory::getUser()->id;
    $path = $this->getuploadFolder($uploadPathData);

    if (JFile::exists($path . $mediaData['source']))
    {
    $mediaModel->save($mediaData);
    $mediaId = $mediaModel->getState($mediaModel->getName() . '.id');

    if (!empty($format))
    {
    if ($format == 'test' && $subformat == 'answer.upload')
    {
    $mediaData['path'] = JRoute::_('index.php?option=com_tjlms&task=lesson. downloadMedia&mid=' . $mediaId);

    JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_tmt/tables');
    $testAnswersTable = JTable::getInstance('testanswers', 'TmtTable', array('dbo', JFactory::getDbo()));

    $test = $post->get('test', array(), "Array");
    $olUserId = JFactory::getUser()->id;
    $testAnswersTable->load(
    array("question_id" => $test['answer']['qid'],
    "user_id" => $olUserId, "test_id" => $test['answer']['testid'],
    "invite_id" => $test['answer']['ltid']
    )
    );
    $mediaData['answer_id'] = $testAnswersTable->id;
    $mediaData['qid'] = $testData['answer']['qid'];
    }
    elseif ($format == 'associate')
    {
    $db = JFactory::getDbo();
    $fileData = new stdClass;
    $fileData->id = '';
    $fileData->lesson_id = $lessonData['associate']['lessonId'];
    $fileData->media_id = $mediaId;
    $db->insertObject('#__tjlms_associated_files', $fileData, 'id');
    }
    }

    $mediaData['media_id'] = $mediaId;
    $msg = JText::_("COM_TJLMS_FILE_TABLE_ENTRIES_ADDED");
    echo new JResponseJson($mediaData, $msg);
    }
    else
    {
    echo new JResponseJson(0, JText::_("COM_TJLMS_ERROR_FILENOTSAFE_TO_UPLOAD"), true);
    }
    }
    else
    {
    echo new JResponseJson(0, JText::_("COM_TJLMS_ERROR_FILENOTSAFE_TO_UPLOAD"), true);
    }
    }
    }

    Voyez-vous dans ce fichier la commande qui indique de changer le nom du fichier ?
    [Précision : dans la base de données, la table pour les fichier uploadé comporte les champs suivants : "org_filename" (qui affiche le nom d’origine) et "source" (qui affiche le nom avec la suite de 10 chiffres)

    Merci à l'avance pour votre aide.

  • #2
    Bonjour,

    Ce composant étant commercial, cher et étant très rarement cité ici, tu devrais poser la question à son auteur.
    Il y a peut-être une raison (et éventuellement un paramétrage) pour que ce champ "source" soit un nombre remplaçant le nom réel. Mais je n'ai pas bien compris sous quel nom il est stocké dans "lessons", sous son nom "numérique" ? Si oui, c'est peut-être un moyen d'empêcher un téléchargement direct d'un fichier précis faute de connaître son nom exact.

    A vue de nez, dans le code que tu cites, j'aurais tendance à penser que c'est là que ce qui te gêne se passe :
    $mediaData['source'] = JFile::makeSafe($file['source']);
    $mediaData['org_filename'] = JFile::makeSafe($file['name']);
    "Patience et longueur de temps font plus que force ni que rage..." (La Fontaine : Le Lion et le Rat) - "Il n'y a pas de problèmes; il n'y a que des solutions" (André Gide).
    MoovJla et LazyDbBackup sur www.joomxtensions.com - FaQ sur www.fontanil.info - Site pro : www.robertg-conseil.fr chez PHPNET, sites perso chez PlanetHoster + sites gérés chez PHPNET, PlanetHoster, Ionos et OVH

    Commentaire


    • #3
      Bonjour,

      Merci pour ta réponse. C’est cool de voir quelqu’un qui s’intéresse un tant soit peu à ce problème, car j’ai bien compris qu’il s’agit d’un composant peu répandu. Il est payant mais il offre beaucoup de services. Moodle aussi devient payant dès lors qu’on veut certains services. Et par rapport à d’autres composant d’elearning pour Joomla, il m’a semblé vraiment le plus abouti, notamment au niveau des statistiques qui offrent plusieurs rapports pour suivre l’activité des étudiants.

      Je me suis tournée vers l’équipe de développement, on m’a répondu que cette demandé était mise sur la file d’attente et qu’elle serait honorée dans les versions futures. C’est un peu vague comme réponse et je voulais voir si j’arrivais à m’en dépatouiller.

      Pour répondre à tes questions, je mets en copie d’écran commet se présente la leçon en FO quand on clique sur le bouton des fichiers associés : on voit le nom d’origine du fichier avec l’extension pdf.
      Mais quand on télécharge le fichier, le nom est remplacé par une suite de 10 chiffres suivie de ".pdf" (la « source »). Sur le FTP, on a bien le fichier avec le nom encodé en chiffres.

      Dans la 2e copie d’écran, voilà comment ça se présente dans la base de données :
      le fichier « bonjour_pdf.pdf » (colonne « org_filename ») et le nom encodé (colonne « source »).

      Dans le fichier fileupload.json.php il y a l’extension JSON qui est utilisée. Elle permet d’encoder une chaîne de caractères.
      Je mets ici le fichier en entier.


      // No direct access
      defined('_JEXEC') or die;

      jimport('joomla.application.component.controllerfo rm');
      jimport('joomla.filesystem.folder');
      jimport('joomla.filesystem.file');

      /**
      * File upload controller class.
      *
      * since 1.0.0
      */
      class TjlmsControllerFileupload extends JControllerForm
      {
      /**
      * The main function triggered to upload file off question
      *
      * @return object of result and message
      *
      * since 1.0.0
      * */

      public function validateAndUpload()
      {
      $app = JFactory::getApplication();
      $input = JFactory::getApplication()->input;
      $tjlmsparams = JComponentHelper::getParams('com_tjlms');

      $return = $input->post->getArray();
      $return['fileToUpload'] = $input->files->get('FileInput', null, 'raw');

      // Validate the uploaded file
      $validate_result = $this->validateupload($return['fileToUpload']);
      $return['fileToUpload']['valid'] = 1;

      if ($validate_result['res'] != 1)
      {
      echo new JResponseJson(0, $validate_result['msg'], true);
      $app->close();
      }

      $res = $this->moveToCorrectFolder($return);

      if (!$res)
      {
      $fileName = $return['fileToUpload']['name'];
      echo new JResponseJson(0, JText::sprintf("COM_TJLMS_ERROR_UPLOADINGFILE", $fileName), true);
      }
      else
      {
      $return['fileToUpload']['source'] = $res;
      echo new JResponseJson($return, JText::sprintf("COM_TJLMS_UPLOAD_SUCCESS"));
      }
      }

      /**
      * The main function triggered to upload file off question
      *
      * @param Array $data Array of data for fileupload
      *
      * @return object of result and message
      *
      * since 1.0.0
      * */
      private function getuploadFolder($data)
      {
      $folder = '';

      if (!empty($data['mediaformat']))
      {
      if ($data['mediaformat'] == 'test' && $data['subformat'] == 'answer.upload')
      {
      $folder = 'media/com_tmt/test/';
      }
      else
      {
      $folder = 'media/com_tjlms/lessons/';
      }
      }

      return $folder;
      }

      /**
      * The main function triggered to upload file off question
      *
      * @param Array $data Array of data for fileupload
      *
      * @return mixed
      *
      * since 1.0.0
      * */

      private function moveToCorrectFolder($data)
      {
      $src = $data['fileToUpload']['tmp_name'];

      // Make the filename safe
      $fileName = JFile::makeSafe($data['fileToUpload']['name']);

      $ext = JFile::getExt($fileName);

      $filepath = $this->getuploadFolder($data);

      if (!$filepath)
      {
      echo new JResponseJson('', JText::sprintf("COM_TJLMS_NO_FOLDER_FOUND_AS_PER_F ORMAT"), true);
      }
      else
      {
      // New file name
      $newfilename = rand(0, 9999999999) . '.' . $ext;

      $PathWithName = $filepath . $newfilename;

      $destination = JPATH_SITE . '/' . $PathWithName;

      $options = array('fobidden_ext_in_content' => false);

      /*3rd param is to stream and 4is set to true to ask to upload unsafe file*/
      if (!JFile::upload($src, $destination, false, false, $options))
      {
      return false;
      }

      return $newfilename;
      }
      }

      /**
      * The function to validate the uploaded format file
      *
      * @param MIXED $fileToUpload file object
      *
      * @return object of result and message
      *
      * since 1.0.0
      * */
      private function validateupload($fileToUpload)
      {
      $tjlmsparams = JComponentHelper::getParams('com_tjlms');
      $mediaParams = JComponentHelper::getParams('com_media');
      $validExtensions = array_map('trim', explode(',', $mediaParams->get('upload_extensions')));
      $ext = JFile::getExt(JFile::makeSafe($fileToUpload['name']));

      $return = 1;
      $msg = '';

      if (!in_array($ext, $validExtensions))
      {
      $return = 0;
      $msg = JText::_("COM_TJLMS_ERROR_UNABLE_TO_UPLOAD_FILE");
      }
      elseif ($fileToUpload["error"] == UPLOAD_ERR_OK)
      {
      // Total length of post back data in bytes.
      $contentLength = (int) $_SERVER['CONTENT_LENGTH'];

      // Instantiate the media helper
      $mediaHelper = new JHelperMedia;

      // Maximum allowed size of post back data in MB.
      $postMaxSize = $mediaHelper->toBytes(ini_get('post_max_size'));

      // Maximum allowed size of script execution in MB.
      $memoryLimit = $mediaHelper->toBytes(ini_get('memory_limit'));

      // Maximum allowed size of script execution in MB.
      $uploadMaxFileSize = $mediaHelper->toBytes(ini_get('upload_max_filesize'));

      /* check if file size in within the uploading limit of site*/

      // Check for the total size of post back data.
      if ($contentLength > ($tjlmsparams->get('lesson_upload_size', 10) * 1024 * 1024)
      || ($postMaxSize > 0 && $contentLength > $postMaxSize)
      || ($uploadMaxFileSize > 0 && $contentLength > $uploadMaxFileSize)
      || ($memoryLimit != -1 && $contentLength > $memoryLimit))
      {
      $return = 0;
      $msg = JText::sprintf('COM_TMT_UPLOAD_SIZE_ERROR', $tjlmsparams->get('lesson_upload_size', 10, 'INT') . ' MB');
      }
      }
      else
      {
      $return = 0;
      $msg = JText::_("COM_TJLMS_ERROR_UPLOADINGFILE", $fileToUpload['name']);
      }

      $output['res'] = $return;
      $output['msg'] = $msg;

      return $output;
      }

      /**
      * Triggered from ajax
      *
      * @return json encoded id of the row of related table
      *
      * since 1.3
      * */
      public function onAfterUpload()
      {
      $input = JFactory::getApplication()->input;
      $return = $input->post->getArray();
      $msg = JText::_("COM_TJLMS_FILE_MOVED_TO_CORRECT_LOCATION ");
      echo new JResponseJson($return, $msg);
      }

      /**
      * Triggered from ajax
      * Add entry in tjlms_media
      *
      * @return json encoded id of the row of related table
      *
      * since 1.3
      * */
      public function addTableEntries()
      {
      $input = JFactory::getApplication()->input;
      $post = $input->post;
      $uploadPathData = $mediaData = [];

      $testData = $post->get('test', array(), 'ARRAY');
      $lessonData = $post->get('lesson', array(), 'ARRAY');
      $format = $uploadPathData['mediaformat'] = $post->get('mediaformat', '', 'STRING');
      $subformat = $uploadPathData['subformat'] = $post->get('subformat', '', 'STRING');
      $file = $post->get('fileToUpload', '', 'Array');

      JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_tjlms/models');
      $mediaModel = JModelLegacy::getInstance('Media', 'TjlmsModel');

      if (!empty($file))
      {
      $mediaData['source'] = JFile::makeSafe($file['source']);
      $mediaData['org_filename'] = JFile::makeSafe($file['name']);
      $mediaData['format'] = $format;
      $mediaData['sub_format'] = $subformat;

      // $mediaData['path'] = $this->getuploadFolder($uploadPathData);
      $mediaData['created_by'] = JFactory::getUser()->id;
      $path = $this->getuploadFolder($uploadPathData);

      if (JFile::exists($path . $mediaData['source']))
      {
      $mediaModel->save($mediaData);
      $mediaId = $mediaModel->getState($mediaModel->getName() . '.id');

      if (!empty($format))
      {
      if ($format == 'test' && $subformat == 'answer.upload')
      {
      $mediaData['path'] = JRoute::_('index.php?option=com_tjlms&task=lesson. downloadMedia&mid=' . $mediaId);

      JTable::addIncludePath(JPATH_ROOT . '/administrator/components/com_tmt/tables');
      $testAnswersTable = JTable::getInstance('testanswers', 'TmtTable', array('dbo', JFactory::getDbo()));

      $test = $post->get('test', array(), "Array");
      $olUserId = JFactory::getUser()->id;
      $testAnswersTable->load(
      array("question_id" => $test['answer']['qid'],
      "user_id" => $olUserId, "test_id" => $test['answer']['testid'],
      "invite_id" => $test['answer']['ltid']
      )
      );
      $mediaData['answer_id'] = $testAnswersTable->id;
      $mediaData['qid'] = $testData['answer']['qid'];
      }
      elseif ($format == 'associate')
      {
      $db = JFactory::getDbo();
      $fileData = new stdClass;
      $fileData->id = '';
      $fileData->lesson_id = $lessonData['associate']['lessonId'];
      $fileData->media_id = $mediaId;
      $db->insertObject('#__tjlms_associated_files', $fileData, 'id');
      }
      }

      $mediaData['media_id'] = $mediaId;
      $msg = JText::_("COM_TJLMS_FILE_TABLE_ENTRIES_ADDED");
      echo new JResponseJson($mediaData, $msg);
      }
      else
      {
      echo new JResponseJson(0, JText::_("COM_TJLMS_ERROR_FILENOTSAFE_TO_UPLOAD"), true);
      }
      }
      else
      {
      echo new JResponseJson(0, JText::_("COM_TJLMS_ERROR_FILENOTSAFE_TO_UPLOAD"), true);
      }
      }
      }

      Je vois le premier appel JSON en ligne 50 :
      echo new JResponseJson(0, $validate_result['msg'], true);
      Est-ce que c’est cette ligne qui encode le nom du fichier avant téléchargement ?
      Par quoi dois-je la remplacer pour que ce remplacement n’ait pas lieu ?

      Merci à l'avance pour votre aide.

      Commentaire


      • #4
        Bonjour,
        Sans connaitre l'extension, je pense plutôt que c'est cette ligne qui modifie le nom du fichier :
        Code:
        / New file name
        $newfilename = rand(0, 9999999999) . '.' . $ext;
        Ceci dit, tu dois prendre en compte le fait que si le fichier a son nom modifié, c'est peut être pour une raison particulière...
        - Protection contre les accès non autorisé ?
        - limite du nom de fichier dans la base pour le normaliser ?
        - est-ce que d'autres vérifications ou traitements sont réalisés par la suite sur ce nom ou c'est juste pour "masquer" le nom du fichier ?

        Dans tous les cas, si tu modifies cette ligne (en la commentant par exemple ou en modifiant en "$newfilename = $fileName.'.'.$ext;"), tu dois alors vérifier intégralement le fonctionnement (est-ce que le fichier reste accessible ? Est-ce qu'il est accessible directement ? Etc..) et en plus garder en tête que si tu fais une mise à jour ultérieure, tu risques d'avoir un gros problème de fonctionnement par la suite (si les personnes développant le composant modifie le code et que tes fichiers deviennent alors inaccessibles...).


        Cordialement,
        Chabi01 - http://www.xlformation.com

        Commentaire


        • #5
          Bonjour,

          En fait, si je comprends bien, le nom est codé à l'enregistrement, et le choix du fichier que doit récupérer l'élève semble le transférer tel qu'il est stocké, sans aucune "traduction".
          Donc à mon avis, deux solutions : empêcher le renommage lors de l'envoi sur le serveur, ou ajouter du code pour remplacer le "source" par son "name".
          Pour ça, il faudrait faire des tests sur une copie du site ou sur un site vierge, en sachant que ce sera à recommencer à chaque mise à jour si les auteurs n'ont pas intégré eux-mêmes la modification.
          "Patience et longueur de temps font plus que force ni que rage..." (La Fontaine : Le Lion et le Rat) - "Il n'y a pas de problèmes; il n'y a que des solutions" (André Gide).
          MoovJla et LazyDbBackup sur www.joomxtensions.com - FaQ sur www.fontanil.info - Site pro : www.robertg-conseil.fr chez PHPNET, sites perso chez PlanetHoster + sites gérés chez PHPNET, PlanetHoster, Ionos et OVH

          Commentaire


          • #6
            Merci pour votre rapidité et pour votre intérêt.

            Oui, RobertG, le nom est bien codé au moment du transfert. J’avais essayé d’intervertir les « org_filename » et « source » dans le fichier tmpl, mais ça donnait une erreur.

            Donc ta solution est bonne, Chabi01. C’est bien là qu’il fallait agir, merci super !

            Le code exact est :

            $newfilename = $fileName;
            tout simplement (sinon, il y avait doublement du point + extension).
            J’ai vérifié, le fonctionnement semble ok.

            Pour les mises à jour ultérieures, pensez-vous que le fait d’avoir modifié des fichiers php puisse empêcher une mise à jour ?
            Est-ce que ça peut être le cas aussi pour des fichiers css ?
            Merci pour vos éclaircissements.

            Commentaire


            • #7
              Bonjour,
              Content d'avoir pu aider
              Sinon, à partir du moment où c'est le code du composant que tu as modifié, à la prochaine mise à jour, tes modifications seront perdues puisque le fichier complet sera remplacé par la mise à jour.

              La solution est alors de noter précieusement toutes modifications que tu pourrais avoir besoin de remettre en place pour pouvoir les remettre à la prochaine mise à jour du composant (si les développeurs n'ont pas complètement changé le code ici

              Cordialement,
              Chabi01 - http://www.xlformation.com

              Commentaire

              Annonce

              Réduire
              Aucune annonce pour le moment.

              Partenaire de l'association

              Réduire

              Hébergeur Web PlanetHoster
              Travaille ...
              X