Any file uploaded to the website is considered to be an attachment.
An attachment represents a file such as a JavaScript, a CSS, an Image, a third party PDF file, etc.
The content plugin handles the creation and update of attachments because it is the same as regular content as far as content on the site is concerned. The attachment files appear in the files table under their corresponding MD5 sum. The MD5 sum is used to avoid duplication, not as a security feature. So if many users all upload the exact same image, the database includes the image exactly once (of course, Cassandra generates duplicates, but the image won't appear more than once from the front end of the database.) Although each user may get a separate page for their attachment.
Since attachments are saved on a page, the branch and revision capability of the page can be used to handle various versions of an attachment. At some point, we may want to offer users a way to edit the branch and revision so it can match their attachment major and minor version numbers.
There are exceptions to this scheme: JavaScript and CSS files MUST include a C-like comment header with fields describing the data. The two fields currently used are the Version and the Browsers fields. In general, these fields define how the file can be used when a client accesses the website.
/* * Name: editor * Version: 1.2.3 * Browsers: firefox, ie, opera * Depends: output (>= 0.1.4), popup (>= 0.1.0.1), server-access (>= 0.0.1.11), * mimetype-basics (>= 0.0.3) * Description: WYSIWYG editor for your website. * Copyright: Made to Order Software Corp (c) 2011-2014 All rights reserved. */
The Version field is mandatory. If missing, an error is generated. The name of JavaScript and CSS files must follow the scheme provided by Snap! This means:
<name>_<version>_<browser>.<ext>
(Note: this is based on the Debian naming convension: <package>_<version>_<processor>.deb)
When uploading a JavaScript or CSS file, the name must be just <name>.js or <name>.css or follow the full scheme (where <browser> is optional—although I'm not 100% sure at this point that the full scheme is acceptable here.) Just <name>.js/.css is used to access the file. The system then chooses which version and browser to use. The system also sends the compressed and minimized version if possible (depending on the user agent capabilities.)
So, for the editor JavaScript file we have a filename that appears as:
http://www.example.com/js/editor/editor.js
However, to the end user we send a full name including the latest version and the user agent corresponding browser information (or no browser information if no specialized versions are defined or the default is to be used; i.e. the system does not put _all.js at the end of files.)
So the end user sees an entry such as:
http://www.example.com/js/editor/editor_1.2.3_ie.js
Internally, when an attachment gets accessed, the version and browser information are removed first then the file is accessed without them. Finally, the version and browser information are used to select the actual file to be sent.
Further, the JavaScript and CSS files can end with .min.js and .min.css to force the retrieval of the minimized version (although that is generally the default anyway) and the .org.js and .org.css to retrieve the original file that way you can download the file non-minimized, which is useful if you are debugging a page.
http://www.example.com/js/editor/editor_1.2.3_ie.min.js http://www.example.com/js/editor/editor_1.2.3_ie.org.js
At some point we will also support the .gz extension to force a compressed version. However, the User Agent is expected to tell us whether a compressed version can be sent (and it is different from using the .gz extension.)
All extensions that correspond to a compression scheme (.bz2, .xlma, etc.) could be supported assuming we offer the feature in our compressor/decompressor system.
For Images we may want to look into supporting any extension. This can be a problem because a user may upload two images rose.jpg and rose.png which are completely different pictures. However, since those attachments are not unlikely to be on different pages, it would work to allow for rose.jpg to automatically be generated from rose.png if the rose.jpg file does not otherwise exist.
As part of the auto-conversion, we support changing a PDF document to an image so the destination browser does not need to support the PDF format for us to show an icon for the document.
Right now we use ImageMagick for this transformation, we may want to also look at the Evince libraries (libevdocument) as it supports quite a few formats and works really nicely as per the output we can see in Evince.
Images can be resized by specifying the size in the filename. So image_100x300.png will return an image with those specific dimensions. This has a funny effect when an image is uploaded with the wrong dimensions (we warn the user of such though.)
We make use of a tool, xhtml2pdf, to generate PDF files. For example, you create an invoice and want to make it downloadable, a good format for that is PDF and this library can be used for that purpose.
We may want to look at the Cocoon project which also includes an XML to PDF conversion ability.
Snap! Websites
An Open Source CMS System in C++