Skip to content

Commit 26b3fd9

Browse files
committed
More Schema options
1 parent 89ab3a0 commit 26b3fd9

File tree

2 files changed

+131
-7
lines changed

2 files changed

+131
-7
lines changed

SCHEMA.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Processing URI Schema Definition
2+
3+
## Local File Schema
4+
```
5+
pde:///path/to/sketch.pde
6+
```
7+
8+
## Sketch Operations
9+
10+
### Create New Sketch
11+
```
12+
pde://sketch/new
13+
```
14+
15+
### Load Base64 Encoded Sketch
16+
```
17+
pde://sketch/base64/<base64_encoded_content>
18+
```
19+
Optional query parameters:
20+
- `data`: Comma-separated URLs of data files to download
21+
- `code`: Comma-separated URLs of code files to download
22+
- `pde`: Comma-separated URLs of Processing sketch files to download
23+
- `mode`: Processing mode identifier
24+
25+
### Load Sketch from URL
26+
```
27+
pde://sketch/url/domain.com/path/to/sketch.pde
28+
```
29+
Supports the same query parameters as base64 endpoint.
30+
Optional query parameters:
31+
32+
- `data`: Comma-separated URLs of data files to download
33+
- `code`: Comma-separated URLs of code files to download
34+
- `pde`: Comma-separated URLs of Processing sketch files to download
35+
- `mode`: Processing mode identifier
36+
37+
Example with query parameters:
38+
```
39+
pde://sketch/url/example.com/sketch.pde?data=image1.png,sound1.mp3&mode=java
40+
```
41+
42+
## Preferences
43+
```
44+
pde://preferences?key1=value1&key2=value2
45+
```
46+
Sets and saves multiple preferences in a single operation.
47+
48+
## Security Considerations
49+
- URL-based operations automatically prepend https:// if no scheme is provided
50+
- All URLs and query parameters are decoded using UTF-8
51+
- File downloads occur asynchronously in a separate thread
52+
- Base64 and remote sketches are saved to temporary folders

app/src/processing/app/Schema.kt

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package processing.app
22

33
import processing.app.ui.Editor
44
import java.io.File
5+
import java.io.FileOutputStream
56
import java.net.URI
7+
import java.net.URL
68
import java.net.URLDecoder
79
import java.nio.charset.StandardCharsets
810

@@ -18,7 +20,7 @@ class Schema {
1820
null -> handleLocalFile(uri.path)
1921
"sketch" -> handleSketch(uri)
2022
"preferences" -> handlePreferences(uri)
21-
else -> handleRemoteFile(uri)
23+
else -> null
2224
}
2325
}
2426
private fun handleLocalFile(input: String): Editor?{
@@ -27,20 +29,94 @@ class Schema {
2729
private fun handleSketch(uri: URI): Editor?{
2830
val paths = uri.path.split("/")
2931
return when(paths.getOrNull(1)){
32+
"new" -> handleSketchNew(uri)
3033
"base64" -> handleSketchBase64(uri)
34+
"url" -> handleSketchUrl(uri)
3135
else -> null
3236
}
3337
}
38+
private fun handleSketchNew(uri: URI): Editor?{
39+
base?.handleNew()
40+
return null
41+
}
3442
private fun handleSketchBase64(uri: URI): Editor?{
3543
val tempSketchFolder = SketchName.nextFolder(Base.untitledFolder);
3644
tempSketchFolder.mkdirs()
3745
val tempSketchFile = File(tempSketchFolder, "${tempSketchFolder.name}.pde")
3846
val sketchB64 = uri.path.replace("/base64/", "")
3947
val sketch = java.util.Base64.getDecoder().decode(sketchB64)
4048
tempSketchFile.writeBytes(sketch)
41-
val editor = base?.handleOpenUntitled(tempSketchFile.absolutePath)
42-
return editor
49+
handleSketchOptions(uri, tempSketchFolder)
50+
return base?.handleOpenUntitled(tempSketchFile.absolutePath)
4351
}
52+
private fun handleSketchUrl(uri: URI): Editor?{
53+
val url = File(uri.path.replace("/url/", ""))
54+
55+
val tempSketchFolder = File(Base.untitledFolder, url.nameWithoutExtension)
56+
tempSketchFolder.mkdirs()
57+
val tempSketchFile = File(tempSketchFolder, "${tempSketchFolder.name}.pde")
58+
59+
60+
URL("https://$url").openStream().use { input ->
61+
FileOutputStream(tempSketchFile).use { output ->
62+
input.copyTo(output)
63+
}
64+
}
65+
handleSketchOptions(uri, tempSketchFolder)
66+
return base?.handleOpenUntitled(tempSketchFile.absolutePath)
67+
}
68+
private fun handleSketchOptions(uri: URI, sketchFolder: File){
69+
val options = uri.query?.split("&")
70+
?.map { it.split("=") }
71+
?.associate {
72+
URLDecoder.decode(it[0], StandardCharsets.UTF_8) to
73+
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
74+
}
75+
?: emptyMap()
76+
77+
options["data"]?.let{ data ->
78+
downloadFiles(uri, data, File(sketchFolder, "data"))
79+
}
80+
options["code"]?.let{ code ->
81+
downloadFiles(uri, code, File(sketchFolder, "code"))
82+
}
83+
options["pde"]?.let{ pde ->
84+
downloadFiles(uri, pde, sketchFolder)
85+
}
86+
options["mode"]?.let{ mode ->
87+
val modeFile = File(sketchFolder, "sketch.properties")
88+
modeFile.writeText("mode.id=$mode")
89+
}
90+
91+
}
92+
private fun downloadFiles(uri: URI, urlList: String, sketchFolder: File){
93+
Thread{
94+
val base = uri.path.split("/").drop(2).dropLast(1).joinToString("/")
95+
val files = urlList.split(",")
96+
.map {
97+
val fileUrl = URI.create(it)
98+
if(fileUrl.host == null){
99+
return@map "https://$base/$it"
100+
}
101+
if(fileUrl.scheme == null){
102+
return@map "https://$it"
103+
}
104+
return@map it
105+
}
106+
sketchFolder.mkdirs()
107+
for(file in files){
108+
val url = URL(file)
109+
val name = url.path.split("/").last()
110+
val dataFile = File(sketchFolder, name)
111+
URL(file).openStream().use { input ->
112+
FileOutputStream(dataFile).use { output ->
113+
input.copyTo(output)
114+
}
115+
}
116+
}
117+
}.start()
118+
}
119+
44120

45121
private fun handlePreferences(uri: URI): Editor?{
46122
val options = uri.query?.split("&")
@@ -57,9 +133,5 @@ class Schema {
57133

58134
return null
59135
}
60-
61-
private fun handleRemoteFile(uri: URI): Editor?{
62-
return null
63-
}
64136
}
65137
}

0 commit comments

Comments
 (0)