git-svn-id: svn://euphorik.ch/pompage@45 02bbb61a-6d21-0410-aba0-cb053bdfd66a
[pompage.git] / doc / webdeveloper / common / validation / html.js
diff --git a/doc/webdeveloper/common/validation/html.js b/doc/webdeveloper/common/validation/html.js
new file mode 100644 (file)
index 0000000..30bc638
--- /dev/null
@@ -0,0 +1,283 @@
+// Constructs a validate HTML object
+function WebDeveloperValidateHTML()
+{
+    this.file              = null;
+    this.fileElement       = null;
+    this.formElement       = null;
+    this.validationRequest = null;
+}
+
+// Cleans up
+WebDeveloperValidateHTML.prototype.cleanUp = function()
+{
+    // If the file is set
+    if(this.file)
+    {
+        // Try to delete the file
+        try
+        {
+            this.file.remove(false);
+        }
+        catch(exception)
+        {
+            // Do nothing
+        }
+
+        this.file = null;
+    }
+
+    // If the validation request is set
+    if(this.validationRequest)
+    {
+        this.validationRequest.abort();
+    }
+}
+
+// Creates a source file
+WebDeveloperValidateHTML.prototype.createSourceFile = function(uri)
+{
+    var temporaryDirectory = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("TmpD", Components.interfaces.nsIFile);
+
+    // If the temporary directory exists, is a directory and is writable
+    if(temporaryDirectory.exists() && temporaryDirectory.isDirectory() && temporaryDirectory.isWritable())
+    {
+        var fileName   = "";
+        var sourceFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+
+        // Try to get the host
+        try
+        {
+            fileName = uri.host;
+        }
+        catch(exception)
+        {
+            // Do nothing
+        }
+
+        temporaryDirectory.append("webdeveloper_" + fileName + "_" + new Date().getTime() + ".html");
+        sourceFile.initWithPath(temporaryDirectory.path);
+
+        return sourceFile;
+    }
+    else
+    {
+        webdeveloper_error(document.getElementById("webdeveloper-string-bundle").getFormattedString("webdeveloper_tempDirectoryFailed", [temporaryDirectory.path]));
+
+        return null;
+    }
+}
+
+// Returns the post data
+WebDeveloperValidateHTML.prototype.getPostData = function()
+{
+    // Try to get the post data
+    try
+    {
+        var sessionHistory = getWebNavigation().sessionHistory;
+        var entry          = sessionHistory.getEntryAtIndex(sessionHistory.index, false).QueryInterface(Components.interfaces.nsISHEntry);
+
+        return entry.postData;
+    }
+    catch(exception)
+    {
+        return null;
+    }
+}
+
+// Saves the HTML
+WebDeveloperValidateHTML.prototype.saveHTML = function(uri)
+{
+    var webBrowserPersistInterface = Components.interfaces.nsIWebBrowserPersist;
+    var webBrowserPersist          = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(webBrowserPersistInterface);
+
+    webBrowserPersist.persistFlags     = webBrowserPersistInterface.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION | webBrowserPersistInterface.PERSIST_FLAGS_FROM_CACHE | webBrowserPersistInterface.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
+    webBrowserPersist.progressListener = this;
+
+    webBrowserPersist.saveURI(uri, null, uri, this.getPostData(), null, this.file);
+}
+
+// Submits the background request to validate the HTML
+WebDeveloperValidateHTML.prototype.submitBackgroundRequest = function()
+{
+    var boundaryString   = new Date().getTime();
+    var boundary         = "--" + boundaryString;
+    var converter        = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+    var inputStream      = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
+    var scriptableStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
+    var requestBody      = boundary + "\r\nContent-Disposition: form-data; name=\"uploaded_file\"; filename=\"" + this.file.leafName + "\"\r\n";
+
+    converter.charset                         = webdeveloper_getContentDocument().characterSet;
+    this.validationRequest.onreadystatechange = webdeveloper_updatePageHTMLValidationDetails;
+
+    inputStream.init(this.file, 0x01, 0444, null);
+    scriptableStream.init(inputStream);
+
+    requestBody += "Content-Type: text/html\r\n\r\n";
+    requestBody += converter.ConvertToUnicode(scriptableStream.read(scriptableStream.available())) + "\r\n";
+    requestBody += boundary + "--";
+
+    scriptableStream.close();
+    inputStream.close();
+
+    this.validationRequest.open("post", "http://validator.w3.org/check", true);
+
+    // Try to set the request header
+    try
+    {
+        this.validationRequest.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundaryString);
+        this.validationRequest.send(requestBody);
+    }
+    catch(exception)
+    {
+        // Reset the validation request
+        this.validationRequest = new XMLHttpRequest();
+    }
+}
+
+// Submits the form to validate the HTML
+WebDeveloperValidateHTML.prototype.submitForm = function()
+{
+    this.fileElement.value = this.file.path;
+
+    this.formElement.submit();
+}
+
+// Validate the HTML from the given URI in the background
+WebDeveloperValidateHTML.prototype.validateBackgroundHTML = function(uri)
+{
+    this.file = this.createSourceFile(uri);
+
+    // If the validation request is not set
+    if(!this.validationRequest)
+    {
+        this.validationRequest = new XMLHttpRequest();
+    }
+
+    this.saveHTML(uri);
+}
+
+// Validate the HTML from the given URI
+WebDeveloperValidateHTML.prototype.validateHTML = function(uri)
+{
+    var oldTab            = getBrowser().selectedTab;
+    var oldURL            = getBrowser().currentURI.spec;
+    var generatedDocument = webdeveloper_generateDocument("");
+    var bodyElement       = webdeveloper_getDocumentBodyElement(generatedDocument);
+    var imageElement      = generatedDocument.createElement("img");
+    var inputElement      = null;
+    var pElement          = generatedDocument.createElement("p");
+    var stringBundle      = document.getElementById("webdeveloper-string-bundle");
+
+    generatedDocument.title = stringBundle.getString("webdeveloper_validateHTML");
+    this.file               = this.createSourceFile(uri);
+    this.formElement        = generatedDocument.createElement("form");
+
+    webdeveloper_addGeneratedStyles(generatedDocument);
+
+    imageElement.setAttribute("alt", "loading");
+    imageElement.setAttribute("src", "chrome://webdeveloper/content/images/content/loading.gif");
+    pElement.appendChild(imageElement);
+    pElement.appendChild(generatedDocument.createTextNode(stringBundle.getString("webdeveloper_contactingValidator")));
+    pElement.setAttribute("class", "loading");
+    bodyElement.appendChild(pElement);
+
+    this.formElement.setAttribute("action", "http://validator.w3.org/check");
+    this.formElement.setAttribute("enctype", "multipart/form-data");
+    this.formElement.setAttribute("method", "post");
+    this.formElement.setAttribute("style", "display: none");
+
+    // If the show outline preference is set
+    if(webdeveloper_getBooleanPreference("webdeveloper.validate.local.html.show.outline", true))
+    {
+        inputElement = generatedDocument.createElement("input");
+
+        inputElement.setAttribute("name", "outline");
+        inputElement.setAttribute("type", "hidden");
+        inputElement.setAttribute("value", "1");
+        this.formElement.appendChild(inputElement);
+    }
+
+    // If the show parse tree preference is set
+    if(webdeveloper_getBooleanPreference("webdeveloper.validate.local.html.show.parse.tree", true))
+    {
+        inputElement = generatedDocument.createElement("input");
+
+        inputElement.setAttribute("name", "sp");
+        inputElement.setAttribute("type", "hidden");
+        inputElement.setAttribute("value", "1");
+        this.formElement.appendChild(inputElement);
+    }
+
+    // If the show source preference is set
+    if(webdeveloper_getBooleanPreference("webdeveloper.validate.local.html.show.source", true))
+    {
+        inputElement = generatedDocument.createElement("input");
+
+        inputElement.setAttribute("name", "ss");
+        inputElement.setAttribute("type", "hidden");
+        inputElement.setAttribute("value", "1");
+        this.formElement.appendChild(inputElement);
+    }
+
+    inputElement = generatedDocument.createElement("input");
+
+    inputElement.setAttribute("name", "verbose");
+    inputElement.setAttribute("type", "hidden");
+    inputElement.setAttribute("value", "1");
+    this.formElement.appendChild(inputElement);
+
+    this.fileElement = generatedDocument.createElement("input");
+
+    this.fileElement.setAttribute("name", "uploaded_file");
+    this.fileElement.setAttribute("type", "file");
+    this.formElement.appendChild(this.fileElement);
+    bodyElement.appendChild(this.formElement);
+
+    // If the open tabs in background preference is set to true
+    if(webdeveloper_getBooleanPreference("webdeveloper.open.tabs.background", true))
+    {
+        getBrowser().selectedTab = oldTab;
+    }
+
+    this.saveHTML(uri);
+}
+
+// Called when the progress state changes
+WebDeveloperValidateHTML.prototype.onStateChange = function(webProgress, request, stateFlags, status)
+{
+    // If the progress has stopped
+    if(stateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
+    {
+        // If the file is set and exists
+        if(this.file && this.file.exists())
+        {
+            // If the validation request is set
+            if(this.validationRequest)
+            {
+                this.submitBackgroundRequest();
+            }
+            else
+            {
+                this.submitForm();
+            }
+        }
+    }
+}
+
+// Indicates the interfaces this object supports
+WebDeveloperValidateHTML.prototype.QueryInterface = function(id)
+{
+    // If the query is for a supported interface
+    if(id.equals(Components.interfaces.nsISupports) || id.equals(Components.interfaces.nsIWebProgressListener))
+    {
+        return this;
+    }
+
+    throw Components.results.NS_NOINTERFACE;
+}
+
+// Dummy methods requiring implementations
+WebDeveloperValidateHTML.prototype.onLocationChange = function(webProgress, request, location) {}
+WebDeveloperValidateHTML.prototype.onProgressChange = function(webProgress, request, currentSelfProgress, maximumSelfProgress, currentTotalProgress, maximumTotalProgress) {}
+WebDeveloperValidateHTML.prototype.onSecurityChange = function(webProgress, request, state) {}
+WebDeveloperValidateHTML.prototype.onStatusChange   = function(webProgress, request, status, message) {}