Mozile

Save a file via the HTTP POST protocol

Document status

Date: 10 June 2005

Testing with additions to Mozile 0.6.20, using Firefox 1.0.4 on a Windows/Apache/PHP platform.

Setting up Save and POST RSD Config options

...Defined elsewhere in Mozile docs...

Processing in mozileSave.js

Content-type and character sets

Internally, the browser uses the UTF-16 character set. To work with a document that you supply to it the browser has to convert from the specified character set to UTF-16, and convert any character entities or numeric chracter references to a single UTF-16 character.

The Mozile save routines use the XML Serializer to convert the document into a text string. The characters "<", ">" and "&" are always replaced by the character entities "&lt;", "&gt;" and "&amp;". RSD configuration options allow you to specify the character set to be saved as, and whether to convert non-ascii characters to character entities or numeric references.

For HTML documents served with a content-type of "text/html" the character set used may NOT be the value specified by a meta tag in the head of the document. The character set specified by the HTTP headers is used and the meta tags are always ignored.

For HTML files served as type "text/html" the browser uses the HTML Document Object Model (DOM). With the HTML DOM tags are all converted to upper case when the DOM is generated. Hence, it is not possible to preserve the case of tags from the original HTML file. There is an optional RSD configuration option to specify whether tags are saved in upper case or lower case. The default is to save in lowercase. There is an additional XHTML compatibility option to add a space before the trailing slash of all empty tags.

E.g. the HTML <BR> tag can be saved as <br />.

There is not currently an option to save tags as strictly valid HTML. The trailing slash is always added.

For files correctly served with an XHTML (application/xhtml+xml) or XML Content-type the case of tag names is always preserved. Other minor changes may be made when constructing the XML DOM, such as removing redundant white space, etc.

Saving the whole document

The whole document is saved.
The id's of editable areas are not sent.

Saving the current block

Only a single block in a document is saved.

If the editable block has an "id" attribute it is added to the save URL.
e.g. An xhtml div element can be used to define an editable block such as:
<div id="EditableArea1"> ... </div>

With a save URL such as:
http://www.mywebsite.com/scripts/saveit.php
the target URL becomes:
http://www.mywebsite.com/scripts/saveit.php?MozileID=EditableArea1

With a save URL such as:
http://www.mywebsite.com/scripts/saveit.php?name=Max
the target URL becomes:
http://www.mywebsite.com/scripts/saveit.php?name=Max&MozileId=EditableArea1

Possible extensions

With the POST method it would also be possible to do a "save as file...". This would require an additional text box for the Save dialogue window.

The XMLHttpRequest has the facility for user authentication via a username and password although I have not tested it to see if it works. This might be useful for implementing a simple CMS.

HTTP Status Codes (Server Response)

2xx : Successful

200 Ok

The request was successful. In reply to the POST method the message-body contains the result of the server action.

If the result of the save is successful Mozile displays a success message in the status bar. If there is an error Mozile pops up the Save Message window giving further details.

204 No content

This contains header fields only but no message-body. This response is used to indicate that the save operation was completely successful.

A new page is not loaded in the current browser window. Mozile displays a success message in the status bar.

201 Created

This is to indicate that a new resource has been created. Further information should be returned in the headers and message-body. (This return information doesn't appear to be used by Mozile. I don't know if there is any planned use for this.)

A new page is not loaded in the current browser window. Mozile displays a success message in the status bar.

4xx : Client Error

Variety of error messages that should be displayed to the user.

Mozile pops up the Save Message window giving further details.

xxx : Other error codes.

There are other error codes that Mozile might need to process.

Processing in mozileDataTransport.js

A dedicated window is opened that handles the POST transfer using the XMLHttpRequest method. An asynchronous request is used.

POST Save : postsave.js/postsave.xul

HTTP Content-Type header

When a whole page is saved the Content-type and character set match those of the document.

When the current block is saved the Content-type is set to "text/plain".

HTTP Content-Location header

The Content-Location header is set to the url of the file being saved.

POST Progress Window

A status window is opened showing a progress bar and an Abort button. A short status message is displayed showing the current state of the XMLHttpRequest. It is not possible to get an idea of how long the save process will take so the progress bar takes the form of a continually spinning barber pole. Normally there should not be a reason for activating the "Abort" function, but this can be used if the save process hangs.

Note: The Post Progress Window does not have the window close icon (X in top right corner). This is to prevent non-tec users from closing the window midway through a request and potentially making a mess of the save process. If the abort button is pressed the request should be stopped in a tidy way. The Abort button then changes to a Close button allowing the user to close the window. If the code controlling this does not execute correctly the Post Progress Window could be left open with no way to close it other than by shutting down the whole browser. I'm not sure if this is likely to happen, but if it does, please report what you did to cause the error. One fix to this potential problem would be to have a background timeout to abort the request and close the window after a certain interval. (People could maybe tweak this value to suit their own setup.)

POST Progress Window messages

Some of these occur too quickly and may not display.

POST Response : 200 OK

The result of the server action is returned in the body of the response. This makes use of a Mozile specific namespace and tags. The response must be in XML or XHTML. Any other response (e.g. HTML) will generate an error.

XML Namespace

http://www.mozile.mozdev.org/ns/save/

Note: The XHTML 1.0 spec says this:

The XHTML namespace may be used with other XML namespaces as per [XMLNS [p.32] ], although such documents are not strictly conforming XHTML 1.0 documents as defined above. Work by W3C is addressing ways to specify conformance for documents involving multiple namespaces.

So, your XHTML pages might not validate. I don't think this causes any problems when browsers try to display the pages.

XML elements

elementuse
postcontainer for result of server action.
statusstatus code
statustexttext description
displayOPTIONAL. Override the default display handling of the Save Message Window. Usually the window is only displayed if there is an error. This can be useful for debugging or showing warning messages.
"yes" : always display the window.
"no" : don't display the window, even if there is an error.
locationOPTIONAL. Specifies a new location (url) to load in the main window.
Can be a full url or a relative path/filename.
Optional attribute: replace="true" overwrites the current history entry.

Status codes
statusmeaning
0reserved
1ok
user definederror

Example 1 : saved ok, no errors.

<mozile xmlns="http://www.mozile.mozdev.org/ns/save/">
	<post>
		<status>1</status>
		<statustext>Saved OK</statustext>
	</post>
</mozile>

The POST Progress Window closes, the Save Message Window is not shown.

Example 2 : Not saved, error.

<mozile xmlns="http://www.mozile.mozdev.org/ns/save/">
	<post>
		<status>2</status>
		<statustext>Database connect error</statustext>
	</post>
</mozile>

This is displayed in the Save Message Window as:

Save Method: HTTP POST

[2] Database connect error


Server response

200 OK

Show full server response

Cancel

It is important to take into account the display limitations when deciding upon the values for status and statustext. A multiline textbox is used for statustext. Both must be present. An error is produced if one or both are empty.

Example 3 : Reload current page.

<mozile xmlns="http://www.mozile.mozdev.org/ns/save/">
	<post>
		<status>3</status>
		<statustext>Invalid data</statustext>
		<location/>
	</post>
</mozile>

Example 4 : Go to the requested location after the save.

<mozile xmlns="http://www.mozile.mozdev.org/ns/save/">
	<post>
		<status>1</status>
		<statustext>Saved OK</statustext>
		<location>http://www.mywebsite.com/newpage.xhtml</location>
	</post>
</mozile>

The location can be an absolute url or a relative pathname.

Example 5 : Replace the current page.

<mozile xmlns="http://www.mozile.mozdev.org/ns/save/">
	<post>
		<status>1</status>
		<statustext>Saved OK</statustext>
		<location replace="true">http://www.mywebsite.com/newpage.xhtml</location>
	</post>
</mozile>

The optional attribute replace="true" overwrites the current history location with the new one. i.e. you won't be able to use the browser back button to go back to the previous page.

Example 6 : saved ok, warning message.

<mozile xmlns="http://www.mozile.mozdev.org/ns/save/">
	<post>
		<status>1</status>
		<statustext>Saved OK, but...running out of disk space!</statustext>
		<display>yes</display>
	</post>
</mozile>

Force the POST Progress Window to display even though there isn't an error. Similarly, by setting the display value to "no", you can prevent the window from displaying even if there is an error.

Main User Error Messages

These are the main error messages you are likely to come across in the Save Message Window.

Unexpected server response Server response other than 200, 201, 204
XML response not received from server. 200 OK received, but server response is not in XHTML. E.g. a plain HTML file has been sent instead.
Something is wrong with the XML response.
<post> tag is missing or namespace is incorrect.
Namespace should be;
http://www.mozile.mozdev.org/ns/save/
<status> tag is missing.
Empty <status></status> tags.
<statustext> tag is missing.
Empty <statustext></statustext> tags.

In addition to these, if the XHTML is not well formed a parse error is generated. This will give an indication of what the (first) parse error is.

Additional errors that shouldn't occur during normal use are logged to the Mozile Debugger. If you find one of these, and can reproduce it, please report it.

Save callback function: function __mozileSaved(reqObj)

This handles the display of error messages to the user for all save methods.

The following are used with the POST method.

.isAbortbooleantrue means the save was aborted.
.isErrorbooleanfalse means saved ok.
.statusstringserver status (a number, e.g. 200)
.statusTextstringserver status in words
.msgTextstringshort unformatted message
.documentXML documentXML server response (not used)
.documentTextstringText server response
.displaybooleantrue means show the POST Message Window.
.locationstring(optional) url to load
.replaceboolean(optional) true means replace current location.

The WEBDAV save method also uses orignalStatus and orignalStatusText. The values of these, together with status and statusText, are always logged to the Mozile debugger.

Save OK (.isError == false)

"Save Successful" is displayed in the browser status bar.

Save Error (.isError == true)

"Save Error" is displayed in the browser status bar.

Save Aborted (.isAbort == true)

"Save Aborted" is displayed in the browser status bar. The save may or may not have completed, it all depends on when the abort was executed.

Save Message Window : postmsg.js/postmsg.xul

The Save Message Window opens when there is an error unless the otpional display element has the value "no". If display has the value "yes" the window always opens.

This has two sections, as in the example above, for the error message and server status. Additionally, if there is a server document (e.g. a 404 Not Found web page) then an additional button is present below the server response. When this is activated the document opens in a new browser window.

Note that this uses document.write to insert the contents into the new window. If you are not using basic Ascii characters in the document you might need to view the page source, and then adjust the character set to get an idea of the true contents. This can often be useful when you want to return info from the server for debugging purposes.

I haven't fully integrated the display of messages for WEBDAV. At the moment they should display as before. (Let me know if they don't!)

The idea at the moment (I don't use WEBDAV) is that the same Save Message Window could be used as above to report errors with the first line changed to;
Save Method: WEBDAV

Obviously, more work needs to be done on displaying error messages if anyone implements the save of multiple editing areas in one go.

Interfacing with PHP

The POST data may be extracted from the global variable $HTTP_RAW_POST_DATA, or from the global variables array $GLOBALS['HTTP_RAW_POST_DATA'].

A more efficient way to access the data is directly from the input stream. E.g. to read the raw data as a string you could use:
$post_data = file_get_contents('php://input');

The ID of the editable area is found in the global variable $_GET['MozileID'].

The name of the file being saved is in the variable $_SERVER['HTTP_CONTENT_LOCATION']

Use the test file save_dump.php to test that the info is received correctly by the server.

Test Files

There are various test files for checking that the save via POST works correctly. Just set the php file as the save to file in the Mozile Save dialogue window.

save_ok.php 200 OK, file saved.
save_error.php 200 OK, with error message.
save_warning.php 200 OK, with warning, display=yes.
save_display_no.php 200 OK, with error, display=no.
save_201.php 201 header only (file created)
save_204.php 204 header only (file saved ok)
save_dump.php Returns the POSTed info for debugging purposes.
save_parse_error.php Example of a parse error.
save_html.php Example of an invalid response in HTML. (Must be XHTML.)