You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2015/02/25 05:15:48 UTC

incubator-nifi git commit: NIFI-353: - Starting to add support for the hex viewer.

Repository: incubator-nifi
Updated Branches:
  refs/heads/NIFI-353 efe8e0682 -> 60c411de0


NIFI-353:
- Starting to add support for the hex viewer.

Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/60c411de
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/60c411de
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/60c411de

Branch: refs/heads/NIFI-353
Commit: 60c411de0dab6e0dc099e9b1fb04adfb1c2507f1
Parents: efe8e06
Author: Matt Gilman <ma...@gmail.com>
Authored: Tue Feb 24 23:15:21 2015 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Tue Feb 24 23:15:21 2015 -0500

----------------------------------------------------------------------
 .../nifi-standard-content-viewer/pom.xml        |  13 +-
 .../web/StandardContentViewerController.java    |  17 +-
 .../main/webapp/META-INF/nifi-content-viewer    |   3 +-
 .../src/main/webapp/WEB-INF/jsp/hexview.jsp     |  35 +++
 .../src/main/webapp/js/application.js           | 282 -------------------
 .../src/main/webapp/js/hexview/LICENSE          |  32 +++
 .../main/webapp/js/hexview/hexview.default.css  |  10 +
 .../src/main/webapp/js/hexview/hexview.js       | 175 ++++++++++++
 8 files changed, 277 insertions(+), 290 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
index b4eabfc..080c2bd 100644
--- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/pom.xml
@@ -26,15 +26,22 @@
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <version>1.9.13</version>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.13</version>
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
index 0b6fe0a..3a361b4 100644
--- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/java/org/apache/nifi/web/StandardContentViewerController.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.web;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.StringWriter;
 
@@ -31,6 +32,8 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.TransformerFactoryConfigurationError;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
 import org.codehaus.jackson.map.ObjectMapper;
 
 /**
@@ -79,12 +82,18 @@ public class StandardContentViewerController extends HttpServlet {
                 formatted = writer.toString();
             }
             
-            // defer the jsp
+            // defer to the jsp
             request.setAttribute("mode", content.getContentType());
             request.setAttribute("content", formatted);
             request.getRequestDispatcher("/WEB-INF/jsp/codemirror.jsp").include(request, response);
-        } 
-        
+        } else if ("application/octet-stream".equals(content.getContentType())) {
+            // convert stream into the base 64 bytes
+            final byte[] bytes = IOUtils.toByteArray(content.getContentStream());
+            final String base64 = Base64.encodeBase64String(bytes);
+            
+            // defer to the jsp
+            request.setAttribute("content", base64);
+            request.getRequestDispatcher("/WEB-INF/jsp/hexview.jsp").include(request, response);
+        }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/META-INF/nifi-content-viewer
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/META-INF/nifi-content-viewer b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/META-INF/nifi-content-viewer
index 29fed60..8693ebb 100644
--- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/META-INF/nifi-content-viewer
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/META-INF/nifi-content-viewer
@@ -1,2 +1,3 @@
 application/xml
-application/json
\ No newline at end of file
+application/json
+application/octet-stream
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/hexview.jsp
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/hexview.jsp b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/hexview.jsp
new file mode 100644
index 0000000..04ec46f
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/WEB-INF/jsp/hexview.jsp
@@ -0,0 +1,35 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<script type="text/javascript" src="../nifi/js/jquery/jquery-2.1.1.min.js"></script>
+<link rel="stylesheet" href="${request.contextPath}/js/hexview/hexview.default.css" type="text/css" />
+<script type="text/javascript" src="${pageContext.request.contextPath}/js/hexview/hexview.js"></script>
+
+<div id="hexview-content" class="hexviewerwindow">
+    ${content}
+    <form id="hexviewwindow_params">
+        <input type="hidden" name="highlights" value="" />
+        <input type="hidden" name="row_width" value="16" />
+        <input type="hidden" name="word_size" value="1" />
+        <input type="hidden" name="caption" value="" />
+    </form>
+</div>
+
+<script type="text/javascript">
+    $(document).ready(function () {
+    });
+</script>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/application.js
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/application.js b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/application.js
deleted file mode 100644
index 3efdbcc..0000000
--- a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/application.js
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-$(document).ready(function () {
-
-    var isUndefined = function (obj) {
-        return typeof obj === 'undefined';
-    };
-
-    var isNull = function (obj) {
-        return obj === null;
-    };
-
-    var isDefinedAndNotNull = function (obj) {
-        return !isUndefined(obj) && !isNull(obj);
-    };
-
-    /**
-     * Get the filter text.
-     * 
-     * @returns {unresolved}
-     */
-    var getFilterText = function () {
-        var filter = '';
-        var ruleFilter = $('#component-filter');
-        if (!ruleFilter.hasClass('component-filter-list')) {
-            filter = ruleFilter.val();
-        }
-        return filter;
-    };
-
-    var applyComponentFilter = function (componentContainer) {
-        var matchingComponents = 0;
-        var componentLinks = $(componentContainer).find('a.component-link');
-
-        if (componentLinks.length === 0) {
-            return matchingComponents;
-        }
-
-        // get the filter text
-        var filter = getFilterText();
-        if (filter !== '') {
-            var filterExp = new RegExp(filter, 'i');
-
-            // update the displayed rule count
-            $.each(componentLinks, function (_, componentLink) {
-                var a = $(componentLink);
-                var li = a.closest('li.component-item');
-
-                // get the rule text for matching
-                var componentName = a.text();
-
-                // see if any of the text from this rule matches
-                var componentMatches = componentName.search(filterExp) >= 0;
-
-                // handle whether the rule matches
-                if (componentMatches === true) {
-                    li.show();
-                    matchingComponents++;
-                } else {
-                    // hide the rule
-                    li.hide();
-                }
-            });
-        } else {
-            // ensure every rule is visible
-            componentLinks.closest('li.component-item').show();
-
-            // set the number of displayed rules
-            matchingComponents = componentLinks.length;
-        }
-
-        // show whether there are status if appropriate
-        var noMatching = componentContainer.find('span.no-matching');
-        if (matchingComponents === 0) {
-            noMatching.show();
-        } else {
-            noMatching.hide();
-        }
-
-        return matchingComponents;
-    };
-
-    var applyFilter = function () {
-        var matchingGeneral = applyComponentFilter($('#general-links'));
-        var matchingProcessors = applyComponentFilter($('#processor-links'));
-        var matchingControllerServices = applyComponentFilter($('#controller-service-links'));
-        var matchingReportingTasks = applyComponentFilter($('#reporting-task-links'));
-        var matchingDeveloper = applyComponentFilter($('#developer-links'));
-
-        // update the rule count
-        $('#displayed-components').text(matchingGeneral + matchingProcessors + matchingControllerServices + matchingReportingTasks + matchingDeveloper);
-    };
-
-    var selectComponent = function (componentName) {
-        var componentLinks = $('a.component-link');
-
-        // consider each link
-        $.each(componentLinks, function () {
-            var componentLink = $(this);
-            if (componentName === componentLink.text()) {
-                // remove all selected styles
-                $('li.component-item').removeClass('selected');
-
-                // select this links item
-                componentLink.closest('li.component-item').addClass('selected');
-
-                // set the header
-                $('#selected-component').text(componentLink.text());
-
-                // stop iteration
-                return false;
-            }
-        });
-    };
-
-    // get the banners if we're not in the shell
-    var banners = $.Deferred(function (deferred) {
-        if (top === window) {
-            $.ajax({
-                type: 'GET',
-                url: '../nifi-api/controller/banners',
-                dataType: 'json'
-            }).then(function (response) {
-                // ensure the banners response is specified
-                if (isDefinedAndNotNull(response.banners)) {
-                    if (isDefinedAndNotNull(response.banners.headerText) && response.banners.headerText !== '') {
-                        // update the header text
-                        var bannerHeader = $('#banner-header').html(response.banners.headerText).show();
-
-                        // show the banner
-                        var updateTop = function (elementId) {
-                            var element = $('#' + elementId);
-                            element.css('top', (parseInt(bannerHeader.css('height')) + parseInt(element.css('top'))) + 'px');
-                        };
-
-                        // update the position of elements affected by top banners
-                        updateTop('documentation-header');
-                        updateTop('component-listing');
-                        updateTop('component-usage-container');
-                    }
-
-                    if (isDefinedAndNotNull(response.banners.footerText) && response.banners.footerText !== '') {
-                        // update the footer text and show it
-                        var bannerFooter = $('#banner-footer').html(response.banners.footerText).show();
-
-                        var updateBottom = function (elementId) {
-                            var element = $('#' + elementId);
-                            element.css('bottom', parseInt(bannerFooter.css('height')) + parseInt(element.css('bottom')) + 'px');
-                        };
-
-                        // update the position of elements affected by bottom banners
-                        updateBottom('component-filter-controls');
-                        updateBottom('component-listing');
-                        updateBottom('component-usage-container');
-                    }
-                }
-
-                deferred.resolve();
-            }, function () {
-                deferred.reject();
-            });
-        } else {
-            deferred.resolve();
-        }
-    }).promise();
-
-    // get the about details
-    var about = $.ajax({
-        type: 'GET',
-        url: '../nifi-api/controller/about',
-        dataType: 'json'
-    }).done(function (response) {
-        var aboutDetails = response.about;
-
-        // set the document title and the about title
-        $('#nf-version').text(aboutDetails.version);
-    });
-
-    // once the banners have loaded, function with remainder of the page
-    $.when(banners, about).always(function () {
-        // define the function for filtering the list
-        $('#component-filter').keyup(function () {
-            applyFilter();
-        }).focus(function () {
-            if ($(this).hasClass('component-filter-list')) {
-                $(this).removeClass('component-filter-list').val('');
-            }
-        }).blur(function () {
-            if ($(this).val() === '') {
-                $(this).addClass('component-filter-list').val('Filter');
-            }
-        }).addClass('component-filter-list').val('Filter');
-
-        // get the component usage container to install the window listener
-        var componentUsageContainer = $('#component-usage-container');
-
-        // size the iframe accordingly
-        var componentUsage = $('#component-usage').css({
-            width: componentUsageContainer.width(),
-            height: componentUsageContainer.height()
-        });
-
-        // add a window resize listener
-        $(window).resize(function () {
-            componentUsage.css({
-                width: componentUsageContainer.width(),
-                height: componentUsageContainer.height()
-            });
-        });
-
-        // listen for loading of the iframe to update the title
-        $('#component-usage').on('load', function () {
-            var componentName = '';
-            var href = $(this).contents().get(0).location.href;
-
-            // see if the href ends in index.htm[l]
-            var indexOfIndexHtml = href.indexOf('index.htm');
-            if (indexOfIndexHtml >= 0) {
-                href = href.substring(0, indexOfIndexHtml);
-            }
-
-            // remove the trailing separator
-            if (href.length > 0) {
-                var indexOfSeparator = href.lastIndexOf('/');
-                if (indexOfSeparator === href.length - 1) {
-                    href = href.substring(0, indexOfSeparator);
-                }
-            }
-
-            // extract the simple name
-            if (href.length > 0) {
-                var indexOfLastDot = href.lastIndexOf('.');
-                if (indexOfLastDot >= 0) {
-                    var indexAfterStrToFind = indexOfLastDot + 1;
-                    if (indexAfterStrToFind < href.length) {
-                        componentName = href.substr(indexAfterStrToFind);
-                    }
-                }
-            }
-
-            // if we could figure out the name
-            if (componentName !== '') {
-                selectComponent(componentName);
-            }
-        });
-        
-        // listen for on the rest api and user guide and developer guide and admin guide and overview
-        $('a.rest-api, a.user-guide, a.developer-guide, a.admin-guide, a.overview, a.expression-language-guide').on('click', function() {
-            selectComponent($(this).text());
-        });
-
-        // get the initial selection
-        var initialComponentLink = $('a.component-link:first');
-        var initialSelection = $('#initial-selection').text();
-        if (initialSelection !== '') {
-            $('a.component-link').each(function () {
-                var componentLink = $(this);
-                if (componentLink.text() === initialSelection) {
-                    initialComponentLink = componentLink;
-                    return false;
-                }
-            });
-        }
-
-        // click the first link
-        initialComponentLink[0].click();
-    });
-});

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/LICENSE
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/LICENSE b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/LICENSE
new file mode 100644
index 0000000..95e1332
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/LICENSE
@@ -0,0 +1,32 @@
+
+HexViewJS License
+-----------------
+
+HexViewJS is written by Nick McVeity <nm...@gmail.com> and is 
+licensed under the terms of the MIT license reproduced below.
+
+========================================================================
+
+Copyright (c) 2010 Nick McVeity <nm...@gmail.com>
+
+Permission is hereby granted, free of charge, to any person 
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be 
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+========================================================================
+

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.default.css
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.default.css b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.default.css
new file mode 100644
index 0000000..581161e
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.default.css
@@ -0,0 +1,10 @@
+.hexviewerwindow { font-family: monospace; background-color: #F2F2F2;}
+div.hexviewerwindow { padding: 20px; }
+.hexviewerwindow_table { border-collapse:collapse; border: 5px solid grey; margin-left: 16px; caption-side:bottom; }
+.hexviewerwindow_offset {background: #A9D0F5; padding-right: 8px; }
+.hexviewerwindow_visual {background: #A9F5F2; padding-left: 8px; }
+.hexviewerwindow_code {}
+.hexviewerwindow_code_hi {background: #F4FA58; }
+.hexviewerwindow_border_start {border-left: solid #E0E0E0 1px; }
+.hexviewerwindow_border_middle {border-bottom: solid #E0E0E0 1px; border-top: solid #E0E0E0 1px;}
+.hexviewerwindow_border_end {border-right: solid #E0E0E0 1px; border-top: solid #E0E0E0 1px; }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/60c411de/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.js
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.js b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.js
new file mode 100644
index 0000000..c5b4401
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-content-viewer/src/main/webapp/js/hexview/hexview.js
@@ -0,0 +1,175 @@
+		var HEX = '0123456789ABCDEF'
+
+		function dec2_to_hex(dec)
+		{
+			if (dec < 0)
+				dec = 0
+			
+			if (dec > 255)
+				dec = 255
+			
+			return HEX.charAt(Math.floor(dec / 16)) + HEX.charAt(dec % 16)
+		}
+		
+		function dec_to_hex8(dec)
+		{
+			var str = ""
+			
+			for (var i = 3; i >= 0; i--)
+			{
+				str += dec2_to_hex((dec >> (i*8)) & 255)
+			}
+			
+			return str;
+		}
+
+		function remove_whitespace(str)
+		{
+			return str.replace(/\n/g, "")
+					  .replace(/\t/g, "")
+					  .replace(/ /g, "")
+					  .replace(/\r/g, "")
+		}
+		
+		var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+		
+		function base64_decode(encoded)
+		{
+			var decoded = ""
+			
+			for (var i = 0; i < encoded.length; i += 4)
+			{
+				var ch0 = encoded.charAt(i+0)
+				var ch1 = encoded.charAt(i+1)
+				var ch2 = encoded.charAt(i+2)
+				var ch3 = encoded.charAt(i+3)
+				
+				var index0 = BASE64_CHARS.indexOf(ch0);
+				var index1 = BASE64_CHARS.indexOf(ch1);
+				var index2 = BASE64_CHARS.indexOf(ch2);
+				var index3 = BASE64_CHARS.indexOf(ch3);
+				
+				decoded += String.fromCharCode((index0 << 2) | (index1 >> 4))
+				decoded += String.fromCharCode(((index1 & 15) << 4) | (index2 >> 2))
+				decoded += String.fromCharCode(((index2 & 3) << 6) | index3)
+			}
+			
+			return decoded
+		}
+		
+		function markup_hexviewwindow(div, index)
+		{
+			var bin_data = base64_decode(remove_whitespace(div.text()))
+			var line_data
+			var title = div.attr("title")
+			
+			var highlights_str = $("form#hexviewwindow_params input[name='highlights']", div).attr("value").split(',')
+			var highlights = []
+			
+			for (var i = 0; i < highlights_str.length; i++)
+			{
+				highlights.push(highlights_str[i].split(":"))
+			}
+			 
+			var params = title.split(':')
+			var step = parseInt($("form#hexviewwindow_params input[name='row_width']", div).attr("value"))
+			var word_size = parseInt($("form#hexviewwindow_params input[name='word_size']", div).attr("value"))
+			var hide_0x = parseInt($("form#hexviewwindow_params input[name='hide_0x']", div).attr("value"))
+			var decimal_offset = parseInt($("form#hexviewwindow_params input[name='decimal_offset']", div).attr("value"))
+			var start_byte_1 = parseInt($("form#hexviewwindow_params input[name='start_byte_1']", div).attr("value"))
+			var caption = $("form#hexviewwindow_params input[name='caption']", div).attr("value")
+			
+			div.text("")
+			div.append("<table></table>")
+			
+			var offset = (start_byte_1 ? 1 : 0)
+
+			function apply_highlights(index)
+			{
+				for (var j = 0; j < highlights.length; j++)
+				{
+					if ((index >= highlights[j][0]) && (index <= highlights[j][1]))
+					{
+						if (index == highlights[j][0])
+						{
+							$("table tr td:last", div).addClass("hexviewerwindow_border_start")
+						}
+						
+						if (index == highlights[j][1])
+						{
+							$("table tr td:last", div).addClass("hexviewerwindow_border_end")
+						}
+						
+						$("table tr td:last", div).addClass("hexviewerwindow_code_hi hexviewerwindow_border_middle")
+						$("table tr td:last", div).attr("style", "background-color: " + highlights[j][2] + ";")
+						$("table tr td:last", div).attr("title", highlights[j][3])
+						
+						runlen += 1
+					}
+					else
+					{
+						$("table tr td:last", div).addClass("hexviewerwindow_code")
+					}
+				}
+			}
+
+			if (caption)
+				$("table", div).append("<caption>" + caption + "</caption>")
+				
+			while (bin_data.length > 0)
+			{
+				line_data = bin_data.slice(0, step)
+				bin_data = bin_data.slice(step)
+			
+				$("table", div).addClass("hexviewerwindow_table")
+				$("table", div).append("<tr></tr>").addClass("hexviewerwindow")
+				$("table tr:last", div).append("<td>" + (decimal_offset ? ("00000000"+offset).slice(-8) : "0x" + dec_to_hex8(offset)) + "</td>")
+				$("table tr td:last", div).addClass("hexviewerwindow_offset")
+				
+				var runlen = 0
+				
+				for (var i = 0; i < line_data.length; i += word_size)
+				{
+					var num = ""
+					
+					for (var j = 0; j < word_size; j++)
+					{
+						num += dec2_to_hex(line_data.charCodeAt(i+j))
+					}
+					
+					$("table tr:last", div).append("<td>" + (hide_0x ? "" : "0x") + num + "</td>")
+
+					apply_highlights(offset+i)
+				}
+				
+				var text = ""
+				
+				for (var i = 0; i < line_data.length; i++)
+				{
+					var cc = line_data.charCodeAt(i)
+					
+					if ((cc >= 32) && (cc <= 126))
+					{
+						text = text + line_data.charAt(i)
+					}
+					else
+					{
+						text = text + "."
+					}
+				}
+				
+				if (line_data.length < step)
+					$("table tr td:last", div).attr("colspan", Math.floor((step - line_data.length) / word_size) + 1)
+
+				offset += step
+				
+				$("table tr:last", div).append("<td>" + text + "</td>")
+				$("table tr td:last", div).addClass("hexviewerwindow_visual")
+			}
+		}
+		
+		$(document).ready(function () {
+			$("div.hexviewwindow").each(function (index) {
+				markup_hexviewwindow($(this), index)
+			})
+		})
\ No newline at end of file