Explorar o código

feat:2025.12.20 整理版本

akay hai 1 mes
achega
a0fde4598f

+ 48 - 0
mPlugin-java/demo/TestToken.java

@@ -0,0 +1,48 @@
+package com.mtoken.gm3000;
+
+import com.yumawk.mToken;
+import org.junit.Test;
+
+public class TestToken {
+
+    @Test
+    public void TestGetUserName() {
+        String userName;
+        mToken token = new mToken();
+        userName = token.GetUserList();
+        if (userName == null || userName.isEmpty()) {
+            System.out.println(token.GetLastError());
+        }
+        System.out.println("用户名称:" + userName);
+    }
+
+    @Test
+    public void TestSignData() {
+        String userName = "";
+        String signdata = "";
+        String cert = "";
+
+        //1.初始化组件
+        mToken token = new mToken();
+
+        //2.获取用户列表
+        userName = token.GetUserList();
+        if (userName == null || userName.isEmpty()) {
+            System.out.println(token.GetLastError());
+            return ;
+        }
+
+        //3.签名数据,为方便演示,这里数据为“Hello"
+        signdata = token.SignData(userName, "123456", "你好");
+
+        //4.导出签名证书,用于验证签名
+        cert = token.exportCert(userName);
+        if (signdata == null || signdata.isEmpty()) {
+            System.out.println(token.GetLastError());
+        } else {
+            System.out.println("签名数据:" + signdata);
+            System.out.println("签名证书:" + cert);
+        }
+    }
+
+}

BIN=BIN
mPlugin-java/package/libs/hamcrest-core-1.3.jar


BIN=BIN
mPlugin-java/package/libs/jackson-annotations-2.8.0.jar


BIN=BIN
mPlugin-java/package/libs/jackson-core-2.8.10.jar


BIN=BIN
mPlugin-java/package/libs/jackson-databind-2.8.10.jar


BIN=BIN
mPlugin-java/package/libs/junit-4.12.jar


BIN=BIN
mPlugin-java/package/libs/okhttp-3.12.13.jar


BIN=BIN
mPlugin-java/package/libs/okio-1.15.0.jar


BIN=BIN
mPlugin-java/package/mPlugin-java-1.0.1.jar


+ 6584 - 0
mPlugin-js/css/bootstrap.css

@@ -0,0 +1,6584 @@
+/*!
+ * Bootstrap v3.3.4 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+html {
+  font-family: sans-serif;
+  -webkit-text-size-adjust: 100%;
+      -ms-text-size-adjust: 100%;
+}
+body {
+  margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+  vertical-align: baseline;
+}
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+[hidden],
+template {
+  display: none;
+}
+a {
+  background-color: transparent;
+}
+a:active,
+a:hover {
+  outline: 0;
+}
+abbr[title] {
+  border-bottom: 1px dotted;
+}
+b,
+strong {
+  font-weight: bold;
+}
+dfn {
+  font-style: italic;
+}
+h1 {
+  margin: .67em 0;
+  font-size: 2em;
+}
+mark {
+  color: #000;
+  background: #ff0;
+}
+small {
+  font-size: 80%;
+}
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+sup {
+  top: -.5em;
+}
+sub {
+  bottom: -.25em;
+}
+img {
+  border: 0;
+}
+svg:not(:root) {
+  overflow: hidden;
+}
+figure {
+  margin: 1em 40px;
+}
+hr {
+  height: 0;
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+}
+pre {
+  overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+  margin: 0;
+  font: inherit;
+  color: inherit;
+}
+button {
+  overflow: visible;
+}
+button,
+select {
+  text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  -webkit-appearance: button;
+  cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+  cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+input {
+  line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+input[type="search"] {
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: textfield;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+fieldset {
+  padding: .35em .625em .75em;
+  margin: 0 2px;
+  border: 1px solid #c0c0c0;
+}
+legend {
+  padding: 0;
+  border: 0;
+}
+textarea {
+  overflow: auto;
+}
+optgroup {
+  font-weight: bold;
+}
+table {
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+td,
+th {
+  padding: 0;
+}
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+@media print {
+  *,
+  *:before,
+  *:after {
+    color: #000 !important;
+    text-shadow: none !important;
+    background: transparent !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  a[href]:after {
+    content: " (" attr(href) ")";
+  }
+  abbr[title]:after {
+    content: " (" attr(title) ")";
+  }
+  a[href^="#"]:after,
+  a[href^="javascript:"]:after {
+    content: "";
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  img {
+    max-width: 100% !important;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  select {
+    background: #fff !important;
+  }
+  .navbar {
+    display: none;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .label {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+@font-face {
+  font-family: 'Glyphicons Halflings';
+
+  src: url('../fonts/glyphicons-halflings-regular.eot');
+  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+  position: relative;
+  top: 1px;
+  display: inline-block;
+  font-family: 'Glyphicons Halflings';
+  font-style: normal;
+  font-weight: normal;
+  line-height: 1;
+
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+  content: "\2a";
+}
+.glyphicon-plus:before {
+  content: "\2b";
+}
+.glyphicon-euro:before,
+.glyphicon-eur:before {
+  content: "\20ac";
+}
+.glyphicon-minus:before {
+  content: "\2212";
+}
+.glyphicon-cloud:before {
+  content: "\2601";
+}
+.glyphicon-envelope:before {
+  content: "\2709";
+}
+.glyphicon-pencil:before {
+  content: "\270f";
+}
+.glyphicon-glass:before {
+  content: "\e001";
+}
+.glyphicon-music:before {
+  content: "\e002";
+}
+.glyphicon-search:before {
+  content: "\e003";
+}
+.glyphicon-heart:before {
+  content: "\e005";
+}
+.glyphicon-star:before {
+  content: "\e006";
+}
+.glyphicon-star-empty:before {
+  content: "\e007";
+}
+.glyphicon-user:before {
+  content: "\e008";
+}
+.glyphicon-film:before {
+  content: "\e009";
+}
+.glyphicon-th-large:before {
+  content: "\e010";
+}
+.glyphicon-th:before {
+  content: "\e011";
+}
+.glyphicon-th-list:before {
+  content: "\e012";
+}
+.glyphicon-ok:before {
+  content: "\e013";
+}
+.glyphicon-remove:before {
+  content: "\e014";
+}
+.glyphicon-zoom-in:before {
+  content: "\e015";
+}
+.glyphicon-zoom-out:before {
+  content: "\e016";
+}
+.glyphicon-off:before {
+  content: "\e017";
+}
+.glyphicon-signal:before {
+  content: "\e018";
+}
+.glyphicon-cog:before {
+  content: "\e019";
+}
+.glyphicon-trash:before {
+  content: "\e020";
+}
+.glyphicon-home:before {
+  content: "\e021";
+}
+.glyphicon-file:before {
+  content: "\e022";
+}
+.glyphicon-time:before {
+  content: "\e023";
+}
+.glyphicon-road:before {
+  content: "\e024";
+}
+.glyphicon-download-alt:before {
+  content: "\e025";
+}
+.glyphicon-download:before {
+  content: "\e026";
+}
+.glyphicon-upload:before {
+  content: "\e027";
+}
+.glyphicon-inbox:before {
+  content: "\e028";
+}
+.glyphicon-play-circle:before {
+  content: "\e029";
+}
+.glyphicon-repeat:before {
+  content: "\e030";
+}
+.glyphicon-refresh:before {
+  content: "\e031";
+}
+.glyphicon-list-alt:before {
+  content: "\e032";
+}
+.glyphicon-lock:before {
+  content: "\e033";
+}
+.glyphicon-flag:before {
+  content: "\e034";
+}
+.glyphicon-headphones:before {
+  content: "\e035";
+}
+.glyphicon-volume-off:before {
+  content: "\e036";
+}
+.glyphicon-volume-down:before {
+  content: "\e037";
+}
+.glyphicon-volume-up:before {
+  content: "\e038";
+}
+.glyphicon-qrcode:before {
+  content: "\e039";
+}
+.glyphicon-barcode:before {
+  content: "\e040";
+}
+.glyphicon-tag:before {
+  content: "\e041";
+}
+.glyphicon-tags:before {
+  content: "\e042";
+}
+.glyphicon-book:before {
+  content: "\e043";
+}
+.glyphicon-bookmark:before {
+  content: "\e044";
+}
+.glyphicon-print:before {
+  content: "\e045";
+}
+.glyphicon-camera:before {
+  content: "\e046";
+}
+.glyphicon-font:before {
+  content: "\e047";
+}
+.glyphicon-bold:before {
+  content: "\e048";
+}
+.glyphicon-italic:before {
+  content: "\e049";
+}
+.glyphicon-text-height:before {
+  content: "\e050";
+}
+.glyphicon-text-width:before {
+  content: "\e051";
+}
+.glyphicon-align-left:before {
+  content: "\e052";
+}
+.glyphicon-align-center:before {
+  content: "\e053";
+}
+.glyphicon-align-right:before {
+  content: "\e054";
+}
+.glyphicon-align-justify:before {
+  content: "\e055";
+}
+.glyphicon-list:before {
+  content: "\e056";
+}
+.glyphicon-indent-left:before {
+  content: "\e057";
+}
+.glyphicon-indent-right:before {
+  content: "\e058";
+}
+.glyphicon-facetime-video:before {
+  content: "\e059";
+}
+.glyphicon-picture:before {
+  content: "\e060";
+}
+.glyphicon-map-marker:before {
+  content: "\e062";
+}
+.glyphicon-adjust:before {
+  content: "\e063";
+}
+.glyphicon-tint:before {
+  content: "\e064";
+}
+.glyphicon-edit:before {
+  content: "\e065";
+}
+.glyphicon-share:before {
+  content: "\e066";
+}
+.glyphicon-check:before {
+  content: "\e067";
+}
+.glyphicon-move:before {
+  content: "\e068";
+}
+.glyphicon-step-backward:before {
+  content: "\e069";
+}
+.glyphicon-fast-backward:before {
+  content: "\e070";
+}
+.glyphicon-backward:before {
+  content: "\e071";
+}
+.glyphicon-play:before {
+  content: "\e072";
+}
+.glyphicon-pause:before {
+  content: "\e073";
+}
+.glyphicon-stop:before {
+  content: "\e074";
+}
+.glyphicon-forward:before {
+  content: "\e075";
+}
+.glyphicon-fast-forward:before {
+  content: "\e076";
+}
+.glyphicon-step-forward:before {
+  content: "\e077";
+}
+.glyphicon-eject:before {
+  content: "\e078";
+}
+.glyphicon-chevron-left:before {
+  content: "\e079";
+}
+.glyphicon-chevron-right:before {
+  content: "\e080";
+}
+.glyphicon-plus-sign:before {
+  content: "\e081";
+}
+.glyphicon-minus-sign:before {
+  content: "\e082";
+}
+.glyphicon-remove-sign:before {
+  content: "\e083";
+}
+.glyphicon-ok-sign:before {
+  content: "\e084";
+}
+.glyphicon-question-sign:before {
+  content: "\e085";
+}
+.glyphicon-info-sign:before {
+  content: "\e086";
+}
+.glyphicon-screenshot:before {
+  content: "\e087";
+}
+.glyphicon-remove-circle:before {
+  content: "\e088";
+}
+.glyphicon-ok-circle:before {
+  content: "\e089";
+}
+.glyphicon-ban-circle:before {
+  content: "\e090";
+}
+.glyphicon-arrow-left:before {
+  content: "\e091";
+}
+.glyphicon-arrow-right:before {
+  content: "\e092";
+}
+.glyphicon-arrow-up:before {
+  content: "\e093";
+}
+.glyphicon-arrow-down:before {
+  content: "\e094";
+}
+.glyphicon-share-alt:before {
+  content: "\e095";
+}
+.glyphicon-resize-full:before {
+  content: "\e096";
+}
+.glyphicon-resize-small:before {
+  content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+  content: "\e101";
+}
+.glyphicon-gift:before {
+  content: "\e102";
+}
+.glyphicon-leaf:before {
+  content: "\e103";
+}
+.glyphicon-fire:before {
+  content: "\e104";
+}
+.glyphicon-eye-open:before {
+  content: "\e105";
+}
+.glyphicon-eye-close:before {
+  content: "\e106";
+}
+.glyphicon-warning-sign:before {
+  content: "\e107";
+}
+.glyphicon-plane:before {
+  content: "\e108";
+}
+.glyphicon-calendar:before {
+  content: "\e109";
+}
+.glyphicon-random:before {
+  content: "\e110";
+}
+.glyphicon-comment:before {
+  content: "\e111";
+}
+.glyphicon-magnet:before {
+  content: "\e112";
+}
+.glyphicon-chevron-up:before {
+  content: "\e113";
+}
+.glyphicon-chevron-down:before {
+  content: "\e114";
+}
+.glyphicon-retweet:before {
+  content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+  content: "\e116";
+}
+.glyphicon-folder-close:before {
+  content: "\e117";
+}
+.glyphicon-folder-open:before {
+  content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+  content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+  content: "\e120";
+}
+.glyphicon-hdd:before {
+  content: "\e121";
+}
+.glyphicon-bullhorn:before {
+  content: "\e122";
+}
+.glyphicon-bell:before {
+  content: "\e123";
+}
+.glyphicon-certificate:before {
+  content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+  content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+  content: "\e126";
+}
+.glyphicon-hand-right:before {
+  content: "\e127";
+}
+.glyphicon-hand-left:before {
+  content: "\e128";
+}
+.glyphicon-hand-up:before {
+  content: "\e129";
+}
+.glyphicon-hand-down:before {
+  content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+  content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+  content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+  content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+  content: "\e134";
+}
+.glyphicon-globe:before {
+  content: "\e135";
+}
+.glyphicon-wrench:before {
+  content: "\e136";
+}
+.glyphicon-tasks:before {
+  content: "\e137";
+}
+.glyphicon-filter:before {
+  content: "\e138";
+}
+.glyphicon-briefcase:before {
+  content: "\e139";
+}
+.glyphicon-fullscreen:before {
+  content: "\e140";
+}
+.glyphicon-dashboard:before {
+  content: "\e141";
+}
+.glyphicon-paperclip:before {
+  content: "\e142";
+}
+.glyphicon-heart-empty:before {
+  content: "\e143";
+}
+.glyphicon-link:before {
+  content: "\e144";
+}
+.glyphicon-phone:before {
+  content: "\e145";
+}
+.glyphicon-pushpin:before {
+  content: "\e146";
+}
+.glyphicon-usd:before {
+  content: "\e148";
+}
+.glyphicon-gbp:before {
+  content: "\e149";
+}
+.glyphicon-sort:before {
+  content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+  content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+  content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+  content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+  content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+  content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+  content: "\e156";
+}
+.glyphicon-unchecked:before {
+  content: "\e157";
+}
+.glyphicon-expand:before {
+  content: "\e158";
+}
+.glyphicon-collapse-down:before {
+  content: "\e159";
+}
+.glyphicon-collapse-up:before {
+  content: "\e160";
+}
+.glyphicon-log-in:before {
+  content: "\e161";
+}
+.glyphicon-flash:before {
+  content: "\e162";
+}
+.glyphicon-log-out:before {
+  content: "\e163";
+}
+.glyphicon-new-window:before {
+  content: "\e164";
+}
+.glyphicon-record:before {
+  content: "\e165";
+}
+.glyphicon-save:before {
+  content: "\e166";
+}
+.glyphicon-open:before {
+  content: "\e167";
+}
+.glyphicon-saved:before {
+  content: "\e168";
+}
+.glyphicon-import:before {
+  content: "\e169";
+}
+.glyphicon-export:before {
+  content: "\e170";
+}
+.glyphicon-send:before {
+  content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+  content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+  content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+  content: "\e174";
+}
+.glyphicon-floppy-save:before {
+  content: "\e175";
+}
+.glyphicon-floppy-open:before {
+  content: "\e176";
+}
+.glyphicon-credit-card:before {
+  content: "\e177";
+}
+.glyphicon-transfer:before {
+  content: "\e178";
+}
+.glyphicon-cutlery:before {
+  content: "\e179";
+}
+.glyphicon-header:before {
+  content: "\e180";
+}
+.glyphicon-compressed:before {
+  content: "\e181";
+}
+.glyphicon-earphone:before {
+  content: "\e182";
+}
+.glyphicon-phone-alt:before {
+  content: "\e183";
+}
+.glyphicon-tower:before {
+  content: "\e184";
+}
+.glyphicon-stats:before {
+  content: "\e185";
+}
+.glyphicon-sd-video:before {
+  content: "\e186";
+}
+.glyphicon-hd-video:before {
+  content: "\e187";
+}
+.glyphicon-subtitles:before {
+  content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+  content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+  content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+  content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+  content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+  content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+  content: "\e194";
+}
+.glyphicon-registration-mark:before {
+  content: "\e195";
+}
+.glyphicon-cloud-download:before {
+  content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+  content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+  content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+  content: "\e200";
+}
+.glyphicon-cd:before {
+  content: "\e201";
+}
+.glyphicon-save-file:before {
+  content: "\e202";
+}
+.glyphicon-open-file:before {
+  content: "\e203";
+}
+.glyphicon-level-up:before {
+  content: "\e204";
+}
+.glyphicon-copy:before {
+  content: "\e205";
+}
+.glyphicon-paste:before {
+  content: "\e206";
+}
+.glyphicon-alert:before {
+  content: "\e209";
+}
+.glyphicon-equalizer:before {
+  content: "\e210";
+}
+.glyphicon-king:before {
+  content: "\e211";
+}
+.glyphicon-queen:before {
+  content: "\e212";
+}
+.glyphicon-pawn:before {
+  content: "\e213";
+}
+.glyphicon-bishop:before {
+  content: "\e214";
+}
+.glyphicon-knight:before {
+  content: "\e215";
+}
+.glyphicon-baby-formula:before {
+  content: "\e216";
+}
+.glyphicon-tent:before {
+  content: "\26fa";
+}
+.glyphicon-blackboard:before {
+  content: "\e218";
+}
+.glyphicon-bed:before {
+  content: "\e219";
+}
+.glyphicon-apple:before {
+  content: "\f8ff";
+}
+.glyphicon-erase:before {
+  content: "\e221";
+}
+.glyphicon-hourglass:before {
+  content: "\231b";
+}
+.glyphicon-lamp:before {
+  content: "\e223";
+}
+.glyphicon-duplicate:before {
+  content: "\e224";
+}
+.glyphicon-piggy-bank:before {
+  content: "\e225";
+}
+.glyphicon-scissors:before {
+  content: "\e226";
+}
+.glyphicon-bitcoin:before {
+  content: "\e227";
+}
+.glyphicon-btc:before {
+  content: "\e227";
+}
+.glyphicon-xbt:before {
+  content: "\e227";
+}
+.glyphicon-yen:before {
+  content: "\00a5";
+}
+.glyphicon-jpy:before {
+  content: "\00a5";
+}
+.glyphicon-ruble:before {
+  content: "\20bd";
+}
+.glyphicon-rub:before {
+  content: "\20bd";
+}
+.glyphicon-scale:before {
+  content: "\e230";
+}
+.glyphicon-ice-lolly:before {
+  content: "\e231";
+}
+.glyphicon-ice-lolly-tasted:before {
+  content: "\e232";
+}
+.glyphicon-education:before {
+  content: "\e233";
+}
+.glyphicon-option-horizontal:before {
+  content: "\e234";
+}
+.glyphicon-option-vertical:before {
+  content: "\e235";
+}
+.glyphicon-menu-hamburger:before {
+  content: "\e236";
+}
+.glyphicon-modal-window:before {
+  content: "\e237";
+}
+.glyphicon-oil:before {
+  content: "\e238";
+}
+.glyphicon-grain:before {
+  content: "\e239";
+}
+.glyphicon-sunglasses:before {
+  content: "\e240";
+}
+.glyphicon-text-size:before {
+  content: "\e241";
+}
+.glyphicon-text-color:before {
+  content: "\e242";
+}
+.glyphicon-text-background:before {
+  content: "\e243";
+}
+.glyphicon-object-align-top:before {
+  content: "\e244";
+}
+.glyphicon-object-align-bottom:before {
+  content: "\e245";
+}
+.glyphicon-object-align-horizontal:before {
+  content: "\e246";
+}
+.glyphicon-object-align-left:before {
+  content: "\e247";
+}
+.glyphicon-object-align-vertical:before {
+  content: "\e248";
+}
+.glyphicon-object-align-right:before {
+  content: "\e249";
+}
+.glyphicon-triangle-right:before {
+  content: "\e250";
+}
+.glyphicon-triangle-left:before {
+  content: "\e251";
+}
+.glyphicon-triangle-bottom:before {
+  content: "\e252";
+}
+.glyphicon-triangle-top:before {
+  content: "\e253";
+}
+.glyphicon-console:before {
+  content: "\e254";
+}
+.glyphicon-superscript:before {
+  content: "\e255";
+}
+.glyphicon-subscript:before {
+  content: "\e256";
+}
+.glyphicon-menu-left:before {
+  content: "\e257";
+}
+.glyphicon-menu-right:before {
+  content: "\e258";
+}
+.glyphicon-menu-down:before {
+  content: "\e259";
+}
+.glyphicon-menu-up:before {
+  content: "\e260";
+}
+* {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+*:before,
+*:after {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+html {
+  font-size: 10px;
+
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #333;
+  background-color: #fff;
+}
+input,
+button,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+a {
+  color: #337ab7;
+  text-decoration: none;
+}
+a:hover,
+a:focus {
+  color: #23527c;
+  text-decoration: underline;
+}
+a:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+figure {
+  margin: 0;
+}
+img {
+  vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  display: block;
+  max-width: 100%;
+  height: auto;
+}
+.img-rounded {
+  border-radius: 6px;
+}
+.img-thumbnail {
+  display: inline-block;
+  max-width: 100%;
+  height: auto;
+  padding: 4px;
+  line-height: 1.42857143;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  -webkit-transition: all .2s ease-in-out;
+       -o-transition: all .2s ease-in-out;
+          transition: all .2s ease-in-out;
+}
+.img-circle {
+  border-radius: 50%;
+}
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+  border: 0;
+  border-top: 1px solid #eee;
+}
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+[role="button"] {
+  cursor: pointer;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+  font-weight: normal;
+  line-height: 1;
+  color: #777;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+  margin-top: 20px;
+  margin-bottom: 10px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+  font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+  font-size: 75%;
+}
+h1,
+.h1 {
+  font-size: 36px;
+}
+h2,
+.h2 {
+  font-size: 30px;
+}
+h3,
+.h3 {
+  font-size: 24px;
+}
+h4,
+.h4 {
+  font-size: 18px;
+}
+h5,
+.h5 {
+  font-size: 14px;
+}
+h6,
+.h6 {
+  font-size: 12px;
+}
+p {
+  margin: 0 0 10px;
+}
+.lead {
+  margin-bottom: 20px;
+  font-size: 16px;
+  font-weight: 300;
+  line-height: 1.4;
+}
+@media (min-width: 768px) {
+  .lead {
+    font-size: 21px;
+  }
+}
+small,
+.small {
+  font-size: 85%;
+}
+mark,
+.mark {
+  padding: .2em;
+  background-color: #fcf8e3;
+}
+.text-left {
+  text-align: left;
+}
+.text-right {
+  text-align: right;
+}
+.text-center {
+  text-align: center;
+}
+.text-justify {
+  text-align: justify;
+}
+.text-nowrap {
+  white-space: nowrap;
+}
+.text-lowercase {
+  text-transform: lowercase;
+}
+.text-uppercase {
+  text-transform: uppercase;
+}
+.text-capitalize {
+  text-transform: capitalize;
+}
+.text-muted {
+  color: #777;
+}
+.text-primary {
+  color: #337ab7;
+}
+a.text-primary:hover {
+  color: #286090;
+}
+.text-success {
+  color: #3c763d;
+}
+a.text-success:hover {
+  color: #2b542c;
+}
+.text-info {
+  color: #31708f;
+}
+a.text-info:hover {
+  color: #245269;
+}
+.text-warning {
+  color: #8a6d3b;
+}
+a.text-warning:hover {
+  color: #66512c;
+}
+.text-danger {
+  color: #a94442;
+}
+a.text-danger:hover {
+  color: #843534;
+}
+.bg-primary {
+  color: #fff;
+  background-color: #337ab7;
+}
+a.bg-primary:hover {
+  background-color: #286090;
+}
+.bg-success {
+  background-color: #dff0d8;
+}
+a.bg-success:hover {
+  background-color: #c1e2b3;
+}
+.bg-info {
+  background-color: #d9edf7;
+}
+a.bg-info:hover {
+  background-color: #afd9ee;
+}
+.bg-warning {
+  background-color: #fcf8e3;
+}
+a.bg-warning:hover {
+  background-color: #f7ecb5;
+}
+.bg-danger {
+  background-color: #f2dede;
+}
+a.bg-danger:hover {
+  background-color: #e4b9b9;
+}
+.page-header {
+  padding-bottom: 9px;
+  margin: 40px 0 20px;
+  border-bottom: 1px solid #eee;
+}
+ul,
+ol {
+  margin-top: 0;
+  margin-bottom: 10px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+  margin-bottom: 0;
+}
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+.list-inline {
+  padding-left: 0;
+  margin-left: -5px;
+  list-style: none;
+}
+.list-inline > li {
+  display: inline-block;
+  padding-right: 5px;
+  padding-left: 5px;
+}
+dl {
+  margin-top: 0;
+  margin-bottom: 20px;
+}
+dt,
+dd {
+  line-height: 1.42857143;
+}
+dt {
+  font-weight: bold;
+}
+dd {
+  margin-left: 0;
+}
+@media (min-width: 768px) {
+  .dl-horizontal dt {
+    float: left;
+    width: 160px;
+    overflow: hidden;
+    clear: left;
+    text-align: right;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .dl-horizontal dd {
+    margin-left: 180px;
+  }
+}
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #777;
+}
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+blockquote {
+  padding: 10px 20px;
+  margin: 0 0 20px;
+  font-size: 17.5px;
+  border-left: 5px solid #eee;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+  margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+  display: block;
+  font-size: 80%;
+  line-height: 1.42857143;
+  color: #777;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+  content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+  padding-right: 15px;
+  padding-left: 0;
+  text-align: right;
+  border-right: 5px solid #eee;
+  border-left: 0;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+  content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+  content: '\00A0 \2014';
+}
+address {
+  margin-bottom: 20px;
+  font-style: normal;
+  line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #c7254e;
+  background-color: #f9f2f4;
+  border-radius: 4px;
+}
+kbd {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 3px;
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+}
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: bold;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+pre {
+  display: block;
+  padding: 9.5px;
+  margin: 0 0 10px;
+  font-size: 13px;
+  line-height: 1.42857143;
+  color: #333;
+  word-break: break-all;
+  word-wrap: break-word;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  white-space: pre-wrap;
+  background-color: transparent;
+  border-radius: 0;
+}
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+.container {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+@media (min-width: 768px) {
+  .container {
+    width: 750px;
+  }
+}
+@media (min-width: 992px) {
+  .container {
+    width: 970px;
+  }
+}
+@media (min-width: 1200px) {
+  .container {
+    width: 1170px;
+  }
+}
+.container-fluid {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+  float: left;
+}
+.col-xs-12 {
+  width: 100%;
+}
+.col-xs-11 {
+  width: 91.66666667%;
+}
+.col-xs-10 {
+  width: 83.33333333%;
+}
+.col-xs-9 {
+  width: 75%;
+}
+.col-xs-8 {
+  width: 66.66666667%;
+}
+.col-xs-7 {
+  width: 58.33333333%;
+}
+.col-xs-6 {
+  width: 50%;
+}
+.col-xs-5 {
+  width: 41.66666667%;
+}
+.col-xs-4 {
+  width: 33.33333333%;
+}
+.col-xs-3 {
+  width: 25%;
+}
+.col-xs-2 {
+  width: 16.66666667%;
+}
+.col-xs-1 {
+  width: 8.33333333%;
+}
+.col-xs-pull-12 {
+  right: 100%;
+}
+.col-xs-pull-11 {
+  right: 91.66666667%;
+}
+.col-xs-pull-10 {
+  right: 83.33333333%;
+}
+.col-xs-pull-9 {
+  right: 75%;
+}
+.col-xs-pull-8 {
+  right: 66.66666667%;
+}
+.col-xs-pull-7 {
+  right: 58.33333333%;
+}
+.col-xs-pull-6 {
+  right: 50%;
+}
+.col-xs-pull-5 {
+  right: 41.66666667%;
+}
+.col-xs-pull-4 {
+  right: 33.33333333%;
+}
+.col-xs-pull-3 {
+  right: 25%;
+}
+.col-xs-pull-2 {
+  right: 16.66666667%;
+}
+.col-xs-pull-1 {
+  right: 8.33333333%;
+}
+.col-xs-pull-0 {
+  right: auto;
+}
+.col-xs-push-12 {
+  left: 100%;
+}
+.col-xs-push-11 {
+  left: 91.66666667%;
+}
+.col-xs-push-10 {
+  left: 83.33333333%;
+}
+.col-xs-push-9 {
+  left: 75%;
+}
+.col-xs-push-8 {
+  left: 66.66666667%;
+}
+.col-xs-push-7 {
+  left: 58.33333333%;
+}
+.col-xs-push-6 {
+  left: 50%;
+}
+.col-xs-push-5 {
+  left: 41.66666667%;
+}
+.col-xs-push-4 {
+  left: 33.33333333%;
+}
+.col-xs-push-3 {
+  left: 25%;
+}
+.col-xs-push-2 {
+  left: 16.66666667%;
+}
+.col-xs-push-1 {
+  left: 8.33333333%;
+}
+.col-xs-push-0 {
+  left: auto;
+}
+.col-xs-offset-12 {
+  margin-left: 100%;
+}
+.col-xs-offset-11 {
+  margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+  margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+  margin-left: 75%;
+}
+.col-xs-offset-8 {
+  margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+  margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+  margin-left: 50%;
+}
+.col-xs-offset-5 {
+  margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+  margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+  margin-left: 25%;
+}
+.col-xs-offset-2 {
+  margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+  margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+  margin-left: 0;
+}
+@media (min-width: 768px) {
+  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+    float: left;
+  }
+  .col-sm-12 {
+    width: 100%;
+  }
+  .col-sm-11 {
+    width: 91.66666667%;
+  }
+  .col-sm-10 {
+    width: 83.33333333%;
+  }
+  .col-sm-9 {
+    width: 75%;
+  }
+  .col-sm-8 {
+    width: 66.66666667%;
+  }
+  .col-sm-7 {
+    width: 58.33333333%;
+  }
+  .col-sm-6 {
+    width: 50%;
+  }
+  .col-sm-5 {
+    width: 41.66666667%;
+  }
+  .col-sm-4 {
+    width: 33.33333333%;
+  }
+  .col-sm-3 {
+    width: 25%;
+  }
+  .col-sm-2 {
+    width: 16.66666667%;
+  }
+  .col-sm-1 {
+    width: 8.33333333%;
+  }
+  .col-sm-pull-12 {
+    right: 100%;
+  }
+  .col-sm-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-sm-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-sm-pull-9 {
+    right: 75%;
+  }
+  .col-sm-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-sm-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-sm-pull-6 {
+    right: 50%;
+  }
+  .col-sm-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-sm-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-sm-pull-3 {
+    right: 25%;
+  }
+  .col-sm-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-sm-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-sm-pull-0 {
+    right: auto;
+  }
+  .col-sm-push-12 {
+    left: 100%;
+  }
+  .col-sm-push-11 {
+    left: 91.66666667%;
+  }
+  .col-sm-push-10 {
+    left: 83.33333333%;
+  }
+  .col-sm-push-9 {
+    left: 75%;
+  }
+  .col-sm-push-8 {
+    left: 66.66666667%;
+  }
+  .col-sm-push-7 {
+    left: 58.33333333%;
+  }
+  .col-sm-push-6 {
+    left: 50%;
+  }
+  .col-sm-push-5 {
+    left: 41.66666667%;
+  }
+  .col-sm-push-4 {
+    left: 33.33333333%;
+  }
+  .col-sm-push-3 {
+    left: 25%;
+  }
+  .col-sm-push-2 {
+    left: 16.66666667%;
+  }
+  .col-sm-push-1 {
+    left: 8.33333333%;
+  }
+  .col-sm-push-0 {
+    left: auto;
+  }
+  .col-sm-offset-12 {
+    margin-left: 100%;
+  }
+  .col-sm-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-sm-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-sm-offset-9 {
+    margin-left: 75%;
+  }
+  .col-sm-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-sm-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-sm-offset-6 {
+    margin-left: 50%;
+  }
+  .col-sm-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-sm-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-sm-offset-3 {
+    margin-left: 25%;
+  }
+  .col-sm-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-sm-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-sm-offset-0 {
+    margin-left: 0;
+  }
+}
+@media (min-width: 992px) {
+  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+    float: left;
+  }
+  .col-md-12 {
+    width: 100%;
+  }
+  .col-md-11 {
+    width: 91.66666667%;
+  }
+  .col-md-10 {
+    width: 83.33333333%;
+  }
+  .col-md-9 {
+    width: 75%;
+  }
+  .col-md-8 {
+    width: 66.66666667%;
+  }
+  .col-md-7 {
+    width: 58.33333333%;
+  }
+  .col-md-6 {
+    width: 50%;
+  }
+  .col-md-5 {
+    width: 41.66666667%;
+  }
+  .col-md-4 {
+    width: 33.33333333%;
+  }
+  .col-md-3 {
+    width: 25%;
+  }
+  .col-md-2 {
+    width: 16.66666667%;
+  }
+  .col-md-1 {
+    width: 8.33333333%;
+  }
+  .col-md-pull-12 {
+    right: 100%;
+  }
+  .col-md-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-md-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-md-pull-9 {
+    right: 75%;
+  }
+  .col-md-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-md-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-md-pull-6 {
+    right: 50%;
+  }
+  .col-md-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-md-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-md-pull-3 {
+    right: 25%;
+  }
+  .col-md-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-md-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-md-pull-0 {
+    right: auto;
+  }
+  .col-md-push-12 {
+    left: 100%;
+  }
+  .col-md-push-11 {
+    left: 91.66666667%;
+  }
+  .col-md-push-10 {
+    left: 83.33333333%;
+  }
+  .col-md-push-9 {
+    left: 75%;
+  }
+  .col-md-push-8 {
+    left: 66.66666667%;
+  }
+  .col-md-push-7 {
+    left: 58.33333333%;
+  }
+  .col-md-push-6 {
+    left: 50%;
+  }
+  .col-md-push-5 {
+    left: 41.66666667%;
+  }
+  .col-md-push-4 {
+    left: 33.33333333%;
+  }
+  .col-md-push-3 {
+    left: 25%;
+  }
+  .col-md-push-2 {
+    left: 16.66666667%;
+  }
+  .col-md-push-1 {
+    left: 8.33333333%;
+  }
+  .col-md-push-0 {
+    left: auto;
+  }
+  .col-md-offset-12 {
+    margin-left: 100%;
+  }
+  .col-md-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-md-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-md-offset-9 {
+    margin-left: 75%;
+  }
+  .col-md-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-md-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-md-offset-6 {
+    margin-left: 50%;
+  }
+  .col-md-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-md-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-md-offset-3 {
+    margin-left: 25%;
+  }
+  .col-md-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-md-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-md-offset-0 {
+    margin-left: 0;
+  }
+}
+@media (min-width: 1200px) {
+  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+    float: left;
+  }
+  .col-lg-12 {
+    width: 100%;
+  }
+  .col-lg-11 {
+    width: 91.66666667%;
+  }
+  .col-lg-10 {
+    width: 83.33333333%;
+  }
+  .col-lg-9 {
+    width: 75%;
+  }
+  .col-lg-8 {
+    width: 66.66666667%;
+  }
+  .col-lg-7 {
+    width: 58.33333333%;
+  }
+  .col-lg-6 {
+    width: 50%;
+  }
+  .col-lg-5 {
+    width: 41.66666667%;
+  }
+  .col-lg-4 {
+    width: 33.33333333%;
+  }
+  .col-lg-3 {
+    width: 25%;
+  }
+  .col-lg-2 {
+    width: 16.66666667%;
+  }
+  .col-lg-1 {
+    width: 8.33333333%;
+  }
+  .col-lg-pull-12 {
+    right: 100%;
+  }
+  .col-lg-pull-11 {
+    right: 91.66666667%;
+  }
+  .col-lg-pull-10 {
+    right: 83.33333333%;
+  }
+  .col-lg-pull-9 {
+    right: 75%;
+  }
+  .col-lg-pull-8 {
+    right: 66.66666667%;
+  }
+  .col-lg-pull-7 {
+    right: 58.33333333%;
+  }
+  .col-lg-pull-6 {
+    right: 50%;
+  }
+  .col-lg-pull-5 {
+    right: 41.66666667%;
+  }
+  .col-lg-pull-4 {
+    right: 33.33333333%;
+  }
+  .col-lg-pull-3 {
+    right: 25%;
+  }
+  .col-lg-pull-2 {
+    right: 16.66666667%;
+  }
+  .col-lg-pull-1 {
+    right: 8.33333333%;
+  }
+  .col-lg-pull-0 {
+    right: auto;
+  }
+  .col-lg-push-12 {
+    left: 100%;
+  }
+  .col-lg-push-11 {
+    left: 91.66666667%;
+  }
+  .col-lg-push-10 {
+    left: 83.33333333%;
+  }
+  .col-lg-push-9 {
+    left: 75%;
+  }
+  .col-lg-push-8 {
+    left: 66.66666667%;
+  }
+  .col-lg-push-7 {
+    left: 58.33333333%;
+  }
+  .col-lg-push-6 {
+    left: 50%;
+  }
+  .col-lg-push-5 {
+    left: 41.66666667%;
+  }
+  .col-lg-push-4 {
+    left: 33.33333333%;
+  }
+  .col-lg-push-3 {
+    left: 25%;
+  }
+  .col-lg-push-2 {
+    left: 16.66666667%;
+  }
+  .col-lg-push-1 {
+    left: 8.33333333%;
+  }
+  .col-lg-push-0 {
+    left: auto;
+  }
+  .col-lg-offset-12 {
+    margin-left: 100%;
+  }
+  .col-lg-offset-11 {
+    margin-left: 91.66666667%;
+  }
+  .col-lg-offset-10 {
+    margin-left: 83.33333333%;
+  }
+  .col-lg-offset-9 {
+    margin-left: 75%;
+  }
+  .col-lg-offset-8 {
+    margin-left: 66.66666667%;
+  }
+  .col-lg-offset-7 {
+    margin-left: 58.33333333%;
+  }
+  .col-lg-offset-6 {
+    margin-left: 50%;
+  }
+  .col-lg-offset-5 {
+    margin-left: 41.66666667%;
+  }
+  .col-lg-offset-4 {
+    margin-left: 33.33333333%;
+  }
+  .col-lg-offset-3 {
+    margin-left: 25%;
+  }
+  .col-lg-offset-2 {
+    margin-left: 16.66666667%;
+  }
+  .col-lg-offset-1 {
+    margin-left: 8.33333333%;
+  }
+  .col-lg-offset-0 {
+    margin-left: 0;
+  }
+}
+table {
+  background-color: transparent;
+}
+caption {
+  padding-top: 8px;
+  padding-bottom: 8px;
+  color: #777;
+  text-align: left;
+}
+th {
+  text-align: left;
+}
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 20px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+  padding: 8px;
+  line-height: 1.42857143;
+  vertical-align: top;
+  border-top: 1px solid #ddd;
+}
+.table > thead > tr > th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #ddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+  border-top: 0;
+}
+.table > tbody + tbody {
+  border-top: 2px solid #ddd;
+}
+.table .table {
+  background-color: #fff;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+  padding: 5px;
+}
+.table-bordered {
+  border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+  border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+  border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-of-type(odd) {
+  background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover {
+  background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+  position: static;
+  display: table-column;
+  float: none;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+  position: static;
+  display: table-cell;
+  float: none;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+  background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+  background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+  background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+  background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+  background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+  background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+  background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+  background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+  background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+  background-color: #ebcccc;
+}
+.table-responsive {
+  min-height: .01%;
+  overflow-x: auto;
+}
+@media screen and (max-width: 767px) {
+  .table-responsive {
+    width: 100%;
+    margin-bottom: 15px;
+    overflow-y: hidden;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+    border: 1px solid #ddd;
+  }
+  .table-responsive > .table {
+    margin-bottom: 0;
+  }
+  .table-responsive > .table > thead > tr > th,
+  .table-responsive > .table > tbody > tr > th,
+  .table-responsive > .table > tfoot > tr > th,
+  .table-responsive > .table > thead > tr > td,
+  .table-responsive > .table > tbody > tr > td,
+  .table-responsive > .table > tfoot > tr > td {
+    white-space: nowrap;
+  }
+  .table-responsive > .table-bordered {
+    border: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:first-child,
+  .table-responsive > .table-bordered > tbody > tr > th:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+  .table-responsive > .table-bordered > thead > tr > td:first-child,
+  .table-responsive > .table-bordered > tbody > tr > td:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+    border-left: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:last-child,
+  .table-responsive > .table-bordered > tbody > tr > th:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+  .table-responsive > .table-bordered > thead > tr > td:last-child,
+  .table-responsive > .table-bordered > tbody > tr > td:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+    border-right: 0;
+  }
+  .table-responsive > .table-bordered > tbody > tr:last-child > th,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+  .table-responsive > .table-bordered > tbody > tr:last-child > td,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+    border-bottom: 0;
+  }
+}
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: 20px;
+  font-size: 21px;
+  line-height: inherit;
+  color: #333;
+  border: 0;
+  border-bottom: 1px solid #e5e5e5;
+}
+label {
+  display: inline-block;
+  max-width: 100%;
+  margin-bottom: 5px;
+  font-weight: bold;
+}
+input[type="search"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 4px 0 0;
+  margin-top: 1px \9;
+  line-height: normal;
+}
+input[type="file"] {
+  display: block;
+}
+input[type="range"] {
+  display: block;
+  width: 100%;
+}
+select[multiple],
+select[size] {
+  height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+output {
+  display: block;
+  padding-top: 7px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #555;
+}
+.form-control {
+  display: block;
+  width: 100%;
+  height: 34px;
+  padding: 6px 12px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #555;
+  background-color: #fff;
+  background-image: none;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+  -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
+       -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+          transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+  border-color: #66afe9;
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+}
+.form-control::-moz-placeholder {
+  color: #999;
+  opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+  color: #999;
+}
+.form-control::-webkit-input-placeholder {
+  color: #999;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+  background-color: #eee;
+  opacity: 1;
+}
+.form-control[disabled],
+fieldset[disabled] .form-control {
+  cursor: not-allowed;
+}
+textarea.form-control {
+  height: auto;
+}
+input[type="search"] {
+  -webkit-appearance: none;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+  input[type="date"],
+  input[type="time"],
+  input[type="datetime-local"],
+  input[type="month"] {
+    line-height: 34px;
+  }
+  input[type="date"].input-sm,
+  input[type="time"].input-sm,
+  input[type="datetime-local"].input-sm,
+  input[type="month"].input-sm,
+  .input-group-sm input[type="date"],
+  .input-group-sm input[type="time"],
+  .input-group-sm input[type="datetime-local"],
+  .input-group-sm input[type="month"] {
+    line-height: 30px;
+  }
+  input[type="date"].input-lg,
+  input[type="time"].input-lg,
+  input[type="datetime-local"].input-lg,
+  input[type="month"].input-lg,
+  .input-group-lg input[type="date"],
+  .input-group-lg input[type="time"],
+  .input-group-lg input[type="datetime-local"],
+  .input-group-lg input[type="month"] {
+    line-height: 46px;
+  }
+}
+.form-group {
+  margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+  position: relative;
+  display: block;
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+  min-height: 20px;
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+  position: absolute;
+  margin-top: 4px \9;
+  margin-left: -20px;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+  margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+  position: relative;
+  display: inline-block;
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  vertical-align: middle;
+  cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+  margin-top: 0;
+  margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+  cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+  cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+  cursor: not-allowed;
+}
+.form-control-static {
+  min-height: 34px;
+  padding-top: 7px;
+  padding-bottom: 7px;
+  margin-bottom: 0;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-sm {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.input-sm {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+  height: auto;
+}
+.form-group-sm .form-control {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.form-group-sm .form-control {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.form-group-sm .form-control,
+select[multiple].form-group-sm .form-control {
+  height: auto;
+}
+.form-group-sm .form-control-static {
+  height: 30px;
+  min-height: 32px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+}
+.input-lg {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.3333333;
+  border-radius: 6px;
+}
+select.input-lg {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+  height: auto;
+}
+.form-group-lg .form-control {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.3333333;
+  border-radius: 6px;
+}
+select.form-group-lg .form-control {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.form-group-lg .form-control,
+select[multiple].form-group-lg .form-control {
+  height: auto;
+}
+.form-group-lg .form-control-static {
+  height: 46px;
+  min-height: 38px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.3333333;
+}
+.has-feedback {
+  position: relative;
+}
+.has-feedback .form-control {
+  padding-right: 42.5px;
+}
+.form-control-feedback {
+  position: absolute;
+  top: 0;
+  right: 0;
+  z-index: 2;
+  display: block;
+  width: 34px;
+  height: 34px;
+  line-height: 34px;
+  text-align: center;
+  pointer-events: none;
+}
+.input-lg + .form-control-feedback {
+  width: 46px;
+  height: 46px;
+  line-height: 46px;
+}
+.input-sm + .form-control-feedback {
+  width: 30px;
+  height: 30px;
+  line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline,
+.has-success.radio label,
+.has-success.checkbox label,
+.has-success.radio-inline label,
+.has-success.checkbox-inline label {
+  color: #3c763d;
+}
+.has-success .form-control {
+  border-color: #3c763d;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-success .form-control:focus {
+  border-color: #2b542c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #3c763d;
+}
+.has-success .form-control-feedback {
+  color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline,
+.has-warning.radio label,
+.has-warning.checkbox label,
+.has-warning.radio-inline label,
+.has-warning.checkbox-inline label {
+  color: #8a6d3b;
+}
+.has-warning .form-control {
+  border-color: #8a6d3b;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-warning .form-control:focus {
+  border-color: #66512c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+}
+.has-warning .input-group-addon {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #8a6d3b;
+}
+.has-warning .form-control-feedback {
+  color: #8a6d3b;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline,
+.has-error.radio label,
+.has-error.checkbox label,
+.has-error.radio-inline label,
+.has-error.checkbox-inline label {
+  color: #a94442;
+}
+.has-error .form-control {
+  border-color: #a94442;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-error .form-control:focus {
+  border-color: #843534;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+}
+.has-error .input-group-addon {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #a94442;
+}
+.has-error .form-control-feedback {
+  color: #a94442;
+}
+.has-feedback label ~ .form-control-feedback {
+  top: 25px;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+  top: 0;
+}
+.help-block {
+  display: block;
+  margin-top: 5px;
+  margin-bottom: 10px;
+  color: #737373;
+}
+@media (min-width: 768px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio,
+  .form-inline .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio label,
+  .form-inline .checkbox label {
+    padding-left: 0;
+  }
+  .form-inline .radio input[type="radio"],
+  .form-inline .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+  padding-top: 7px;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+  min-height: 27px;
+}
+.form-horizontal .form-group {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .control-label {
+    padding-top: 7px;
+    margin-bottom: 0;
+    text-align: right;
+  }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+  right: 15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-lg .control-label {
+    padding-top: 14.333333px;
+  }
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-sm .control-label {
+    padding-top: 6px;
+  }
+}
+.btn {
+  display: inline-block;
+  padding: 6px 12px;
+  margin-bottom: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1.42857143;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus,
+.btn.focus {
+  color: #333;
+  text-decoration: none;
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+  pointer-events: none;
+  cursor: not-allowed;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  opacity: .65;
+}
+.btn-default {
+  color: #333;
+  background-color: #fff;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus,
+.btn-default.focus,
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  color: #333;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #fff;
+  border-color: #ccc;
+}
+.btn-default .badge {
+  color: #fff;
+  background-color: #333;
+}
+.btn-primary {
+  color: #fff;
+  background-color: #337ab7;
+  border-color: #2e6da4;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary.focus,
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  color: #fff;
+  background-color: #286090;
+  border-color: #204d74;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #337ab7;
+  border-color: #2e6da4;
+}
+.btn-primary .badge {
+  color: #337ab7;
+  background-color: #fff;
+}
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success:hover,
+.btn-success:focus,
+.btn-success.focus,
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success .badge {
+  color: #5cb85c;
+  background-color: #fff;
+}
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info:hover,
+.btn-info:focus,
+.btn-info.focus,
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info .badge {
+  color: #5bc0de;
+  background-color: #fff;
+}
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning.focus,
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning .badge {
+  color: #f0ad4e;
+  background-color: #fff;
+}
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger.focus,
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger .badge {
+  color: #d9534f;
+  background-color: #fff;
+}
+.btn-link {
+  font-weight: normal;
+  color: #337ab7;
+  border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+  background-color: transparent;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+  border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+  color: #23527c;
+  text-decoration: underline;
+  background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+  color: #777;
+  text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.3333333;
+  border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+  padding: 1px 5px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-block {
+  display: block;
+  width: 100%;
+}
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+       -o-transition: opacity .15s linear;
+          transition: opacity .15s linear;
+}
+.fade.in {
+  opacity: 1;
+}
+.collapse {
+  display: none;
+}
+.collapse.in {
+  display: block;
+}
+tr.collapse.in {
+  display: table-row;
+}
+tbody.collapse.in {
+  display: table-row-group;
+}
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition-timing-function: ease;
+       -o-transition-timing-function: ease;
+          transition-timing-function: ease;
+  -webkit-transition-duration: .35s;
+       -o-transition-duration: .35s;
+          transition-duration: .35s;
+  -webkit-transition-property: height, visibility;
+       -o-transition-property: height, visibility;
+          transition-property: height, visibility;
+}
+.caret {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 2px;
+  vertical-align: middle;
+  border-top: 4px dashed;
+  border-right: 4px solid transparent;
+  border-left: 4px solid transparent;
+}
+.dropup,
+.dropdown {
+  position: relative;
+}
+.dropdown-toggle:focus {
+  outline: 0;
+}
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  font-size: 14px;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .15);
+  border-radius: 4px;
+  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu .divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 1.42857143;
+  color: #333;
+  white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  color: #262626;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #337ab7;
+  outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+.open > .dropdown-menu {
+  display: block;
+}
+.open > a {
+  outline: 0;
+}
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+.dropdown-header {
+  display: block;
+  padding: 3px 20px;
+  font-size: 12px;
+  line-height: 1.42857143;
+  color: #777;
+  white-space: nowrap;
+}
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+.pull-right > .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 4px solid;
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+  .navbar-right .dropdown-menu {
+    right: 0;
+    left: auto;
+  }
+  .navbar-right .dropdown-menu-left {
+    right: auto;
+    left: 0;
+  }
+}
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+.btn-toolbar {
+  margin-left: -5px;
+}
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group > .btn-group {
+  float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+  padding-right: 8px;
+  padding-left: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+  padding-right: 12px;
+  padding-left: 12px;
+}
+.btn-group.open .dropdown-toggle {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn .caret {
+  margin-left: 0;
+}
+.btn-lg .caret {
+  border-width: 5px 5px 0;
+  border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+  border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  border-bottom-left-radius: 4px;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.btn-group-justified {
+  display: table;
+  width: 100%;
+  table-layout: fixed;
+  border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+  display: table-cell;
+  float: none;
+  width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+  width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+  left: auto;
+}
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+.input-group {
+  position: relative;
+  display: table;
+  border-collapse: separate;
+}
+.input-group[class*="col-"] {
+  float: none;
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.3333333;
+  border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+  height: 46px;
+  line-height: 46px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+  height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+  height: 30px;
+  line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+  height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+.input-group-addon {
+  padding: 6px 12px;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1;
+  color: #555;
+  text-align: center;
+  background-color: #eee;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+.input-group-addon.input-sm {
+  padding: 5px 10px;
+  font-size: 12px;
+  border-radius: 3px;
+}
+.input-group-addon.input-lg {
+  padding: 10px 16px;
+  font-size: 18px;
+  border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.input-group-addon:first-child {
+  border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.input-group-addon:last-child {
+  border-left: 0;
+}
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+.input-group-btn > .btn {
+  position: relative;
+}
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+  z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+  margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+  margin-left: -1px;
+}
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+.nav > li {
+  position: relative;
+  display: block;
+}
+.nav > li > a {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+  text-decoration: none;
+  background-color: #eee;
+}
+.nav > li.disabled > a {
+  color: #777;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+  color: #777;
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+  background-color: #eee;
+  border-color: #337ab7;
+}
+.nav .nav-divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.nav > li > a > img {
+  max-width: none;
+}
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+.nav-tabs > li {
+  float: left;
+  margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+  margin-right: 2px;
+  line-height: 1.42857143;
+  border: 1px solid transparent;
+  border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+  border-color: #eee #eee #ddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+  color: #555;
+  cursor: default;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+.nav-tabs.nav-justified {
+  width: 100%;
+  border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+  float: none;
+}
+.nav-tabs.nav-justified > li > a {
+  margin-bottom: 5px;
+  text-align: center;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+  top: auto;
+  left: auto;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li {
+    display: table-cell;
+    width: 1%;
+  }
+  .nav-tabs.nav-justified > li > a {
+    margin-bottom: 0;
+  }
+}
+.nav-tabs.nav-justified > li > a {
+  margin-right: 0;
+  border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+  border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li > a {
+    border-bottom: 1px solid #ddd;
+    border-radius: 4px 4px 0 0;
+  }
+  .nav-tabs.nav-justified > .active > a,
+  .nav-tabs.nav-justified > .active > a:hover,
+  .nav-tabs.nav-justified > .active > a:focus {
+    border-bottom-color: #fff;
+  }
+}
+.nav-pills > li {
+  float: left;
+}
+.nav-pills > li > a {
+  border-radius: 4px;
+}
+.nav-pills > li + li {
+  margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+  color: #fff;
+  background-color: #337ab7;
+}
+.nav-stacked > li {
+  float: none;
+}
+.nav-stacked > li + li {
+  margin-top: 2px;
+  margin-left: 0;
+}
+.nav-justified {
+  width: 100%;
+}
+.nav-justified > li {
+  float: none;
+}
+.nav-justified > li > a {
+  margin-bottom: 5px;
+  text-align: center;
+}
+.nav-justified > .dropdown .dropdown-menu {
+  top: auto;
+  left: auto;
+}
+@media (min-width: 768px) {
+  .nav-justified > li {
+    display: table-cell;
+    width: 1%;
+  }
+  .nav-justified > li > a {
+    margin-bottom: 0;
+  }
+}
+.nav-tabs-justified {
+  border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+  margin-right: 0;
+  border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+  border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs-justified > li > a {
+    border-bottom: 1px solid #ddd;
+    border-radius: 4px 4px 0 0;
+  }
+  .nav-tabs-justified > .active > a,
+  .nav-tabs-justified > .active > a:hover,
+  .nav-tabs-justified > .active > a:focus {
+    border-bottom-color: #fff;
+  }
+}
+.tab-content > .tab-pane {
+  display: none;
+}
+.tab-content > .active {
+  display: block;
+}
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.navbar {
+  position: relative;
+  min-height: 50px;
+  margin-bottom: 20px;
+  border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+  .navbar {
+    border-radius: 4px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-header {
+    float: left;
+  }
+}
+.navbar-collapse {
+  padding-right: 15px;
+  padding-left: 15px;
+  overflow-x: visible;
+  -webkit-overflow-scrolling: touch;
+  border-top: 1px solid transparent;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+}
+.navbar-collapse.in {
+  overflow-y: auto;
+}
+@media (min-width: 768px) {
+  .navbar-collapse {
+    width: auto;
+    border-top: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-collapse.collapse {
+    display: block !important;
+    height: auto !important;
+    padding-bottom: 0;
+    overflow: visible !important;
+  }
+  .navbar-collapse.in {
+    overflow-y: visible;
+  }
+  .navbar-fixed-top .navbar-collapse,
+  .navbar-static-top .navbar-collapse,
+  .navbar-fixed-bottom .navbar-collapse {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+  max-height: 340px;
+}
+@media (max-device-width: 480px) and (orientation: landscape) {
+  .navbar-fixed-top .navbar-collapse,
+  .navbar-fixed-bottom .navbar-collapse {
+    max-height: 200px;
+  }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .container > .navbar-header,
+  .container-fluid > .navbar-header,
+  .container > .navbar-collapse,
+  .container-fluid > .navbar-collapse {
+    margin-right: 0;
+    margin-left: 0;
+  }
+}
+.navbar-static-top {
+  z-index: 1000;
+  border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+  .navbar-static-top {
+    border-radius: 0;
+  }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+@media (min-width: 768px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+.navbar-fixed-top {
+  top: 0;
+  border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+  bottom: 0;
+  margin-bottom: 0;
+  border-width: 1px 0 0;
+}
+.navbar-brand {
+  float: left;
+  height: 50px;
+  padding: 15px 15px;
+  font-size: 18px;
+  line-height: 20px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+  text-decoration: none;
+}
+.navbar-brand > img {
+  display: block;
+}
+@media (min-width: 768px) {
+  .navbar > .container .navbar-brand,
+  .navbar > .container-fluid .navbar-brand {
+    margin-left: -15px;
+  }
+}
+.navbar-toggle {
+  position: relative;
+  float: right;
+  padding: 9px 10px;
+  margin-top: 8px;
+  margin-right: 15px;
+  margin-bottom: 8px;
+  background-color: transparent;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.navbar-toggle:focus {
+  outline: 0;
+}
+.navbar-toggle .icon-bar {
+  display: block;
+  width: 22px;
+  height: 2px;
+  border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+  margin-top: 4px;
+}
+@media (min-width: 768px) {
+  .navbar-toggle {
+    display: none;
+  }
+}
+.navbar-nav {
+  margin: 7.5px -15px;
+}
+.navbar-nav > li > a {
+  padding-top: 10px;
+  padding-bottom: 10px;
+  line-height: 20px;
+}
+@media (max-width: 767px) {
+  .navbar-nav .open .dropdown-menu {
+    position: static;
+    float: none;
+    width: auto;
+    margin-top: 0;
+    background-color: transparent;
+    border: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+  .navbar-nav .open .dropdown-menu > li > a,
+  .navbar-nav .open .dropdown-menu .dropdown-header {
+    padding: 5px 15px 5px 25px;
+  }
+  .navbar-nav .open .dropdown-menu > li > a {
+    line-height: 20px;
+  }
+  .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-nav .open .dropdown-menu > li > a:focus {
+    background-image: none;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-nav {
+    float: left;
+    margin: 0;
+  }
+  .navbar-nav > li {
+    float: left;
+  }
+  .navbar-nav > li > a {
+    padding-top: 15px;
+    padding-bottom: 15px;
+  }
+}
+.navbar-form {
+  padding: 10px 15px;
+  margin-top: 8px;
+  margin-right: -15px;
+  margin-bottom: 8px;
+  margin-left: -15px;
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid transparent;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+}
+@media (min-width: 768px) {
+  .navbar-form .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .navbar-form .form-control-static {
+    display: inline-block;
+  }
+  .navbar-form .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .navbar-form .input-group .input-group-addon,
+  .navbar-form .input-group .input-group-btn,
+  .navbar-form .input-group .form-control {
+    width: auto;
+  }
+  .navbar-form .input-group > .form-control {
+    width: 100%;
+  }
+  .navbar-form .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .radio,
+  .navbar-form .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .navbar-form .radio label,
+  .navbar-form .checkbox label {
+    padding-left: 0;
+  }
+  .navbar-form .radio input[type="radio"],
+  .navbar-form .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .navbar-form .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+@media (max-width: 767px) {
+  .navbar-form .form-group {
+    margin-bottom: 5px;
+  }
+  .navbar-form .form-group:last-child {
+    margin-bottom: 0;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-form {
+    width: auto;
+    padding-top: 0;
+    padding-bottom: 0;
+    margin-right: 0;
+    margin-left: 0;
+    border: 0;
+    -webkit-box-shadow: none;
+            box-shadow: none;
+  }
+}
+.navbar-nav > li > .dropdown-menu {
+  margin-top: 0;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+  margin-bottom: 0;
+  border-top-left-radius: 4px;
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.navbar-btn {
+  margin-top: 8px;
+  margin-bottom: 8px;
+}
+.navbar-btn.btn-sm {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+.navbar-btn.btn-xs {
+  margin-top: 14px;
+  margin-bottom: 14px;
+}
+.navbar-text {
+  margin-top: 15px;
+  margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+  .navbar-text {
+    float: left;
+    margin-right: 15px;
+    margin-left: 15px;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-left {
+    float: left !important;
+  }
+  .navbar-right {
+    float: right !important;
+    margin-right: -15px;
+  }
+  .navbar-right ~ .navbar-right {
+    margin-right: 0;
+  }
+}
+.navbar-default {
+  background-color: #f8f8f8;
+  border-color: #e7e7e7;
+}
+.navbar-default .navbar-brand {
+  color: #777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+  color: #5e5e5e;
+  background-color: transparent;
+}
+.navbar-default .navbar-text {
+  color: #777;
+}
+.navbar-default .navbar-nav > li > a {
+  color: #777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+  color: #333;
+  background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+  color: #ccc;
+  background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+  border-color: #ddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+  background-color: #ddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+  background-color: #888;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+  border-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+  color: #555;
+  background-color: #e7e7e7;
+}
+@media (max-width: 767px) {
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+    color: #777;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #333;
+    background-color: transparent;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #555;
+    background-color: #e7e7e7;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+    color: #ccc;
+    background-color: transparent;
+  }
+}
+.navbar-default .navbar-link {
+  color: #777;
+}
+.navbar-default .navbar-link:hover {
+  color: #333;
+}
+.navbar-default .btn-link {
+  color: #777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+  color: #333;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+  color: #ccc;
+}
+.navbar-inverse {
+  background-color: #222;
+  border-color: #080808;
+}
+.navbar-inverse .navbar-brand {
+  color: #9d9d9d;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+  color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a {
+  color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+  color: #fff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+  color: #444;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+  border-color: #333;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+  background-color: #333;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+  background-color: #fff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+  border-color: #101010;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+  color: #fff;
+  background-color: #080808;
+}
+@media (max-width: 767px) {
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+    border-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+    background-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+    color: #9d9d9d;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #fff;
+    background-color: transparent;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #fff;
+    background-color: #080808;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+    color: #444;
+    background-color: transparent;
+  }
+}
+.navbar-inverse .navbar-link {
+  color: #9d9d9d;
+}
+.navbar-inverse .navbar-link:hover {
+  color: #fff;
+}
+.navbar-inverse .btn-link {
+  color: #9d9d9d;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+  color: #fff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+  color: #444;
+}
+.breadcrumb {
+  padding: 8px 15px;
+  margin-bottom: 20px;
+  list-style: none;
+  background-color: #f5f5f5;
+  border-radius: 4px;
+}
+.breadcrumb > li {
+  display: inline-block;
+}
+.breadcrumb > li + li:before {
+  padding: 0 5px;
+  color: #ccc;
+  content: "/\00a0";
+}
+.breadcrumb > .active {
+  color: #777;
+}
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin: 20px 0;
+  border-radius: 4px;
+}
+.pagination > li {
+  display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+  position: relative;
+  float: left;
+  padding: 6px 12px;
+  margin-left: -1px;
+  line-height: 1.42857143;
+  color: #337ab7;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+  margin-left: 0;
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+  color: #23527c;
+  background-color: #eee;
+  border-color: #ddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #337ab7;
+  border-color: #337ab7;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+  padding: 10px 16px;
+  font-size: 18px;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+  border-top-left-radius: 6px;
+  border-bottom-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+  border-top-right-radius: 6px;
+  border-bottom-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+  padding: 5px 10px;
+  font-size: 12px;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+  border-top-left-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+}
+.pager {
+  padding-left: 0;
+  margin: 20px 0;
+  text-align: center;
+  list-style: none;
+}
+.pager li {
+  display: inline;
+}
+.pager li > a,
+.pager li > span {
+  display: inline-block;
+  padding: 5px 14px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+  text-decoration: none;
+  background-color: #eee;
+}
+.pager .next > a,
+.pager .next > span {
+  float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+  float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #fff;
+}
+.label {
+  display: inline;
+  padding: .2em .6em .3em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+.label:empty {
+  display: none;
+}
+.btn .label {
+  position: relative;
+  top: -1px;
+}
+.label-default {
+  background-color: #777;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+  background-color: #5e5e5e;
+}
+.label-primary {
+  background-color: #337ab7;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+  background-color: #286090;
+}
+.label-success {
+  background-color: #5cb85c;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+  background-color: #449d44;
+}
+.label-info {
+  background-color: #5bc0de;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+  background-color: #31b0d5;
+}
+.label-warning {
+  background-color: #f0ad4e;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+  background-color: #ec971f;
+}
+.label-danger {
+  background-color: #d9534f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+  background-color: #c9302c;
+}
+.badge {
+  display: inline-block;
+  min-width: 10px;
+  padding: 3px 7px;
+  font-size: 12px;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  background-color: #777;
+  border-radius: 10px;
+}
+.badge:empty {
+  display: none;
+}
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+.btn-xs .badge,
+.btn-group-xs > .btn .badge {
+  top: 0;
+  padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+  color: #337ab7;
+  background-color: #fff;
+}
+.list-group-item > .badge {
+  float: right;
+}
+.list-group-item > .badge + .badge {
+  margin-right: 5px;
+}
+.nav-pills > li > a > .badge {
+  margin-left: 3px;
+}
+.jumbotron {
+  padding: 30px 15px;
+  margin-bottom: 30px;
+  color: inherit;
+  background-color: #eee;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+  color: inherit;
+}
+.jumbotron p {
+  margin-bottom: 15px;
+  font-size: 21px;
+  font-weight: 200;
+}
+.jumbotron > hr {
+  border-top-color: #d5d5d5;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+  border-radius: 6px;
+}
+.jumbotron .container {
+  max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+  .jumbotron {
+    padding: 48px 0;
+  }
+  .container .jumbotron,
+  .container-fluid .jumbotron {
+    padding-right: 60px;
+    padding-left: 60px;
+  }
+  .jumbotron h1,
+  .jumbotron .h1 {
+    font-size: 63px;
+  }
+}
+.thumbnail {
+  display: block;
+  padding: 4px;
+  margin-bottom: 20px;
+  line-height: 1.42857143;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  -webkit-transition: border .2s ease-in-out;
+       -o-transition: border .2s ease-in-out;
+          transition: border .2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+  margin-right: auto;
+  margin-left: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+  border-color: #337ab7;
+}
+.thumbnail .caption {
+  padding: 9px;
+  color: #333;
+}
+.alert {
+  padding: 15px;
+  margin-bottom: 20px;
+  border: 1px solid transparent;
+  border-radius: 4px;
+}
+.alert h4 {
+  margin-top: 0;
+  color: inherit;
+}
+.alert .alert-link {
+  font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+  margin-bottom: 0;
+}
+.alert > p + p {
+  margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+  padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+  position: relative;
+  top: -2px;
+  right: -21px;
+  color: inherit;
+}
+.alert-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+.alert-success hr {
+  border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+  color: #2b542c;
+}
+.alert-info {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.alert-info hr {
+  border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+  color: #245269;
+}
+.alert-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #faebcc;
+}
+.alert-warning hr {
+  border-top-color: #f7e1b5;
+}
+.alert-warning .alert-link {
+  color: #66512c;
+}
+.alert-danger {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #ebccd1;
+}
+.alert-danger hr {
+  border-top-color: #e4b9c0;
+}
+.alert-danger .alert-link {
+  color: #843534;
+}
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+.progress {
+  height: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+  background-color: #f5f5f5;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+}
+.progress-bar {
+  float: left;
+  width: 0;
+  height: 100%;
+  font-size: 12px;
+  line-height: 20px;
+  color: #fff;
+  text-align: center;
+  background-color: #337ab7;
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+  -webkit-transition: width .6s ease;
+       -o-transition: width .6s ease;
+          transition: width .6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 40px 40px;
+          background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+       -o-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+  background-color: #5cb85c;
+}
+.progress-striped .progress-bar-success {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+  background-color: #5bc0de;
+}
+.progress-striped .progress-bar-info {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+  background-color: #f0ad4e;
+}
+.progress-striped .progress-bar-warning {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+  background-color: #d9534f;
+}
+.progress-striped .progress-bar-danger {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.media {
+  margin-top: 15px;
+}
+.media:first-child {
+  margin-top: 0;
+}
+.media,
+.media-body {
+  overflow: hidden;
+  zoom: 1;
+}
+.media-body {
+  width: 10000px;
+}
+.media-object {
+  display: block;
+}
+.media-right,
+.media > .pull-right {
+  padding-left: 10px;
+}
+.media-left,
+.media > .pull-left {
+  padding-right: 10px;
+}
+.media-left,
+.media-right,
+.media-body {
+  display: table-cell;
+  vertical-align: top;
+}
+.media-middle {
+  vertical-align: middle;
+}
+.media-bottom {
+  vertical-align: bottom;
+}
+.media-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+.list-group {
+  padding-left: 0;
+  margin-bottom: 20px;
+}
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+.list-group-item:first-child {
+  border-top-left-radius: 4px;
+  border-top-right-radius: 4px;
+}
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+a.list-group-item {
+  color: #555;
+}
+a.list-group-item .list-group-item-heading {
+  color: #333;
+}
+a.list-group-item:hover,
+a.list-group-item:focus {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+  color: #777;
+  cursor: not-allowed;
+  background-color: #eee;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+  color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+  color: #777;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  z-index: 2;
+  color: #fff;
+  background-color: #337ab7;
+  border-color: #337ab7;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+  color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+  color: #c7ddef;
+}
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+a.list-group-item-success {
+  color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-success:hover,
+a.list-group-item-success:focus {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+a.list-group-item-info {
+  color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-info:hover,
+a.list-group-item-info:focus {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+a.list-group-item-warning {
+  color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-warning:hover,
+a.list-group-item-warning:focus {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+a.list-group-item-danger {
+  color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+a.list-group-item-danger:hover,
+a.list-group-item-danger:focus {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+.panel {
+  margin-bottom: 20px;
+  background-color: #fff;
+  border: 1px solid transparent;
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+}
+.panel-body {
+  padding: 15px;
+}
+.panel-heading {
+  padding: 10px 15px;
+  border-bottom: 1px solid transparent;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+  color: inherit;
+}
+.panel-title {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-size: 16px;
+  color: inherit;
+}
+.panel-title > a,
+.panel-title > small,
+.panel-title > .small,
+.panel-title > small > a,
+.panel-title > .small > a {
+  color: inherit;
+}
+.panel-footer {
+  padding: 10px 15px;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .list-group,
+.panel > .panel-collapse > .list-group {
+  margin-bottom: 0;
+}
+.panel > .list-group .list-group-item,
+.panel > .panel-collapse > .list-group .list-group-item {
+  border-width: 1px 0;
+  border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child,
+.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
+  border-top: 0;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child,
+.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
+  border-bottom: 0;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+  border-top-width: 0;
+}
+.list-group + .panel-footer {
+  border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+  margin-bottom: 0;
+}
+.panel > .table caption,
+.panel > .table-responsive > .table caption,
+.panel > .panel-collapse > .table caption {
+  padding-right: 15px;
+  padding-left: 15px;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+  border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+  border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+  border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+  border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+  border-top: 1px solid #ddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+  border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+  border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+  border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+  border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+  border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+  border-bottom: 0;
+}
+.panel > .table-responsive {
+  margin-bottom: 0;
+  border: 0;
+}
+.panel-group {
+  margin-bottom: 20px;
+}
+.panel-group .panel {
+  margin-bottom: 0;
+  border-radius: 4px;
+}
+.panel-group .panel + .panel {
+  margin-top: 5px;
+}
+.panel-group .panel-heading {
+  border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body,
+.panel-group .panel-heading + .panel-collapse > .list-group {
+  border-top: 1px solid #ddd;
+}
+.panel-group .panel-footer {
+  border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+  border-bottom: 1px solid #ddd;
+}
+.panel-default {
+  border-color: #ddd;
+}
+.panel-default > .panel-heading {
+  color: #333;
+  background-color: #f5f5f5;
+  border-color: #ddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ddd;
+}
+.panel-default > .panel-heading .badge {
+  color: #f5f5f5;
+  background-color: #333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ddd;
+}
+.panel-primary {
+  border-color: #337ab7;
+}
+.panel-primary > .panel-heading {
+  color: #fff;
+  background-color: #337ab7;
+  border-color: #337ab7;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #337ab7;
+}
+.panel-primary > .panel-heading .badge {
+  color: #337ab7;
+  background-color: #fff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #337ab7;
+}
+.panel-success {
+  border-color: #d6e9c6;
+}
+.panel-success > .panel-heading {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #d6e9c6;
+}
+.panel-success > .panel-heading .badge {
+  color: #dff0d8;
+  background-color: #3c763d;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #d6e9c6;
+}
+.panel-info {
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+  color: #31708f;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #bce8f1;
+}
+.panel-info > .panel-heading .badge {
+  color: #d9edf7;
+  background-color: #31708f;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #bce8f1;
+}
+.panel-warning {
+  border-color: #faebcc;
+}
+.panel-warning > .panel-heading {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #faebcc;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #faebcc;
+}
+.panel-warning > .panel-heading .badge {
+  color: #fcf8e3;
+  background-color: #8a6d3b;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #faebcc;
+}
+.panel-danger {
+  border-color: #ebccd1;
+}
+.panel-danger > .panel-heading {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #ebccd1;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ebccd1;
+}
+.panel-danger > .panel-heading .badge {
+  color: #f2dede;
+  background-color: #a94442;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ebccd1;
+}
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+}
+.well blockquote {
+  border-color: #ddd;
+  border-color: rgba(0, 0, 0, .15);
+}
+.well-lg {
+  padding: 24px;
+  border-radius: 6px;
+}
+.well-sm {
+  padding: 9px;
+  border-radius: 3px;
+}
+.close {
+  float: right;
+  font-size: 21px;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  filter: alpha(opacity=20);
+  opacity: .2;
+}
+.close:hover,
+.close:focus {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+button.close {
+  -webkit-appearance: none;
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+}
+.modal-open {
+  overflow: hidden;
+}
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  -webkit-overflow-scrolling: touch;
+  outline: 0;
+}
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+       -o-transition:      -o-transform .3s ease-out;
+          transition:         transform .3s ease-out;
+  -webkit-transform: translate(0, -25%);
+      -ms-transform: translate(0, -25%);
+       -o-transform: translate(0, -25%);
+          transform: translate(0, -25%);
+}
+.modal.in .modal-dialog {
+  -webkit-transform: translate(0, 0);
+      -ms-transform: translate(0, 0);
+       -o-transform: translate(0, 0);
+          transform: translate(0, 0);
+}
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #999;
+  border: 1px solid rgba(0, 0, 0, .2);
+  border-radius: 6px;
+  outline: 0;
+  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+          box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+.modal-backdrop.fade {
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.modal-backdrop.in {
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+.modal-header {
+  min-height: 16.42857143px;
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+  margin-top: -2px;
+}
+.modal-title {
+  margin: 0;
+  line-height: 1.42857143;
+}
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+  margin-bottom: 0;
+  margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+  margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+  margin-left: 0;
+}
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+@media (min-width: 768px) {
+  .modal-dialog {
+    width: 600px;
+    margin: 30px auto;
+  }
+  .modal-content {
+    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+            box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+  }
+  .modal-sm {
+    width: 300px;
+  }
+}
+@media (min-width: 992px) {
+  .modal-lg {
+    width: 900px;
+  }
+}
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 12px;
+  font-weight: normal;
+  line-height: 1.4;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+.tooltip.in {
+  filter: alpha(opacity=90);
+  opacity: .9;
+}
+.tooltip.top {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+.tooltip.right {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+.tooltip.bottom {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+.tooltip.left {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  text-decoration: none;
+  background-color: #000;
+  border-radius: 4px;
+}
+.tooltip-arrow {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.top-left .tooltip-arrow {
+  right: 5px;
+  bottom: 0;
+  margin-bottom: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.top-right .tooltip-arrow {
+  bottom: 0;
+  left: 5px;
+  margin-bottom: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+.tooltip.right .tooltip-arrow {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+.tooltip.left .tooltip-arrow {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+.tooltip.bottom .tooltip-arrow {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+  top: 0;
+  right: 5px;
+  margin-top: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+  top: 0;
+  left: 5px;
+  margin-top: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: none;
+  max-width: 276px;
+  padding: 1px;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1.42857143;
+  text-align: left;
+  white-space: normal;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .2);
+  border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+}
+.popover.top {
+  margin-top: -10px;
+}
+.popover.right {
+  margin-left: 10px;
+}
+.popover.bottom {
+  margin-top: 10px;
+}
+.popover.left {
+  margin-left: -10px;
+}
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 14px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 5px 5px 0 0;
+}
+.popover-content {
+  padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.popover > .arrow {
+  border-width: 11px;
+}
+.popover > .arrow:after {
+  content: "";
+  border-width: 10px;
+}
+.popover.top > .arrow {
+  bottom: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-color: #999;
+  border-top-color: rgba(0, 0, 0, .25);
+  border-bottom-width: 0;
+}
+.popover.top > .arrow:after {
+  bottom: 1px;
+  margin-left: -10px;
+  content: " ";
+  border-top-color: #fff;
+  border-bottom-width: 0;
+}
+.popover.right > .arrow {
+  top: 50%;
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: #999;
+  border-right-color: rgba(0, 0, 0, .25);
+  border-left-width: 0;
+}
+.popover.right > .arrow:after {
+  bottom: -10px;
+  left: 1px;
+  content: " ";
+  border-right-color: #fff;
+  border-left-width: 0;
+}
+.popover.bottom > .arrow {
+  top: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-width: 0;
+  border-bottom-color: #999;
+  border-bottom-color: rgba(0, 0, 0, .25);
+}
+.popover.bottom > .arrow:after {
+  top: 1px;
+  margin-left: -10px;
+  content: " ";
+  border-top-width: 0;
+  border-bottom-color: #fff;
+}
+.popover.left > .arrow {
+  top: 50%;
+  right: -11px;
+  margin-top: -11px;
+  border-right-width: 0;
+  border-left-color: #999;
+  border-left-color: rgba(0, 0, 0, .25);
+}
+.popover.left > .arrow:after {
+  right: 1px;
+  bottom: -10px;
+  content: " ";
+  border-right-width: 0;
+  border-left-color: #fff;
+}
+.carousel {
+  position: relative;
+}
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+.carousel-inner > .item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+       -o-transition: .6s ease-in-out left;
+          transition: .6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  line-height: 1;
+}
+@media all and (transform-3d), (-webkit-transform-3d) {
+  .carousel-inner > .item {
+    -webkit-transition: -webkit-transform .6s ease-in-out;
+         -o-transition:      -o-transform .6s ease-in-out;
+            transition:         transform .6s ease-in-out;
+
+    -webkit-backface-visibility: hidden;
+            backface-visibility: hidden;
+    -webkit-perspective: 1000;
+            perspective: 1000;
+  }
+  .carousel-inner > .item.next,
+  .carousel-inner > .item.active.right {
+    left: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+            transform: translate3d(100%, 0, 0);
+  }
+  .carousel-inner > .item.prev,
+  .carousel-inner > .item.active.left {
+    left: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+            transform: translate3d(-100%, 0, 0);
+  }
+  .carousel-inner > .item.next.left,
+  .carousel-inner > .item.prev.right,
+  .carousel-inner > .item.active {
+    left: 0;
+    -webkit-transform: translate3d(0, 0, 0);
+            transform: translate3d(0, 0, 0);
+  }
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+.carousel-inner > .active {
+  left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+.carousel-inner > .next {
+  left: 100%;
+}
+.carousel-inner > .prev {
+  left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+.carousel-inner > .active.left {
+  left: -100%;
+}
+.carousel-inner > .active.right {
+  left: 100%;
+}
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+  filter: alpha(opacity=50);
+  opacity: .5;
+}
+.carousel-control.left {
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  background-image:      -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));
+  background-image:         linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+  background-repeat: repeat-x;
+}
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  background-image:      -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));
+  background-image:         linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+  background-repeat: repeat-x;
+}
+.carousel-control:hover,
+.carousel-control:focus {
+  color: #fff;
+  text-decoration: none;
+  filter: alpha(opacity=90);
+  outline: 0;
+  opacity: .9;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+  left: 50%;
+  margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+  right: 50%;
+  margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+  line-height: 1;
+}
+.carousel-control .icon-prev:before {
+  content: '\2039';
+}
+.carousel-control .icon-next:before {
+  content: '\203a';
+}
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: #000 \9;
+  background-color: rgba(0, 0, 0, 0);
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+}
+.carousel-caption .btn {
+  text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .glyphicon-chevron-left,
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
+  display: table;
+  content: " ";
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
+  clear: both;
+}
+.center-block {
+  display: block;
+  margin-right: auto;
+  margin-left: auto;
+}
+.pull-right {
+  float: right !important;
+}
+.pull-left {
+  float: left !important;
+}
+.hide {
+  display: none !important;
+}
+.show {
+  display: block !important;
+}
+.invisible {
+  visibility: hidden;
+}
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+.hidden {
+  display: none !important;
+}
+.affix {
+  position: fixed;
+}
+@-ms-viewport {
+  width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+  display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+  display: none !important;
+}
+@media (max-width: 767px) {
+  .visible-xs {
+    display: block !important;
+  }
+  table.visible-xs {
+    display: table;
+  }
+  tr.visible-xs {
+    display: table-row !important;
+  }
+  th.visible-xs,
+  td.visible-xs {
+    display: table-cell !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-block {
+    display: block !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-inline {
+    display: inline !important;
+  }
+}
+@media (max-width: 767px) {
+  .visible-xs-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm {
+    display: block !important;
+  }
+  table.visible-sm {
+    display: table;
+  }
+  tr.visible-sm {
+    display: table-row !important;
+  }
+  th.visible-sm,
+  td.visible-sm {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-block {
+    display: block !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .visible-sm-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md {
+    display: block !important;
+  }
+  table.visible-md {
+    display: table;
+  }
+  tr.visible-md {
+    display: table-row !important;
+  }
+  th.visible-md,
+  td.visible-md {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-block {
+    display: block !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .visible-md-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg {
+    display: block !important;
+  }
+  table.visible-lg {
+    display: table;
+  }
+  tr.visible-lg {
+    display: table-row !important;
+  }
+  th.visible-lg,
+  td.visible-lg {
+    display: table-cell !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-block {
+    display: block !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-inline {
+    display: inline !important;
+  }
+}
+@media (min-width: 1200px) {
+  .visible-lg-inline-block {
+    display: inline-block !important;
+  }
+}
+@media (max-width: 767px) {
+  .hidden-xs {
+    display: none !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+  .hidden-sm {
+    display: none !important;
+  }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+  .hidden-md {
+    display: none !important;
+  }
+}
+@media (min-width: 1200px) {
+  .hidden-lg {
+    display: none !important;
+  }
+}
+.visible-print {
+  display: none !important;
+}
+@media print {
+  .visible-print {
+    display: block !important;
+  }
+  table.visible-print {
+    display: table;
+  }
+  tr.visible-print {
+    display: table-row !important;
+  }
+  th.visible-print,
+  td.visible-print {
+    display: table-cell !important;
+  }
+}
+.visible-print-block {
+  display: none !important;
+}
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+.visible-print-inline {
+  display: none !important;
+}
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+.visible-print-inline-block {
+  display: none !important;
+}
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */

+ 173 - 0
mPlugin-js/getCertInfo.html

@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>智能密码卡国密中间件</title>
+
+    <script src="./js/mTokenPlugin/base64.js"></script>
+    <script src="./js/mTokenPlugin/mToken.js"></script>
+    <script src="./js/mTokenPlugin/hunca_mToken_core.js"></script>
+    <link href="css/bootstrap.css" rel="stylesheet">
+    <style>
+        body {
+            margin: 0px 0px auto;
+        }
+
+        .head {
+            width: 950px;
+            margin: 0px auto;
+        }
+
+        .nav {
+            width: auto;
+            margin: 0px auto;
+            text-align: center;
+        }
+
+        .content {
+            width: 1200px;
+            margin: 0px auto;
+            text-align: center;
+            margin-top: 40px;
+        }
+    </style>
+    <script>
+        var mToken = new hunca_mToken_core();
+
+        function enumDevice() {
+            var devList = "";
+            var selectDev = null;
+
+            selectDev = document.getElementById("optionDevList");
+            selectDev.options.length = 0;
+
+            devList = mToken.Hunca_GetUserList(); //枚举Ukey,获取证书G项信息列表
+            if (null == devList || devList.length == 0) {
+                selectDev.value = "";
+                alert(mToken.Hunca_GetLastError());
+                return false;
+            }
+
+            addOption(devList, selectDev, 1);
+            return false;
+        }
+
+        function getSN() {
+            var selectDev = null;
+            var userName = null;
+            var caSN = "",
+                cert_subject = "";
+                cert_validTime = "";
+                cert_notBeforeTime = ""; 
+                device_number = "";
+
+            selectDev = document.getElementById("optionDevList");
+            if (selectDev.length == 0) {
+                alert('请插入Ukey,点击“刷新”按钮')
+                return false;
+            }
+            index = selectDev.selectedIndex;
+
+            userName = selectDev.options[index].text;
+    
+
+            if (!mToken.Hunca_DealCertInfo(userName)) {
+                alert(mToken.Hunca_GetLastError());
+                return false;
+            }
+
+            device_number = mToken.HUnca_GetDeviceNumber(userName);
+            caSN = mToken.Hunca_GetSignCertSn();
+            cert_subject = mToken.Hunca_GetSignCertSubject();
+            cert_validTime = mToken.Hunca_GetValidTime();
+            cert_notBeforeTime = mToken.HUnca_GetNotBeforeTime();
+           
+
+            document.getElementById("ca_sn").value = caSN;
+            document.getElementById("ca_subject").value = cert_subject;
+            document.getElementById("ca_notBeforeTime").value = cert_notBeforeTime;
+            document.getElementById("ca_validTime").value = cert_validTime;
+            document.getElementById("device_number").value = device_number;
+            
+            return false;
+        }
+
+        //动态添加option选项
+        function addOption(optionStr, selectID, flag) {
+            if (flag == 1) {
+                for (var i = 0; i < optionStr.length; ++i)
+                    selectID.options.add(new Option(optionStr[i], i));
+            }
+            if (flag == 2) {
+                for (var i = 0; i < optionStr.length; ++i) {
+                    selectID.options.add(new Option(optionStr[i][1], i));
+                }
+            }
+        }
+    </script>
+</head>
+
+<body>
+    <embed id="id_mPluginV2Router" type="application/mPluginV2Router" width="0" height="0" />
+    <object id="mTokenPlugin" width="0" height="0">
+        <param value="pluginLoaded" />
+    </object>
+    <div class="head">
+        <img src="">
+    </div>
+    <div class="nav">
+        <h2>智能密码卡国密中间件(获取证书序列号)</h2>
+    </div>
+    <div class="content" style="width: 720px">
+        <form class="form-horizontal" method="POST">
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">证书名称:</label>
+                <div class="col-sm-6">
+                    <select id="optionDevList" class="form-control"></select>
+                </div>
+                <div class="col-sm-2">
+                    <button class="btn btn-default" onclick="return enumDevice();">刷新</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">证书序号:</label>
+                <div class="col-sm-6">
+                    <input id="ca_sn" type="text" readonly class="form-control">
+                </div>
+                <div class="col-sm-2">
+                    <button class="btn btn-primary" onclick="return getSN();">获取</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">设备序号:</label>
+                <div class="col-sm-6">
+                    <input id="device_number" type="text" readonly class="form-control">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">证书信息:</label>
+                <div class="col-sm-6">
+                    <input id="ca_subject" type="text" readonly class="form-control">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">生效时间:</label>
+                <div class="col-sm-6">
+                    <input id="ca_notBeforeTime" type="text" readonly class="form-control">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">过期时间:</label>
+                <div class="col-sm-6">
+                    <input id="ca_validTime" type="text" readonly class="form-control">
+                </div>
+            </div>
+        </form>
+    </div>
+
+</body>
+
+</html>

+ 145 - 0
mPlugin-js/js/mTokenPlugin/base64.js

@@ -0,0 +1,145 @@
+/*******************************************************
+ *
+ * 函数名称:Base64encode()
+ * 功    能:对数据进行Base64加密
+ * 说	明:函数中将数据使用_utf8_encode()进行编码转换后再加密,保证数据完整
+ *
+ **********************************************************/
+
+var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+function _Base64encode(input) {
+
+	var output = "";
+	var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+	var i = 0;
+
+	input = _utf8_encode(input);
+
+	while (i < input.length) {
+
+		chr1 = input.charCodeAt(i++);
+		chr2 = input.charCodeAt(i++);
+		chr3 = input.charCodeAt(i++);
+
+		enc1 = chr1 >> 2;
+		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+		enc4 = chr3 & 63;
+
+		if (isNaN(chr2)) {
+			enc3 = enc4 = 64;
+		} else if (isNaN(chr3)) {
+			enc4 = 64;
+		}
+
+		output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+	}
+	return output;
+}
+
+/*******************************************************
+ *
+ * 函数名称:Base64decode()
+ * 功    能:对数据进行Base64解密
+ * 说	明:函数中将数据使用_utf8_decode()将解密后的数据编码,保证数据完整
+ *
+ **********************************************************/
+function _Base64decode(input) {
+	var output = "";
+	var chr1, chr2, chr3;
+	var enc1, enc2, enc3, enc4;
+	var i = 0;
+
+	//input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+	input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+	while (i < input.length) {
+
+		enc1 = this._keyStr.indexOf(input.charAt(i++));
+		enc2 = this._keyStr.indexOf(input.charAt(i++));
+		enc3 = this._keyStr.indexOf(input.charAt(i++));
+		enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+		chr1 = (enc1 << 2) | (enc2 >> 4);
+		chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+		chr3 = ((enc3 & 3) << 6) | enc4;
+
+		output = output + String.fromCharCode(chr1);
+
+		if (enc3 != 64) {
+			output = output + String.fromCharCode(chr2);
+		}
+		if (enc4 != 64) {
+			output = output + String.fromCharCode(chr3);
+		}
+
+	}
+
+	output = _utf8_decode(output);
+
+	return output;
+}
+
+/*******************************************************
+ *
+ * 函数名称:_utf8_encode()
+ * 功    能:将数据进行utf8编码
+ * 说	明:
+ *
+ **********************************************************/
+function _utf8_encode(in_string) {
+	string = "" + in_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;
+}
+
+/*******************************************************
+ *
+ * 函数名称:_utf8_decode()
+ * 功    能:将数据进行utf8解码
+ * 说	明:
+ *
+ **********************************************************/
+function _utf8_decode(utftext) {
+	var string = "";
+	var i = 0;
+	var c = c1 = c2 = 0;
+
+	while (i < utftext.length) {
+
+		c = utftext.charCodeAt(i);
+
+		if (c < 128) {
+			string += String.fromCharCode(c);
+			i++;
+		} else if ((c > 191) && (c < 224)) {
+			c2 = utftext.charCodeAt(i + 1);
+			string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+			i += 2;
+		} else {
+			c2 = utftext.charCodeAt(i + 1);
+			c3 = utftext.charCodeAt(i + 2);
+			string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+			i += 3;
+		}
+	}
+	return string;
+}

+ 1405 - 0
mPlugin-js/js/mTokenPlugin/hunca_mToken_core.js

@@ -0,0 +1,1405 @@
+/**
+ * @name mTokenPlugin集成代码
+ * @author Akay
+ * @version 0.7.10
+ * @date 2020.04.04
+ * 
+ * @description
+ * ver 0.7.10 2020.04.04
+ * 1. 新增获取设备序号
+ * 2. 支持多Key
+ *
+ * ver 0.7.9 2020.01.08
+ * 1. 支持SJK1137型号
+ *
+ * ver 0.7.8 2019.10.23
+ * 1. 新增UKey适配
+ *
+ * ver 0.7.4  2019.09.18
+ * 1. 新增证书生效,失效时间
+ * 
+ * ver 0.7.3  2019.08.19
+ * 1. 获取证书使用者信息
+ * 
+ * ver 0.7.2  2019.08.08
+ * 1. 新增远程解锁接口
+ *
+ * ver 0.7.1 2019.07.17
+ * TODO: 未安装组件时,判断组件是否安装(暂定,未解决)
+ * 
+ * ver 0.7.0 2019.07.04
+ * 1. 更新核心文件,解决多Key插入问题
+ * 2. Ukey目前仅支持国密证书
+ *
+ * ver 0.6.3 2019.06.24
+ * 1. 修复部分Bug
+ * 
+ * ver 0.6.1 2019.06.24
+ * 1. 支持数字信封数据解密接口
+ * 2. 修复加密接口错误部分。
+ *
+ * ver 0.6.0 2019.06.20
+ * 1. 支持数字信封数据加密接口
+ * 2. 暂不支持多Ukey
+ * 
+ * ver 0.5.1 2019.06.19
+ * 1. 修正新Ukey引入导致的Bug
+ * 
+ * ver 0.5  2019.06.18
+ * 1. 适配SJK1137型号Ukey
+ * 
+ * ver 0.4  2019.03.16
+ * 1. 新增方法 枚举Ukey获取证书“G项信息”列表
+ * 2. 新增方法 将“证书G项信息”转化为“证书名称”方法
+ * 
+ * ver 0.3  2018.12.10
+ * 1. 新增修改Ukey密码的方法
+ *
+ * ver 0.2  2018.09.26
+ * 1. 新增获取签名证书SN号的方法
+ * 2. 修正部分Bug
+ * 
+ * ver 0.1 2018.09.21
+ * 1. 搭建初步框架
+ * 2. 完成签名功能
+ * 
+ */
+function hunca_mToken_core() {
+
+    var token = new mToken("mTokenPlugin");
+    var certInfoList = null;
+	var singleKey = 0;
+
+	var libraryNameList = Array("GM3000"); 
+    /**
+     * 错误信息
+     */
+    var LAST_ERRORSTRING = "";
+
+    /**
+     * 证书用途
+     */
+    var KEY_SPEC_TYPE_ENCRYPT = 0;
+    var KEY_SPEC_TYPE_SIGN = 1;
+
+    /**
+     * 摘要算法
+     */
+    var SGD_SM3 = 1;
+    var SGD_SHA1 = 2;
+
+    /**
+     * 加密算法
+     */
+    //分组加密算法标识
+    var SGD_SM1_ECB = 0x00000101;
+    var SGD_SM1_CBC = 0x00000102;
+    var SGD_SM1_CFB = 0x00000104;
+    var SGD_SM1_OFB = 0x00000108;
+    var SGD_SM1_MAC = 0x00000110;
+    var SGD_SM4_ECB = 0x00000401;
+    var SGD_SM4_CBC = 0x00000402;
+    var SGD_SM4_CFB = 0x00000404;
+    var SGD_SM4_OFB = 0x00000408;
+    var SGD_SM4_MAC = 0x00000410;
+
+
+    /**
+     * 用户ID(固定)
+     */
+    var USER_ID = "1234567812345678";
+
+
+    /**
+     * 错误信息提示列表
+     */
+    var ERROR_MESSAGE_NOT_LOADLIBRARY = "控件加载失败,错误码:";
+    var ERROR_MESSAGE_NOT_FIND_UKEY = "未找到UKey!\n1.请确认是否安装最新驱动!\n2.计算机是否插入CA UKey!";
+    var ERROR_MSSSAGE_FIND_MORE_UKEY = "计算机插入多个UKey,请拔除多余“CA UKey”!";
+    var ERROR_MESSAGE_NOT_INSTANCE_DEVICE = "USBKey实例化失败,请确认此UKey是否插入计算机!\n点击‘刷新’按钮,更新设备列表。\n错误码:";
+    var ERROR_MESSAGE_USERPIN_LENGTH = "Ukey密码必须为4~16位!";
+    var ERROR_MESSAGE_USERPIN_IS_ERROR = "UKey密码错误";
+    var ERROR_MESSAGE_USERPIN_CHANGE_ERROR = "UKey密码修改失败";
+    var ERROR_MESSAGE_KEY_NOT_EXIT = "UKey不存在,请确认此UKey是否插入计算机,并点击'刷新'按钮,更新设备列表!";
+    var ERROR_MESSAGE_USERNAME_IS_NULL = "请点击‘刷新’按钮,更新设备列表并选择相应设备!";
+    var ERROR_MESSAGE_KEY_EXPORT_CERT = "证书获取失败,请加检测Key中是否存在证书!";
+    var ERROR_MESSAGE_SET_DIGEST_METHOD_ERROR = "设置摘要算法失败,请重新刷新浏览器!";
+    var ERROR_MESSAGE_SET_USERID_ERROR = "设置用户ID失败,请重新刷新浏览器";
+    var ERROR_MESSAGE_SIGN_ORIGINALDATA_IS_NULL = "签名失败,待签名原文不能为空";
+    var ERROR_MESSAGE_SIGN_ERROR = "签名失败,返回错误码:";
+    var ERROR_MESSAGE_USERNAMEGN_IS_NULL = "请点击‘刷新’按钮,更新设备列表并选择相应设备!";
+    var ERROR_MESSAGE_USERNAMEGN_TO_USERNAME_ERROR = "证书G项信息转化证书名称失败,请点击“刷新”按钮!";
+    var ERROR_MESSAGE_KEY_LIBRAY = "加载国密库失败!";
+    var ERROR_MESSAGE_ENCRYPT_DATA_IS_NULL = "加密失败:待加密原文不能为空!";
+    var ERROR_MESSAGE_DECRYPT_DATA_IS_NULL = "解密失败:待解密密文不能为空!";
+    var ERROR_MESSAGE_DECRYPT_DATA_IS_ERROR = "解密失败:请确认密文是否完整!\n解密所采用的Ukey是否为加密时的Ukey!";
+    var ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_FAIL = "申请解锁请求失败!";
+    var ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_NOT_SUPPORT = "此型号Ukey不支持解锁!";
+    var ERROR_MESSAGE_REMOTE_UNLOCK_FAIL = "Ukey解锁失败!";
+
+    /**
+     * 私有变量
+     */
+    var tokenInfoList = null;
+
+    /**
+     * 私有变量
+     */
+    var signResultSignData = null;
+    var signResultCert = null;
+
+    /**
+     * 证书信息
+     */
+    var certSn = null; //证书Sn
+    var cert_subject_GN = null; //证书Gn
+    var cert_subject = null; //证书使用者
+    var cert_validTime = null;    //证书失效时间
+    var cert_notbeforetime = null;   //证书生效时间
+
+    /**
+     * 返回错误信息
+     */
+    this.Hunca_GetLastError = function () {
+        return LAST_ERRORSTRING;
+    }
+
+    /**
+     * 获取证书列表
+     */
+    this.Hunca_GetUserList = function () {
+        var deviceArray = null;
+        var containerName = null;
+        var userName = null;
+        var tmpInfo = null;
+
+        signResultCert = null;
+        signResultSignData = null;
+        tokenInfoList = new Array(); //清空信息
+
+        for (var index = 0; index < libraryNameList.length; index++) {
+            libraryName = libraryNameList[index];
+            if (!SOF_LoadLibrary(libraryName)) {
+                continue;
+            }
+
+            deviceArray = SOF_EnumDevice();
+            if (null == deviceArray) {
+                continue;
+            }
+
+            for (var i = 0; i < deviceArray.length; i++) {
+                var tokenInfo = new Object();
+                //实例化设备失败
+                if (!SOF_GetDeviceInstance(deviceArray[i])) {
+                    break;
+                }
+
+                //获取设备信息
+                tmpInfo = SOF_GetUserList();
+                if (null != tmpInfo || tmpInfo.length != 0) {
+                    containerName = tmpInfo[0][1];
+                    userName = tmpInfo[0][0];
+
+                    tokenInfo.libraryName = libraryName; //Ukey型号
+                    tokenInfo.serial = deviceArray[i]; //设备序列号
+                    tokenInfo.userName = userName; //证书名称
+                    tokenInfo.containerName = containerName; //应用名称
+
+                    tokenInfoList.push(tokenInfo);
+                } else {
+                    continue;
+                }
+                SOF_LogOut();
+            }
+        }
+
+        //返回证书信息
+        var userNameList = new Array();
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            userNameList[i] = tokenInfoList[i].userName;
+        }
+
+        if (userNameList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return "";
+        }
+
+        return userNameList;
+    }
+
+    /**
+     * 获取证书G项信息列表
+     */
+    this.Hunca_GetUserListGN = function () {
+        var deviceArray = null;
+        var containerName = null;
+        var userName = null;
+        var tmpInfo = null;
+        var certB64 = null;
+        var deviceSerial = "";
+
+        signResultCert = null;
+        signResultSignData = null;
+        tokenInfoList = new Array(); //清空信息
+        LAST_ERRORSTRING = "";
+
+        for (var index = 0; index < libraryNameList.length; index++) {
+            libraryName = libraryNameList[index];
+            //加载控件
+            if (!SOF_LoadLibrary(libraryName)) {
+                continue;
+            }
+
+            deviceArray = SOF_EnumDevice();
+            if (null == deviceArray) {
+                continue;
+            }
+
+            for (var i = 0; i < deviceArray.length; i++) {
+                cert_subject_GN = null;
+                certSn = null;
+                deviceSerial = deviceArray[i];
+
+                var tokenInfo = new Object();
+
+                //实例化设备失败
+                if (!SOF_GetDeviceInstance(deviceSerial)) {
+                    break;
+                }
+
+                //获取设备信息
+                tmpInfo = SOF_GetUserList();
+                if (null != tmpInfo || tmpInfo.length != 0) {
+                    containerName = tmpInfo[0][1];
+                    userName = tmpInfo[0][0];
+
+                    tokenInfo.libraryName = libraryName;
+                    tokenInfo.serial = deviceArray[i]; //设备序列号
+                    tokenInfo.userName = userName; //证书名称
+                    tokenInfo.containerName = containerName;
+                } else {
+                    continue;
+                }
+
+                //获取证书G项信息
+                certB64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_SIGN);
+                if (SOF_GetCertInfo(certB64)) {
+                    tokenInfo.subjectGN = cert_subject_GN; //设备证书G项目;
+                } else {
+                    continue;
+                }
+
+                tokenInfoList.push(tokenInfo);
+                SOF_LogOut();
+            }
+        }
+
+        //返回证书G项信息
+        var userNameGNList = new Array();
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            userNameGNList[i] = tokenInfoList[i].subjectGN;
+        }
+
+        if (userNameGNList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return "";
+        }
+
+	/*****
+        if (userNameGNList.length > 1){
+            LAST_ERRORSTRING = ERROR_MSSSAGE_FIND_MORE_UKEY;
+            return "";
+        }
+	****/
+        return userNameGNList;
+    }
+
+    /**
+     * 将证书G项信息转化为证书名称
+     */
+    this.Hunca_userNameGNToUserName = function (userNameGN) {
+        var userName = null;
+        LAST_ERRORSTRING = "";
+        if (null == userNameGN || userNameGN.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAMEGN_IS_NULL;
+        }
+
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            if (userNameGN == tokenInfoList[i].subjectGN) {
+                userName = tokenInfoList[i].userName;
+                break;
+            }
+        }
+
+        if (null == userName || userName.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAMEGN_TO_USERNAME_ERROR;
+            return null;
+        }
+        return userName;
+    }
+
+    this.Hunca_GenRemoteUnblockRequest = function (userName) {
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        var request = "";
+
+        LAST_ERRORSTRING = "";
+
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return false;
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return false;
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return false;
+        }
+
+        //判断设备是否支持远程解锁
+        if (tokenInfo.libraryName != "GM3000") {
+            LAST_ERRORSTRING = ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_NOT_SUPPORT;
+            return false;
+        }
+
+        //加载库文件
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+            return false;
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return false;
+        }
+
+        //枚举容器,并选择第一个容器
+        if (SOF_GetUserList() == null) {
+            return false;
+        }
+
+        //远程解锁
+        request = SOF_GenRemoteUnblockRequest()
+
+        return request;
+    }
+
+    this.HUnca_GetDeviceNumber = function(userName){
+        var m_devNumber = null;
+
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return false;
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return false;
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return false;
+        }
+
+          //加载库文件
+          if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+            return false;
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return false;
+        }
+        m_devNumber =SOF_GetDeviceNumber();
+
+        return m_devNumber + "";
+    }
+
+    this.Hunca_RemoteUnlockPIN = function (userName, response) {
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        var result = false;
+
+        LAST_ERRORSTRING = "";
+
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return false;
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return false;
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return false;
+        }
+
+        //判断设备是否支持远程解锁
+        if (tokenInfo.libraryName != "GM3000") {
+            LAST_ERRORSTRING = ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_NOT_SUPPORT;
+            return false;
+        }
+
+        //加载库文件
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+            return false;
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return false;
+        }
+
+        //枚举容器,并选择第一个容器
+        if (SOF_GetUserList() == null) {
+            return false;
+        }
+
+        //远程解锁
+        result = SOF_RemoteUnlockPIN(response)
+        return result;
+    }
+
+    /**
+     * 修改Ukey密码
+     */
+    this.Hunca_ChangeUserPin = function (userName, oldUserPin, newUserPin) {
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        LAST_ERRORSTRING = "";
+
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return false;
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return false;
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return false;
+        }
+
+        //加载库文件
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return false;
+        }
+
+        //修改密码
+        if (!SOF_ChangeUserPin(oldUserPin, newUserPin)) {
+            return false;
+        }
+
+        SOF_LogOut();
+        return true;
+    }
+
+    /**
+     * 对数据进行签名,并返回签名是否成功
+     * @param {string} originalData 待签名原文
+     * @param {string} userName Ukey用户名称
+     * @param {string} userPin Ukey密码
+     */
+    this.Hunca_PKCS1 = function (originalData, userName, userPin) {
+        var libraryName = null;
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        var certBase64 = null; //签名证书值
+
+        LAST_ERRORSTRING = "";
+        signResultInfo = null;
+        certInfo = new Object();
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return false;
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return false;
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return false;
+        }
+
+        //加载库文件
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return false;
+        }
+
+        //登陆应用
+        if (!SOF_Login(userPin)) {
+            return false;
+        }
+
+        //获取签名证书Base64
+        certBase64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_SIGN);
+        if (null == certBase64) {
+            return false;
+        }
+
+        //设置摘要算法
+        if (!SOF_SetDigestMethod(SGD_SM3)) {
+            return false;
+        }
+
+        if (!SOF_SetUserID()) {
+            return false;
+        }
+
+        //进行签名
+        if (!SOF_SignData(tokenInfo.containerName, SGD_SM3, originalData, certBase64)) {
+            return false;
+        }
+
+        //获取证书信息
+        if (!SOF_GetCertInfo(certBase64)) {
+            return false;
+        }
+
+        SOF_LogOut();
+        return true;
+    }
+
+    /**
+     * 获取签名结果
+     */
+    this.Hunca_GetSignData = function () {
+        return signResultSignData;
+    }
+
+    /**
+     * 获取签名证书
+     */
+    this.Hunca_GetSignCert = function () {
+        return signResultCert;
+    }
+
+    this.Hunca_GetSignCertSn = function () {
+        return certSn
+    }
+
+    this.Hunca_GetSignCertSubject = function (){
+        return cert_subject;
+    }
+
+    this.Hunca_GetValidTime = function(){
+        return cert_validTime;
+    }
+
+    this.HUnca_GetNotBeforeTime = function(){
+        return cert_notbeforetime;
+    }
+    /**
+     * 处理设备中签名证书信息
+     * @param {*} userName 
+     */
+    this.Hunca_DealCertInfo = function (userName) {
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        var certBase64 = null; //签名证书值
+
+        LAST_ERRORSTRING = "";
+        signResultInfo = null;
+        certInfo = new Object();
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return false;
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return false;
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return false;
+        }
+
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+            return false;
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return false;
+        }
+
+        //导出证书
+        certBase64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_SIGN);
+        if (null == certBase64 || certBase64.length == 0) {
+            return false;
+        }
+
+        SOF_GetCertInfo(certBase64);
+        SOF_LogOut();
+        return true;
+    }
+
+    /**
+     * 对数据进行数字信封加密
+     * @param {string} inData 待加密原文
+     * @param {string} userName Ukey用户名称
+     * @param {string} EncryptMethod 对称加密方式
+     * @param {string} EncryptIV 加密IV值
+     * @returns {string} "",加密失败;非空,加密成功
+     */
+    this.Hunca_EncryptDataPKCS7 = function (inData, userName, EncryptMethod, EncryptIV) {
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        var certBase64 = null; //签名证书值
+        var m_EncryptMethod = "",
+            m_EncryptIV = "";
+
+        LAST_ERRORSTRING = "";
+        signResultInfo = null;
+        certInfo = new Object();
+
+
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return "";
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return "";
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return "";
+        }
+
+        //加载链接库
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+            return "";
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return "";
+        }
+
+        //导出加密证书
+        certBase64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_ENCRYPT);
+        if (null == certBase64 || certBase64.length == 0) {
+            return "";
+        }
+
+        //设置加密方式
+
+        m_EncryptMethod = EncryptMethod + "";
+        m_EncryptIV = EncryptIV + "";
+
+        if (m_EncryptMethod == null || m_EncryptMethod.length == 0) {
+            m_EncryptMethod = SGD_SM4_ECB;
+            m_EncryptIV = "";
+        }
+
+        if (!SOF_SetEncryptMethodAndIV(m_EncryptMethod, m_EncryptIV)) {
+            return "";
+        }
+
+        //对数据进行加密
+        encryptData = SOF_EncryptDataPKCS7(certBase64, inData);
+
+        SOF_LogOut();
+
+        return encryptData;
+    }
+
+    /**
+     * 对密文进行数字信封解密操作
+     * @param {string}  encryptData 待解密密文
+     * @param {string}  userName Ukey用户名称
+     * @param {string}  userPin Ukey用户PIN码
+     * @param {string}  EncryptMethod 对称加密方式
+     * @param {string}  EncryptIV 加密IV值
+     * @returns {string} "",加密失败;非空,加密成功
+     */
+    this.Hunca_DecryptDataPKCS7 = function (encryptData, userName, userPin, EncryptMethod, EncryptIV) {
+        var tokenInfo = null; //Ukey设备信息
+        var tempTokenInfo = null; //临时设备信息,循环遍历用
+        var m_EncryptMethod = "",
+            m_EncryptIV = "";
+        var m_EncryptData = "";
+        var m_DecryptData = "";
+        var resData = "";
+
+        LAST_ERRORSTRING = "";
+        signResultInfo = null;
+        certInfo = new Object();
+
+
+        m_EncryptData = "" + encryptData;
+        //设备名称为空
+        if (null == userName || userName.length == null) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
+            return "";
+        }
+
+        //查找匹配的设备序列号
+        if (null == tokenInfoList || tokenInfoList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return "";
+        }
+
+        //索引设备编号
+        for (var i = 0; i < tokenInfoList.length; i++) {
+            tempTokenInfo = tokenInfoList[i];
+            if (tempTokenInfo.userName == userName) {
+                tokenInfo = tempTokenInfo;
+                break;
+            }
+        }
+
+        //如果所选择的设备不存在
+        if (null == tokenInfo) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
+            return "";
+        }
+
+        //加载链接库
+        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
+            return "";
+        }
+
+        //实例化设备
+        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
+            return "";
+        }
+
+        //登陆应用
+        if (!SOF_Login(userPin)) {
+            return "";
+        }
+
+        //设置加密方式
+        m_EncryptMethod = EncryptMethod + "";
+        m_EncryptIV = EncryptIV + "";
+        if (m_EncryptMethod == null || m_EncryptMethod.length == 0) {
+            m_EncryptMethod = SGD_SM4_ECB;
+            m_EncryptIV = "";
+        }
+
+        if (!SOF_SetEncryptMethodAndIV(m_EncryptMethod, m_EncryptIV)) {
+            return "";
+        }
+
+        m_DecryptData = SOF_DecryptDataPKCS7(tokenInfo.containerName, KEY_SPEC_TYPE_ENCRYPT, m_EncryptData);
+        if (m_DecryptData.length == 0) {
+            return "";
+        }
+
+        try {
+            resData = _Base64decode(m_DecryptData);
+        } catch (e) {
+            resData = m_DecryptData;
+            LAST_ERRORSTRING = "解密失败:Base64解码失败";
+        }
+
+        return resData;
+    }
+
+    /**
+     * 加载底层文件
+     * @returns {boolean} true,加载成功;false加载失败;
+     */
+    function SOF_LoadLibrary(libraryName) {
+        var resultCode = 0;
+        if (libraryName == "GM3000") {
+            resultCode = token.SOF_LoadLibrary(token.GM3000);
+        } else if (libraryName == "GM3000_HUNCA"){
+            resultCode = token.SOF_LoadLibrary(token.GM3000_HUNCA);
+        }
+		else if (libraryName == "HT"){
+			resultCode = token.SOF_LoadLibrary(token.HT);
+		}
+		else if (libraryName == "SJK1137") {
+            resultCode = token.SOF_LoadLibrary(token.SJK1137);
+        }
+
+        if (resultCode != 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_LOADLIBRARY + token.SOF_GetLastError();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 枚举设备
+     */
+    function SOF_EnumDevice() {
+        var deviceNameList = "";
+
+        deviceNameList = token.SOF_EnumDevice();
+
+        //检测是否插入USBKey
+        if (null == deviceNameList || deviceNameList.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
+            return null;
+        }
+
+        return deviceNameList;
+    }
+
+    /**
+     * 实例化设备,为后续一系列操作准备
+     * @param {string} deviceName 设备名称
+     */
+    function SOF_GetDeviceInstance(deviceName) {
+        var resultCode = 0;
+
+        resultCode = token.SOF_GetDeviceInstance(deviceName, "");
+        //设备未正常实例化
+        if (resultCode != 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_INSTANCE_DEVICE + token.SOF_GetLastError();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 枚举应用中的容器
+     */
+    function SOF_GetUserList() {
+        var userList = "";
+
+        userList = token.SOF_GetUserList();
+        if (null == userList || userList.length == 0) {
+            LAST_ERRORSTRING = "USBkey中未找到证书!";
+            return null;
+        }
+
+        return userList;
+    }
+
+    /**
+     * 登陆应用,验证密码是否正确
+     * @param {string} userPin 
+     */
+    function SOF_Login(userPin) {
+        var resultCode = 0;
+        var m_userPin = "" + userPin;
+        var RetryCount = 0;
+
+        if (null == m_userPin || m_userPin.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
+            return false;
+        }
+
+        if (m_userPin.length < 4 || m_userPin.length > 16) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
+            return false;
+        }
+
+        resultCode = token.SOF_Login(m_userPin);
+        if (resultCode != 0) {
+            RetryCount = SOF_GetPinRetryCount();
+            if (RetryCount > 0) {
+                LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_IS_ERROR + ",还剩 " + RetryCount + " 次重试机会!";
+            } else {
+                LAST_ERRORSTRING = "UKey已经锁死,请联系管理员进行解锁!"
+            }
+            return false;
+        }
+        return true
+    }
+
+    /**
+     * 修改UKey密码
+     * @param {*} oldUserPin 
+     * @param {*} newUserPin 
+     */
+    function SOF_ChangeUserPin(oldUserPin, newUserPin) {
+        var resultCode = 0;
+        var m_oldUserPin = "" + oldUserPin;
+        var m_newUserPin = "" + newUserPin;
+        var RetryCount = 0;
+
+        if (null == m_oldUserPin || m_oldUserPin.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
+            return false;
+        }
+
+        if (null == m_newUserPin || m_newUserPin.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
+            return false;
+        }
+
+        if (m_oldUserPin.length < 4 || m_oldUserPin.length > 16) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
+            return false;
+        }
+
+        if (m_newUserPin.length < 4 || m_newUserPin.length > 16) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
+            return false;
+        }
+
+        resultCode = token.SOF_ChangePassWd(m_oldUserPin, m_newUserPin);
+        if (resultCode != 0) {
+            RetryCount = SOF_GetPinRetryCount();
+            if (RetryCount > 0) {
+                LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_CHANGE_ERROR + ",还剩 " + RetryCount + " 次重试机会!";
+            } else {
+                LAST_ERRORSTRING = "UKey已经锁死,请联系管理员进行解锁!"
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 返回重试次数
+     */
+    function SOF_GetPinRetryCount() {
+        var retryCount = 0;
+        retryCount = token.SOF_GetPinRetryCount();
+        return retryCount;
+    }
+
+    function SOF_GetDeviceNumber(){
+        var deviceNumber = null;
+        deviceNumber = token.SOF_GetDeviceInfo(token.SGD_DEVICE_SERIAL_NUMBER);
+        return deviceNumber;
+    }
+
+    /**
+     * 导出证书值
+     * @param {string} containerName 容器名称
+     * @param {int} keySec 证书用途 
+     */
+    function SOF_ExportUserCert(containerName, keySec) {
+        var certBase64;
+        certBase64 = token.SOF_ExportUserCert(containerName, keySec);
+        if (null == certBase64 || certBase64.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_EXPORT_CERT;
+            return null;
+        }
+        return certBase64;
+    }
+
+    /**
+     * 设置加密算法
+     * @param {*} EncryptMethod    设置加密算法
+     * @param {*} EncryptIV 设置IV值
+     */
+    function SOF_SetEncryptMethodAndIV(EncryptMethod, EncryptIV) {
+        var resCode = 1;
+
+        if (EncryptMethod == undefined || EncryptMethod == null) {
+            LAST_ERRORSTRING = "请设置加密方式!";
+            return false;
+        }
+
+        resCode = token.SOF_SetEncryptMethodAndIV(EncryptMethod, _Base64encode(EncryptIV));
+        if (resCode != 0) {
+            LAST_ERRORSTRING = token.SOF_GetLastError();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 设置签名算法
+     * @param {}} digestMethod 
+     */
+    function SOF_SetDigestMethod(digestMethod) {
+        var resultCode = 0;
+        resultCode = token.SOF_SetDigestMethod(digestMethod);
+        if (resultCode != 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_SET_DIGEST_METHOD_ERROR;
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 设置默认USERID
+     */
+    function SOF_SetUserID() {
+        var resultCode = 0;
+        resultCode = token.SOF_SetUserID(USER_ID);
+        if (resultCode != 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_SET_USERID_ERROR;
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 数字信封加密
+     * @param {String} Base64EncodeCert 加密证书值
+     * @param {String} inData 待加密原文
+     * @returns {*} "",表示加密失败;非空,加密成功
+     */
+    function SOF_EncryptDataPKCS7(Base64EncodeCert, inData) {
+        var encryptData = "";
+        var inDataBase64 = "";
+        var m_inData = "";
+
+        m_inData = "" + inData;
+        if (m_inData.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_ENCRYPT_DATA_IS_NULL;
+            return "";
+        }
+
+        inDataBase64 = _Base64encode(m_inData)
+        encryptData = token.SOF_EncryptDataPKCS7(Base64EncodeCert, inDataBase64, inData.length);
+
+        if (encryptData == null || encryptData.length == 0) {
+            LAST_ERRORSTRING = "加密失败," + token.SOF_GetLastError();
+            return "";
+        }
+        return encryptData;
+    }
+
+    /**
+     * 数字信封解密
+     * @param {*} containerName 应用名称
+     * @param {int} cerType 
+     * @param {*} encrypedData 
+     */
+    function SOF_DecryptDataPKCS7(containerName, cerType, encrypedData) {
+        var m_EncrypedData = "",
+            m_DecryptData = "";
+
+        m_EncrypedData = "" + encrypedData;
+        if (containerName == null || containerName.length == 0) {
+            LAST_ERRORSTRING = "应用名称不能为空!";
+            return "";
+        }
+
+        if (m_EncrypedData.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_DECRYPT_DATA_IS_NULL;
+            return "";
+        }
+
+        try {
+            m_DecryptData = token.SOF_DecryptDataPKCS7(containerName, cerType, m_EncrypedData);
+        } catch (e) {
+            m_DecryptData = "";
+        }
+        if (undefined == m_DecryptData || m_DecryptData == null || m_DecryptData == "") {
+            LAST_ERRORSTRING = ERROR_MESSAGE_DECRYPT_DATA_IS_ERROR;
+            return "";
+        }
+
+        return m_DecryptData;
+    }
+
+    /**
+     * 数据签名
+     * @param {*} containerName 
+     * @param {*} ulKeySpec 
+     * @param {*} data 
+     * @param {*} certBase64 
+     */
+    function SOF_SignData(containerName, ulKeySpec, data, certBase64) {
+        var signData = null;
+        var b64Data = null;
+        var m_data = "" + data;
+
+
+        if (null == m_data || m_data.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_SIGN_ORIGINALDATA_IS_NULL;
+            return false;
+        }
+
+        b64Data = _Base64encode(m_data);
+        signData = token.SOF_SignData(containerName, ulKeySpec, _Base64encode(b64Data), b64Data.length)
+        if (null == signData || signData.length == 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_SIGN_ERROR + SOF_GetLastError();
+            return false;
+        }
+
+        signResultCert = certBase64;
+        signResultSignData = signData;
+
+        return true;
+    }
+
+    /**
+     * 导出证书
+     * @param {*} certBase64 
+     */
+    function SOF_GetCertInfo(certBase64) {
+        var str = null;
+        var subject = null;
+        var tmpList = null;
+        var validTime = null;
+        var notBeforetime = null;
+        var key, value;
+
+        if (null == certBase64 || certBase64.length == 0) {
+            return false;
+        }
+
+        cert_subject_GN = "";
+        certSn = "";
+        cert_subject = "";
+
+        str = token.SOF_GetCertInfo(certBase64, token.SGD_CERT_SERIAL);
+        certSn = hexToDec(str);
+
+        subject = token.SOF_GetCertInfo(certBase64, token.SGD_CERT_SUBJECT);
+        cert_subject = subject;
+
+        validTime = token.SOF_GetCertInfo(certBase64,token.SGD_CERT_VALID_TIME);
+        cert_validTime = validTime;
+
+        notBeforetime = token.SOF_GetCertInfo(certBase64,token.SGD_CERT_NOT_BEFORE);
+        cert_notbeforetime = notBeforetime;
+        
+        tmpList = subject.split(',');
+        for (var i = 0; i < tmpList.length; i++) {
+            if (tmpList[i].indexOf("=") == -1) {
+                continue;
+            }
+
+            key = tmpList[i].split('=')[0];
+            value = tmpList[i].split('=')[1];
+
+            if (key == 'GN') {
+                cert_subject_GN = value;
+                break;
+            }
+        }
+        return true;
+    }
+
+
+
+    /**
+     * 登出UKey
+     */
+    function SOF_LogOut() {
+        token.SOF_LogOut();
+    }
+
+    /**
+     * 生成解锁请求
+     */
+    function SOF_GenRemoteUnblockRequest() {
+        var request = token.SOF_GenRemoteUnblockRequest();
+        if (request == null || request == "") {
+            LAST_ERRORSTRING = ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_FAIL;
+            return "";
+        }
+
+        return request;
+    }
+
+    function SOF_RemoteUnlockPIN(response) {
+        var result = false;
+
+        if (null == response || response.length == 0) {
+            LAST_ERRORSTRING = "解锁失败解:响应不能为空!";
+            return false;
+        }
+
+        result = token.SOF_RemoteUnblockPIN(response);
+        if (result != 0) {
+            LAST_ERRORSTRING = ERROR_MESSAGE_REMOTE_UNLOCK_FAIL;
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    function add(x, y, base) {
+        var z = [];
+        var n = Math.max(x.length, y.length);
+        var carry = 0;
+        var i = 0;
+        while (i < n || carry) {
+            var xi = i < x.length ? x[i] : 0;
+            var yi = i < y.length ? y[i] : 0;
+            var zi = carry + xi + yi;
+            z.push(zi % base);
+            carry = Math.floor(zi / base);
+            i++;
+        }
+        return z;
+    }
+
+    function multiplyByNumber(num, x, base) {
+        if (num < 0) return null;
+        if (num == 0) return [];
+
+        var result = [];
+        var power = x;
+        while (true) {
+            if (num & 1) {
+                result = add(result, power, base);
+            }
+            num = num >> 1;
+            if (num === 0) break;
+            power = add(power, power, base);
+        }
+
+        return result;
+    }
+
+    function parseToDigitsArray(str, base) {
+        var digits = str.split('');
+        var ary = [];
+        for (var i = digits.length - 1; i >= 0; i--) {
+            var n = parseInt(digits[i], base);
+            if (isNaN(n)) return null;
+            ary.push(n);
+        }
+        return ary;
+    }
+
+
+    function convertBase(str, fromBase, toBase) {
+        var digits = parseToDigitsArray(str, fromBase);
+        if (digits === null) return null;
+
+        var outArray = [];
+        var power = [1];
+        for (var i = 0; i < digits.length; i++) {
+            // invariant: at this point, fromBase^i = power
+            if (digits[i]) {
+                outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase);
+            }
+            power = multiplyByNumber(fromBase, power, toBase);
+        }
+
+        var out = '';
+        for (var i = outArray.length - 1; i >= 0; i--) {
+            out += outArray[i].toString(toBase);
+        }
+        return out;
+    }
+
+    function decToHex(decStr) {
+        var hex = convertBase(decStr, 10, 16);
+        return hex ? '0x' + hex : null;
+    }
+
+
+    function hexToDec(hexStr) {
+        if (hexStr.substring(0, 2) === '0x') hexStr = hexStr.substring(2);
+        hexStr = hexStr.toLowerCase();
+        return convertBase(hexStr, 16, 10);
+    }
+}

+ 4173 - 0
mPlugin-js/js/mTokenPlugin/mToken.js

@@ -0,0 +1,4173 @@
+/******************************************************* 
+* 
+* 使用此JS脚本之前请先仔细阅读帮助文档! 
+* 
+* @author longmai 
+* @version 4.1.22.0915
+* @date 2022/9/15 
+* 
+**********************************************************/
+
+
+
+var split;
+
+var _curDevName = "";
+var separatorExp;
+// Avoid running twice; that would break the `nativeSplit` reference
+split = split || function (undef) {
+
+    var nativeSplit = String.prototype.split,
+        compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group
+        self;
+
+    self = function (str, separator, limit) {
+        // If `separator` is not a regex, use `nativeSplit`
+        if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
+            return nativeSplit.call(str, separator, limit);
+        }
+        var output = [],
+            flags = (separator.ignoreCase ? "i" : "") +
+                (separator.multiline ? "m" : "") +
+                (separator.extended ? "x" : "") + // Proposed for ES6
+                (separator.sticky ? "y" : ""), // Firefox 3+
+            lastLastIndex = 0,
+            // Make `global` and avoid `lastIndex` issues by working with a copy
+            separatorExp = new RegExp(separator.source, flags + "g"),
+            separator2, match, lastIndex, lastLength;
+        str += ""; // Type-convert
+        if (!compliantExecNpcg) {
+            // Doesn't need flags gy, but they don't hurt
+            separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
+        }
+        /* Values for `limit`, per the spec:
+         * If undefined: 4294967295 // Math.pow(2, 32) - 1
+         * If 0, Infinity, or NaN: 0
+         * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
+         * If negative number: 4294967296 - Math.floor(Math.abs(limit))
+         * If other: Type-convert, then use the above rules
+         */
+        limit = limit === undef ?
+            -1 >>> 0 : // Math.pow(2, 32) - 1
+            limit >>> 0; // ToUint32(limit)
+        while (match = separatorExp.exec(str)) {
+            // `separator.lastIndex` is not reliable cross-browser
+            lastIndex = match.index + match[0].length;
+            if (lastIndex > lastLastIndex) {
+                output.push(str.slice(lastLastIndex, match.index));
+                // Fix browsers whose `exec` methods don't consistently return `undefined` for
+                // nonparticipating capturing groups
+                if (!compliantExecNpcg && match.length > 1) {
+                    match[0].replace(separator2, function () {
+                        for (var i = 1; i < arguments.length - 2; i++) {
+                            if (arguments[i] === undef) {
+                                match[i] = undef;
+                            }
+                        }
+                    });
+                }
+                if (match.length > 1 && match.index < str.length) {
+                    Array.prototype.push.apply(output, match.slice(1));
+                }
+                lastLength = match[0].length;
+                lastLastIndex = lastIndex;
+                if (output.length >= limit) {
+                    break;
+                }
+            }
+            if (separatorExp.lastIndex === match.index) {
+                separatorExp.lastIndex++; // Avoid an infinite loop
+            }
+        }
+        if (lastLastIndex === str.length) {
+            if (lastLength || !separatorExp.test("")) {
+                output.push("");
+            }
+        } else {
+            output.push(str.slice(lastLastIndex));
+        }
+        return output.length > limit ? output.slice(0, limit) : output;
+    };
+
+    // For convenience
+    String.prototype.split = function (separator, limit) {
+        return self(this, separator, limit);
+    };
+
+    return self;
+
+}();
+
+
+function mToken(obj) {
+    this.obj = obj;
+
+    this.SAR_OK = 0;
+    this.SAR_FALSE = 1;
+
+    //分组加密算法标识
+    this.SGD_SM1_ECB = 0x00000101;
+    this.SGD_SM1_CBC = 0x00000102;
+    this.SGD_SM1_CFB = 0x00000104;
+    this.SGD_SM1_OFB = 0x00000108;
+    this.SGD_SM1_MAC = 0x00000110;
+    this.SGD_SSF33_ECB = 0x00000201;
+    this.SGD_SSF33_CBC = 0x00000202;
+    this.SGD_SSF33_CFB = 0x00000204;
+    this.SGD_SSF33_OFB = 0x00000208;
+    this.SGD_SSF33_MAC = 0x00000210;
+    this.SGD_SM4_ECB = 0x00000401;
+    this.SGD_SM4_CBC = 0x00000402;
+    this.SGD_SM4_CFB = 0x00000404;
+    this.SGD_SM4_OFB = 0x00000408;
+    this.SGD_SM4_MAC = 0x00000410;
+
+    this.SGD_VENDOR_DEFINED = 0x80000000;
+    this.SGD_DES_ECB = this.SGD_VENDOR_DEFINED + 0x00000211
+    this.SGD_DES_CBC = this.SGD_VENDOR_DEFINED + 0x00000212
+
+    this.SGD_3DES168_ECB = this.SGD_VENDOR_DEFINED + 0x00000241
+    this.SGD_3DES168_CBC = this.SGD_VENDOR_DEFINED + 0x00000242
+
+    this.SGD_3DES112_ECB = this.SGD_VENDOR_DEFINED + 0x00000221
+    this.SGD_3DES112_CBC = this.SGD_VENDOR_DEFINED + 0x00000222
+
+    this.SGD_AES128_ECB = this.SGD_VENDOR_DEFINED + 0x00000111
+    this.SGD_AES128_CBC = this.SGD_VENDOR_DEFINED + 0x00000112
+
+    this.SGD_AES192_ECB = this.SGD_VENDOR_DEFINED + 0x00000121
+    this.SGD_AES192_CBC = this.SGD_VENDOR_DEFINED + 0x00000122
+
+    this.SGD_AES256_ECB = this.SGD_VENDOR_DEFINED + 0x00000141
+    this.SGD_AES256_CBC = this.SGD_VENDOR_DEFINED + 0x00000142
+
+
+    //非对称密码算法标识
+    this.SGD_RSA = 0x00010000;
+    this.SGD_SM2_1 = 0x00020100; //ECC签名
+    this.SGD_SM2_2 = 0x00020200; //ECC密钥交换
+    this.SGD_SM2_3 = 0x00020400; //ECC加密
+
+    //密码杂凑算法标识
+    this.SGD_SM3 = 0x00000001;
+    this.SGD_SHA1 = 0x00000002;
+    this.SGD_SHA256 = 0x00000004;
+    this.SGD_RAW = 0x00000080;
+    this.SGD_MD5 = 0x00000081;
+    this.SGD_SHA384 = 0x00000082;
+    this.SGD_SHA512 = 0x00000083;
+
+
+    this.SGD_CERT_VERSION = 0x00000001;
+    this.SGD_CERT_SERIAL = 0x00000002;
+    this.SGD_CERT_ISSUE = 0x00000005;
+    this.SGD_CERT_VALID_TIME = 0x00000006;
+    this.SGD_CERT_SUBJECT = 0x00000007;
+    this.SGD_CERT_DER_PUBLIC_KEY = 0x00000008;
+    this.SGD_CERT_DER_EXTENSIONS = 0x00000009;
+    this.SGD_CERT_NOT_BEFORE = 0x00000010;
+    this.SGD_CERT_ISSUER_CN = 0x00000021;
+    this.SGD_CERT_ISSUER_O = 0x00000022;
+    this.SGD_CERT_ISSUER_OU = 0x00000023;
+    this.SGD_CERT_ISSUER_C = 0x00000024;
+    this.SGD_CERT_ISSUER_P = 0x00000025;
+    this.SGD_CERT_ISSUER_L = 0x00000026;
+    this.SGD_CERT_ISSUER_S = 0x00000027;
+    this.SGD_CERT_ISSUER_EMAIL = 0x00000028;
+
+    this.SGD_CERT_SUBJECT_CN = 0x00000031;
+    this.SGD_CERT_SUBJECT_O = 0x00000032;
+    this.SGD_CERT_SUBJECT_OU = 0x00000033;
+    this.SGD_CERT_SUBJECT_EMALL = 0x00000034;
+    this.SGD_REMAIN_TIME = 0x00000035;
+    this.SGD_SIGNATURE_ALG = 0x00000036;
+    this.SGD_CERT_SUBJECT_C = 0x00000037;
+    this.SGD_CERT_SUBJECT_P = 0x00000038;
+    this.SGD_CERT_SUBJECT_L = 0x00000039;
+    this.SGD_CERT_SUBJECT_S = 0x0000003A;
+
+    this.SGD_CERT_CRL = 0x00000041;
+
+
+    this.SGD_DEVICE_SORT = 0x00000201;
+    this.SGD_DEVICE_TYPE = 0x00000202;
+    this.SGD_DEVICE_NAME = 0x00000203;
+    this.SGD_DEVICE_MANUFACTURER = 0x00000204;
+    this.SGD_DEVICE_HARDWARE_VERSION = 0x00000205;
+    this.SGD_DEVICE_SOFTWARE_VERSION = 0x00000206;
+    this.SGD_DEVICE_STANDARD_VERSION = 0x00000207;
+    this.SGD_DEVICE_SERIAL_NUMBER = 0x00000208;
+    this.SGD_DEVICE_SUPPORT_SYM_ALG = 0x00000209;
+    this.SGD_DEVICE_SUPPORT_ASYM_ALG = 0x0000020A;
+    this.SGD_DEVICE_SUPPORT_HASH_ALG = 0x0000020B;
+    this.SGD_DEVICE_SUPPORT_STORANGE_SPACE = 0x0000020C;
+    this.SGD_DEVICE_SUPPORT_FREE_SAPCE = 0x0000020D;
+    this.SGD_DEVICE_RUNTIME = 0x0000020E;
+    this.SGD_DEVICE_USED_TIMES = 0x0000020F;
+    this.SGD_DEVICE_LOCATION = 0x00000210;
+    this.SGD_DEVICE_DESCRIPTION = 0x00000211;
+    this.SGD_DEVICE_MANAGER_INFO = 0x00000212;
+    this.SGD_DEVICE_MAX_DATA_SIZE = 0x00000213;
+
+    this.TRUE = 1;
+    this.FALSE = 0;
+
+    this.GM3000PCSC = 0;
+    this.GM3000 = 1;
+    this.K7 = 2;
+    this.K5 = 3;
+    this.TF = 4;
+
+    this.TYPE_UKEY = 1; //普通UKEY
+    this.TYPE_FPKEY = 2; //指纹UKEY
+
+    var g_mTokenPlugin = null;
+    var g_deviceNames = null;
+
+
+    this.SOF_GetLastError = function () {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_GetLastError();
+    }
+
+    function isIe() {
+        return ("ActiveXObject" in window);
+    }
+
+    function isMobile() {
+        var browser = {
+            versions: function () {
+                var u = navigator.userAgent;
+                return {//移动终端浏览器版本信息   
+                    trident: u.indexOf('Trident') > -1, //IE内核  
+                    presto: u.indexOf('Presto') > -1, //opera内核  
+                    webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核  
+                    gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核  
+                    mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端  
+                    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端  
+                    android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器  
+                    iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器  
+                    iPad: u.indexOf('iPad') > -1, //是否iPad    
+                    webApp: u.indexOf('Safari') == -1
+                    //是否web应该程序,没有头部与底部  
+                };
+            }(),
+            language: (navigator.browserLanguage || navigator.language).toLowerCase()
+        }
+        if (browser.versions.mobile) {
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+
+    this.SOF_LoadLibrary = function (type) {
+        os = check_os();
+        var ret;
+        if (g_mTokenPlugin == null) {
+            g_mTokenPlugin = new mTokenPlugin();
+        }
+
+        if (type == this.GM3000PCSC) {
+            if (isMobile()) {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("1", "mToken OTG", "com.longmai.security.plugin.driver.otg.OTGDriver");
+            }
+            else {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("mtoken_gm3000_pcsc.dll", "libgm3000_scard.1.0.so", "libgm3000_scard.1.0.dylib");
+            }
+        }
+        else if (type == this.GM3000) {
+            if (isMobile()) {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("1", "mToken OTG", "com.longmai.security.plugin.driver.otg.OTGDriver");
+            }
+            else {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("mtoken_gm3000.dll", "libgm3000.1.0.so", "libgm3000.1.0.dylib");
+            }
+        }
+        else if (type == this.K7) {
+            ret = g_mTokenPlugin.SOF_LoadLibrary("mtoken_k7.dll", "libk7.1.0.so", "libk7.1.0.dylib");
+        }
+        else if (type == this.K5) {
+            if (isMobile()) {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("2", "mToken K5 Bluetooth", "com.longmai.security.plugin.driver.ble.BLEDriver");
+            }
+            else {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("mtoken_k5.dll", "libk5.1.0.so", "libk5.1.0.dylib");
+            }
+        }
+        else if (type == this.TF) {
+            if (isMobile()) {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("0", "mToken TF/SD Card", "com.longmai.security.plugin.driver.tf.TFDriver");
+            } else {
+                ret = g_mTokenPlugin.SOF_LoadLibrary("mtoken_tf.dll", "libtf.so", "libtf.dylib");
+            }
+
+        }
+        else {
+            return -1;
+        }
+
+        if (ret != 0) {
+            return -2;
+        }
+        return this.SAR_OK;
+    };
+
+
+    this.SOF_EnumDevice = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        var array = g_mTokenPlugin.SOF_EnumDevice();
+        if (array == null || array.length <= 0) {
+            return null;
+        }
+
+        return array.split("||");
+
+    };
+
+    this.SOF_DevAuth = function (deviceName, authCode) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DevAuth(deviceName, authCode)
+    };
+
+    this.SOF_ChangeDevAuthKey = function (newAuthCode) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_ChangeDevAuthKey(newAuthCode);
+    }
+
+    this.SOF_CreateApplication = function (applicationName, adminPin, adminPinRetryCount, userPin, userPinRetryCount,fileRights) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_CreateApplication(applicationName, adminPin, adminPinRetryCount, userPin, userPinRetryCount,fileRights);
+    }
+
+    this.SOF_GetApplicationList = function (deviceName) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        var array = g_mTokenPlugin.SOF_GetApplicationList(deviceName);
+        if (array == null || array.length <= 0) {
+            return null;
+        }
+
+        return array.split("||");
+    }
+
+    this.SOF_DeleteApplication = function (applicationName) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DeleteApplication(applicationName);
+    }
+
+    this.SOF_CheckExists = function (deviceName) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_CheckExists(deviceName);
+    }
+
+
+    this.SOF_GetVersion = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GetVersion();
+    };
+
+
+    this.SOF_GetDeviceInstance = function (DeviceName, ApplicationName) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_GetDeviceInstance(DeviceName, ApplicationName);
+    };
+
+    this.SOF_ReleaseDeviceInstance = function () {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_ReleaseDeviceInstance()
+    }
+
+
+    this.SOF_GetUserList = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        var array = g_mTokenPlugin.SOF_GetUserList();
+        if (array == null || array.length <= 0)
+            return null;
+
+        var list = new Array();
+        var user = array.split("&&&");
+        var length = user.length;
+        for (var i = 0; i < length; i++) {
+            list[i] = user[i].split("||");
+        }
+
+        return list;
+    };
+
+
+    this.SOF_ExportUserCert = function (ContainerName, KeySpec) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_ExportUserCert(ContainerName, KeySpec);
+    };
+
+
+    this.SOF_GetDeviceInfo = function (Type) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GetDeviceInfo(Type);
+    };
+
+
+    this.SOF_GetCertInfo = function (Base64EncodeCert, Type) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GetCertInfo(Base64EncodeCert, Type);
+    };
+
+    this.SOF_GetCertInfoByOid = function (Base64EncodeCert, OID) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GetCertInfoByOid(Base64EncodeCert, OID);
+    }
+
+    this.SOF_Login = function (PassWd) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_Login(PassWd);
+    };
+
+    this.SOF_LoginSoPin = function (PassWd) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_LoginSoPin(PassWd);
+    }
+
+
+    this.SOF_LogOut = function () {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_LogOut();
+    };
+
+    this.SOF_SetLabel = function (Label) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_SetLabel(Label);
+    }
+
+
+    this.SOF_GetPinRetryCount = function () {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_GetPinRetryCount();
+    };
+
+    this.SOF_GetPinMaxRetryCount = function () {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_GetPinMaxRetryCount();
+    };
+
+    this.SOF_ChangePassWd = function (OldPassWd, NewPassWd) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_ChangePassWd(OldPassWd, NewPassWd);
+    };
+
+    this.SOF_ChangeSoPin = function (OldPassWd, NewPassWd) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_ChangeSoPin(OldPassWd, NewPassWd);
+    };
+
+
+    this.SOF_SetDigestMethod = function (DigestMethod) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_SetDigestMethod(DigestMethod);
+    };
+
+
+    this.SOF_SetUserID = function (UserID) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_SetUserID(UserID);
+    };
+
+
+    this.SOF_SetEncryptMethodAndIV = function (EncryptMethod, EncryptIV) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_SetEncryptMethodAndIV(EncryptMethod, EncryptIV);
+    };
+
+
+    this.SOF_EncryptFileToPKCS7 = function (Cert, InFile, OutFile, type) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_EncryptFileToPKCS7(Cert, InFile, OutFile, type);
+    };
+
+
+    this.SOF_SignFileToPKCS7 = function (ContainerName, InFile, OutFile) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_SignFileToPKCS7(ContainerName, InFile, OutFile);
+    };
+
+    this.SOF_VerifyFileToPKCS7 = function (strPkcs7Data, InFilePath) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyFileToPKCS7(strPkcs7Data, InFilePath);
+    };
+
+    this.SOF_DecryptFileToPKCS7 = function (ContainerName, keySpec, Pkcs7Data, InFile, OutFile, type) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_DecryptFileToPKCS7(ContainerName, keySpec, Pkcs7Data, InFile, OutFile, type);
+    };
+
+    this.SOF_DigestData = function (ContainerName, nData, InDataLen) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DigestData(ContainerName, nData, InDataLen);
+    };
+
+    this.SOF_SignData = function (ContainerName, ulKeySpec, InData, InDataLen, mode) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SignData(ContainerName, ulKeySpec, InData, InDataLen, mode);
+    };
+    //交互式签名
+    this.SOF_SignDataInteractive = function (ContainerName, ulKeySpec, InData, InDataLen) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SignDataInteractive(ContainerName, ulKeySpec, InData, InDataLen);
+    }
+
+
+    this.SOF_SignDataToPKCS7 = function (ContainerName, ulKeySpec, InData, ulDetached) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SignDataToPKCS7(ContainerName, ulKeySpec, InData, ulDetached);
+    };
+
+
+
+    this.SOF_VerifyDataToPKCS7 = function (Base64EncodeCert, InData, SignedValue) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyDataToPKCS7(Base64EncodeCert, InData, SignedValue);
+    };
+
+    this.SOF_VerifySignedData = function (Base64EncodeCert, digestMethod, InData, SignedValue, mode) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_VerifySignedData(Base64EncodeCert, digestMethod, InData, SignedValue, mode);
+    };
+
+
+    this.SOF_EncryptDataPKCS7 = function (Base64EncodeCert, InData, InDataLen) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_EncryptDataPKCS7(Base64EncodeCert, InData, InDataLen);
+    };
+    this.SOF_EncryptDataPKCS7EX = function (Base64EncodeCert, InData, InDataLen) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_EncryptDataPKCS7EX(Base64EncodeCert, InData, InDataLen);
+    };
+
+
+    this.SOF_DecryptDataPKCS7 = function (ContainerName, ulKeySpec, InData) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DecryptDataPKCS7(ContainerName, ulKeySpec, InData);
+    };
+
+    this.SOF_DecryptDataPKCS7EX = function (ContainerName, ulKeySpec, InData) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DecryptDataPKCS7EX(ContainerName, ulKeySpec, InData);
+    };
+
+    this.SOF_GenRemoteUnblockRequest = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GenRemoteUnblockRequest();
+    };
+
+
+    this.SOF_GenResetpwdResponse = function (request, soPin, userPin) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GenResetpwdResponse(request, soPin, userPin);
+    };
+
+
+    this.SOF_RemoteUnblockPIN = function (request) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_RemoteUnblockPIN(request);
+    };
+
+
+    this.SOF_SignDataToPKCS7 = function (ContainerName, ulKeySpec, InData, ulDetached) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SignDataToPKCS7(ContainerName, ulKeySpec, InData, ulDetached);
+    };
+
+
+    this.SOF_VerifyDataToPKCS7 = function (strPkcs7Data, OriginalText, ulDetached) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyDataToPKCS7(strPkcs7Data, OriginalText, ulDetached);
+    };
+
+    this.CSOF_VerifyDigestDataToPKCS7 = function (strPkcs7Data, OriginalText, ulDetached) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.CSOF_VerifyDigestDataToPKCS7(strPkcs7Data, OriginalText, ulDetached);
+    };
+
+    //按expType导出的公钥,格式为国密规范指定的格式或DER格式
+    this.SOF_ExportPubKey = function (containerName, cerType, expType) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_ExportPubKey(containerName, cerType, expType);
+    }
+
+    this.SOF_PublicVerify = function (pubKey, inData, signedValue, digestMethod) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_PublicVerify(pubKey, inData, signedValue, digestMethod);
+    }
+
+    this.SOF_EncryptByPubKey = function (strPubKey, strInput, cerType) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_EncryptByPubKey(strPubKey, strInput, cerType);
+    }
+
+    this.SOF_DecryptByPrvKey = function (containerName, cerType, strAsymCipher) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DecryptByPrvKey(containerName, cerType, strAsymCipher);
+    }
+
+    //RA客户端相关接口:P10及证书导入等
+    this.SOF_GenerateP10Request = function (deviceName, container, dn, asymAlg, keySpec, keyLength) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GenerateP10Request(deviceName, container, dn, asymAlg, keySpec, keyLength);
+    }
+
+    this.SOF_CreateContainer = function (containerName) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_CreateContainer(containerName);
+    }
+
+    this.SOF_EnumCertContiner = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_EnumCertContiner();
+    }
+
+
+    this.SOF_FindContainer = function (certSN) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_FindContainer(certSN);
+    }
+
+    this.SOF_DeleteCert = function (certSN) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DeleteCert(certSN);
+    }
+
+    this.SOF_DeleteContainer = function (certSN) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_DeleteContainer(certSN);
+    }
+
+    this.SOF_SignByCert = function (certSN, plain) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SignByCert(certSN, plain);
+    }
+
+    this.SOF_VerifyByCert = function (certSN, plain, signature) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyByCert(certSN, plain, signature);
+    }
+
+
+    this.SOF_ImportCert = function (container, cert, keySpec) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_ImportCert(container, cert, keySpec);
+    }
+
+    this.SOF_ImportCryptoCertAndKey = function (container, cert, nAsymAlg, EncryptedSessionKeyData, symAlg, EncryptedPrivateKeyData, mode) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_ImportCryptoCertAndKey(container, cert, nAsymAlg, EncryptedSessionKeyData, symAlg, EncryptedPrivateKeyData, mode);
+    }
+
+    this.SOF_VerifyByExtCert = function (cert, plain, signature, digestMethod) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyByExtCert(cert, plain, signature, digestMethod);
+    }
+
+    this.SOF_GenerateRandom = function (length) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GenerateRandom(length);
+    }
+
+    this.SOF_SymEncryptFile = function (sessionKey, srcfile, destfile, type) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SymEncryptFile(sessionKey, srcfile, destfile, type);
+    }
+
+    this.SOF_SymDecryptFile = function (sessionKey, srcfile, destfile, type) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SymDecryptFile(sessionKey, srcfile, destfile, type);
+    }
+
+    this.SOF_SymEncryptData = function (sessionKey, inData) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SymEncryptData(sessionKey, inData);
+    }
+
+    this.SOF_SymDecryptData = function (sessionKey, inData) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_SymDecryptData(sessionKey, inData);
+    }
+
+    this.SOF_GenerateQRCode = function (qrcode_text) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GenerateQRCode(qrcode_text);
+    }
+
+
+    this.SOF_VerifyPinMS = function (responseKey) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyPinMS(responseKey);
+    }
+
+    this.SOF_GetHardwareType = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_GetHardwareType();
+    }
+
+    this.SOF_VerifyFingerprint = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyFingerprint();
+    }
+
+    this.SOF_VerifyFingerprintEx = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyFingerprintEx();
+    }
+
+    this.SOF_QueryFinger = function (fignerType) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        return g_mTokenPlugin.SOF_QueryFinger(fignerType);
+    }
+
+    this.SOF_EnumFiles = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+
+        var array = g_mTokenPlugin.SOF_EnumFiles();
+        if (array == null || array.length <= 0) {
+            return null;
+        }
+
+        return array.split("||");
+    }
+
+    this.SOF_ReadFile = function (fileName, offset, length) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_ReadFile(fileName, Number(offset), Number(length));
+    }
+
+    this.SOF_WriteFile = function (fileName, offset, data) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_WriteFile(fileName, offset, data);
+    }
+
+    this.SOF_CreateFile = function (fileName, length, readRight, writeRight) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_CreateFile(fileName, length, readRight, writeRight);
+    }
+
+    this.SOF_DeleteFile = function (fileName) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_DeleteFile(fileName);
+    }
+
+    this.SOF_SetCrossAccess = function (crossAccess) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_SetCrossAccess(crossAccess);
+    }
+
+    this.SOF_DigestInit = function (pubKey, mode) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_DigestInit(pubKey, mode);
+    }
+
+    this.SOF_DigestUpdate = function (inData) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_DigestUpdate(inData);
+    }
+
+    this.SOF_DigestFinal = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_DigestFinal();
+    }
+
+
+    this.SOF_DigestToSignData = function (ContainerName, ulKeySpec, singedType, hashData) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_DigestToSignData(ContainerName, ulKeySpec, singedType, hashData);
+    }
+
+    this.SOF_CreateKeyPair = function (container, keySpec, asymAlg, keyLength) {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_CreateKeyPair(container, keySpec, asymAlg, keyLength);
+    }
+
+    this.SOF_IsVerifyPIN = function () {
+        if (g_mTokenPlugin == null) {
+            return null;
+        }
+        return g_mTokenPlugin.SOF_IsVerifyPIN();
+    }
+    this.SOF_VerifyCode = function (code) {
+        if (g_mTokenPlugin == null) {
+            return -1;
+        }
+
+        return g_mTokenPlugin.SOF_VerifyCode(code);
+    };
+}
+
+//判断插件名称是否存在
+function hasPlugin(name) {
+    name = name.toLowerCase();
+    for (var i = 0; i < navigator.plugins.length; i++) {
+        console.log(navigator.plugins[i].name.toLowerCase());
+        if (navigator.plugins[i].name.toLowerCase().indexOf(name) > -1) {
+            return true;
+        }
+    }
+    return false;
+}
+//判断系统
+function check_os() {
+    var os_type;
+    var windows = (navigator.userAgent.indexOf("Windows", 0) != -1) ? 1 : 0;
+    var mac = (navigator.userAgent.indexOf("mac", 0) != -1) ? 1 : 0;
+    var linux = (navigator.userAgent.indexOf("Linux", 0) != -1) ? 1 : 0;
+    var unix = (navigator.userAgent.indexOf("X11", 0) != -1) ? 1 : 0;
+    if (windows) os_type = "MS Windows";
+    else if (linux) os_type = "Lunix";
+    if (hasPlugin("mPlugin1.0.0.1")) {
+        linuxWin = 2;
+        return "id_mPluginV2Router";
+    } else {
+        linuxWin = 1;
+        return "mTokenPlugin";
+    }
+
+
+}
+var linuxWin = 0;
+var os;
+
+function mTokenPlugin() {
+    var _xmlhttp;
+    var retJSON;
+
+    function AjaxIO(json_in) {
+        var linux = (navigator.userAgent.indexOf("Linux", 0) != -1) ? 1 : 0;
+        if (os == "id_mPluginV2Router") {
+            var router = null;
+            var url = "http://127.0.0.1:51235/alpha";
+
+            router = document.getElementById("id_mPluginV2Router");
+            if (null == router) {
+                return -3;
+            }
+
+            if ("https:" == document.location.protocol) {
+                url = "https://127.0.0.1:51245/alpha";
+            }
+            var json_mPluginV2Router = json_in;
+            retJSON = router.invoke(url, json_mPluginV2Router);
+            return retJSON;
+        } else {
+
+            var _url = "http://127.0.0.1:51235/alpha";
+            var json = json_in;
+            if (_xmlhttp == null) {
+                if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
+                    _xmlhttp = new XMLHttpRequest();
+                } else { // code for IE6, IE5
+                    _xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+                }
+            }
+            if ("https:" == document.location.protocol) {
+                _url = "https://127.0.0.1:51245/alpha";
+            }
+            
+            if (linux == 1){
+                _url = "http://127.0.0.1:51235/alpha";
+            }
+            _xmlhttp.open("POST", _url, false);
+            _xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+            _xmlhttp.send("json=" + json);
+        }
+
+
+
+
+    }
+
+    function GetHttpResult() {
+        if (_xmlhttp.readyState == 4 && _xmlhttp.status == 200) {
+            var obj = eval("(" + _xmlhttp.responseText + ")");
+            return obj;
+        }
+        else {
+            return null;
+        }
+    }
+
+    this.SOF_GetLastError = function () {
+        var json = '{"function":"SOF_GetLastError"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.errorCode.toString(16);
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn.toString(16);
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_LoadLibrary = function (windows, linux, mac) {
+        var json = '{"function":"SOF_LoadLibrary", "winDllName":"' + windows + '", "linuxSOName":"' + linux + '", "macDylibName":"' + mac + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_EnumDevice = function () {
+        var json = '{"function":"SOF_EnumDevice"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.array;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.array;
+            }
+
+            return -2;
+        }
+    };
+    this.SOF_DevAuth = function (deviceName, authCode) {
+        var json = '{"function":"SOF_DevAuth", "deviceName":"' + deviceName + '", "authPassWd":"' + authCode + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                _curDevName = deviceName;
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                if (ret.rtn == 0) {
+                    _curDevName = deviceName;
+                }
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_ChangeDevAuthKey = function (newAuthCode) {
+        var json = '{"function":"SOF_ChangeDevAuthKey", "deviceName":"' + _curDevName + '", "authPassWd":"' + newAuthCode + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+            }
+
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_CreateApplication = function (ApplicationName, adminPin, adminPinRetryCount, userPin, userPinRetryCount,fileRights) {
+        var json = '{"function":"SOF_CreateApplication", "deviceName":"' + _curDevName + '", "applicationName":"' + ApplicationName + '", "soPin":"' + adminPin + '", "soPinRetryCount":' + adminPinRetryCount + ', "userPin":"' + userPin + '", "userPinRetryCount":' + userPinRetryCount + ',"rights":'+fileRights+'}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+            }
+
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_DeleteApplication = function (ApplicationName) {
+        var json = '{"function":"SOF_DeleteApplication", "deviceName":"' + _curDevName + '", "applicationName":"' + ApplicationName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+            }
+
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_GetApplicationList = function (deviceName) {
+        var json = '{"function":"SOF_GetApplicationList", "deviceName":"' + deviceName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                _curDevName = deviceName;
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.array;
+            } else {
+                return -2;
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                if (ret.rtn == 0) {
+                    _curDevName = deviceName;
+                }
+                return ret.array;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_CheckExists = function (deviceName) {
+        var json = '{"function":"SOF_CheckExists", "deviceName":"' + deviceName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                if (obj.rtn == 0) {
+                    return obj.isExist;
+                } else {
+                    obj.rtn;
+                }
+            } else {
+                return -2;
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                if (ret.rtn == 0) {
+                    return ret.isExist;
+                } else {
+                    return ret.rtn;
+                }
+
+                return;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_GetVersion = function () {
+        var json = '{"function":"SOF_GetVersion"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.version;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.version;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_GetDeviceInstance = function (DeviceName, ApplicationName) {
+        var json = '{"function":"SOF_GetDeviceInstance", "deviceName":"' + DeviceName + '", "applicationName":"' + ApplicationName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                _curDevName = DeviceName;
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                if (ret.rtn == 0) {
+                    _curDevName = DeviceName;
+                }
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_ReleaseDeviceInstance = function () {
+        var json = '{"function":"SOF_ReleaseDeviceInstance", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.array;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_GetUserList = function () {
+        var json = '{"function":"SOF_GetUserList", "deviceName":"' + _curDevName + '"}';
+
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.array;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.array;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_ExportUserCert = function (ContainerName, KeySpec) {
+
+        var json = '{"function":"SOF_ExportUserCert", "deviceName":"' + _curDevName + '", "containerName":"' + ContainerName + '", "keySpec":' + KeySpec + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.cert;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.cert;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_GetDeviceInfo = function (Type) {
+        var json = '{"function":"SOF_GetDeviceInfo", "deviceName":"' + _curDevName + '", "type":' + Type + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.info;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.info;
+            }
+
+            return -2;
+        }
+
+    };
+
+
+    this.SOF_GetCertInfo = function (Base64EncodeCert, Type) {
+        var json = '{"function":"SOF_GetCertInfo", "base64EncodeCert":"' + Base64EncodeCert + '", "type":' + Type + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.info;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.info;
+            }
+
+            return -2;
+        }
+
+    };
+
+
+    this.SOF_GetCertInfoByOid = function (Base64EncodeCert, OID) {
+        var json = '{"function":"SOF_GetCertInfoByOid", "base64EncodeCert":"' + Base64EncodeCert + '", "oid":"' + OID + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.info;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.info;
+            }
+
+            return null;
+        }
+
+    };
+
+
+
+    this.SOF_Login = function (PassWd) {
+
+        var json = '{"function":"SOF_Login", "deviceName":"' + _curDevName + '", "passWd":"' + PassWd + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_LoginSoPin = function (PassWd) {
+
+        var json = '{"function":"SOF_LoginSoPin", "deviceName":"' + _curDevName + '", "passWd":"' + PassWd + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_LogOut = function () {
+
+        var json = '{"function":"SOF_LogOut", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_GetPinRetryCount = function () {
+
+        var json = '{"function":"SOF_GetPinRetryCount", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.retryCount;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.retryCount;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_GetPinMaxRetryCount = function () {
+
+        var json = '{"function":"SOF_GetPinRetryCount", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.maxRetryCount;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.maxRetryCount;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_ChangePassWd = function (OldPassWd, NewPassWd) {
+
+        var json = '{"function":"SOF_ChangePassWd", "deviceName":"' + _curDevName + '",  "oldUpin":"' + OldPassWd + '", "newUpin":"' + NewPassWd + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_ChangeSoPin = function (OldPassWd, NewPassWd) {
+
+        var json = '{"function":"SOF_ChangeSoPin", "deviceName":"' + _curDevName + '",  "oldUpin":"' + OldPassWd + '", "newUpin":"' + NewPassWd + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_SetDigestMethod = function (DigestMethod) {
+
+        var json = '{"function":"SOF_SetDigestMethod","deviceName":"' + _curDevName + '", "digestMethod":' + DigestMethod + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_SetUserID = function (UserID) {
+
+        var json = '{"function":"SOF_SetUserID","deviceName":"' + _curDevName + '", "userID":"' + UserID + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_SetEncryptMethodAndIV = function (EncryptMethod, EncryptIV) {
+
+        var json = '{"function":"SOF_SetEncryptMethodAndIV","deviceName":"' + _curDevName + '", "encryptMethod":' + EncryptMethod + ', "encryptIV":"' + EncryptIV + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_EncryptFileToPKCS7 = function (Cert, InFile, OutFile, type) {
+
+        var json = '{"function":"SOF_EncryptFileToPKCS7", "deviceName":"' + _curDevName + '", "cert":"' + Cert + '", "inFile":"' + InFile.replace(/\\/g, '\\\\') + '", "outFile":"' + OutFile.replace(/\\/g, '\\\\') + '", "type":' + type + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.envelopData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.envelopData;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_SignFileToPKCS7 = function (ContainerName, KeySpec, InFile) {
+
+        var json = '{"function":"SOF_SignFileToPKCS7", "deviceName":"' + _curDevName + '",  "containerName":"' + ContainerName + '", "KeySpec":' + KeySpec + ', "inFile":"' + InFile.replace(/\\/g, '\\\\') + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.signed;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.signed;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_VerifyFileToPKCS7 = function (strPkcs7Data, InFilePath) {
+        var json = '{"function":"SOF_VerifyFileToPKCS7", "deviceName":"' + _curDevName + '","strPkcs7Data":"' + strPkcs7Data + '", "inFile":"' + InFilePath.replace(/\\/g, '\\\\') + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_DecryptFileToPKCS7 = function (ContainerName, keySpec, Pkcs7Data, InFile, OutFile, type) {
+
+        var json = '{"function":"SOF_DecryptFileToPKCS7", "deviceName":"' + _curDevName + '",  "containerName":"' + ContainerName + '", "keySpec":' + keySpec + ', "pkcs7Data":"' + Pkcs7Data + '", "inFile":"' + InFile.replace(/\\/g, '\\\\') + '", "outFile":"' + OutFile.replace(/\\/g, '\\\\') + '", "type":' + type + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_DigestData = function (ContainerName, InData, InDataLen) {
+
+        var json = '{"function":"SOF_DigestData","deviceName":"' + _curDevName + '",  "containerName":"' + ContainerName + '", "inData":"' + InData + '", "inDataLen":' + InDataLen + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.digest;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.digest;
+            }
+
+            return -2;
+        }
+    };
+
+    //交互式签名
+    this.SOF_SignDataInteractive = function (ContainerName, ulKeySpec, inData, InDataLen) {
+        var InDataBase64 = inData; //对报文进行Base64编码
+        var json = '{"function":"SOF_SignDataInteractive", "deviceName":"' + _curDevName + '",  "containerName":"' + ContainerName + '", "keySpec":' + ulKeySpec + ', "inData":"' + InDataBase64 + '", "inDataLen":' + InDataLen + '}';
+
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.signed;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.signed;
+            }
+
+            return null;
+        }
+    };
+
+    this.SOF_SignData = function (ContainerName, ulKeySpec, InData, InDataLen, mode) {
+
+        var json = '{"function":"SOF_SignDataEx", "deviceName":"' + _curDevName + '", "containerName":"' + ContainerName + '", "keySpec":' + ulKeySpec + ', "inData":"' + InData + '", "inDataLen":' + InDataLen + ', "mode":' + mode + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.signed;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.signed;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_VerifySignedData = function (Base64EncodeCert, digestMethod, InData, SignedValue, mode) {
+        var json = '{"function":"SOF_VerifySignedDataEx","deviceName":"' + _curDevName + '", "base64EncodeCert":"' + Base64EncodeCert + '", "digestMethod":' + digestMethod + ', "inData":"' + InData + '", "signedValue":"' + SignedValue + '", "mode":' + mode + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_EncryptDataPKCS7 = function (Base64EncodeCert, InData, InDataLen) {
+
+        var json = '{"function":"SOF_EncryptDataPKCS7", "deviceName":"' + _curDevName + '", "base64EncodeCert":"' + Base64EncodeCert + '", "inData":"' + InData + '", "inDataLen":' + InDataLen + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.encrypedData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.encrypedData;
+            }
+
+            return -2;
+        }
+
+    };
+
+    this.SOF_EncryptDataPKCS7EX = function (Base64EncodeCert, InData, InDataLen) {
+
+        var json = '{"function":"SOF_EncryptDataPKCS7EX", "deviceName":"' + _curDevName + '", "base64EncodeCert":"' + Base64EncodeCert + '", "inData":"' + InData + '", "inDataLen":' + InDataLen + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.encrypedData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.encrypedData;
+            }
+
+            return -2;
+        }
+
+    };
+
+
+
+    this.SOF_DecryptDataPKCS7 = function (ContainerName, ulKeySpec, InData) {
+
+        var json = '{"function":"SOF_DecryptDataPKCS7", "deviceName":"' + _curDevName + '", "containerName":"' + ContainerName + '", "keySpec":' + ulKeySpec + ', "inData":"' + InData + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.decryptedData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.decryptedData;
+            }
+
+            return -2;
+        }
+    };
+    this.SOF_DecryptDataPKCS7EX = function (ContainerName, ulKeySpec, InData) {
+
+        var json = '{"function":"SOF_DecryptDataPKCS7EX", "deviceName":"' + _curDevName + '", "containerName":"' + ContainerName + '", "keySpec":' + ulKeySpec + ', "inData":"' + InData + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.decryptedData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.decryptedData;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_GenRemoteUnblockRequest = function () {
+
+        var json = '{"function":"SOF_GenRemoteUnblockRequest", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.request;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.request;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_GenResetpwdResponse = function (request, soPin, userPin) {
+
+        var json = '{"function":"SOF_GenResetpwdResponse", "deviceName":"' + _curDevName + '",  "request":"' + request + '", "soPin":"' + soPin + '", "userPin":"' + userPin + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.request;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.request;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_RemoteUnblockPIN = function (request) {
+
+        var json = '{"function":"SOF_RemoteUnblockPIN", "deviceName":"' + _curDevName + '", "request":"' + request + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_SignDataToPKCS7 = function (ContainerName, ulKeySpec, InData, ulDetached) {
+
+        var json = '{"function":"SOF_SignDataToPKCS7", "deviceName":"' + _curDevName + '", "containerName":"' + ContainerName + '", "keySpec":' + ulKeySpec + ', "inData":"' + InData + '",  "detached":' + ulDetached + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.pkcs7;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.pkcs7;
+            }
+
+            return -2;
+        }
+    };
+
+
+    this.SOF_VerifyDataToPKCS7 = function (strPkcs7Data, OriginalText, ulDetached) {
+
+        var json = '{"function":"SOF_VerifyDataToPKCS7", "deviceName":"' + _curDevName + '", "pkcs7":"' + strPkcs7Data + '", "original":"' + OriginalText + '", "detached":' + ulDetached + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_VerifyDigestDataToPKCS7 = function (strPkcs7Data, OriginalText, ulDetached) {
+
+        var json = '{"function":"SOF_VerifyDigestDataToPKCS7", "deviceName":"' + _curDevName + '", "pkcs7":"' + strPkcs7Data + '", "original":"' + OriginalText + '", "detached":' + ulDetached + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    //按expType导出的公钥,格式为国密规范指定的格式或DER格式或裸数据格式
+    //expType=1: 国密格式; 2:DER; 3:RAW (SM2 public key ONLY: X|Y, X,Y各为32字节)
+    this.SOF_ExportPubKey = function (containerName, keySpec, expType) {
+        var json = '{"function":"SOF_ExportPubKeyEx","deviceName":"' + _curDevName + '",  "containerName":"' + containerName + '", "keySpec":' + keySpec + ', "expType":' + expType + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.pubKey;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.pubKey;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_PublicVerify = function (pubKey, inData, signedValue, digestMethod) {
+        var json = '{"function":"SOF_PublicVerify", "deviceName":"' + _curDevName + '", "digestMethod":' + digestMethod + ', "pubKey":"' + pubKey + '", "inData":"' + inData + '",  "signedValue":"' + signedValue + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.pubKey;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    //公钥加密
+    this.SOF_EncryptByPubKey = function (strPubKey, strInput, cerType) {
+        var json = '{"function":"SOF_EncryptByPubKey", "deviceName":"' + _curDevName + '", "pubKey":"' + strPubKey + '", "asymPlain":"' + strInput + '", "keySpec":' + cerType + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.asymCipher;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.asymCipher;
+            }
+
+            return null;
+        }
+    }
+
+    //私钥解密
+    this.SOF_DecryptByPrvKey = function (containerName, cerType, strAsymCipher) {
+        var json = '{"function":"SOF_DecryptByPrvKey", "deviceName":"' + _curDevName + '", "containerName":"' + containerName + '", "asymCipher":"' + strAsymCipher + '", "keySpec":' + cerType + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.asymPlain;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.asymPlain;
+            }
+
+            return null;
+        }
+    }
+
+    //RA客户端控件
+    this.SOF_CreateKeyPair = function (container, keySpec, asymAlg, keyLength) {
+        var json = '{"function":"SOF_CreateKeyPair","deviceName":"' + _curDevName + '",  "containerName":"' + container + '", "asymAlg":' + asymAlg + ', "keySpec":' + keySpec + ',"keyLength":' + keyLength + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_EnumCertContiner = function () {
+        var json = '{"function":"SOF_EnumCertContiner", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.containerName;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.containerName;
+            }
+
+            return "";
+        }
+    }
+
+    this.SOF_CreateContainer = function (containerName) {
+        var json = '{"function":"SOF_CreateContainer","deviceName":"' + _curDevName + '",  "containerName":"' + containerName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return "";
+        }
+    }
+
+
+    this.SOF_FindContainer = function (certSN) {
+        var json = '{"function":"SOF_FindContainer","deviceName":"' + _curDevName + '",  "certSN":"' + certSN + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.containerName;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.containerName;
+            }
+
+            return "";
+        }
+    }
+
+    this.SOF_DeleteCert = function (certSN) {
+        var json = '{"function":"SOF_DeleteCert","deviceName":"' + _curDevName + '",  "certSN":"' + certSN + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_DeleteContainer = function (certSN) {
+        var json = '{"function":"SOF_DeleteContainer", "deviceName":"' + _curDevName + '", "certSN":"' + certSN + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_SignByCert = function (certSN, plain) {
+        var json = '{"function":"SOF_SignByCert", "deviceName":"' + _curDevName + '", "certSN":"' + certSN + '", "inData":"' + plain + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.signed;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.signed;
+            }
+
+            return null;
+        }
+    }
+
+    this.SOF_VerifyByCert = function (certSN, plain, signature, digestMethod) {
+
+        var json = '{"function":"SOF_VerifyByCert", "deviceName":"' + _curDevName + '", "certSN":"' + certSN + '","digestMethod":' + digestMethod + ', "inData":"' + plain + '", "signed":"' + signature + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_VerifyByExtCert = function (cert, plain, signature, digestMethod) {
+        var json = '{"function":"SOF_VerifyByExtCert","deviceName":"' + _curDevName + '",  "cert":"' + cert + '", "digestMethod":' + digestMethod + ', "inData":"' + plain + '", "signed":"' + signature + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_GenerateP10Request = function (_curDevName, container, dn, asymAlg, keySpec, keyLength) {
+        var json = '{"function":"SOF_GenerateP10Request", "deviceName":"' + _curDevName + '", "containerName":"' + container + '", "certDN":"' + dn + '", "asymAlg":' + asymAlg + ', "keySpec":' + keySpec + ',"keyLength":' + keyLength + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.outData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.outData;
+            }
+
+            return null;
+        }
+    }
+    this.SOF_ImportCert = function (container, cert, keySpec) {
+        var json = '{"function":"SOF_ImportCert", "deviceName":"' + _curDevName + '", "containerName":"' + container + '", "cert":"' + cert + '", "keySpec":' + keySpec + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_ImportCryptoCertAndKey = function (container, cert, nAsymAlg, EncryptedSessionKeyData, symAlg, EncryptedPrivateKeyData, mode) {
+        var json = '{"function":"SOF_ImportCryptoCertAndKey", "deviceName":"' + _curDevName + '", "containerName":"' + container + '", "cert":"' + cert + '", "asymAlg":' + nAsymAlg + ', "sessionKey":"' + EncryptedSessionKeyData + '", "symAlg":"' + symAlg + '", "encrypedData":"' + EncryptedPrivateKeyData + '", "mode":"' + mode + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_GenerateRandom = function (length) {
+        var json = '{"function":"SOF_GenRandom", "deviceName":"' + _curDevName + '", "inDataLen":' + length + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.outData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.outData;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_SymEncryptFile = function (sessionKey, srcfile, destfile, type) {
+        var json = '{"function":"SOF_SymEncryptFile", "deviceName":"' + _curDevName + '", "sessionKey":"' + sessionKey + '", "inFile":"' + srcfile.replace(/\\/g, '\\\\') + '", "outFile":"' + destfile.replace(/\\/g, '\\\\') + '", "type":' + type + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_SymDecryptFile = function (sessionKey, srcfile, destfile, type) {
+        var json = '{"function":"SOF_SymDecryptFile", "deviceName":"' + _curDevName + '", "sessionKey":"' + sessionKey + '", "inFile":"' + srcfile.replace(/\\/g, '\\\\') + '", "outFile":"' + destfile.replace(/\\/g, '\\\\') + '", "type":' + type + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_SymEncryptData = function (sessionKey, inData) {
+        var json = '{"function":"SOF_SymEncryptData", "deviceName":"' + _curDevName + '", "sessionKey":"' + sessionKey + '", "inData":"' + inData + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.outData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.outData;
+            }
+
+            return null;
+        }
+    }
+
+    this.SOF_SymDecryptData = function (sessionKey, inData) {
+        var json = '{"function":"SOF_SymDecryptData", "deviceName":"' + _curDevName + '", "sessionKey":"' + sessionKey + '", "inData":"' + inData + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.outData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.outData;
+            }
+
+            return null;
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////
+    this.SOF_GenerateQRCode = function (qrcode_text_in) {
+        var qrcode_text = qrcode_text_in.replace(/"/g, '\\"');
+        var json = '{"module":"libQR","function":"SOF_GenerateQRCode", "inData":"' + qrcode_text + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.outData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.outData;
+            }
+
+            return null;
+        }
+    }
+
+    this.SOF_VerifyPinMS = function (responseKey) {
+        var json = '{"function":"SOF_VerifyPinMS", "deviceName":"' + _curDevName + '", "passWd":"' + responseKey + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+    /////////////////////////////////////////////////////////////////
+    this.SOF_GetHardwareType = function () {
+        var json = '{"function":"SOF_GetHardwareType", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.type;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.type;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_VerifyFingerprint = function () {
+        var json = '{"function":"SOF_VerifyFingerprint", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_VerifyFingerprintEx = function () {
+        var json = '{"function":"SOF_VerifyFingerprintEx", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.FingerId;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                if (ret.rtn != 0) {
+                    return ret.RetryCount;
+                }
+                else {
+                    return ret.FingerId;
+                }
+
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_QueryFinger = function (fignerType) {
+        var json = '{"function":"SOF_QueryFinger", "deviceName":"' + _curDevName + '", "fignerType":"' + fignerType + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.FingerId;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                if (ret.rtn != 0) {
+                    return ret.rtn;
+                }
+                else {
+                    return ret.FingerId;
+                }
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_EnumFiles = function () {
+        var json = '{"function":"SOF_EnumFiles", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.array;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.array;
+            }
+
+            return -2;
+        }
+    }
+
+    this.SOF_ReadFile = function (fileName, offset, length) {
+        var json = '{"function":"SOF_ReadFile", "deviceName":"' + _curDevName + '", "fileName":"' + fileName + '", "offset":' + offset + ',"length":' + length + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.outData;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.outData;
+            }
+        }
+    }
+
+    this.SOF_WriteFile = function (fileName, offset, data) {
+        var json = '{"function":"SOF_WriteFile", "deviceName":"' + _curDevName + '", "fileName":"' + fileName + '", "offset":' + offset + ',"inData":"' + data + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+    this.SOF_CreateFile = function (fileName, length, readRight, writeRight) {
+        var json = '{"function":"SOF_CreateFile", "deviceName":"' + _curDevName + '","fileName":"' + fileName + '", "length" :' + length + ', "readRight":' + readRight + ',"writeRight":' + writeRight + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+    this.SOF_VerifyCode = function (code) {
+
+        var json = '{"function":"SOF_VerifyCode", "deviceName":"' + _curDevName + '", "inData":"' + code + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+
+    this.SOF_DeleteFile = function (fileName) {
+        var json = '{"function":"SOF_DeleteFile", "deviceName":"' + _curDevName + '","fileName":"' + fileName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+    this.SOF_SetCrossAccess = function (crossAccess) {
+
+        var json = '{"function":"SOF_SetCrossAccess", "deviceName":"' + _curDevName + '", "crossAccess":"' + crossAccess + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+
+    this.SOF_DigestInit = function (pubKey, mode) {
+        var json = '{"function":"SOF_DigestInit", "deviceName":"' + _curDevName + '", "mode":' + mode + ',"pubKey":"' + pubKey + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+    this.SOF_DigestUpdate = function (inData) {
+        var json = '{"function":"SOF_DigestUpdate", "deviceName":"' + _curDevName + '", "inData":"' + inData + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+    this.SOF_DigestFinal = function () {
+        var json = '{"function":"SOF_DigestFinal", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.digest;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.digest;
+            }
+        }
+    }
+
+    this.SOF_DigestToSignData = function (ContainerName, ulKeySpec, singedType, hashData) {
+        var json = '{"function":"SOF_DigestToSignData", "deviceName":"' + _curDevName + '", "containerName":"' + ContainerName + '", "keySpec":' + ulKeySpec + ',"strSignedType":"' + singedType + '", "inData":"' + hashData + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.signed;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.signed;
+            }
+
+            return -2;
+        }
+    }
+
+
+    this.SOF_IsVerifyPIN = function () {
+        var json = '{"function":"SOF_IsVerifyPIN", "deviceName":"' + _curDevName + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+
+    //Socket API
+    this.SocketConnect = function (HostName, Port) {
+        var json = '{"module":"libSocket","function":"SocketConnect", "HostName":"' + HostName + '", "Port":' + Port + '}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+    this.SocketDisConnect = function () {
+        var json = '{"module":"libSocket","function":"SocketDisConnect"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+        }
+    }
+
+    this.SocketSendText = function (SendText) {
+        var json = '{"module":"libSocket","function":"SocketSendText", "SendText":"' + SendText + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.RecvText;
+            } else {
+                return -2;
+
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            }
+            catch (e) {
+                return -3;
+            }
+
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.RecvText;
+            }
+        }
+    }
+    this.SOF_SetLabel = function (Label) {
+
+        var json = '{"function":"SOF_SetLabel", "deviceName":"' + _curDevName + '", "Label":"' + Label + '"}';
+        if (linuxWin == 2) {
+            var retJSON = "";
+            try {
+                retJSON = AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+
+            if (retJSON.length > 3) {
+                var obj = eval("(" + retJSON + ")");
+                return obj.rtn;
+            } else {
+                return -2;
+            }
+        } else {
+            try {
+                AjaxIO(json);
+            } catch (e) {
+                return -3;
+            }
+            var ret = GetHttpResult();
+            if (ret) {
+                return ret.rtn;
+            }
+
+            return -2;
+        }
+    };
+}

+ 145 - 0
mPlugin-js/signData.html

@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>智能密码卡国密中间件</title>
+
+    <script src="./js/mTokenPlugin/base64.js"></script>
+    <script src="./js/mTokenPlugin/mToken.js"></script>
+    <script src="./js/mTokenPlugin/hunca_mToken_core.js"></script>
+    <link href="css/bootstrap.css" rel="stylesheet">
+    <style>
+        body {
+            margin: 0px 0px auto;
+        }
+
+        .nav {
+            width: auto;
+            margin: 0px auto;
+            text-align: center;
+        }
+
+        .head {
+            width: 950px;
+            margin: 0px auto;
+        }
+
+        .content {
+            width: 1200px;
+            margin: 0px auto;
+            text-align: center;
+            margin-top: 40px;
+        }
+    </style>
+    <script>
+        var mToken = new hunca_mToken_core();
+
+        function enumDevice() {
+            var devList = "";
+            var selectDev = null;
+
+            selectDev = document.getElementById("optionDevList");
+            selectDev.options.length = 0;
+
+            devList = mToken.Hunca_GetUserList(); //枚举Ukey,获取证书G项信息列表
+            if (null == devList || devList.length == 0) {
+                alert(mToken.Hunca_GetLastError());
+                return false;
+            }
+
+            addOption(devList, selectDev, 1);
+            return false;
+
+        }
+
+        function signData() {
+            var data = "你好";
+            var password = "";
+            var userName = "";
+            var selectDev = null;
+            var index = 0;
+
+            var startTime,endTime;
+
+            selectDev = document.getElementById("optionDevList");
+            if (selectDev.length == 0) {
+                alert('请插入Ukey,点击“刷新”按钮')
+                return false;
+            }
+            index = selectDev.selectedIndex;
+            password = document.getElementById("password").value;
+            userName = selectDev.options[index].text;
+
+            startTime = new Date().getTime();
+            if (!mToken.Hunca_PKCS1(data, userName, password)) {
+               alert(mToken.Hunca_GetLastError());
+                return false;
+            }
+
+            document.getElementById("ca_signData").value = mToken.Hunca_GetSignData();
+            document.getElementById("ca_cert").value = mToken.Hunca_GetSignCert();
+
+            console.log(mToken.Hunca_GetSignData());
+            console.log(mToken.Hunca_GetSignCert());
+            alert("签名成功!");
+            return false;
+        }
+
+        //动态添加option选项
+        function addOption(optionStr, selectID, flag) {
+            if (flag == 1) {
+                for (var i = 0; i < optionStr.length; ++i)
+                    selectID.options.add(new Option(optionStr[i], i));
+            }
+            if (flag == 2) {
+                for (var i = 0; i < optionStr.length; ++i) {
+                    selectID.options.add(new Option(optionStr[i][1], i));
+                }
+            }
+        }
+    </script>
+</head>
+
+<body>
+    <embed id="id_mPluginV2Router" type="application/mPluginV2Router" width="0" height="0" />
+    <object id="mTokenPlugin" width="0" height="0">
+        <param value="pluginLoaded" />
+    </object>
+    <div class="head">
+        <img src="">
+    </div>
+    <div class="nav">
+        <h2>智能密码卡国密中间件(系统登陆)</h2>
+        <h3>(基于随机数的数字签名实现数字证书登录)</h3>
+    </div>
+    <div class="content" style="width: 720px">
+        <form class="form-horizontal" method="POST">
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">证书名称:</label>
+                <div class="col-sm-6">
+                    <select id="optionDevList" class="form-control"></select>
+                </div>
+                <div class="col-sm-2">
+                    <button class="btn btn-default" onclick="return enumDevice();">刷新</button>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label col-md-offset-1">设备密码:</label>
+                <div class="col-sm-6">
+                    <input id="password" type="password" class="form-control">
+                </div>
+                <div class="col-sm-2">
+                    <input type="hidden" name="ca_signData" id="ca_signData">
+                    <input type="hidden" name="ca_cert" id="ca_cert">
+                    <button class="btn btn-primary" onclick="return signData();">登陆</button>
+                </div>
+            </div>
+        </form>
+    </div>
+
+</body>
+
+</html>

BIN=BIN
驱动(含国密库)/mPlugin_SKF_Setup.exe