Randomly name images uploaded with clipboard

Hey @mleduc
Just saw the issue Loading... has been closed and marked as resolved. I’m using xWiki 14.10.4 and yet the problem still appears. Is there anything I can do ?

Thanks,
Marius

Hello @Marius, sorry to hear that.
You can first try to clean your browser cache.
If it does not fix the issue, you can create a new issue, mentioning XWIKI-20314 and describing:

  1. the reproduction steps (that are likely to be identical to XWIKI-20314)
  2. the environment (e.g., OS, Brower, OS language, Brower language, wiki language configuration)

Yes sure.
Just to understand the components I’m using, how could I know what is my current text editor ? I’m lost between CKEditor and WYSIWYG.

WYSIWYG is for things that are common to all rich editors. What makes it confusing is that we currently only support one rich editor: CKEditor.
So in short, you can create the issue using the CKEditor component.

PS: In any case, don’t be afraid of small mistakes. If the wrong component is used, someone will easily fix it :slight_smile:

Ok it is clearer for me. Thank you for the information.
I’ve created the issue Loading.... Please let me know if I can do anything else.

Marius

1 Like

Hello @Marius,

I tried to reproduce you issue on XWiki 14.10.3, 14.10.4 and 14.10.5 (detailed environments below), following your reproduction steps
I only managed to reproduce on 14.10.3. The issue has been fixed on 14.10.4 by Loading... so this is expected.

I’ve use two environments:

  • Ubuntu + English
  • Window 11 + French

Can you confirm that you tested on XWiki 14.10.4 and/or 14.10.5? You initially reported affect versions 14.10.1, 14.10.2, and 14.10.3, and mentioned 14.10.4 in the Environment section.

Did you try to clean your browser cache before testing?
Can you think of something specific to your installation that could lead to the issue (e.g., some custom config related to temporary attachment upload)?
Ultimately, can you share the content of CKEditor.FileUploader (e.g., http://localhost:8080/xwiki/bin/edit/CKEditor/FileUploader?editor=wiki)? This is where the fix to replace __fileCreatedFromDataURI__ with a timestamp and a random value is support to take place.

Hey ! Thank you for your time :slightly_smiling_face:

I indeed have the issue on xWiki 14.10.4, and made a mistake by saying 14.10.1, 2 and 3 where it was 2, 3 and 4. Sorry about that.
I didn’t know there was a release on 14.10.5 but I can give it a try today if you think it might resolves the issue.
I tried to clean my browser cache mostly by going into private navigation and try other navigators.

I haven’t done anything specific to my xWiki’s install. I went from 14.10.2 to 14.10.4 by apt upgrading my packages, but maybe it could be resolved by doing a fresh install ? It could be worth the try.

Here is the content of the url you gave me:

{{velocity output="false"}}
#macro (createAttachment $fileName)
  #set ($document = $doc)
  #if ("$!request.document" != '')
    #set ($document = $xwiki.getDocument($request.document))
  #end
  #if ($document && $document.hasAccessLevel('edit'))
    ## If the attachment is uploaded to a new document then make sure we create the document with the right default
    ## locale. See CKEDITOR-316: Document translations are created when uploading a file from the WYSIWYG editor in a
    ## multi-language wiki. The following code replicates the behavior of the Upload action, but it has the desired
    ## effect only on XWiki 11.9+
    #if ($document.isNew())
      #set ($rootLocale = $services.localization.toLocale(''))
      #set ($discard = $document.setLocale($rootLocale))
      #if ($rootLocale.equals($document.getDefaultLocale()))
        #set ($discard = $document.setDefaultLocale($xwiki.getLocalePreference()))
      #end
      ## We also need to make sure the new document is created with the right syntax (e.g. the one coming from the
      ## template used to create the document rather than the default wiki syntax).
      #if ("$!request.syntax" != '')
        #set ($discard = $document.setSyntaxId($request.syntax))
      #end
    #end
    ## FIXME: Get the file content as an input stream instead of a byte array, but for this we need to expose
    ## getFileItemInputStream in the public API of the fileupload plugin (or use a script service).
    #set ($bytes = $xwiki.fileupload.getFileItemData('upload'))
    #if (!$bytes)
      ## Empty file (unfortunately getFileItemData returns null instead of an empty byte array).
      #set ($bytes = [])
    #end
    #set ($discard = $document.addAttachment($fileName, $bytes))
    #set ($discard = $document.save($services.localization.render('core.comment.uploadAttachmentComment', [$fileName])))
    #sendSuccess($document $fileName)
  #else
    ## Forbidden
    #sendError(403 'You are not allowed to perform this action.')
  #end
#end

## Old way of uploading, with a save of the document for each upload.
#macro (handleUploadRequest)
  #set ($fileName = $xwiki.fileupload.getFileName('upload'))
  #if ("$!fileName" != '')
    #if ($services.csrf.isTokenValid($request.form_token))
      #if ($fileName.startsWith('__fileCreatedFromDataURI__.'))
        ## We need to generate a new name so that we don't overwrite existing attachments.
        #set ($extension = $stringtool.substringAfter($fileName, '.'))
        #set ($fileName = "${datetool.date.time}-${mathtool.random(100, 1000)}.$extension")
      #end
      #createAttachment($fileName)
    #else
      #sendError(403 "$services.localization.render('ckeditor.upload.error.csrf')")
    #end
  #else
    ## Bad Request
    #sendError(400 "$services.localization.render('ckeditor.upload.error.emptyReturn')")
  #end
#end

## New way of handling attachment without saving immediately the document.
#macro (handleTemporaryUploadRequest)
  #if ($services.csrf.isTokenValid($request.form_token))
    #set ($document = $doc)
    #if ("$!request.document" != '')
      #set ($document = $xwiki.getDocument($request.document))
    #end
    #set ($reference = $document.documentReference)
    #try('uploadTemporaryAttachmentException')
      #if ("$!request.filename" != '')
        ## If the filename is explicitly provided, no need to recompute it.
        #set ($fileName = $request.filename)
      #else
        #set ($fileName = $request.getPart('upload').getSubmittedFileName())
        #if ($fileName.startsWith('__fileCreatedFromDataURI__.'))
          ## We need to generate a new name so that we don't overwrite existing attachments.
          #set ($extension = $stringtool.substringAfter($fileName, '.'))
          #set ($fileName = "${datetool.date.time}-${mathtool.random(100, 1000)}.$extension")
        #end
      #end
      #set ($attachment = $services.temporaryAttachments.uploadTemporaryAttachment($reference, 'upload', $fileName))
    #end
    #if ($attachment)
      #sendSuccess($document, $attachment.filename)
    #elseif ("$!uploadTemporaryAttachmentException" != '')
      ## The exception is wrapped in an org.apache.velocity.exception.MethodInvocationException
      #set ($validationException = $uploadTemporaryAttachmentException.cause)
      #if ($validationException.translationKey)
        #sendError(400 "$services.localization.render($validationException.translationKey, $validationException.translationParameters)")
      #else
        #sendError(400 "$services.localization.render('ckeditor.upload.error.emptyReturn')")
      #end
    #else
      #sendError(400 "$services.localization.render('ckeditor.upload.error.emptyReturn')")
    #end
  #else
    #sendError(403 "$services.localization.render('ckeditor.upload.error.csrf')")
  #end
#end

#macro (sendSuccess $document $fileName)
  #set ($url = $document.getAttachmentURL($fileName))
  #set ($attachmentReference = $services.model.createAttachmentReference($document.documentReference, $fileName))
  #set ($resourceReference = {
    'type': 'attach',
    'reference': $services.model.serialize($attachmentReference, $document.documentReference)
  })
  #set ($discard = $response.setContentType('application/json'))
  #if ($request.initiator == 'filetools')
    $jsontool.serialize({
      'uploaded': 1,
      'fileName': $fileName,
      'url': $url,
      'resourceReference': $resourceReference
    })
  #else
    ## JSON expected by the filebrowser plugin.
    $jsontool.serialize({
      'uploaded': 1,
      'url': $url,
      'fileName': $fileName,
      'message': {
        'resourceReference': $resourceReference
      }
    })
  #end
#end

#macro (sendError $code $message)
  #set ($discard = $response.setContentType('application/json'))
  ## The filetools plugin doesn't display the proper message if we call sendError() or setStatus() on the response.
  #if ($request.initiator != 'filetools')
    #set ($discard = $response.setStatus($code))
  #end
  $jsontool.serialize({
    'uploaded': 0,
    'error': {
      'number': $code,
      'message': $message
    }
  })
#end
{{/velocity}}

{{velocity wiki="false"}}
#if ($xcontext.action == 'get')
  ## We fallback on the old mechanism also in case of editing a translation to avoid any problem.
  ## See: XWIKI-20034
  #set ($document = $tdoc)
  #if ("$!request.document" != '')
    #set ($document = $xwiki.getDocument($request.document))
  #end
  ## Special handling if we're editing a translation that does not exist yet: in such case we cannot rely on $document.isTranslation because the context $tdoc
  ## automatically fallback on the default locale in view mode, and we're getting this through a /get/ request.
  ## See: XWIKI-20537
  #set ($isNewTranslation = false)
  #if ($document.locale == "" && $services.localization.currentLocale != $services.localization.defaultLocale)
    #set ($docRefWithLocale = $services.model.createDocumentReference($document.documentReference, $services.localization.currentLocale))
    #set ($isNewTranslation = $xwiki.getDocument($docRefWithLocale).isNew())
  #end
  #if ($request.getHeader('X-XWiki-Temporary-Attachment-Support') == 'true' && !$document.isTranslation() && !$isNewTranslation)
    #handleTemporaryUploadRequest()
  #else
    #handleUploadRequest()
  #end
#end
{{/velocity}}

Hope you have all the infos you need, don’t mind asking if I can do antyhing else.

Thanks a lot,
Marius

Di you try this? Let me know if it improved things.

Thanks. It’s the expected content.

Another thing you can do is:

  1. open your browser console before editing a page and pasting an image
  2. then go to the network tab
  3. search for a request containing sheet=CKEditor.FileUploader

If you can find such request and export it as a HAR (preferably with firefox but chrome would be ok as well) and share it with me. That might be helpful.

Otherwise. Are you comfortable with remote debugging? If that’s the case it could be helpful to narrow down where the issue occurs.

Something else I did not ask. Did you notice any error log server side?

Another option.
You can also edit CKEditor.FileUploader and replace it with the following content (I’ve add a few debug logs).

{{velocity output="false"}}
#macro (createAttachment $fileName)
  #set ($document = $doc)
  #if ("$!request.document" != '')
    #set ($document = $xwiki.getDocument($request.document))
  #end
  #if ($document && $document.hasAccessLevel('edit'))
    ## If the attachment is uploaded to a new document then make sure we create the document with the right default
    ## locale. See CKEDITOR-316: Document translations are created when uploading a file from the WYSIWYG editor in a
    ## multi-language wiki. The following code replicates the behavior of the Upload action, but it has the desired
    ## effect only on XWiki 11.9+
    #if ($document.isNew())
      #set ($rootLocale = $services.localization.toLocale(''))
      #set ($discard = $document.setLocale($rootLocale))
      #if ($rootLocale.equals($document.getDefaultLocale()))
        #set ($discard = $document.setDefaultLocale($xwiki.getLocalePreference()))
      #end
      ## We also need to make sure the new document is created with the right syntax (e.g. the one coming from the
      ## template used to create the document rather than the default wiki syntax).
      #if ("$!request.syntax" != '')
        #set ($discard = $document.setSyntaxId($request.syntax))
      #end
    #end
    ## FIXME: Get the file content as an input stream instead of a byte array, but for this we need to expose
    ## getFileItemInputStream in the public API of the fileupload plugin (or use a script service).
    #set ($bytes = $xwiki.fileupload.getFileItemData('upload'))
    #if (!$bytes)
      ## Empty file (unfortunately getFileItemData returns null instead of an empty byte array).
      #set ($bytes = [])
    #end
    #set ($discard = $document.addAttachment($fileName, $bytes))
    #set ($discard = $document.save($services.localization.render('core.comment.uploadAttachmentComment', [$fileName])))
    #sendSuccess($document $fileName)
  #else
    ## Forbidden
    #sendError(403 'You are not allowed to perform this action.')
  #end
#end

## Old way of uploading, with a save of the document for each upload.
#macro (handleUploadRequest)
  #set ($fileName = $xwiki.fileupload.getFileName('upload'))
  #if ("$!fileName" != '')
    #if ($services.csrf.isTokenValid($request.form_token))
      $services.logging.getLogger('FileUploader').debug("handleUploadRequest $fileName $fileName.startsWith('__fileCreatedFromDataURI__.')")
      #if ($fileName.startsWith('__fileCreatedFromDataURI__.'))
        ## We need to generate a new name so that we don't overwrite existing attachments.
        #set ($extension = $stringtool.substringAfter($fileName, '.'))
        #set ($fileName = "${datetool.date.time}-${mathtool.random(100, 1000)}.$extension")
      #end
      $services.logging.getLogger('FileUploader').debug("createAttachment $fileName")
      #createAttachment($fileName)
    #else
      #sendError(403 "$services.localization.render('ckeditor.upload.error.csrf')")
    #end
  #else
    ## Bad Request
    #sendError(400 "$services.localization.render('ckeditor.upload.error.emptyReturn')")
  #end
#end

## New way of handling attachment without saving immediately the document.
#macro (handleTemporaryUploadRequest)
  #if ($services.csrf.isTokenValid($request.form_token))
    #set ($document = $doc)
    #if ("$!request.document" != '')
      #set ($document = $xwiki.getDocument($request.document))
    #end
    #set ($reference = $document.documentReference)
    #try('uploadTemporaryAttachmentException')
      #if ("$!request.filename" != '')
        ## If the filename is explicitly provided, no need to recompute it.
        #set ($fileName = $request.filename)
      #else
        #set ($fileName = $request.getPart('upload').getSubmittedFileName())
        $services.logging.getLogger('FileUploader').debug("handleTemporaryUploadRequest $fileName $fileName.startsWith('__fileCreatedFromDataURI__.')")
        #if ($fileName.startsWith('__fileCreatedFromDataURI__.'))
          ## We need to generate a new name so that we don't overwrite existing attachments.
          #set ($extension = $stringtool.substringAfter($fileName, '.'))
          #set ($fileName = "${datetool.date.time}-${mathtool.random(100, 1000)}.$extension")
        #end
      #end
      $services.logging.getLogger('FileUploader').debug("uploadTemporaryAttachment $reference / $fileName")
      #set ($attachment = $services.temporaryAttachments.uploadTemporaryAttachment($reference, 'upload', $fileName))
      $services.logging.getLogger('FileUploader').debug("post uploadTemporaryAttachment $attachment")
    #end
    #if ($attachment)
      #sendSuccess($document, $attachment.filename)
    #elseif ("$!uploadTemporaryAttachmentException" != '')
      ## The exception is wrapped in an org.apache.velocity.exception.MethodInvocationException
      #set ($validationException = $uploadTemporaryAttachmentException.cause)
      #if ($validationException.translationKey)
        #sendError(400 "$services.localization.render($validationException.translationKey, $validationException.translationParameters)")
      #else
        #sendError(400 "$services.localization.render('ckeditor.upload.error.emptyReturn')")
      #end
    #else
      #sendError(400 "$services.localization.render('ckeditor.upload.error.emptyReturn')")
    #end
  #else
    #sendError(403 "$services.localization.render('ckeditor.upload.error.csrf')")
  #end
#end

#macro (sendSuccess $document $fileName)
  #set ($url = $document.getAttachmentURL($fileName))
  #set ($attachmentReference = $services.model.createAttachmentReference($document.documentReference, $fileName))
  #set ($resourceReference = {
    'type': 'attach',
    'reference': $services.model.serialize($attachmentReference, $document.documentReference)
  })
  #set ($discard = $response.setContentType('application/json'))
  #if ($request.initiator == 'filetools')
    $jsontool.serialize({
      'uploaded': 1,
      'fileName': $fileName,
      'url': $url,
      'resourceReference': $resourceReference
    })
  #else
    ## JSON expected by the filebrowser plugin.
    $jsontool.serialize({
      'uploaded': 1,
      'url': $url,
      'fileName': $fileName,
      'message': {
        'resourceReference': $resourceReference
      }
    })
  #end
#end

#macro (sendError $code $message)
  #set ($discard = $response.setContentType('application/json'))
  ## The filetools plugin doesn't display the proper message if we call sendError() or setStatus() on the response.
  #if ($request.initiator != 'filetools')
    #set ($discard = $response.setStatus($code))
  #end
  $jsontool.serialize({
    'uploaded': 0,
    'error': {
      'number': $code,
      'message': $message
    }
  })
#end
{{/velocity}}

{{velocity wiki="false"}}
#if ($xcontext.action == 'get')
  ## We fallback on the old mechanism also in case of editing a translation to avoid any problem.
  ## See: XWIKI-20034
  #set ($document = $tdoc)
  #if ("$!request.document" != '')
    #set ($document = $xwiki.getDocument($request.document))
  #end
  ## Special handling if we're editing a translation that does not exist yet: in such case we cannot rely on $document.isTranslation because the context $tdoc
  ## automatically fallback on the default locale in view mode, and we're getting this through a /get/ request.
  ## See: XWIKI-20537
  #set ($isNewTranslation = false)
  #if ($document.locale == "" && $services.localization.currentLocale != $services.localization.defaultLocale)
    #set ($docRefWithLocale = $services.model.createDocumentReference($document.documentReference, $services.localization.currentLocale))
    #set ($isNewTranslation = $xwiki.getDocument($docRefWithLocale).isNew())
  #end
  #if ($request.getHeader('X-XWiki-Temporary-Attachment-Support') == 'true' && !$document.isTranslation() && !$isNewTranslation)
    #handleTemporaryUploadRequest()
  #else
    #handleUploadRequest()
  #end
#end
{{/velocity}}

Then:

  • past an image (the logger needs to be executed once to appear in the logging admin)
  • go to the logging admin, search for FileUploader and set its level to ‘debug’
    image

Next time you upload an image, you should see logs the the one below that you can share with me.

2023-02-23 09:58:00,822 [qtp173099767-1198 - http://localhost:8080/xwiki/bin/get/Main/?sheet=CKEditor.FileUploader&outputSyntax=plain&syntax=xwiki%2F2.1&language=fr&form_token=eeu8hnCUCq0s5kU1fCBtPA&initiator=filetools] DEBUG FileUploader                   - handleUploadRequest __fileCreatedFromDataURI__.png true

Hey !

So I’ve just been updating xWiki to 14.10.5 and just found out by initializing my wikis (3 including main) that my flavors were versionned as 14.10.3. I tried to consciously updating my flavors and gave it another try.
It looks like I can upload files as intended, having random names and no longer fileCreatedFromDataURI.

Does it makes sense to you ?
I’m currently pushing my tests to be sure that it works (and not coming back afterwards like “I thought it was working but it’s not” again), but I’ll be glad to have your confirmation :slightly_smiling_face:

Thank you,

That’s good news :slight_smile:

The final step of the upgrade process is only proposed when you login with a user with enough rights.
Would it be possible that you did the tests before finalizing the upgrade?

I’ll close Loading... as cannot reproduce for now (to keep things tidy), but feel free to reopen it (and to ping me on this discussion if you find out that you still have some issue).

1 Like