Trouble using xmldb:store with collection name with space

138 views Asked by At

I cannot seem to get this right. I have a system where the web user is running a jQuery request to add a new document. The code works perfect if the collection they are storing to have no spaces in the name. This code is:

xquery version "3.0";
declare option exist:serialize "method=xhtml media-type=text/html indent=yes";
let $specialty := request:get-parameter("specialty", "")
let $collection := xmldb:encode-uri($specialty)
let $docnum := request:get-parameter("docnum", "")
let $title := request:get-parameter("title", "")
let $file := concat($docnum, '.xml')
let $path := concat($collection, '/', $file)
let $content := <article>
<div
    class="content"
    doc="{$docnum}"
    title="{xmldb:decode($title)}">
    <div
        class="panel">
        <h1>First Panel</h1>
        <p>Content goes here</p>
    </div>
 </div>
 </article>
 return
   let $new_article := xmldb:store($collection, $file, $content, 'application/xml')
      return
        let $changepermiss := sm:chmod($new_article, 'rw-rw----')
           return
             <li
            class="file"
            data-xpath="{$path}"
        >
            <a
                data-xpath="{$path}"
                onclick="doc_open('{$path}')"
                href="#"><span
                    class="glyphicon glyphicon-tags"></span>&#160;&#160;&#160;{$docnum, ': ', xmldb:decode($title)}</a>
        </li>

Now, if the collection name that comes from the request contains a space ... like this (after encoding) ... it fails.

"/db/Test/data/Core/Test%20Collection"

The error is:

exerr:ERROR Could not locate collection: /db/Test/data/Core/Test%20Collection

This occurs at this line: xmldb:store($collection, $file, $content, 'application/xml') with $collection not be recognized because of the space.

Now, to test things out, I run this and it is fine.

    xquery version "3.0";
    declare option exist:serialize "method=xhtml media-type=text/html indent=yes";
    let $test := "/db/EIDO/data/Core/Disease%20Prevention"
    let $content := <article>
        <div
            class="content"
            doc="D777"
            title="Test Document">
            <div
                class="panel">
                <h1>First Panel</h1>
                <p>Content goes here</p>
            </div>
        </div>
    </article>
    return
    let $newdoc := xmldb:store($test, "test.xml", $content, 'application/xml')
    return
        $newdoc

I cannot understand where I am going wrong in trying to reference the collection with a space in xmldb:store.

NOTE: As I said, the code works if there is no space in the name of the collection.

I have tried many combinations of encoding the URL and making a string from it but nothing seems to work.

2

There are 2 answers

6
Kevin Brown On

The answer was permission issue (although I am a bit lost at that). The collection had rw-rw-r-- and the user is in the group and is in fact the owner of the collection.

When I change to include execute (rwxrwxr--) it works as expected. Confusing, but apparently execute permission in required on the collection that is going to be stored into.

0
Joe Wicentowski On

If your collection or resource names are possibly going to contain characters that need to be encoded, you need to use xmldb:encode-uri() on the names. In your first sample, you encode the collection name ($collection) but not the resource name ($file). In your second sample, you pre-encode the collection name, but the resource name contains no characters that need to be encoded; so you've fully accounted for the encoding.

Take care to ensure that the collection name, as encoded, does exist. If not, you should pre-create the collection. This could actually be the cause of the error you cite.

When you create links to these resources in HTML output, take care not to double-encode them.

You might find it useful to reference an app that handles encoding well. See the source to eXide https://github.com/wolfgangmm/eXide.