Browse Source

Merge branch 'master' of github.com:inconshreveable/ngrok

Alan Shreve 12 years ago
parent
commit
b63f9bc718

+ 5 - 4
assets/client/page.html

@@ -8,6 +8,7 @@
         <script src="/static/js/jquery-1.9.1.min.js"></script>
         <script src="/static/js/jquery.timeago.js"></script>
         <script src="/static/js/angular.js"></script>
+        <script src="/static/js/angular-sanitize.min.js"></script>
         <script src="/static/js/base64.js"></script>
         <script src="/static/js/ngrok.js"></script>
         <script type="text/javascript">
@@ -18,8 +19,8 @@
             table.params { font-size: 12px; font-family: Courier, monospace; }
             .txn-selector tr { cursor: pointer; }
             .txn-selector tr:hover { background-color: #ddd; }
-            tr.selected, tr.selected:hover { 
-                background-color: #ff9999; 
+            tr.selected, tr.selected:hover {
+                background-color: #ff9999;
                 background-color: #000000;
                 color:white;
 
@@ -70,11 +71,11 @@
                             </span>
                         </div>
                         <div class="span4">
-                            <i class="icon-time"></i> Duration 
+                            <i class="icon-time"></i> Duration
                             <span style="margin-left: 8px;" class="muted">{{Txn.Duration}}</span>
                         </div>
                         <div  class="span4">
-                            <i class="icon-user"></i> IP 
+                            <i class="icon-user"></i> IP
                             <span style="margin-left: 8px;" class="muted">{{Txn.Req.Header['X-Real-Ip'][0]}}</span>
                         </div>
                     </div>

+ 13 - 0
assets/client/static/js/angular-sanitize.min.js

@@ -0,0 +1,13 @@
+/*
+ AngularJS v1.1.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(I,h){'use strict';function i(a){var d={},a=a.split(","),c;for(c=0;c<a.length;c++)d[a[c]]=!0;return d}function z(a,d){function c(a,b,c,f){b=h.lowercase(b);if(m[b])for(;e.last()&&n[e.last()];)g("",e.last());o[b]&&e.last()==b&&g("",b);(f=p[b]||!!f)||e.push(b);var j={};c.replace(A,function(a,b,d,c,g){j[b]=k(d||c||g||"")});d.start&&d.start(b,j,f)}function g(a,b){var c=0,g;if(b=h.lowercase(b))for(c=e.length-1;c>=0;c--)if(e[c]==b)break;if(c>=0){for(g=e.length-1;g>=c;g--)d.end&&d.end(e[g]);e.length=
+c}}var b,f,e=[],j=a;for(e.last=function(){return e[e.length-1]};a;){f=!0;if(!e.last()||!q[e.last()]){if(a.indexOf("<\!--")===0)b=a.indexOf("--\>"),b>=0&&(d.comment&&d.comment(a.substring(4,b)),a=a.substring(b+3),f=!1);else if(B.test(a)){if(b=a.match(r))a=a.substring(b[0].length),b[0].replace(r,g),f=!1}else if(C.test(a)&&(b=a.match(s)))a=a.substring(b[0].length),b[0].replace(s,c),f=!1;f&&(b=a.indexOf("<"),f=b<0?a:a.substring(0,b),a=b<0?"":a.substring(b),d.chars&&d.chars(k(f)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
+e.last()+"[^>]*>","i"),function(a,b){b=b.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(b));return""}),g("",e.last());if(a==j)throw"Parse Error: "+a;j=a}g()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,c=h.bind(a,a.push);return{start:function(a,b,f){a=h.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
+!0&&(c("<"),c(a),h.forEach(b,function(a,b){var d=h.lowercase(b);if(G[d]==!0&&(w[d]!==!0||a.match(H)))c(" "),c(b),c('="'),c(t(a)),c('"')}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);!d&&v[a]==!0&&(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
+E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|tel:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=h.extend({},y,x),m=h.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=h.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
+q=i("script,style"),v=h.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=h.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");h.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
+z(a,u(d));return d.join("")});h.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,c,g){c.addClass("ng-binding").data("$binding",g.ngBindHtml);d.$watch(g.ngBindHtml,function(b){b=a(b);c.html(b||"")})}}]);h.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(c,g){if(!c)return c;var b,f=c,e=[],j=u(e),i,k,l={};if(h.isDefined(g))l.target=g;for(;b=f.match(a);)i=
+b[0],b[2]==b[3]&&(i="mailto:"+i),k=b.index,j.chars(f.substr(0,k)),l.href=i,j.start("a",l),j.chars(b[0].replace(d,"")),j.end("a"),f=f.substring(k+b[0].length);j.chars(f);return e.join("")}})})(window,window.angular);

+ 14 - 14
assets/client/static/js/ngrok.js

@@ -1,4 +1,4 @@
-var ngrok = angular.module("ngrok", []);
+var ngrok = angular.module("ngrok", ["ngSanitize"]);
 
 var hexRepr = function(bytes) {
     var buf = [];
@@ -47,7 +47,7 @@ ngrok.factory("txnSvc", function() {
         body.exists = body.Length > 0;
         body.hasError = !!body.Error;
 
-        body.syntaxClass = {
+        var syntaxClass = {
             "text/xml":               "xml",
             "application/xml":        "xml",
             "text/html":              "xml",
@@ -63,12 +63,12 @@ ngrok.factory("txnSvc", function() {
         } else {
             body.Text = Base64.decode(body.Text).text;
         }
-        
+
         // prettify
         var transform = {
             "xml": "xml",
             "json": "json"
-        }[body.syntaxClass];
+        }[syntaxClass];
 
         if (!body.hasError && !!transform) {
             try {
@@ -79,6 +79,13 @@ ngrok.factory("txnSvc", function() {
             } catch (e) {
             }
         }
+
+        if (!!syntaxClass) {
+            body.Text = hljs.highlight(syntaxClass, body.Text).value;
+        } else {
+            // highlight.js doesn't have a 'plaintext' syntax, so we'll just copy its escaping function.
+            body.Text = body.Text.replace(/&/gm, '&amp;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;');
+        }
     };
 
     var processReq = function(req) {
@@ -214,7 +221,7 @@ ngrok.directive({
                 "onbtnclick": "&"
             },
             replace: true,
-            template: '' + 
+            template: '' +
             '<ul class="nav nav-pills">' +
                 '<li ng-repeat="tab in tabNames" ng-class="{\'active\': isTab(tab)}">' +
                     '<a href="" ng-click="setTab(tab)">{{tab}}</a>' +
@@ -247,7 +254,7 @@ ngrok.directive({
             '</h6>' +
 '' +
             '<div ng-show="!body.isForm && !body.binary">' +
-                '<pre ng-show="body.exists"><code ng-class="body.syntaxClass">{{ body.Text }}</code></pre>' +
+                '<pre ng-show="body.exists"><code ng-bind-html="body.Text"></code></pre>' +
             '</div>' +
 '' +
             '<div ng-show="body.isForm">' +
@@ -259,13 +266,6 @@ ngrok.directive({
 
             link: function($scope, $elem) {
                 $scope.$watch(function() { return $scope.body; }, function() {
-                    $code = $elem.find("code");
-                    // if we highlight when the code is empty, hljs manipulates the dom in a
-                    // a bad way that causes angular to fail
-                    if (!!$code.text()) {
-                        hljs.highlightBlock($code.get(0));
-                    }
-
                     if ($scope.body && $scope.body.ErrorOffset > -1) {
                         var offset = $scope.body.ErrorOffset;
 
@@ -317,7 +317,7 @@ ngrok.controller({
                     txnSvc.add(message.data);
                 });
             };
-            
+
             ws.onerror = function(err) {
                 console.log("Web socket error:" + err);
             };

+ 9 - 8
src/ngrok/client/views/web/http.go

@@ -112,21 +112,22 @@ func makeBody(h http.Header, body []byte) SerializedBody {
 	if b.RawContentType != "" {
 		b.ContentType = strings.TrimSpace(strings.Split(b.RawContentType, ";")[0])
 		switch b.ContentType {
-		case "application/xml":
-		case "text/xml":
+		case "application/xml", "text/xml":
 			err = xml.Unmarshal(body, new(XMLDoc))
 			if err != nil {
-				syntaxError := err.(*xml.SyntaxError)
-				// xml syntax errors only give us a line number, so we
-				// count to find an offset
-				b.ErrorOffset = offsetForLine(syntaxError.Line)
+				if syntaxError, ok := err.(*xml.SyntaxError); ok {
+					// xml syntax errors only give us a line number, so we
+					// count to find an offset
+					b.ErrorOffset = offsetForLine(syntaxError.Line)
+				}
 			}
 
 		case "application/json":
 			err = json.Unmarshal(body, new(json.RawMessage))
 			if err != nil {
-				syntaxError := err.(*json.SyntaxError)
-				b.ErrorOffset = int(syntaxError.Offset)
+				if syntaxError, ok := err.(*json.SyntaxError); ok {
+					b.ErrorOffset = int(syntaxError.Offset)
+				}
 			}
 
 		case "application/x-www-form-urlencoded":