daisy / pipeline

Super-project that aggregates all Pipeline related code, provides a common tracker for Pipeline related issues and holds the Pipeline website
http://daisy.github.io/pipeline
21 stars 21 forks source link

dp2.exe does not accept UNC paths #696

Open PaulRambags opened 1 year ago

PaulRambags commented 1 year ago

Expected Behavior

I'm trying to run the Daisy Pipeline CLI with an UNC path and I expect that the DTBook is processed.

Actual Behavior

The job is not processed with error Job request is not valid.

Steps to Reproduce

  1. Construct a share such that you have read and write permission. For instance, if the machine name is DEV, create a share Temp so that new files can be created in \\DEV\Temp and so that they can be read too.
  2. Put an arbitrary DTBook file in that share, for instance \\DEV\Temp\dtbook.xml
  3. Execute in a CMD, dp2.exe dtbook-to-pef --source \\DEV\Temp\dtbook.xml --output \\DEV\Temp\output-folder

Details

Changing the backward slashes to forward slashes gives the same issue.

Environment

Logs

2023-08-14 15:41:03,958 [ERROR] o.d.p.webservice.impl.JobsResource - bad request:
java.io.FileNotFoundException: Input not found: not a valid file URI: file://dev-10/Tekstproductie/pip-job-handler/in/soft-hyphen-test-1.xml
    at org.daisy.pipeline.script.ScriptInput$Builder.checkInputURI(ScriptInput.java:200) ~[org.daisy.pipeline.framework-core-7.0.1.jar:na]
    at org.daisy.pipeline.script.ScriptInput$Builder.withInput(ScriptInput.java:103) ~[org.daisy.pipeline.framework-core-7.0.1.jar:na]
    at org.daisy.pipeline.script.BoundScript$Builder.withInput(BoundScript.java:44) ~[org.daisy.pipeline.framework-core-7.0.1.jar:na]
    at org.daisy.pipeline.webservice.impl.JobsResource.addInputsToJob(JobsResource.java:458) ~[org.daisy.pipeline.webservice-3.1.0.jar:na]
    at org.daisy.pipeline.webservice.impl.JobsResource.createJob(JobsResource.java:387) ~[org.daisy.pipeline.webservice-3.1.0.jar:na]
    at org.daisy.pipeline.webservice.impl.JobsResource.createResource(JobsResource.java:178) ~[org.daisy.pipeline.webservice-3.1.0.jar:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.restlet.resource.ServerResource.doHandle(ServerResource.java:503) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.resource.ServerResource.post(ServerResource.java:1215) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.resource.ServerResource.doHandle(ServerResource.java:592) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.resource.ServerResource.doNegotiatedHandle(ServerResource.java:649) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.resource.ServerResource.doConditionalHandle(ServerResource.java:348) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.resource.ServerResource.handle(ServerResource.java:951) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.resource.Finder.handle(Finder.java:246) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Router.doHandle(Router.java:431) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Router.handle(Router.java:648) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:155) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:84) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.Application.handle(Application.java:381) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Router.doHandle(Router.java:431) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Router.handle(Router.java:648) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Router.doHandle(Router.java:431) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Router.handle(Router.java:648) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:155) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.doHandle(Filter.java:159) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.routing.Filter.handle(Filter.java:206) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.Component.handle(Component.java:392) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.Server.handle(Server.java:516) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.ServerHelper.handle(ServerHelper.java:72) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:152) ~[org.restlet.osgi.org.restlet-2.1-RC6.jar:na]
    at org.restlet.ext.jetty.JettyServerHelper$WrappedServer.handle(JettyServerHelper.java:170) ~[org.restlet.osgi.org.restlet.ext.jetty-2.1-RC6.jar:na]
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:452) ~[org.eclipse.jetty.jetty-server-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:894) ~[org.eclipse.jetty.jetty-server-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:948) ~[org.eclipse.jetty.jetty-server-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:851) ~[org.eclipse.jetty.jetty-http-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235) ~[org.eclipse.jetty.jetty-http-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77) ~[org.eclipse.jetty.jetty-server-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:622) ~[org.eclipse.jetty.jetty-io-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46) ~[org.eclipse.jetty.jetty-io-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603) ~[org.eclipse.jetty.jetty-util-7.6.5.v20120716.jar:7.6.5.v20120716]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538) ~[org.eclipse.jetty.jetty-util-7.6.5.v20120716.jar:7.6.5.v20120716]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
2023-08-14 15:41:03,958 [DEBUG] o.d.p.w.impl.GenericResource - Bad Request (400) - The request could not be understood by the server due to malformed syntax
2023-08-14 15:41:03,958 [DEBUG] o.d.p.w.impl.GenericResource - Input not found: not a valid file URI: file://dev-10/Tekstproductie/pip-job-handler/in/soft-hyphen-test-1.xml
2023-08-14 15:41:03,960 [DEBUG] o.d.p.w.impl.GenericResource - <?xml version="1.0" encoding="UTF-8"?><error xmlns="http://www.daisy.org/ns/pipeline/data" query="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1"><description>Input not found: not a valid file URI: file://dev-10/Tekstproductie/pip-job-handler/in/soft-hyphen-test-1.xml</description><trace>java.lang.Throwable: Input not found: not a valid file URI: file://dev-10/Tekstproductie/pip-job-handler/in/soft-hyphen-test-1.xml&#xD;
    at org.daisy.pipeline.webservice.impl.GenericResource.getErrorRepresentation(GenericResource.java:40)&#xD;
    at org.daisy.pipeline.webservice.impl.JobsResource.badRequest(JobsResource.java:220)&#xD;
    at org.daisy.pipeline.webservice.impl.JobsResource.createResource(JobsResource.java:182)&#xD;
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&#xD;
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)&#xD;
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)&#xD;
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)&#xD;
    at org.restlet.resource.ServerResource.doHandle(ServerResource.java:503)&#xD;
    at org.restlet.resource.ServerResource.post(ServerResource.java:1215)&#xD;
    at org.restlet.resource.ServerResource.doHandle(ServerResource.java:592)&#xD;
    at org.restlet.resource.ServerResource.doNegotiatedHandle(ServerResource.java:649)&#xD;
    at org.restlet.resource.ServerResource.doConditionalHandle(ServerResource.java:348)&#xD;
    at org.restlet.resource.ServerResource.handle(ServerResource.java:951)&#xD;
    at org.restlet.resource.Finder.handle(Finder.java:246)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Router.doHandle(Router.java:431)&#xD;
    at org.restlet.routing.Router.handle(Router.java:648)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:155)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211)&#xD;
    at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:84)&#xD;
    at org.restlet.Application.handle(Application.java:381)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Router.doHandle(Router.java:431)&#xD;
    at org.restlet.routing.Router.handle(Router.java:648)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Router.doHandle(Router.java:431)&#xD;
    at org.restlet.routing.Router.handle(Router.java:648)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:155)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.routing.Filter.doHandle(Filter.java:159)&#xD;
    at org.restlet.routing.Filter.handle(Filter.java:206)&#xD;
    at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211)&#xD;
    at org.restlet.Component.handle(Component.java:392)&#xD;
    at org.restlet.Server.handle(Server.java:516)&#xD;
    at org.restlet.engine.ServerHelper.handle(ServerHelper.java:72)&#xD;
    at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:152)&#xD;
    at org.restlet.ext.jetty.JettyServerHelper$WrappedServer.handle(JettyServerHelper.java:170)&#xD;
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:452)&#xD;
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:894)&#xD;
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:948)&#xD;
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:851)&#xD;
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)&#xD;
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)&#xD;
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:622)&#xD;
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)&#xD;
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)&#xD;
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)&#xD;
    at java.base/java.lang.Thread.run(Thread.java:833)&#xD;
</trace></error>
bertfrees commented 1 year ago

@PaulRambags Thanks for the report. This seems to be a Java issue with the 2-slash form of UNC URIs.

Here is a possible solution:

--- a/framework/framework-core/src/main/java/org/daisy/pipeline/script/ScriptInput.java
+++ b/framework/framework-core/src/main/java/org/daisy/pipeline/script/ScriptInput.java
@@ -195,6 +195,12 @@ public class ScriptInput {
                                        throw new FileNotFoundException(
                                                "Input not found: expected an absolute file or a relative path, but got: " + uri);
                                try {
+                                       // Windows: try to convert 2-slash UNC form to 4-slash form
+                                       if (uri.getAuthority() != null && !"".equals(uri.getAuthority()))
+                                               try {
+                                                       uri = new URI("file", "", "//" + uri.getAuthority() + uri.getPath(), uri.getQuery(), uri.getFragment());
+                                               } catch (URISyntaxException e) {
+                                               }
                                        absoluteFile = new File(uri);
                                } catch (IllegalArgumentException e) {
                                        throw new FileNotFoundException(

Someone would need to test it on Windows. There might be similar issues in different places in the code.