소스 검색

万物墙手写更新

shaogen1995 3 년 전
부모
커밋
eb2b2134ee

+ 0 - 5
web/src/views/gui/compomemt/hotspot.vue

@@ -6,7 +6,6 @@
         <span
           :class="{ active: hotInd === index }"
           @click="openHot(item, index)"
-          :title="item.info.title ? item.info.title : '热点'"
           v-for="(item, index) in data"
           :key="index"
           >{{ item.info.title ? item.info.title : "热点" }}</span
@@ -92,9 +91,6 @@ export default {
       color: #7e522f;
       font-size: 16px;
       & > span {
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
         margin-top: 20px;
         cursor: pointer;
         display: block;
@@ -107,7 +103,6 @@ export default {
     }
     .active {
       color: #d4a781;
-      pointer-events: none;
     }
     .txt::-webkit-scrollbar-thumb {
       outline: 2px solid #cc946d;

+ 2 - 4
webM/src/views/gui/component/hotspot.vue

@@ -76,7 +76,7 @@ export default {
   }
   .main {
     border-radius: 8px;
-    padding: 10px 0;
+    padding: 25px 0 10px 0;
     background-color: #fff6d2;
     width: 100%;
     height: calc(100% - 60px);
@@ -96,12 +96,10 @@ export default {
         color: #774926;
         text-align: center;
         width: 100%;
-        height: 34px;
-        line-height: 34px;
+        margin-bottom: 15px;
       }
       .active {
         color: #d4a781;
-        pointer-events: none;
       }
     }
   }

+ 6 - 5
万物墙后台/shurufa/css/index.css

@@ -62,7 +62,8 @@ button,input{
 }
 
 .content{
-  width: 90%;
+  width: 1728px;
+  height: 900px;
   margin: 0 auto;
 }
 
@@ -123,6 +124,7 @@ button,input{
 }
 
 .result{
+  display: flex;
   width: 100%;
   margin: 0.63rem 0;
   min-height: 1.88rem;
@@ -153,10 +155,9 @@ button,input{
 #canvasWrap {
   position:relative;
   margin:0 auto;
-  width:100%;
-  height:40%;
-  min-height: 20rem;
-  border:0.13rem solid #EA9649;
+  width:1728px;
+  height:700px;
+  border:5px solid #EA9649;
   font-size: 0;
 }
 

+ 196 - 7
万物墙后台/shurufa/index.html

@@ -1,11 +1,20 @@
 <!DOCTYPE html>
 <html lang="en">
+
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
   <link rel="stylesheet" href="./css/index.css">
   <title>手写</title>
+  <script type="text/javascript" src="./md5.js"></script>
+  <style>
+    #clear2 {
+      opacity: 0;
+    }
+
+  </style>
 </head>
+
 <body>
   <div class="body">
     <!-- <img id="bg" class="bg" src="./images/bg.png" alt=""> -->
@@ -18,17 +27,17 @@
         </span>
         <div id="search" class="button">搜索</div>
       </div>
-      
+
       <!-- 搜索页面 -->
       <div class="search-page">
         <ul class="result">
           <li>
-            <ul id="result"></ul>
+            <ul id="ret"></ul>
           </li>
-          <li><img id="clear" src="./images/close.png" alt=""></li>
+          <li><img id="clear2" src="./images/close.png" alt=""></li>
         </ul>
         <div id="canvasWrap">
-          <canvas id="canvas"></canvas>
+          <canvas id="cav"></canvas>
         </div>
       </div>
 
@@ -40,7 +49,7 @@
         </ul>
         <div class="no-result">
           <img src="./images/no-result.png" alt="">
-          <p>暂时没有结果呢,<br/>请试一下其他关键字</p>
+          <p>暂时没有结果呢,<br />请试一下其他关键字</p>
         </div>
       </div>
 
@@ -51,7 +60,187 @@
     </div>
   </div>
   <script src="./js/jquery.min.js"></script>
-  <script src="./js/handwritingapi.js"></script>
+  <!-- <script src="./js/handwritingapi.js"></script> -->
   <script src="./js/index.js?t=20200921"></script>
+  <script type="text/javascript">
+    var index = 0;
+    var BH = "";
+    var Down = false;
+    let cav = document.getElementById("cav");
+    var ctx = cav.getContext("2d");
+    cav.width = 1728;
+    cav.height = 700;
+    var lastX = -1,
+      lastY = -1;
+    var Timer = 0;
+
+
+    // 移动端禁止拉动页面
+    document.body.addEventListener('touchmove', function (e) {
+      e.preventDefault();
+    }, {
+      passive: false
+    });
+
+    // PC
+    cav.addEventListener("mousedown", onStartInput);
+    cav.addEventListener("mousemove", onMoveInput);
+    cav.addEventListener("mouseup", onOverInput);
+
+    // 手机
+    cav.addEventListener("touchstart", onStartInput);
+    cav.addEventListener("touchmove", onMoveInput);
+    cav.addEventListener("touchend", onOverInput);
+    cav.addEventListener("touchcancel", onOverInput);
+
+    function onStartInput(event) {
+      var event = event || window.event;
+
+      Down = true;
+      if (!event.touches) {
+        // pc
+        lastX = parseInt(event.offsetX);
+        lastY = parseInt(event.offsetY);
+      } else {
+        lastX = parseInt(event.touches[0].clientX - cav.offsetLeft);
+        lastY = parseInt(event.touches[0].clientY - cav.offsetTop);
+      }
+      // console.log("down");
+    }
+
+    function onMoveInput(event) {
+      var event = event || window.event;
+      if (Down) {
+        var x, y;
+        if (!event.touches) {
+          // pc
+          x = parseInt(event.offsetX);
+          y = parseInt(event.offsetY);
+        } else {
+          x = parseInt(event.touches[0].clientX - cav.offsetLeft);
+          y = parseInt(event.touches[0].clientY - cav.offsetTop);
+        }
+        BH += `${x},${y},`;
+        renderPoint(lastX, lastY, x, y);
+        lastX = x;
+        lastY = y;
+
+        // console.log("move");
+      }
+    }
+
+    function onOverInput(event) {
+      var event = event || window.event;
+      if (Down) {
+        // 加入一个笔画的结束符
+        Down = false;
+        BH += "-1,0,";
+
+        if (Timer != 0)
+          window.clearInterval(Timer);
+        Timer = self.setInterval("hwRecognition()", 1000);
+
+        // console.log("up");
+      }
+    }
+
+    function hwRecognition() {
+      var lang = 'zh-cn';
+
+      // 识别前要加入-1-1, 结束符
+      sk = BH + "-1,-1";
+      window.clearInterval(Timer);
+      var user = "testUser";
+      var token = hex_md5(hex_md5(sk) + user.toLowerCase() + "728420db91ffc71a4784ce4cef36d63b");
+      var dt = "user=" + user + "&token=" + token + "&sk=" + sk + "&lang=" + lang + "&os=Windows&multi=1&count=10";
+      request(dt);
+    }
+
+    // 输入框的X按钮
+    let inputX = document.querySelector('#clsipt')
+
+    // X按钮
+    let closeBtnDom = document.querySelector('#clear2')
+    closeBtnDom.onclick = (() => {
+      // 删除ul下面的所有子元素
+      ulDom.innerHTML = ''
+      // 清空写字板
+      resetCtx()
+      // 隐藏X按钮
+      closeBtnDom.style.opacity = 0
+    })
+
+
+    function request(data) {
+      let szURL = 'http://handwriting.dwinput.com:4555/temp/';
+      var xhr = new XMLHttpRequest();
+      xhr.open("POST", szURL, true);
+      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+      xhr.onreadystatechange = function () {
+        if (xhr.readyState == 4 && xhr.status == 200) {
+          let temp = xhr.responseText
+          // 笔画太少的时候 直接return
+          if (temp.includes('error')) return
+          temp = temp.split('\t')
+          let ul = document.querySelector('#ret')
+          // 生成的子元素文字
+          let liAll = ''
+          temp.forEach(v => {
+            liAll += `<li>${v}</li>`
+            ulDom.innerHTML = liAll
+          })
+          // 显示X按钮
+          closeBtnDom.style.opacity = 1
+          // document.getElementById("ret").value = xhr.responseText; 
+          //alert("识别结果:" + xhr.responseText);
+        }
+      }
+
+      try {
+        xhr.send(data);
+      } catch (e) {
+        return null;
+      }
+    }
+
+    // 给生成的li文字绑定点击事件
+    let ulDom = document.querySelector('#ret')
+    ulDom.onclick = ((e) => {
+      if (e.target.tagName === 'LI') {
+        // 获取当前点击的li文本
+        let txt = e.target.innerHTML
+        // 加到输入框后面
+        let inputDom = document.querySelector('#input')
+        inputDom.value = inputDom.value + txt
+        // 删除ul下面的所有子元素
+        ulDom.innerHTML = ''
+        // 清空写字板
+        resetCtx()
+        // 隐藏X按钮
+        closeBtnDom.style.opacity = 0
+        // 显示输入框的X按钮
+        inputX.style.opacity = 1
+      }
+    })
+
+    // 画线
+    function renderPoint(x1, y1, x2, y2) {
+      ctx.strokeStyle = '#EA9649';
+      ctx.save();
+      ctx.beginPath();
+      ctx.lineWidth = 5;
+      ctx.moveTo(x1, y1);
+      ctx.lineTo(x2, y2);
+      ctx.stroke();
+      ctx.restore();
+    }
+
+    function resetCtx() {
+      BH = "";
+      ctx.clearRect(0, 0, cav.width, cav.height);
+    }
+
+  </script>
 </body>
-</html>
+
+</html>

+ 0 - 295
万物墙后台/shurufa/js/handwritingapi.js

@@ -1,295 +0,0 @@
-QQShuru = {};
-QQShuru.Util = {};
-QQShuru.Util.Browser = {};
-QQShuru.Util.Browser.isIE = (navigator.appName == "Microsoft Internet Explorer");
-
-QQShuru.Util.Ajax = {};
-QQShuru.Util.Ajax.get = function(a, c) {
-    var b = document.createElement("script");
-    b.setAttribute("charset", "utf-8");
-    b.id = Math.random();
-    document.getElementsByTagName("head")[0].appendChild(b);
-    b.src = a + "&c=" + c;
-    if (QQShuru.Util.Browser.isIE) {
-        b.onreadystatechange = function() {
-            if (b.readyState == "loaded") {
-                document.getElementsByTagName("head")[0].removeChild(b)
-            }
-        }
-    } else {
-        b.onload = function() {
-            document.getElementsByTagName("head")[0].removeChild(b)
-        }
-    }
-};
-QQShuru.Util.Event = {};
-QQShuru.Util.Event.addEvent = function() {
-    if (QQShuru.Util.Browser.isIE) {
-        return function(b, c, a) {
-            b.attachEvent("on" + c, a)
-        }
-    } else {
-        return function(b, c, a, d) {
-            b.addEventListener(c, a, d || false)
-        }
-    }
-} ();
-QQShuru.Util.Event.remEvent = function() {
-    if (QQShuru.Util.Browser.isIE) {
-        return function(b, c, a) {
-            b.detachEvent("on" + c, a)
-        }
-    } else {
-        return function(b, c, a, d) {
-            b.removeEventListener(c, a, d || false)
-        }
-    }
-} ();
-QQShuru.Util.Event.getPoint = function(a) {
-    if (QQShuru.Util.Browser.isIE) {
-        return [a.x, a.y]
-    } else {
-        return [a.layerX, a.layerY]
-    }
-};
-/*
-    初始化函数
-*   params:obj
-*   obj={
-*       canvasId:canvas的id  --required
-*       lineColor:  默认#606060  ,
-*       lineWidth:  默认10
-*       backBtnId: 退一步按钮id
-*       clearBtnId:清空canvas按钮id
-*       callback:func  每次请求后回调
-*   }
-*
-*
-*/
-QQShuru.HWPanel = function(obj) {
-    var o = QQShuru.Util.Browser.isIE;
-    var m = QQShuru.Util.Event.addEvent;
-    var j = QQShuru.Util.Event.remEvent;
-    var B = QQShuru.Util.Event.getPoint;
-    var h = document;
-    var H = document.body;
-    var z = document.documentElement;
-    var f = [];
-    var K = [];
-    var O = [];
-
-    var i = document.querySelector(obj.canvasId);
-    var v = o ? 1 : 0;
-    var a = 2;
-    var N = i.clientWidth;//canvas宽度
-    var R = i.clientHeight;//canvas高度
-    var c = obj.lineColor?obj.lineColor:"#606060"; //线条颜色
-    var y = obj.lineWidth?obj.lineWidth:10;//线条宽度
-    var t = "round";
-    var J = !!i.getContext;
-    if (J) {
-        var Q = i.getContext("2d");
-        Q.lineCap = t;
-        Q.lineJoin = t;
-        Q.lineWidth = y;
-        Q.strokeStyle = c
-    }
-    var L = false;
-    var P = false;
-    var u = 0;
-    var T = [];
-    var r = 0;
-    var e = [],
-        d = [],
-        I = [];
-    var D = [],
-        C = [];
-    pointsDeltaXY = [];
-    var k = [0, 0];
-    //鼠标按下事件
-    var l = function(W) {
-        if (v !== W.button) {
-            return
-        }
-        var Y = B(W);
-        if (!Y) {
-            return
-        }
-        L = true;
-        r = 0;
-        e = [];
-        d = [];
-        I = [];
-        D = [];
-        C = [];
-        pointsDeltaXY = [];
-        e[r] = Y[0];
-        d[r] = Y[1];
-        I[r * 2] = Y[0];
-        I[r * 2 + 1] = Y[1];
-        D[r] = Y[0];
-        C[r] = Y[1];
-        pointsDeltaXY[r * 2] = Y[0];
-        pointsDeltaXY[r * 2 + 1] = Y[1];
-        if (J) {
-            Q.beginPath();
-            Q.moveTo(Y[0], Y[1])
-        }
-        k[0] = Y[0];
-        k[1] = Y[1];
-        r++;
-        if (o) {
-            m(i, "losecapture", n);
-            i.setCapture()
-        } else {
-            m(window, "blur", n)
-        }
-    };
-    //鼠标移动事件
-    var A = function(W) {
-        if (!L) {
-            return
-        }
-        var Y = B(W);//坐标
-        if (!Y) {
-            return
-        }
-        e[r] = Y[0];
-        d[r] = Y[1];
-        I[r * 2] = Y[0];
-        I[r * 2 + 1] = Y[1];
-        D[r] = Y[0] - k[0];
-        C[r] = Y[1] - k[1];
-        pointsDeltaXY[r * 2] = D[r];
-        pointsDeltaXY[r * 2 + 1] = C[r];
-        if (J) {
-            Q.lineTo(Y[0], Y[1]);
-            Q.stroke()
-        } else {
-            var X = T[u].e.path;
-            X.value = X.value.replace(" e", "," + Y[0] + "," + Y[1] + " e")
-        }
-        k[0] = Y[0];
-        k[1] = Y[1];
-        r++
-    };
-    //鼠标松开事件
-    var n = function(W) {
-        if (!L) {
-            return
-        }
-        L = false;
-        if (1 === r) {
-            if (!J) {
-                T[u].e.style.visibility = "hidden"
-            }
-            return
-        }
-        if (J) {
-            Q.closePath();
-            var Z = i.cloneNode(false);
-            Z.style.display = "none";
-            Z.getContext("2d").drawImage(i, 0, 0);
-            T[u] = {
-                e: Z
-            };
-            Z = null
-        }
-        var aa = T[u];
-        aa.count = r;
-        aa.x = e.slice(0);
-        aa.y = d.slice(0);
-        aa.xy = I.slice(0);
-        aa.deltaX = D.slice(0);
-        aa.deltaY = C.slice(0);
-        aa.deltaXY = pointsDeltaXY.slice(0);
-        u++;
-        var X = [];
-        for (var Y = 0; Y < r; Y++) {
-            X[Y] = "[" + e[Y] + ", " + d[Y] + "]"
-        }
-        if (o) {
-            j(i, "losecapture", n);
-            i.releaseCapture()
-        } else {
-            j(window, "blur", n)
-        }
-        if (1 === u) {
-            i.className = "writting"
-        }
-        s(u);
-    };
-    //清空所有
-    var V = function(W) {
-        if (0 === u) {
-            return
-        }
-        var ab = "";
-        if (J) {
-            Q.clearRect(0, 0, N, R)
-        }
-        for (var Z = 0; Z < u; Z++) {
-            T[Z].e.style.visibility = "hidden"
-        }
-        u = 0;
-        i.className = ""
-    };
-    //退一笔
-    var g = function(W) {
-        if (0 === u) {
-            return
-        }
-        if (1 === u) {
-            V();
-            return
-        }
-        u--;
-        if (J) {
-            Q.clearRect(0, 0, N, R);
-            Q.drawImage(T[u - 1].e, 0, 0)
-        }
-        T[u].e.style.visibility = "hidden";
-        s(u)
-    };
-    var p = function(W, ab) {
-        var aa = ab || W.length;
-        var Z = "";
-        var ad = "";
-        for (var X = 0; X < aa; ++X) {
-            var ac = W[X];
-            ad = X ? ",eb,": "";
-            var Y = ad + ac.deltaXY.join(",");
-            Z += Y
-        }
-        return Z
-    };
-    this.ajax_callback = function(X) {
-        obj.callback&&obj.callback(X)
-    };
-    QQShuru.HWPanel.ajax_callback = this.ajax_callback;
-    var s = function(Y) {
-        var Z = p(T, Y);
-        var ab = "QQShuru.HWPanel.ajax_callback";
-        var W = "https://handwriting.shuru.qq.com/cloud/cgi-bin/cloud_hw_pub.wsgi";
-        var aa = "track_str=" + Z + "&cmd=0";
-        var X = W + "?" + aa;
-        QQShuru.Util.Ajax.get(X, ab)
-    };
-    m(i, "mousedown", l);
-    m(i, "mousemove", A);
-    m(i, "mouseup", n);
-    m(i, "dblclick", V);
-    m(i, "contextmenu",
-        function(W) {
-            o ? (W.returnValue = false) : W.preventDefault()
-        });
-    m(h, "mouseup", n);
-    if(obj.backBtnId){
-        m(document.querySelector(obj.backBtnId), "click", g);
-    }
-    if(obj.clearBtnId){
-        m(document.querySelector(obj.clearBtnId), "click", V);
-    }
-    this.clear=V;//暴露清空canvas的方法到外部
-    this.back=g;//暴露退一步的方法到外部
-};

+ 10 - 10
万物墙后台/shurufa/js/index.js

@@ -1,5 +1,5 @@
 $(function () {
-  // let base = 'http://119.23.129.199:8100/'
+  // let base = 'http://project.4dage.com:8017'
   let base = '/'
 
   var stopClick = false
@@ -12,7 +12,7 @@ $(function () {
   $('#canvas').attr('width', $('#canvasWrap').width())
   $('#canvas').attr('height', $('#canvasWrap').height())
 
-  init()
+  // init()
 
   $('#clear').click(function () {
     $('#clear').css('opacity', 0)
@@ -135,12 +135,12 @@ $(function () {
     })
   }
 
-  function init () {
-    QQShuru.HWPanel({
-      canvasId: '#canvas',
-      lineColor: '#EA9649',
-      clearBtnId: '#clear',
-      callback: callbackfunc
-    })
-  }
+  // function init () {
+  //   QQShuru.HWPanel({
+  //     canvasId: '#canvas',
+  //     lineColor: '#EA9649',
+  //     clearBtnId: '#clear',
+  //     callback: callbackfunc
+  //   })
+  // }
 })

+ 256 - 0
万物墙后台/shurufa/md5.js

@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}