/*! This file came from Pixelsilk at http://www.brokentop.org/api2.js  (Smaller version available at http://www.brokentop.org/api2.min.js)
 *  Version: 3.0.16.6940 | 8/24/2010 5:45:46 PM */

/*********************************************************
 * DOCUMENTATION:
 *
 * Example usage: 
 * pixelsilk2.addNewPageType({ pageTypeName: 'test', baseId: '25E52B42-1580-4843-A76E-023F7340EEE4', image: 'HTML' }, function(pageType) {
 *     alert('Added page type ' + pageType.name + ' with id ' + pageType.id + '.');
 * });
 *
 *
 * pixelsilk2 API Functions:
 *
 **** Category: Configuration ****
 *
 ** getConfiguration()
 *    Return the key-value set of config settings for the site.
 *    Requires the advanced-admin-access permission.
 *
 ** updateConfig({ oldKey: String, newKey: String, value: String })
 *    Edit a configuration setting.
 *    Requires the advanced-admin-access permission.
 *
 ** getPlugins()
 *    Get a list of plugins.
 *    Requires the advanced-admin-access permission.
 *
 ** getPluginsWithJavaScript()
 *    Gets a list of plugins with and without a JavaScriptFilename member
 *    Requires the advanced-admin-access permission.
 *
 ** enablePlugin({ pluginName: String, enabled: Boolean })
 *    Turn a plugin on or off.
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: Content ****
 *
 ** getContent({ path: String })
 *    Get the unparsed content of a section by its path relative to the root.  Used by the content editor. 
 *
 ** setContent({ path: String, value: String })
 *    Update the content of a section by its path relative to the root.
 *
 ** setWebboxContent({ webboxName: String, value: String, path: String })
 *    Update the content of a webboox.
 *
 ** getWebboxContent({ webboxName: String, path: String })
 *    Get the unparsed content of a webbox.  Used by the content editor.
 *
 *
 **** Category: Controls ****
 *
 ** getControlSkins({ controlId: Guid })
 *    Gets the skins for a control.
 *    Requires the advanced-admin-access permission.
 *
 ** copyControl({ controlId: Guid })
 *    Make a copy of the control with its settings and skins.
 *    Requires the advanced-admin-access permission.
 *
 ** getControls()
 *    Get the list of controls.
 *    Requires the advanced-admin-access permission.
 *
 ** getControlSecurity({ controlId: Guid })
 *    Get the security options for a control.
 *    Requires the advanced-admin-access permission.
 *
 ** getControlTypes()
 *    Get the list of types of controls (for new controls ui.)
 *    Requires the advanced-admin-access permission.
 *
 ** getControlProperties({ controlId: Guid })
 *    Get the properties on a control.
 *    Requires the advanced-admin-access permission.
 *
 ** checkValidNewControl({ name: String, type: String })
 *    Validate a control name to check if it conflicts with another control or field.
 *    Requires the advanced-admin-access permission.
 *
 ** createControl({ name: String, type: String })
 *    Add a new control.
 *    Requires the advanced-admin-access permission.
 *
 ** updateControlProperties({ controlId: Guid, controlName: String, properties: KeyValue, permissions: Array })
 *    Requires the advanced-admin-access permission.
 *
 ** deleteControl({ controlId: Guid })
 *    Remove a control.
 *    Requires the advanced-admin-access permission.
 *
 ** promoteControl({ controlId: Guid })
 *    Make a copy of the theme at the top most group.  Currently only available to limited users. 
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: Email ****
 *
 ** updateEmailSettings({ settings: Setting[] })
 *    Update the email settings for a Site 
 *    Requires the advanced-admin-access permission.
 *
 ** getEmailSettings()
 *    Retrieve the email settings for a site 
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: Files ****
 *
 ** getAlbums({ type: String })
 *    Gets the list of files inside an album
 *    Requires the access-libraries permission.
 *
 ** saveAlbum({ type: String, albumName: String })
 *    Saves an album, either adding a new one or updating an existing one. 
 *    Requires the access-libraries permission.
 *
 ** deleteAlbum({ type: String, albumName: String })
 *    Delete an album from the site.
 *    Requires the access-libraries permission.
 *
 ** getAlbumContents({ type: String, albumName: String })
 *    Gets the list of files inside an album 
 *    Requires the access-libraries permission.
 *
 ** deleteFile({ type: String, filename: String, albumName: String })
 *    Deletes a file from an album.
 *    Requires the access-libraries permission.
 *
 ** getSystemFilenames()
 *    Get a list of system files.
 *    Requires the advanced-admin-access permission.
 *
 ** getSystemFiles()
 *    Get a list of system files.
 *    Requires the advanced-admin-access permission.
 *
 ** getSystemFile({ filename: String })
 *    Get the contents of a system file.
 *    Requires the advanced-admin-access permission.
 *
 ** updateSystemFile({ filename: String, text: String })
 *    Edit a system file.
 *    Requires the advanced-admin-access permission.
 *
 ** renameSystemFile({ oldName: String, newName: String })
 *    Rename a file in the SystemFiles tab.
 *    Requires the advanced-admin-access permission.
 *
 ** addNewSystemFile({ filename: String })
 *    Create a system file.
 *    Requires the advanced-admin-access permission.
 *
 ** deleteSystemFile({ filename: String })
 *    Remove a system file.
 *    Requires the advanced-admin-access permission.
 *
 ** copySystemFile({ filename: String })
 *    Copy the file. 
 *    Requires the advanced-admin-access permission.
 *
 ** promoteFile({ type: String, filename: String })
 *    Make a copy of the file at the top most group.  Currently only available to limited users. 
 *    Requires the advanced-admin-access permission.
 *
 ** renameFile({ type: String, oldName: String, album: String, newName: String })
 *    Renames a library file. 
 *    Requires the advanced-admin-access permission.
 *
 ** moveFile({ type: String, filename: String, albumId: Guid })
 *    Moves a file to an album. 
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: List Items ****
 *
 ** deleteItem({ itemId: Guid, deleteMode: String })
 *    Delete a list item.
 *
 ** getListItems({ sorts: Array, filters: Array, filterrel: String, pageSize: String, page: String, path: String, fields: Array })
 *
 *
 **** Category: Page Types ****
 *
 ** addPageTypeFieldValue({ pageTypeId: Guid, fieldId: Guid, listValue: String, listText: String })
 *    Add a value to a field's values.
 *    Requires the advanced-admin-access permission.
 *
 ** updatePageTypeFieldValue({ pageTypeId: Guid, fieldId: Guid, valueId: Guid, listValue: String, listText: String })
 *    Modify one of a field's values.
 *    Requires the advanced-admin-access permission.
 *
 ** movePageTypeFieldValueInsertBefore({ pageTypeId: String, fieldId: String, valueToMoveId: String, valueToInsertBeforeId: String })
 *    When a field value is dragged to be above another value.
 *    Requires the advanced-admin-access permission.
 *
 ** movePageTypeFieldValueInsertBefore({ pageTypeId: Guid, fieldId: Guid, valueToMoveId: Guid, valueToInsertBeforeId: Guid })
 *    When a field value is dragged to be above another value.
 *    Requires the advanced-admin-access permission.
 *
 ** deletePageTypeFieldValue({ pageTypeId: Guid, fieldId: Guid, valueId: Guid })
 *    Delete's one of a field's values.
 *    Requires the advanced-admin-access permission.
 *
 ** updatePageType({ id: Guid, name: String, image: String })
 *    Edit a page type's properties.
 *    Requires the advanced-admin-access permission.
 *
 ** copyPageType({ pageTypeId: Guid })
 *    Make a copy of a page type.
 *    Requires the advanced-admin-access permission.
 *
 ** promotePageType({ pageTypeId: Guid })
 *    Copy a page type to the root group.
 *    Requires the advanced-admin-access permission.
 *
 ** getPageTypeSkins({ pageTypeId: Guid })
 *    Gets the skins object for a page type.
 *    Requires the advanced-admin-access permission.
 *
 ** getPageTypes()
 *    Return an object containing all of the page types available sorted into system and site specific types. 
 *    Requires the edit-page-properties permission.
 *
 ** getBaseTypes()
 *    Return an object containing all of the page types available sorted into system and site specific types. 
 *    Requires the edit-page-properties permission.
 *
 ** addNewPageType({ name: String, baseType: String, image: String })
 *    Create a new page type based on an existing site type or a system type
 *    Requires the advanced-admin-access permission.
 *
 ** deletePageType({ pageTypeId: Guid })
 *    Deletes a page type.
 *    Requires the advanced-admin-access permission.
 *
 ** getPageTypeFields({ pageTypeId: Guid })
 *    Get the fields in a page type.
 *    Requires the advanced-admin-access permission.
 *
 ** checkValidNewPageTypeField({ pageTypeId: Guid, fieldName: String })
 *    Validate a field name to make sure it does not conflict with another field or control. 
 *    Requires the advanced-admin-access permission.
 *
 ** addPageTypeField({ pageTypeId: Guid, fieldName: String, fieldType: String })
 *    Add a new field to a page type.
 *    Requires the advanced-admin-access permission.
 *
 ** deletePageTypeField({ pageTypeId: Guid, fieldId: Guid })
 *    Delete a field from a page type.
 *    Requires the advanced-admin-access permission.
 *
 ** updatePageTypeField({ pageTypeId: Guid, input: PageTypeFieldForJson })
 *    Save changes to a page type's field.
 *    Requires the advanced-admin-access permission.
 *
 ** getPageTypeFieldValues({ pageTypeId: Guid, fieldId: Guid })
 *    Get the values for a page type (choices in a drop down for example.)
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: Sections ****
 *
 ** getAllSections()
 *    Get a list of all the sections (used from the Manage Pages UI). 
 *    Requires the edit-page-properties permission.
 *
 ** getSections({ parentId: Nullable`1 })
 *    Get a list of sections based on the parent. 
 *    Requires the edit-page-properties permission.
 *
 ** getSection({ sectionId: Guid })
 *    Get full information about a given section. 
 *    Requires the edit-page-properties permission.
 *
 ** newSection()
 *    Create an empty section. 
 *    Requires the add-page permission.
 *
 ** moveSectionMakeChild({ childId: Guid, parentId: Guid })
 *    Move a section to be a child of another section (used from the Manage Pages UI). 
 *    Requires the move-page permission.
 *
 ** moveSectionInsertBefore({ sectionToMoveId: Guid, sectionToInsertBeforeId: Guid })
 *    Move a section to be immediately before another section (used from the Manage Pages UI). 
 *    Requires the move-page permission.
 *
 ** enableSectionById({ sectionId: Guid, enabled: Boolean })
 *    Enable or disable a section (used from the Manage Pages UI).
 *    Requires the edit-page-properties permission.
 *
 ** showSectionInMenu({ sectionId: Guid, show: Boolean })
 *    Hide or unhide a section (used from the Manage Pages UI).
 *    Requires the edit-page-properties permission.
 *
 ** showSectionInSitemap({ sectionId: Guid, show: Boolean })
 *    Hide or unhide a section (used from the Manage Pages UI).
 *    Requires the edit-page-properties permission.
 *
 ** deleteSectionById({ sectionId: Guid })
 *    Delete a section (used from the Manage Pages UI)
 *    Requires the delete-page permission.
 *
 ** updateSection({ input: FullSectionForJson })
 *    Updates the properties of a section.
 *    Requires the edit-page-properties permission.
 *
 ** getSectionsUrl({ sectionId: Guid })
 *    Get's a section's relative url.
 *    Requires the edit-page-properties permission.
 *
 ** getPotentialUrl({ sectionId: Guid, urlMode: String, pathName: String, extension: String, rewriteUrl: String, toLowerCase: Boolean, useParentSettings: Boolean })
 *    Returns what a section's url would be with different settings on the URL tab in admin. 
 *    Requires the edit-page-properties permission.
 *
 ** addSection({ name: String, parentId: Guid, typeId: Guid })
 *    Adds a new section.
 *    Requires the add-page permission.
 *
 ** getSkins({ sectionId: Guid })
 *    Gets the skins object for a section.
 *    Requires the edit-page-properties permission.
 *
 ** createNewSectionSkin({ sectionId: Guid })
 *    Create a new skin for a section that will override its type skin.
 *    Requires the edit-page-properties permission.
 *
 ** deleteSectionSkin({ sectionId: Guid })
 *    Deletes a section's skin and falls back to the type skin for the section.
 *    Requires the edit-page-properties permission.
 *
 ** getSiteListSections()
 *    Get List sections in the site.
 *    Requires the edit-page-properties permission.
 *
 *
 **** Category: Security ****
 *
 ** updateSecuritySettings({ settings: KeyValue })
 *    Requires the advanced-admin-access permission.
 *
 ** getSecuritySettings()
 *    Retrieve the settings for a site 
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: Skins ****
 *
 ** renderSkin({ skin: String, path: String, format: String })
 *    Renders a simple skin.
 *
 *
 **** Category: Themes ****
 *
 ** getThemes()
 *    Get the themes in the site.
 *    Requires the edit-skin permission.
 *
 ** addTheme({ themeName: String })
 *    Add a theme to the site.
 *    Requires the edit-skin permission.
 *
 ** editTheme({ input: ThemeForJson })
 *    Edit a theme's name.
 *    Requires the edit-skin permission.
 *
 ** deleteTheme({ themeId: Guid })
 *    Delete a theme.
 *    Requires the edit-skin permission.
 *
 ** copyTheme({ themeId: Guid })
 *    Duplicate a theme.
 *    Requires the edit-skin permission.
 *
 ** getLayoutSkins({ themeId: Guid })
 *    Gets the layout skin for the theme.
 *    Requires the edit-skin permission.
 *
 ** updateSkins({ input: SkinsForJson })
 *    Save changes to any skins object.
 *    Requires the edit-skin permission.
 *
 ** promoteTheme({ themeId: Guid })
 *    Make a copy of the theme at the top most group.  Currently only available to limited users. 
 *    Requires the advanced-admin-access permission.
 *
 *
 **** Category: Users ****
 *
 ** login({ username: String, password: String })
 *    Login function for external application.  Takes a username and password, retuns an auth cookie and a token. 
 *
 ** updateUser({ username: String, emailAddress: String, firstName: String, lastName: String, password: String, enabled: Boolean, locked: Boolean, emailVerified: Boolean, roles: Guid[], id: String })
 *    Edit a user.
 *    Requires the access-users permission.
 *
 ** sendMailForPasswordUpdate({ originalUser: SiteUser, newPassword: String })
 *    Cause an email to be sent to a user with thier new password.
 *    Requires the access-users permission.
 *
 ** updateRole({ hiddenName: String, name: String, description: String, isHidden: String, isSystemRole: String, adminAccess: String[] })
 *    Edit a role.
 *    Requires the access-users permission.
 *
 ** addRole({ name: String, description: String, isHidden: String, isSystemRole: String, adminAccess: String[] })
 *    Add a new role.
 *    Requires the access-users permission.
 *
 ** addUser({ username: String, emailAddress: String, firstName: String, lastName: String, password: String, sendPasswordLink: Boolean, enabled: Boolean, locked: Boolean, emailVerified: Boolean, roles: Guid[] })
 *    Add a new user.
 *    Requires the access-users permission.
 *
 ** deleteRole({ roleName: String })
 *    Delete a role.
 *    Requires the access-users permission.
 *
 ** deleteUser({ userId: String })
 *    Delete a user.
 *    Requires the access-users permission.
 *
 ** getUsers()
 *    Get site users.
 *    Requires the access-users permission.
 *
 ** getRoles()
 *    Get site roles.
 *    Requires the access-users or edit-page-properties permission.
 *
 ** getEveryone()
 *    Returns only the everyone role.  Needed currently because sections need to "show Everyone plus all the roles on the roles tab"  See bug [I3-2692]. 
 *    Requires the access-users permission.
 *
 ** useEmailAsUsername()
 *    Determines if the site encourages to use the email address as the username.
 *    Requires the access-users permission.
 *
 ** verifyUserUniqueness({ id: String, loginId: String, email: String })
 *    Determines if the username and email given as parameters already exist.
 *
 ** sendPasswordLink({ userId: String })
 *    Send an email to the user with the password link.
 *    Requires the access-users permission.
 *
 ** sendEmailVerificationLink({ userId: String })
 *    Send an email to the user with the password link.
 *    Requires the access-users permission.
 *
 ** sendVerificationEmail({ user: PixelsilkUser })
 *    Send an email to the user with the password link. 
 *    Requires the access-users permission.
 *
 ** getPasswordRequirements()
 *    Get Password Requirements from Site Settings.
 *
 ** getUsernameMessages()
 *    Get Username Messages from Site Settings.
 *
 ** getEmailAddressMessages()
 *    Get Email Messages from Site Settings.
 *
 ** getPasswordMessages()
 *    Get Password Messages from Site Settings.
 *
 ** getLoginMessages()
 *    Get Login Messages from Site Settings.
 *
 ** canEditPassword()
 *    Determines if the user has a Role with the "edit-password" permission.
 *    Requires the access-users permission.
 *
 *
 **** Category: unspecified ****
 *
 ** getTokens({ skinId: Nullable`1 })
 *    Get the tokens for a given page if it is a special page. Otherwise the TscGetTokens() function is called. 
 *    Requires the edit-skin permission.
 *
 ** checkPermissions({ permissionsNeeded: String[] })
 *    Sees if the user has at least one of the specified permissions.
 *
 *
 *********************************************************/

if (!window['pixelsilk2']) {

    window['pixelsilk2'] = (function() {

        var nextId = 1;
        var token;  // prevents csrf
        var appId;  // id of the application, can be blank at this time.
        var privateKey;  // key used for signing if the application is specified.

        // Methods here are not globally accessible.

        var startHandler, endHandler, errorHandler;
        function start() {
            if (typeof (startHandler) === 'function') {
                startHandler();
            }
        }

        function end() {
            if (typeof (endHandler) === 'function') {
                endHandler();
            }
        }

        function error(e) {
            if (typeof (errorHandler) === 'function') {
                errorHandler(e);
            } else if (e.error) {
                alert(e.message);
            }
        }

        function ajax(url, data, auth, callback) {
            includeJson('JSON', '/_System/Scripts/json2.min.js');
            start();

            if (typeof (callback) !== 'function' && typeof (auth) === 'function') {
                // If there's callback, but no auth.
                callback = auth;
                auth = null;
            } else if (typeof (callback) !== 'function' && typeof (data) === 'function') {
                // If there's a callback, but no data.
                callback = data;
                data = null;
            }

            var eventCallback = function(data) {
                end();
                if (callback) {
                    callback(data);
                }
            };

            // This will first try an XmlHttpRequest, if that is unavailable it will try a JSONP script request.
            ajaxXhr(url, data, auth, eventCallback);
        }

        function ajaxXhr(url, data, auth, callback) {
            // Setup the request
            var request = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
            request.open('POST', url, true);
            request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

            // Event handler
            request.onreadystatechange = function() {
                // If the request is done without error.
                if (request.readyState === 4 && request.status === 200 && (request.responseText || request.responseText === "")) {

                    // Parse the result.
                    var result = JSON.parse(request.responseText);

                    if (result && result.error === true) {  // Error could be a 200 with json if noHttp500 is set to true.
                        error(result);
                    } else if (callback !== null) {  // Call the callback in client code.
                        callback(result);
                    }

                    // If the request completed with an error...
                } else if (request.readyState === 4 && request.status === 500) {
                    var json = JSON.parse(request.responseText);
                    error(json);
                } else if (request.readyState === 4 && request.status === 0) {
                    // Try a JSONP request.
                    ajaxScriptTag(url, data, eventCallback);  // no post == no auth :(
                }
            };

            // Set the data
            var body = objectToQuery(data, auth);

            // Send the request to the server
            request.send(body);
        }

        function ajaxScriptTag(url, data, callback) {
            var id = nextId++;
            var callbackName = setupCallback(id, callback);
            var query = objectToQuery(data);
            var script = makeScriptTag(url, query, callbackName, id);

            var head = document.getElementsByTagName('head')[0];
            head.appendChild(script);
        }

        function setupCallback(id, callback) {
            // Generate a name because the callback needs to be globally accessable: pixelsilk2.callback1()
            var callbackName = 'callback' + id;

            window['pixelsilk2'][callbackName] = function(result) {
                // remove the callback wrapper
                window['pixelsilk2'][callbackName] = null;

                // remove the script tag
                var script = document.getElementById('pixelsilk2api' + id);
                if (script) {
                    script.parentNode.removeChild(script);
                }

                // call the real callback
                callback(result);
            };

            // return the name;
            return 'pixelsilk2.' + callbackName;
        }

        function objectToQuery(data, auth) {
            var query = 'json=';

            if (typeof (data) !== 'undefined') {
                var json = JSON.stringify(data);
                query += encodeURIComponent(json);
            }

            if (token && !auth) {
                query += '&token=' + encodeURIComponent(token);
            }
            if (appId) {
                var signature = signRequest(json);
                query += '&appId=' + encodeURIComponent(appId) + '&signature=' + encodeURIComponent(signature);
            }
            if (auth) {
                query += '&auth=' + encodeURIComponent(auth.auth) + '&token=' + encodeURIComponent(auth.token);
            }
            return query;
        }

        function signRequest(json) {
            // TODO: include the user's token and a random string (nonce) in the toHash var.
            if (typeof (json) === 'undefined') {
                json = '';
            }
            var toHash = json + privateKey;
            includeJson('SHA1', '/_System/Scripts/webtoolkit.sha1.min.js');
            return SHA1(toHash);
        }

        function makeScriptTag(url, query, callback, id) {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            var src = url + '?' + query + '&callback=' + callback;
            if (src.length > 2000) {
                throw "URL length is over 2000 characters, not creating script tag.";
            }
            script.src = src;
            script.id = 'pixelsilk2api' + id;
            script.className = 'pixelsilk2api';
            return script;
        }

        function createApiFunction(functionName) {
            return function(data, auth, callback) {
                var url = window['pixelsilk2'].urlBase + functionName;
                ajax(url, data, auth, callback);
            };
        }

        // Return just the 'public' functions.
        var api = {
            // init must be called first if you need to do anything as a logged in user
            init: function(t) {
                token = t;
            },
            setKey: function(id, key) {
                appId = id;
                privateKey = key;
            },
            start: function(handler) {
                startHandler = handler;
            },
            end: function(handler) {
                endHandler = handler;
            },
            error: function(handler) {
                errorHandler = handler;
            },

            // Necessary context info.
            domain: 'www.brokentop.org',
            urlBase: 'http://www.brokentop.org/api2/',
            appPath: ''
        };

        function includeJson(name, path) {
            if (!window[name]) {
                var url = 'http://' + api.domain;
                if (api.appPath) {
                    url += '/' + api.appPath;
                }
                url += path;

                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.src = url;

                var head = document.getElementsByTagName('head')[0];
                head.appendChild(script);
            }
        }

        /*!
        *
        *  Secure Hash Algorithm (SHA1)
        *  http://www.webtoolkit.info/
        *
        **/
        function SHA1(msg) {

            function rotate_left(n, s) {
                var t4 = (n << s) | (n >>> (32 - s));
                return t4;
            };

            function lsb_hex(val) {
                var str = "";
                var i;
                var vh;
                var vl;

                for (i = 0; i <= 6; i += 2) {
                    vh = (val >>> (i * 4 + 4)) & 0x0f;
                    vl = (val >>> (i * 4)) & 0x0f;
                    str += vh.toString(16) + vl.toString(16);
                }
                return str;
            };

            function cvt_hex(val) {
                var str = "";
                var i;
                var v;

                for (i = 7; i >= 0; i--) {
                    v = (val >>> (i * 4)) & 0x0f;
                    str += v.toString(16);
                }
                return str;
            };


            function Utf8Encode(string) {
                string = string.replace(/\r\n/g, "\n");
                var utftext = "";

                for (var n = 0; n < string.length; n++) {

                    var c = string.charCodeAt(n);

                    if (c < 128) {
                        utftext += String.fromCharCode(c);
                    }
                    else if ((c > 127) && (c < 2048)) {
                        utftext += String.fromCharCode((c >> 6) | 192);
                        utftext += String.fromCharCode((c & 63) | 128);
                    }
                    else {
                        utftext += String.fromCharCode((c >> 12) | 224);
                        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                        utftext += String.fromCharCode((c & 63) | 128);
                    }

                }

                return utftext;
            };

            var blockstart;
            var i, j;
            var W = new Array(80);
            var H0 = 0x67452301;
            var H1 = 0xEFCDAB89;
            var H2 = 0x98BADCFE;
            var H3 = 0x10325476;
            var H4 = 0xC3D2E1F0;
            var A, B, C, D, E;
            var temp;

            msg = Utf8Encode(msg);

            var msg_len = msg.length;

            var word_array = new Array();
            for (i = 0; i < msg_len - 3; i += 4) {
                j = msg.charCodeAt(i) << 24 | msg.charCodeAt(i + 1) << 16 |
                    msg.charCodeAt(i + 2) << 8 | msg.charCodeAt(i + 3);
                word_array.push(j);
            }

            switch (msg_len % 4) {
                case 0:
                    i = 0x080000000;
                    break;
                case 1:
                    i = msg.charCodeAt(msg_len - 1) << 24 | 0x0800000;
                    break;

                case 2:
                    i = msg.charCodeAt(msg_len - 2) << 24 | msg.charCodeAt(msg_len - 1) << 16 | 0x08000;
                    break;

                case 3:
                    i = msg.charCodeAt(msg_len - 3) << 24 | msg.charCodeAt(msg_len - 2) << 16 | msg.charCodeAt(msg_len - 1) << 8 | 0x80;
                    break;
            }

            word_array.push(i);

            while ((word_array.length % 16) != 14) word_array.push(0);

            word_array.push(msg_len >>> 29);
            word_array.push((msg_len << 3) & 0x0ffffffff);


            for (blockstart = 0; blockstart < word_array.length; blockstart += 16) {

                for (i = 0; i < 16; i++) W[i] = word_array[blockstart + i];
                for (i = 16; i <= 79; i++) W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);

                A = H0;
                B = H1;
                C = H2;
                D = H3;
                E = H4;

                for (i = 0; i <= 19; i++) {
                    temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
                    E = D;
                    D = C;
                    C = rotate_left(B, 30);
                    B = A;
                    A = temp;
                }

                for (i = 20; i <= 39; i++) {
                    temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
                    E = D;
                    D = C;
                    C = rotate_left(B, 30);
                    B = A;
                    A = temp;
                }

                for (i = 40; i <= 59; i++) {
                    temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
                    E = D;
                    D = C;
                    C = rotate_left(B, 30);
                    B = A;
                    A = temp;
                }

                for (i = 60; i <= 79; i++) {
                    temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
                    E = D;
                    D = C;
                    C = rotate_left(B, 30);
                    B = A;
                    A = temp;
                }

                H0 = (H0 + A) & 0x0ffffffff;
                H1 = (H1 + B) & 0x0ffffffff;
                H2 = (H2 + C) & 0x0ffffffff;
                H3 = (H3 + D) & 0x0ffffffff;
                H4 = (H4 + E) & 0x0ffffffff;

            }

            var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);

            return temp.toLowerCase();

        }
        /**
        *
        *  End SHA1
        *
        **/


        // Define API functions..
        var apiFunctions = ["addPageTypeFieldValue","updatePageTypeFieldValue","movePageTypeFieldValueInsertBefore","movePageTypeFieldValueInsertBefore","deletePageTypeFieldValue","updatePageType","copyPageType","promotePageType","getControlSkins","copyControl","getControls","getControlSecurity","getControlTypes","getControlProperties","checkValidNewControl","createControl","updateControlProperties","deleteControl","promoteControl","getConfiguration","updateConfig","getPlugins","getPluginsWithJavaScript","enablePlugin","login","updateUser","sendMailForPasswordUpdate","updateRole","addRole","addUser","deleteRole","deleteUser","getUsers","getRoles","getEveryone","useEmailAsUsername","verifyUserUniqueness","sendPasswordLink","sendEmailVerificationLink","sendVerificationEmail","getPasswordRequirements","getUsernameMessages","getEmailAddressMessages","getPasswordMessages","getLoginMessages","canEditPassword","getTokens","updateSecuritySettings","getSecuritySettings","updateEmailSettings","getEmailSettings","checkPermissions","renderSkin","getContent","setContent","setWebboxContent","getWebboxContent","deleteItem","getListItems","getAlbums","saveAlbum","deleteAlbum","getAlbumContents","getSystemImages","deleteFile","getSystemFilenames","getSystemFiles","getSystemFile","updateSystemFile","renameSystemFile","addNewSystemFile","deleteSystemFile","copySystemFile","promoteFile","renameFile","moveFile","getAllSections","getSections","getSection","newSection","moveSectionMakeChild","moveSectionInsertBefore","enableSectionById","showSectionInMenu","showSectionInSitemap","deleteSectionById","updateSection","getSectionsUrl","getPotentialUrl","addSection","getSkins","getTypeSkins","createNewSectionSkin","deleteSectionSkin","getSiteListSections","getThemes","addTheme","editTheme","deleteTheme","copyTheme","getLayoutSkins","updateSkins","promoteTheme","getPageTypeSkins","getPageTypes","getBaseTypes","addNewPageType","deletePageType","getPageTypeFields","checkValidNewPageTypeField","addPageTypeField","deletePageTypeField","updatePageTypeField","getPageTypeFieldValues"];
        for (var i = 0; i < apiFunctions.length; i++) {
            var functionName = apiFunctions[i];
            api[functionName] = createApiFunction(functionName);
        }

        return api;

    } ());

} // if (!window['pixelsilk2'])
