-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME
319 lines (254 loc) · 13.5 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
Dyphal, the Dynamic Photo Album
===============================
Dyphal is a web photo album designed to allow photographers to show off their
work without needing to turn to commercial providers that inject advertising
and may do ethically dubious things with the photos and information that they
host.
An album is displayed as a list of photos; each photo can be opened to show a
larger view with metadata. The photo's size scales to best fit the browser
window. An album can be navigated by mouse, touch, or keyboard.
An album can be hosted on any web document server; no server-side scripts or
databases are required. All necessary files are generated from original
photographs and their metadata up front and stored on the server. The album
and its metadata files are designed to require minimal storage space and
minimal network traffic.
There is a demo album at <https://ciphertext.info/software/dyphal/#/demo>.
Design principles
-----------------
Dyphal was designed to satisfy the following goals:
1. The photo is central. It must be the most prominent element of the page.
It must be entirely visible within the browser window; scrolling is not
allowed. Do not up-scale the photo beyond its actual size. Do down-scale
the photo to fit the browser window if necessary.
2. Metadata is important. Information about what is in a photo, where and
when it was taken, and photographic properties such as exposure and
aperture must be visible for each photo.
3. The album must not break the web. Browsers' Forward and Back buttons must
work. Bookmarks and saved links to photos and albums must work. The URI
in the address bar must represent the current album or photo.
4. The album must work using a document server as the back end.
5. The album must be as small as possible with as many elements as possible
shared between pages.
6. The album must use modern web standards with a minimum of cruft to support
old browsers. It must follow security best practices and support CSP.
7. All features of the album must work properly on recent versions of Chrome
and Firefox. There should be no major problems in minor browsers such as
Opera or Edge.
8. All content must be in HTML or be inserted at run-time. All styling must
be in CSS or inserted at run-time.
9. Album styles should be changeable without needing to change scripts.
Generating Dyphal albums
------------------------
Dyphal albums are created using DyphalGenerator:
1. Use the **Add Photos** button to import photo files or gThumb 3 catalogs.
Photos can be re-ordered by dragging.
2. Choose the caption and property fields to display for each photo. The
fields available depend on what metadata tags are stored in the selected
photos. By default, only the fields available in *all* selected photos are
listed; check the **Show all** box to list all fields that are available in
*any* selected photo. Fields can be re-ordered by dragging.
3. Set a title, description and footer for the album. The title and footer
will appear on photo pages as well as the album page. No HTML markup is
allowed.
4. Choose the size for photos in the album. Larger sizes will show more
detail, but require more space and time to load.
5. Use the **Generate Album** button to save the album and generate the
down-scaled photos, thumbnails, and metadata files that it requires.
6. If you haven't already done so, use the **Install Album Template** button
to install the Dyphal web template into the album directory.
If you generated the album "Vacation" in a directory served as
http://example.com/photos and installed the web template to the same directory,
you can view the album at http://example.com/photos/#/Vacation.
To edit an album in DyphalGenerator, open the ".dyphal" file for the album.
DyphalGenerator does not currently have a metadata editor. Instead, it pulls
metadata fields from embedded photo tags. The following tags are recognized
as "properties" (using exiftool's naming scheme):
* Composite:Aperture
* Composite:DigitalZoom
* Composite:DriveMode
* Composite:FlashType
* Composite:FOV
* Composite:FocalLength35efl
* Composite:HyperfocalDistance
* Composite:ImageSize
* Composite:Lens35efl
* Composite:LensID
* Composite:LightValue
* Composite:ScaleFactor35efl
* Composite:ShootingMode
* Composite:ShutterSpeed
* EXIF:DateTimeOriginal
* EXIF:ExposureCompensation
* EXIF:ExposureMode
* EXIF:Flash
* EXIF:FocalLength
* EXIF:ISO
* EXIF:Make
* EXIF:Model
* EXIF:Orientation
* File:FileSize
* File:FileType
* MakerNotes:MacroMode
* MakerNotes:Rotation
Only three fields are recognized as "captions": Description, Location, and
Date. They are synthesized from various tags that are commonly used to store
such information (again, using exiftool's naming scheme):
* Description
* XMP:Description
* IPTC:Caption-Abstract
* EXIF:UserComment
* Location
* XMP:Location
* IPTC:ContentLocationName
* Date:
* XMP:DateTimeOriginal
* Composite:DateTimeCreated
* EXIF:DateTimeOriginal
Recent versions of gThumb use these fields for metadata; there are probably
other photo managers that do as well. Older versions of gThumb stored metadata
only in external XML files; the tool "gthumb-comment-update" can be used to
import metadata from the XML files into embedded tags.
Serving Dyphal albums
---------------------
Nothing special is required to serve Dyphal albums, just a basic web document
server such as Apache or lighttpd. For improved security, server operators are
encouraged to serve Dyphal albums over HTTPS with the following headers:
* `Content-Security-Policy: default-src 'none'; script-src 'self'; style-src
'self'; img-src 'self'; connect-src 'self';`
* `X-Frame-Options: DENY`
* `Strict-Transport-Security: max-age=31536000`
Since Dyphal uses asynchronous queries, it won't work from file:// URIs.
The ".dyphal" files created by DyphalGeneraor should **not** be served with the
web page. These files are intended to allow DyphalGenerator to re-open and
edit albums.
Technical details
-----------------
An album is represented by a single web page, index.html. JavaScript running
within that page determines what to display based on hash parameters. The
first parameter, which must always be present, identifies the album. This
value is the name of the JSON file that describes the album with the ".json"
suffix omitted. If your directory structure looks like this:
album.css
common.css
dyphal.js
index.html
photo.css
vacation.json
photos/photo1.jpeg
metadata/photo1.jpeg.json
...
then the path to load the "vacation" album is
/#/vacation
This will load **album view**, which shows the title and description of the
album as a whole alongside thumbnails for every photo in the album. Clicking
on any one of the thumbnails will open **photo view** for that photo,
containing a larger view of the selected photo and its metadata, along with
controls to move to the previous or next photos in the album, or to return to
album view. The photo will re-scale to the largest size that fits in your
browser window without hiding the header, footer, or metadata or going beyond
its physical dimensions. If the photo is not shown at its full size, clicking
on it will open **overlay view** to show the photo at the largest size that
can fit in the window, potentially hiding the header, footer, and metadata.
There is also a **help view** that can be opened from either album or photo
view using the question mark icon.
When loaded in a window smaller than 750 CSS-pixels wide or tall, the album
will use **compact layout** that omits the metadata and footer from photo
view in order to show the photo at the largest size possible. In compact
layout, overlay view shows the metadata and footer rather than another view of
the photo. The album is also displayed full-screen in browsers that support
this feature if the display is less than 750 CSS-pixels wide or tall (though,
for technical reasons, the user needs to interact with the page before it can
enter full-screen mode).
Each photo view has its own URI, consisting of the URI to the album followed by
the index number of the photo (indices start from 1). For example, the path
for the third photo in the "Vacation" album might be
/#/vacation/3
The photo and help overlays do not have independent URIs.
Since only one HTML document is used for all views, its differences in
appearance are implemented by switching styles and, to a lesser extent, by
adding and removing document elements. Photos, thumbnails, and photo metadata
are not stored in the HTML; they are loaded from JSON files and their contents
are inserted or removed from the document when appropriate. The album JSON
file (`vacation.json` in the above example) contains a title, footer, and
description of the album, plus a list of the photos in the album. Each photo
has its own JSON file (the photo's name from the album JSON with "`.json`"
appended), containing the name of the photo file, its dimensions, and its
metadata. JSON files, thumbnails, and photos are loaded on demand; the JSON
and photo for the next photo in the album are pre-cached to reduce load time.
Appending "`/debug`" to any album or photo URI will load it in debug mode,
which suppresses some of the styling, outlines various document elements in
various colours, and logs some information to the browser console.
Everything is implemented in as standards-conformant a manner as possible.
Browser-specific logic is implemented using feature detection rather than
browser detection where possible; browser detection is only used to work around
the buggy touch tracking in Android browsers and the broken scrolling in
full-screen Internet Explorer because no ways to fix these issues using feature
detection could be found.
If my JavaScript has idiosyncrasies, it's probably because I'm a C++ programmer
who learned JavaScript by trial and error.
History
-------
The original version of Dyphal was the BestFit template for gThumb, which I
wrote in 2005 and became part of gThumb starting with version 2.9.1 in 2006.
That template was designed to take scale the photo to fit in the browser window
and show metadata around its edges; superficially, it looked a lot like this
album. However, it was limited by the hacks required to support Internet
Explorer 6 and albums built from that template consisted of a large number of
repetitive generated HTML files.
At some point after 2008, gThumb removed the BestFit template without telling
its author (i.e., me) why. Since working with the gThumb maintainer in the
past had been a pain, I opted to not try to get it reinstated. Instead, I
dropped support for IE6 (simplifying the code considerably) and started work on
a version where photos and metadata would be inserted into a single page at
run-time using JavaScript. I eventually merged the album and photo pages,
accidentally re-invented JSON before learning how to use JSON properly, and
ended up with this.
The main disadvantage of the new album over the old gThumb-generated one is
that I can no longer rely on gThumb to select the photos to include, create
down-sized versions of them, and extract their metadata. Instead, I wrote my
own tool, DyphalGenerator. gThumb, despite a couple annoying mis-features,
still has the best support for photo metadata of any Linux photo manager that I
could find, so DyphalGenerator pulls metadata from the places where gThumb
stores it and pulls lists of photos from gThumb collections.
Security Model
--------------
DyphalGenerator, which generates the server-side data, fills the role of a
server component. It is trusted, as are the shell commands that it invokes.
The image files loaded by DyphalGenerator are *not* trusted and are assumed to
contain arbitrary malicious content. The JSON files emitted by DyphalGenerator
are partially trusted. The following fields are safe to insert into URIs with
no additional encoding:
* `metadataDir`
* `thumbnail`
* `path`
* `name`
* `photo`
The following fields are restricted to hard-coded values:
* `orientation`
* `albumVersion`
* `captionFields`
* `propertyFields`
* `photoResolution`
* the first element of each `properties` tuple
All other values should be assumed to be attacker-controlled.
To be secure, DyphalGenerator must never emit photo URIs outside of the album
directory and albums must never execute any scripts or interpret any markup
found in properties, captions, or other fields. Additionally, albums must
never load JSON files or images from outside of the album directory.
See [javascript.html](javascript.html) for information about Dyphal's use of
JavaScript.
The ".dyphal" files created by DyphalGenerator contain local paths and should
not be served with the web page.
Why am I so concerned about TOCTOU in DyphalGenerator when there's no privilege
separation to be attacked? Practice.
Licence
-------
Dyphal is copyright (c) Rennie deGraaf, 2005-2023. It is distributed under the
terms of the GNU General Public Licence, either version 2 or (at your option)
version 3. See LICENCE or <http://www.gnu.org/licenses/> for details.
Contact information
-------------------
Rennie deGraaf (rennie-dot-degraaf-at-gmail-dot-com)
The latest version of Dyphal, including full source code, can be obtained at
<https://ciphertext.info/software/dyphal/>.
Version VERSION, DATE