mirror of
				https://github.com/crypto-pro-web/crypto-pro-js.git
				synced 2025-10-31 06:13:22 +03:00 
			
		
		
		
	Merge branch 'master' into single-codebase
# Conflicts: # dist/1.crypto-pro.js.map # dist/2.crypto-pro.js.map # dist/crypto-pro.js.map # npm-shrinkwrap.json
This commit is contained in:
		
						commit
						1b4c840d55
					
				
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							| @ -7,13 +7,23 @@ | ||||
| - [Mozilla Firefox](https://www.mozilla.org/ru/firefox/new/) (v43+). Начиная с версии 52, с [расширением](https://www.cryptopro.ru/sites/default/files/products/cades/extensions/cryptopro_extension_for_cades_browser_plug_in-1.1.1-an+fx-windows.xpi). | ||||
| - [Internet Explorer](http://windows.microsoft.com/ru-ru/internet-explorer/download-ie) (v8+). | ||||
| 
 | ||||
| Полифилл для Promise необходимо подключать самостоятельно. | ||||
| Список необходимых полифиллов (подключаются самостоятельно): | ||||
| - Promise | ||||
| - EventTarget.addEventListener | ||||
| - Array.prototype.forEach | ||||
| - Array.prototype.map | ||||
| 
 | ||||
| ## Установка и настройка | ||||
| ### NPM | ||||
| ```bash | ||||
| npm install crypto-pro | ||||
| ``` | ||||
| 
 | ||||
| ### Bower | ||||
| ```bash | ||||
| bower install crypto-pro | ||||
| ``` | ||||
| 
 | ||||
| Для корректной работы используйте: | ||||
| 1. [КриптоПРО CSP](https://www.cryptopro.ru/products/csp/downloads) (v3.6+) *рекомендуется использование только сертифицированных версий*. Инструкция по установке: | ||||
|     - [Linux / OSX](#install_csp_linux) | ||||
|  | ||||
							
								
								
									
										24
									
								
								bower.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								bower.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| { | ||||
|   "name": "crypto-pro", | ||||
|   "description": "API для взаимодействия с КриптоПро", | ||||
|   "main": "dist/crypto-pro.js", | ||||
|   "authors": [ | ||||
|     "vgoma <vgoma@yandex.ru>" | ||||
|   ], | ||||
|   "license": "ISC", | ||||
|   "keywords": [ | ||||
|     "crypto", | ||||
|     "cryptopro", | ||||
|     "crypto-pro", | ||||
|     "cades", | ||||
|     "КриптоПро" | ||||
|   ], | ||||
|   "homepage": "https://github.com/vgoma/crypto-pro", | ||||
|   "ignore": [ | ||||
|     "**/.*", | ||||
|     "node_modules", | ||||
|     "bower_components", | ||||
|     "test", | ||||
|     "tests" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										2
									
								
								dist/1.crypto-pro.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/1.crypto-pro.js
									
									
									
									
										vendored
									
									
								
							| @ -733,7 +733,7 @@ webpackJsonpCryptoPro([1],[ | ||||
| 	 * */ | ||||
| 	function prepareCertsInfo(items) { | ||||
| 	    return items.map(function (c) { | ||||
| 	        c.name = c.subjectName.match(/CN=(.+?),/); | ||||
| 	        c.name = c.subjectName.match(/CN=(.+?)(?:,|$)/); | ||||
| 	 | ||||
| 	        // Удалось ли вытащить Common Name
 | ||||
| 	        if (c.name && c.name[1]) { | ||||
|  | ||||
							
								
								
									
										2
									
								
								dist/1.crypto-pro.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/1.crypto-pro.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/2.crypto-pro.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/2.crypto-pro.js
									
									
									
									
										vendored
									
									
								
							| @ -176,7 +176,7 @@ webpackJsonpCryptoPro([2],[ | ||||
| 	 * */ | ||||
| 	function prepareCertsInfo(items) { | ||||
| 	    return items.map(function (c) { | ||||
| 	        c.name = c.subjectName.match(/CN=(.+?),/); | ||||
| 	        c.name = c.subjectName.match(/CN=(.+?)(?:,|$)/); | ||||
| 	 | ||||
| 	        // Удалось ли вытащить Common Name
 | ||||
| 	        if (c.name && c.name[1]) { | ||||
|  | ||||
							
								
								
									
										2
									
								
								dist/2.crypto-pro.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/2.crypto-pro.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										131
									
								
								dist/crypto-pro.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										131
									
								
								dist/crypto-pro.js
									
									
									
									
										vendored
									
									
								
							| @ -741,8 +741,8 @@ var CryptoPro = | ||||
| 	    var plugin_reject; | ||||
| 	    var plugin_resolve; | ||||
| 	    var isOpera = 0; | ||||
| 	    var isYaBrowser = 0; | ||||
| 	    var isFireFox = 0; | ||||
| 		var isEdge = 0; | ||||
| 	    var failed_extensions = 0; | ||||
| 	 | ||||
| 	    var canPromise = !!window.Promise; | ||||
| @ -759,6 +759,22 @@ var CryptoPro = | ||||
| 	    { | ||||
| 	        cadesplugin = {}; | ||||
| 	    } | ||||
| 	     | ||||
| 	    function check_browser() { | ||||
| 	        var ua= navigator.userAgent, tem, M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; | ||||
| 	        if(/trident/i.test(M[1])){ | ||||
| 	            tem=  /\brv[ :]+(\d+)/g.exec(ua) || []; | ||||
| 	            return {name:'IE',version:(tem[1] || '')}; | ||||
| 	        } | ||||
| 	        if(M[1]=== 'Chrome'){ | ||||
| 	            tem= ua.match(/\b(OPR|Edge)\/(\d+)/); | ||||
| 	            if(tem!= null) return {name:tem[1].replace('OPR', 'Opera'),version:tem[2]}; | ||||
| 	        } | ||||
| 	        M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?']; | ||||
| 	        if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]); | ||||
| 	        return {name:M[0],version:M[1]}; | ||||
| 	    } | ||||
| 	    var browserSpecs = check_browser(); | ||||
| 	 | ||||
| 	    function cpcsp_console_log(level, msg){ | ||||
| 	        //IE9 не может писать в консоль если не открыта вкладка developer tools
 | ||||
| @ -920,9 +936,9 @@ var CryptoPro = | ||||
| 	    } | ||||
| 	 | ||||
| 	    function isIE() { | ||||
| 	        var retVal = (("Microsoft Internet Explorer" == navigator.appName) || // IE < 11
 | ||||
| 	            navigator.userAgent.match(/Trident\/./i)); // IE 11
 | ||||
| 	        return retVal; | ||||
| 	        // var retVal = (("Microsoft Internet Explorer" == navigator.appName) || // IE < 11
 | ||||
| 	        //     navigator.userAgent.match(/Trident\/./i)); // IE 11
 | ||||
| 	        return (browserSpecs.name == 'IE' || browserSpecs.name == 'MSIE'); | ||||
| 	    } | ||||
| 	 | ||||
| 	    function isIOS() { | ||||
| @ -934,25 +950,41 @@ var CryptoPro = | ||||
| 	 | ||||
| 	    function isNativeMessageSupported() | ||||
| 	    { | ||||
| 	        var retVal_chrome = navigator.userAgent.match(/chrome/i); | ||||
| 	        isOpera = navigator.userAgent.match(/opr/i); | ||||
| 	        isYaBrowser = navigator.userAgent.match(/YaBrowser/i); | ||||
| 	        isFireFox = navigator.userAgent.match(/Firefox/i); | ||||
| 	 | ||||
| 	        if(isFireFox && window.allow_firefox_cadesplugin_async) | ||||
| 	            return true; | ||||
| 	 | ||||
| 	        if(retVal_chrome == null) // В IE работаем через NPAPI
 | ||||
| 	        // В IE работаем через NPAPI
 | ||||
| 	        if(isIE()) | ||||
| 	            return false; | ||||
| 	        else | ||||
| 	        { | ||||
| 	            // В Chrome и Opera работаем через асинхронную версию
 | ||||
| 	            if(retVal_chrome.length > 0 || isOpera != null ) | ||||
| 	            { | ||||
| 	        // В Edge работаем через NativeMessage
 | ||||
| 	        if(browserSpecs.name == 'Edge') { | ||||
| 	            isEdge = true; | ||||
| 	            return true; | ||||
| 	        } | ||||
| 	        // В Chrome, Firefox и Opera работаем через асинхронную версию в зависимости от версии
 | ||||
| 	        if(browserSpecs.name == 'Opera') { | ||||
| 	            isOpera = true; | ||||
| 	            if(browserSpecs.version >= 33){ | ||||
| 	                return true; | ||||
| 	            } | ||||
| 	            else{ | ||||
| 	                return false; | ||||
| 	            } | ||||
| 	        } | ||||
| 	        if(browserSpecs.name == 'Firefox') { | ||||
| 	            isFireFox = true; | ||||
| 	            if(browserSpecs.version >= 52){ | ||||
| 	                return true; | ||||
| 	            } | ||||
| 	            else{ | ||||
| 	                return false; | ||||
| 	            } | ||||
| 	        } | ||||
| 	        if(browserSpecs.name == 'Chrome') { | ||||
| 	            if(browserSpecs.version >= 42){ | ||||
| 	                return true; | ||||
| 	            } | ||||
| 	            else{ | ||||
| 	                return false; | ||||
| 	            } | ||||
| 	        } | ||||
| 	        return false; | ||||
| 	    } | ||||
| 	 | ||||
| 	    // Функция активации объектов КриптоПро ЭЦП Browser plug-in
 | ||||
| @ -984,7 +1016,7 @@ var CryptoPro = | ||||
| 	                return new ActiveXObject(name); | ||||
| 	            } | ||||
| 	        } | ||||
| 	        // В Firefox, Safari создаются объекты NPAPI
 | ||||
| 	        // создаются объекты NPAPI
 | ||||
| 	        return pluginObject.CreateObject(name); | ||||
| 	    } | ||||
| 	 | ||||
| @ -1018,6 +1050,11 @@ var CryptoPro = | ||||
| 	        } | ||||
| 	    } | ||||
| 	 | ||||
| 	    // Функция для удаления созданных объектов
 | ||||
| 	    function ReleasePluginObjects() { | ||||
| 	        return cpcsp_chrome_nmcades.ReleasePluginObjects(); | ||||
| 	    } | ||||
| 	 | ||||
| 	    // Функция активации асинхронных объектов КриптоПро ЭЦП Browser plug-in
 | ||||
| 	    function CreateObjectAsync(name) { | ||||
| 	        return pluginObject.CreateObjectAsync(name); | ||||
| @ -1076,6 +1113,35 @@ var CryptoPro = | ||||
| 	        return tmpobj; | ||||
| 	    } | ||||
| 	 | ||||
| 	    function show_firefox_missing_extension_dialog() | ||||
| 	    { | ||||
| 	        if (!window.cadesplugin_skip_extension_install) | ||||
| 	        {   | ||||
| 	            var ovr = document.createElement('div'); | ||||
| 	            ovr.id = "cadesplugin_ovr"; | ||||
| 	            ovr.style = "visibility: hidden; position: fixed; left: 0px; top: 0px; width:100%; height:100%; background-color: rgba(0,0,0,0.7)"; | ||||
| 	            ovr.innerHTML = "<div id='cadesplugin_ovr_item' style='position:relative; width:400px; margin:100px auto; background-color:#fff; border:2px solid #000; padding:10px; text-align:center; opacity: 1; z-index: 1500'>" + | ||||
| 	                            "<button id='cadesplugin_close_install' style='float: right; font-size: 10px; background: transparent; border: 1; margin: -5px'>X</button>" + | ||||
| 	                            "<p>Для работы КриптоПро ЭЦП Browser plugin на данном сайте необходимо расширение для браузера. Убедитесь, что оно у Вас включено или установите его." + | ||||
| 	                            "<p><a href='https://www.cryptopro.ru/sites/default/files/products/cades/extensions/firefox_cryptopro_extension_latest.xpi'>Скачать расширение</a></p>" + | ||||
| 	                            "</div>"; | ||||
| 	            document.getElementsByTagName("Body")[0].appendChild(ovr); | ||||
| 	            document.getElementById("cadesplugin_close_install").addEventListener('click',function() | ||||
| 	                                    { | ||||
| 	                                        plugin_loaded_error("Плагин недоступен"); | ||||
| 	                                        document.getElementById("cadesplugin_ovr").style.visibility = 'hidden'; | ||||
| 	                                    }); | ||||
| 	 | ||||
| 	            ovr.addEventListener('click',function() | ||||
| 	                                { | ||||
| 	                                    plugin_loaded_error("Плагин недоступен"); | ||||
| 	                                    document.getElementById("cadesplugin_ovr").style.visibility = 'hidden'; | ||||
| 	                                }); | ||||
| 	            ovr.style.visibility="visible"; | ||||
| 	        } | ||||
| 	    } | ||||
| 	 | ||||
| 	 | ||||
| 	    //Выводим окно поверх других с предложением установить расширение для Opera.
 | ||||
| 	    //Если установленна переменная cadesplugin_skip_extension_install - не предлагаем установить расширение
 | ||||
| 	    function install_opera_extension() | ||||
| @ -1124,7 +1190,7 @@ var CryptoPro = | ||||
| 	        } | ||||
| 	    } | ||||
| 	 | ||||
| 	    function firefox_nmcades_onload() { | ||||
| 	    function firefox_or_edge_nmcades_onload() { | ||||
| 	        cpcsp_chrome_nmcades.check_chrome_plugin(plugin_loaded, plugin_loaded_error); | ||||
| 	    } | ||||
| 	 | ||||
| @ -1133,7 +1199,7 @@ var CryptoPro = | ||||
| 	        window.addEventListener("message", function (event){ | ||||
| 	            if (typeof(event.data) != "string" || !event.data.match("cadesplugin_loaded")) | ||||
| 	               return; | ||||
| 	            if(isFireFox) | ||||
| 	            if(isFireFox || isEdge) | ||||
| 	            { | ||||
| 	                // Для Firefox вместе с сообщением cadesplugin_loaded прилетает url для загрузки nmcades_plugin_api.js
 | ||||
| 	                var url = event.data.substring(event.data.indexOf("url:") + 4); | ||||
| @ -1141,9 +1207,10 @@ var CryptoPro = | ||||
| 	                fileref.setAttribute("type", "text/javascript"); | ||||
| 	                fileref.setAttribute("src", url); | ||||
| 	                fileref.onerror = plugin_loaded_error; | ||||
| 	                fileref.onload = firefox_nmcades_onload; | ||||
| 	                fileref.onload = firefox_or_edge_nmcades_onload; | ||||
| 	                document.getElementsByTagName("head")[0].appendChild(fileref); | ||||
| 	 | ||||
| 	                // Для Firefox и Edge у нас только по одному расширению.
 | ||||
| 	                failed_extensions++; | ||||
| 	            }else { | ||||
| 	                cpcsp_chrome_nmcades.check_chrome_plugin(plugin_loaded, plugin_loaded_error); | ||||
| 	            } | ||||
| @ -1154,7 +1221,7 @@ var CryptoPro = | ||||
| 	    function load_extension() | ||||
| 	    { | ||||
| 	 | ||||
| 	        if(isFireFox){ | ||||
| 	        if(isFireFox || isEdge){ | ||||
| 	            // вызываем callback руками т.к. нам нужно узнать ID расширения. Он уникальный для браузера.
 | ||||
| 	            nmcades_api_onload(); | ||||
| 	            return; | ||||
| @ -1242,6 +1309,10 @@ var CryptoPro = | ||||
| 	    { | ||||
| 	        if(plugin_resolved == 1) | ||||
| 	            return; | ||||
| 	        if(isFireFox) | ||||
| 	        { | ||||
| 	            show_firefox_missing_extension_dialog(); | ||||
| 	        } | ||||
| 	        plugin_resolved = 1; | ||||
| 	        if(canPromise) | ||||
| 	        { | ||||
| @ -1307,10 +1378,15 @@ var CryptoPro = | ||||
| 	                false); | ||||
| 	        }else | ||||
| 	        { | ||||
| 	            window.addEventListener("load", function (event) { | ||||
| 	            if(document.readyState === "complete"){ | ||||
| 	                load_npapi_plugin(); | ||||
| 	                check_npapi_plugin(); | ||||
| 	            }, false); | ||||
| 	            } else { | ||||
| 	                window.addEventListener("load", function (event) { | ||||
| 	                    load_npapi_plugin(); | ||||
| 	                    check_npapi_plugin(); | ||||
| 	                }, false); | ||||
| 	            } | ||||
| 	        } | ||||
| 	    } | ||||
| 	 | ||||
| @ -1329,6 +1405,7 @@ var CryptoPro = | ||||
| 	    if(isNativeMessageSupported()) | ||||
| 	    { | ||||
| 	        cadesplugin.CreateObjectAsync = CreateObjectAsync; | ||||
| 	        cadesplugin.ReleasePluginObjects = ReleasePluginObjects; | ||||
| 	    } | ||||
| 	 | ||||
| 	    if(!isNativeMessageSupported()) | ||||
|  | ||||
							
								
								
									
										2
									
								
								dist/crypto-pro.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/crypto-pro.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -3,7 +3,6 @@ | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <title>Пример использования CryptoPro</title> | ||||
|     <script src="https://cdn.polyfill.io/v2/polyfill.js"></script> | ||||
| </head> | ||||
| <body> | ||||
|     <select id="certList"></select> | ||||
| @ -16,7 +15,20 @@ | ||||
|             publicPath: '../dist/' | ||||
|         }; | ||||
|     </script> | ||||
| 
 | ||||
|     <!-- Полифиллы для работы библиотеки --> | ||||
|     <script src="polyfills/addEventListener.js"></script> | ||||
|     <script src="polyfills/promise.js"></script> | ||||
|     <script src="polyfills/forEach.js"></script> | ||||
|     <script src="polyfills/map.js"></script> | ||||
| 
 | ||||
|     <!-- Библиотека --> | ||||
|     <script src="../dist/crypto-pro.js"></script> | ||||
| 
 | ||||
|     <!-- Полифиллы для работы демо скриптов --> | ||||
|     <script src="polyfills/atob-btoa.js"></script> | ||||
| 
 | ||||
|     <!-- Демо скрипты --> | ||||
|     <script src="cert-list.js"></script> | ||||
|     <script src="create-sign.js"></script> | ||||
| </body> | ||||
|  | ||||
							
								
								
									
										32
									
								
								example/polyfills/addEventListener.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								example/polyfills/addEventListener.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| !window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) { | ||||
|     WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) { | ||||
|         var target = this; | ||||
| 
 | ||||
|         registry.unshift([target, type, listener, function (event) { | ||||
|             event.currentTarget = target; | ||||
|             event.preventDefault = function () { | ||||
|                 event.returnValue = false | ||||
|             }; | ||||
|             event.stopPropagation = function () { | ||||
|                 event.cancelBubble = true | ||||
|             }; | ||||
|             event.target = event.srcElement || target; | ||||
| 
 | ||||
|             listener.call(target, event); | ||||
|         }]); | ||||
| 
 | ||||
|         this.attachEvent("on" + type, registry[0][3]); | ||||
|     }; | ||||
| 
 | ||||
|     WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) { | ||||
|         for (var index = 0, register; register = registry[index]; ++index) { | ||||
|             if (register[0] == this && register[1] == type && register[2] == listener) { | ||||
|                 return this.detachEvent("on" + type, registry.splice(index, 1)[0][3]); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) { | ||||
|         return this.fireEvent("on" + eventObject.type, eventObject); | ||||
|     }; | ||||
| })(Window.prototype, HTMLDocument.prototype, Element.prototype, "addEventListener", "removeEventListener", "dispatchEvent", []); | ||||
							
								
								
									
										76
									
								
								example/polyfills/atob-btoa.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								example/polyfills/atob-btoa.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| (function (root, factory) { | ||||
|     if (typeof define === 'function' && define.amd) { | ||||
|         // AMD. Register as an anonymous module.
 | ||||
|         define([], function () { | ||||
|             factory(root); | ||||
|         }); | ||||
|     } else factory(root); | ||||
| // node.js has always supported base64 conversions, while browsers that support
 | ||||
| // web workers support base64 too, but you may never know.
 | ||||
| })(typeof exports !== "undefined" ? exports : this, function (root) { | ||||
|     if (root.atob) { | ||||
|         // Some browsers' implementation of atob doesn't support whitespaces
 | ||||
|         // in the encoded string (notably, IE). This wraps the native atob
 | ||||
|         // in a function that strips the whitespaces.
 | ||||
|         // The original function can be retrieved in atob.original
 | ||||
|         try { | ||||
|             root.atob(" "); | ||||
|         } catch (e) { | ||||
|             root.atob = (function (atob) { | ||||
|                 var func = function (string) { | ||||
|                     return atob(String(string).replace(/[\t\n\f\r ]+/g, "")); | ||||
|                 }; | ||||
|                 func.original = atob; | ||||
|                 return func; | ||||
|             })(root.atob); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // base64 character set, plus padding character (=)
 | ||||
|     var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", | ||||
|         // Regular expression to check formal correctness of base64 encoded strings
 | ||||
|         b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; | ||||
| 
 | ||||
|     root.btoa = function (string) { | ||||
|         string = String(string); | ||||
|         var bitmap, a, b, c, | ||||
|             result = "", i = 0, | ||||
|             rest = string.length % 3; // To determine the final padding
 | ||||
| 
 | ||||
|         for (; i < string.length;) { | ||||
|             if ((a = string.charCodeAt(i++)) > 255 | ||||
|                 || (b = string.charCodeAt(i++)) > 255 | ||||
|                 || (c = string.charCodeAt(i++)) > 255) | ||||
|                 throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."); | ||||
| 
 | ||||
|             bitmap = (a << 16) | (b << 8) | c; | ||||
|             result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) | ||||
|                 + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); | ||||
|         } | ||||
| 
 | ||||
|         // If there's need of padding, replace the last 'A's with equal signs
 | ||||
|         return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result; | ||||
|     }; | ||||
| 
 | ||||
|     root.atob = function (string) { | ||||
|         // atob can work with strings with whitespaces, even inside the encoded part,
 | ||||
|         // but only \t, \n, \f, \r and ' ', which can be stripped.
 | ||||
|         string = String(string).replace(/[\t\n\f\r ]+/g, ""); | ||||
|         if (!b64re.test(string)) | ||||
|             throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); | ||||
| 
 | ||||
|         // Adding the padding if missing, for semplicity
 | ||||
|         string += "==".slice(2 - (string.length & 3)); | ||||
|         var bitmap, result = "", r1, r2, i = 0; | ||||
|         for (; i < string.length;) { | ||||
|             bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | ||||
|                 | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); | ||||
| 
 | ||||
|             result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) | ||||
|                 : r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) | ||||
|                     : String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); | ||||
|         } | ||||
|         return result; | ||||
|     }; | ||||
| }); | ||||
							
								
								
									
										59
									
								
								example/polyfills/forEach.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								example/polyfills/forEach.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| // Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.18
 | ||||
| // Ссылка (en): http://es5.github.io/#x15.4.4.18
 | ||||
| // Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.18
 | ||||
| if (!Array.prototype.forEach) { | ||||
| 
 | ||||
|     Array.prototype.forEach = function (callback, thisArg) { | ||||
| 
 | ||||
|         var T, k; | ||||
| 
 | ||||
|         if (this == null) { | ||||
|             throw new TypeError(' this is null or not defined'); | ||||
|         } | ||||
| 
 | ||||
|         // 1. Положим O равным результату вызова ToObject passing the |this| value as the argument.
 | ||||
|         var O = Object(this); | ||||
| 
 | ||||
|         // 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length".
 | ||||
|         // 3. Положим len равным ToUint32(lenValue).
 | ||||
|         var len = O.length >>> 0; | ||||
| 
 | ||||
|         // 4. Если IsCallable(callback) равен false, выкинем исключение TypeError.
 | ||||
|         // Смотрите: http://es5.github.com/#x9.11
 | ||||
|         if (typeof callback !== 'function') { | ||||
|             throw new TypeError(callback + ' is not a function'); | ||||
|         } | ||||
| 
 | ||||
|         // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
 | ||||
|         if (arguments.length > 1) { | ||||
|             T = thisArg; | ||||
|         } | ||||
| 
 | ||||
|         // 6. Положим k равным 0
 | ||||
|         k = 0; | ||||
| 
 | ||||
|         // 7. Пока k < len, будем повторять
 | ||||
|         while (k < len) { | ||||
| 
 | ||||
|             var kValue; | ||||
| 
 | ||||
|             // a. Положим Pk равным ToString(k).
 | ||||
|             //   Это неявное преобразование для левостороннего операнда в операторе in
 | ||||
|             // b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk.
 | ||||
|             //   Этот шаг может быть объединён с шагом c
 | ||||
|             // c. Если kPresent равен true, то
 | ||||
|             if (k in O) { | ||||
| 
 | ||||
|                 // i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk.
 | ||||
|                 kValue = O[k]; | ||||
| 
 | ||||
|                 // ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и
 | ||||
|                 // списком аргументов, содержащим kValue, k и O.
 | ||||
|                 callback.call(T, kValue, k, O); | ||||
|             } | ||||
|             // d. Увеличим k на 1.
 | ||||
|             k++; | ||||
|         } | ||||
|         // 8. Вернём undefined.
 | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										91
									
								
								example/polyfills/map.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								example/polyfills/map.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| // Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.19
 | ||||
| // Ссылка (en): http://es5.github.com/#x15.4.4.19
 | ||||
| // Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.19
 | ||||
| if (!Array.prototype.map) { | ||||
| 
 | ||||
|     Array.prototype.map = function(callback, thisArg) { | ||||
| 
 | ||||
|         var T, A, k; | ||||
| 
 | ||||
|         if (this == null) { | ||||
|             throw new TypeError(' this is null or not defined'); | ||||
|         } | ||||
| 
 | ||||
|         // 1. Положим O равным результату вызова ToObject с передачей ему
 | ||||
|         //    значения |this| в качестве аргумента.
 | ||||
|         var O = Object(this); | ||||
| 
 | ||||
|         // 2. Положим lenValue равным результату вызова внутреннего метода Get
 | ||||
|         //    объекта O с аргументом "length".
 | ||||
|         // 3. Положим len равным ToUint32(lenValue).
 | ||||
|         var len = O.length >>> 0; | ||||
| 
 | ||||
|         // 4. Если вызов IsCallable(callback) равен false, выкидываем исключение TypeError.
 | ||||
|         // Смотрите (en): http://es5.github.com/#x9.11
 | ||||
|         // Смотрите (ru): http://es5.javascript.ru/x9.html#x9.11
 | ||||
|         if (typeof callback !== 'function') { | ||||
|             throw new TypeError(callback + ' is not a function'); | ||||
|         } | ||||
| 
 | ||||
|         // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
 | ||||
|         if (arguments.length > 1) { | ||||
|             T = thisArg; | ||||
|         } | ||||
| 
 | ||||
|         // 6. Положим A равным новому масиву, как если бы он был создан выражением new Array(len),
 | ||||
|         //    где Array является стандартным встроенным конструктором с этим именем,
 | ||||
|         //    а len является значением len.
 | ||||
|         A = new Array(len); | ||||
| 
 | ||||
|         // 7. Положим k равным 0
 | ||||
|         k = 0; | ||||
| 
 | ||||
|         // 8. Пока k < len, будем повторять
 | ||||
|         while (k < len) { | ||||
| 
 | ||||
|             var kValue, mappedValue; | ||||
| 
 | ||||
|             // a. Положим Pk равным ToString(k).
 | ||||
|             //   Это неявное преобразование для левостороннего операнда в операторе in
 | ||||
|             // b. Положим kPresent равным результату вызова внутреннего метода HasProperty
 | ||||
|             //    объекта O с аргументом Pk.
 | ||||
|             //   Этот шаг может быть объединён с шагом c
 | ||||
|             // c. Если kPresent равен true, то
 | ||||
|             if (k in O) { | ||||
| 
 | ||||
|                 // i. Положим kValue равным результату вызова внутреннего метода Get
 | ||||
|                 //    объекта O с аргументом Pk.
 | ||||
|                 kValue = O[k]; | ||||
| 
 | ||||
|                 // ii. Положим mappedValue равным результату вызова внутреннего метода Call
 | ||||
|                 //     функции callback со значением T в качестве значения this и списком
 | ||||
|                 //     аргументов, содержащим kValue, k и O.
 | ||||
|                 mappedValue = callback.call(T, kValue, k, O); | ||||
| 
 | ||||
|                 // iii. Вызовем внутренний метод DefineOwnProperty объекта A с аргументами
 | ||||
|                 // Pk, Описатель Свойства
 | ||||
|                 // { Value: mappedValue,
 | ||||
|                 //   Writable: true,
 | ||||
|                 //   Enumerable: true,
 | ||||
|                 //   Configurable: true }
 | ||||
|                 // и false.
 | ||||
| 
 | ||||
|                 // В браузерах, поддерживающих Object.defineProperty, используем следующий код:
 | ||||
|                 // Object.defineProperty(A, k, {
 | ||||
|                 //   value: mappedValue,
 | ||||
|                 //   writable: true,
 | ||||
|                 //   enumerable: true,
 | ||||
|                 //   configurable: true
 | ||||
|                 // });
 | ||||
| 
 | ||||
|                 // Для лучшей поддержки браузерами, используем следующий код:
 | ||||
|                 A[k] = mappedValue; | ||||
|             } | ||||
|             // d. Увеличим k на 1.
 | ||||
|             k++; | ||||
|         } | ||||
| 
 | ||||
|         // 9. Вернём A.
 | ||||
|         return A; | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										236
									
								
								example/polyfills/promise.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								example/polyfills/promise.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,236 @@ | ||||
| (function (root) { | ||||
| 
 | ||||
|     // Store setTimeout reference so promise-polyfill will be unaffected by
 | ||||
|     // other code modifying setTimeout (like sinon.useFakeTimers())
 | ||||
|     var setTimeoutFunc = setTimeout; | ||||
| 
 | ||||
|     function noop() { | ||||
|     } | ||||
| 
 | ||||
|     // Polyfill for Function.prototype.bind
 | ||||
|     function bind(fn, thisArg) { | ||||
|         return function () { | ||||
|             fn.apply(thisArg, arguments); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     function Promise(fn) { | ||||
|         if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); | ||||
|         if (typeof fn !== 'function') throw new TypeError('not a function'); | ||||
|         this._state = 0; | ||||
|         this._handled = false; | ||||
|         this._value = undefined; | ||||
|         this._deferreds = []; | ||||
| 
 | ||||
|         doResolve(fn, this); | ||||
|     } | ||||
| 
 | ||||
|     function handle(self, deferred) { | ||||
|         while (self._state === 3) { | ||||
|             self = self._value; | ||||
|         } | ||||
|         if (self._state === 0) { | ||||
|             self._deferreds.push(deferred); | ||||
|             return; | ||||
|         } | ||||
|         self._handled = true; | ||||
|         Promise._immediateFn(function () { | ||||
|             var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; | ||||
|             if (cb === null) { | ||||
|                 (self._state === 1 ? resolve : reject)(deferred.promise, self._value); | ||||
|                 return; | ||||
|             } | ||||
|             var ret; | ||||
|             try { | ||||
|                 ret = cb(self._value); | ||||
|             } catch (e) { | ||||
|                 reject(deferred.promise, e); | ||||
|                 return; | ||||
|             } | ||||
|             resolve(deferred.promise, ret); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     function resolve(self, newValue) { | ||||
|         try { | ||||
|             // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
 | ||||
|             if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); | ||||
|             if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { | ||||
|                 var then = newValue.then; | ||||
|                 if (newValue instanceof Promise) { | ||||
|                     self._state = 3; | ||||
|                     self._value = newValue; | ||||
|                     finale(self); | ||||
|                     return; | ||||
|                 } else if (typeof then === 'function') { | ||||
|                     doResolve(bind(then, newValue), self); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             self._state = 1; | ||||
|             self._value = newValue; | ||||
|             finale(self); | ||||
|         } catch (e) { | ||||
|             reject(self, e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function reject(self, newValue) { | ||||
|         self._state = 2; | ||||
|         self._value = newValue; | ||||
|         finale(self); | ||||
|     } | ||||
| 
 | ||||
|     function finale(self) { | ||||
|         if (self._state === 2 && self._deferreds.length === 0) { | ||||
|             Promise._immediateFn(function () { | ||||
|                 if (!self._handled) { | ||||
|                     Promise._unhandledRejectionFn(self._value); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         for (var i = 0, len = self._deferreds.length; i < len; i++) { | ||||
|             handle(self, self._deferreds[i]); | ||||
|         } | ||||
|         self._deferreds = null; | ||||
|     } | ||||
| 
 | ||||
|     function Handler(onFulfilled, onRejected, promise) { | ||||
|         this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; | ||||
|         this.onRejected = typeof onRejected === 'function' ? onRejected : null; | ||||
|         this.promise = promise; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Take a potentially misbehaving resolver function and make sure | ||||
|      * onFulfilled and onRejected are only called once. | ||||
|      * | ||||
|      * Makes no guarantees about asynchrony. | ||||
|      */ | ||||
|     function doResolve(fn, self) { | ||||
|         var done = false; | ||||
|         try { | ||||
|             fn(function (value) { | ||||
|                 if (done) return; | ||||
|                 done = true; | ||||
|                 resolve(self, value); | ||||
|             }, function (reason) { | ||||
|                 if (done) return; | ||||
|                 done = true; | ||||
|                 reject(self, reason); | ||||
|             }); | ||||
|         } catch (ex) { | ||||
|             if (done) return; | ||||
|             done = true; | ||||
|             reject(self, ex); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Promise.prototype['catch'] = function (onRejected) { | ||||
|         return this.then(null, onRejected); | ||||
|     }; | ||||
| 
 | ||||
|     Promise.prototype.then = function (onFulfilled, onRejected) { | ||||
|         var prom = new (this.constructor)(noop); | ||||
| 
 | ||||
|         handle(this, new Handler(onFulfilled, onRejected, prom)); | ||||
|         return prom; | ||||
|     }; | ||||
| 
 | ||||
|     Promise.all = function (arr) { | ||||
|         var args = Array.prototype.slice.call(arr); | ||||
| 
 | ||||
|         return new Promise(function (resolve, reject) { | ||||
|             if (args.length === 0) return resolve([]); | ||||
|             var remaining = args.length; | ||||
| 
 | ||||
|             function res(i, val) { | ||||
|                 try { | ||||
|                     if (val && (typeof val === 'object' || typeof val === 'function')) { | ||||
|                         var then = val.then; | ||||
|                         if (typeof then === 'function') { | ||||
|                             then.call(val, function (val) { | ||||
|                                 res(i, val); | ||||
|                             }, reject); | ||||
|                             return; | ||||
|                         } | ||||
|                     } | ||||
|                     args[i] = val; | ||||
|                     if (--remaining === 0) { | ||||
|                         resolve(args); | ||||
|                     } | ||||
|                 } catch (ex) { | ||||
|                     reject(ex); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             for (var i = 0; i < args.length; i++) { | ||||
|                 res(i, args[i]); | ||||
|             } | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     Promise.resolve = function (value) { | ||||
|         if (value && typeof value === 'object' && value.constructor === Promise) { | ||||
|             return value; | ||||
|         } | ||||
| 
 | ||||
|         return new Promise(function (resolve) { | ||||
|             resolve(value); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     Promise.reject = function (value) { | ||||
|         return new Promise(function (resolve, reject) { | ||||
|             reject(value); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     Promise.race = function (values) { | ||||
|         return new Promise(function (resolve, reject) { | ||||
|             for (var i = 0, len = values.length; i < len; i++) { | ||||
|                 values[i].then(resolve, reject); | ||||
|             } | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     // Use polyfill for setImmediate for performance gains
 | ||||
|     Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { | ||||
|             setImmediate(fn); | ||||
|         }) || | ||||
|         function (fn) { | ||||
|             setTimeoutFunc(fn, 0); | ||||
|         }; | ||||
| 
 | ||||
|     Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { | ||||
|         if (typeof console !== 'undefined' && console) { | ||||
|             console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
 | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     /** | ||||
|      * Set the immediate function to execute callbacks | ||||
|      * @param fn {function} Function to execute | ||||
|      * @deprecated | ||||
|      */ | ||||
|     Promise._setImmediateFn = function _setImmediateFn(fn) { | ||||
|         Promise._immediateFn = fn; | ||||
|     }; | ||||
| 
 | ||||
|     /** | ||||
|      * Change the function to execute on unhandled rejection | ||||
|      * @param {function} fn Function to execute on unhandled rejection | ||||
|      * @deprecated | ||||
|      */ | ||||
|     Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { | ||||
|         Promise._unhandledRejectionFn = fn; | ||||
|     }; | ||||
| 
 | ||||
|     if (typeof module !== 'undefined' && module.exports) { | ||||
|         module.exports = Promise; | ||||
|     } else if (!root.Promise) { | ||||
|         root.Promise = Promise; | ||||
|     } | ||||
| 
 | ||||
| })(this); | ||||
							
								
								
									
										1572
									
								
								npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1572
									
								
								npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "crypto-pro", | ||||
|   "version": "1.0.11", | ||||
|   "version": "1.0.13", | ||||
|   "description": "API для взаимодействия с КриптоПро", | ||||
|   "main": "src/index.js", | ||||
|   "scripts": { | ||||
|  | ||||
| @ -167,7 +167,7 @@ function getDateObj(dateObj) { | ||||
|  * */ | ||||
| function prepareCertsInfo(items) { | ||||
|     return items.map(function (c) { | ||||
|         c.name = c.subjectName.match(/CN=(.+?),/); | ||||
|         c.name = c.subjectName.match(/CN=(.+?)(?:,|$)/); | ||||
| 
 | ||||
|         // Удалось ли вытащить Common Name
 | ||||
|         if (c.name && c.name[1]) { | ||||
|  | ||||
							
								
								
									
										131
									
								
								vendor/cadesplugin_api.js
									
									
									
									
										vendored
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										131
									
								
								vendor/cadesplugin_api.js
									
									
									
									
										vendored
									
									
										
										
										Executable file → Normal file
									
								
							| @ -8,8 +8,8 @@ | ||||
|     var plugin_reject; | ||||
|     var plugin_resolve; | ||||
|     var isOpera = 0; | ||||
|     var isYaBrowser = 0; | ||||
|     var isFireFox = 0; | ||||
| 	var isEdge = 0; | ||||
|     var failed_extensions = 0; | ||||
| 
 | ||||
|     var canPromise = !!window.Promise; | ||||
| @ -26,6 +26,22 @@ | ||||
|     { | ||||
|         cadesplugin = {}; | ||||
|     } | ||||
|      | ||||
|     function check_browser() { | ||||
|         var ua= navigator.userAgent, tem, M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; | ||||
|         if(/trident/i.test(M[1])){ | ||||
|             tem=  /\brv[ :]+(\d+)/g.exec(ua) || []; | ||||
|             return {name:'IE',version:(tem[1] || '')}; | ||||
|         } | ||||
|         if(M[1]=== 'Chrome'){ | ||||
|             tem= ua.match(/\b(OPR|Edge)\/(\d+)/); | ||||
|             if(tem!= null) return {name:tem[1].replace('OPR', 'Opera'),version:tem[2]}; | ||||
|         } | ||||
|         M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?']; | ||||
|         if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]); | ||||
|         return {name:M[0],version:M[1]}; | ||||
|     } | ||||
|     var browserSpecs = check_browser(); | ||||
| 
 | ||||
|     function cpcsp_console_log(level, msg){ | ||||
|         //IE9 не может писать в консоль если не открыта вкладка developer tools
 | ||||
| @ -187,9 +203,9 @@ | ||||
|     } | ||||
| 
 | ||||
|     function isIE() { | ||||
|         var retVal = (("Microsoft Internet Explorer" == navigator.appName) || // IE < 11
 | ||||
|             navigator.userAgent.match(/Trident\/./i)); // IE 11
 | ||||
|         return retVal; | ||||
|         // var retVal = (("Microsoft Internet Explorer" == navigator.appName) || // IE < 11
 | ||||
|         //     navigator.userAgent.match(/Trident\/./i)); // IE 11
 | ||||
|         return (browserSpecs.name == 'IE' || browserSpecs.name == 'MSIE'); | ||||
|     } | ||||
| 
 | ||||
|     function isIOS() { | ||||
| @ -201,25 +217,41 @@ | ||||
| 
 | ||||
|     function isNativeMessageSupported() | ||||
|     { | ||||
|         var retVal_chrome = navigator.userAgent.match(/chrome/i); | ||||
|         isOpera = navigator.userAgent.match(/opr/i); | ||||
|         isYaBrowser = navigator.userAgent.match(/YaBrowser/i); | ||||
|         isFireFox = navigator.userAgent.match(/Firefox/i); | ||||
| 
 | ||||
|         if(isFireFox && window.allow_firefox_cadesplugin_async) | ||||
|             return true; | ||||
| 
 | ||||
|         if(retVal_chrome == null) // В IE работаем через NPAPI
 | ||||
|         // В IE работаем через NPAPI
 | ||||
|         if(isIE()) | ||||
|             return false; | ||||
|         else | ||||
|         { | ||||
|             // В Chrome и Opera работаем через асинхронную версию
 | ||||
|             if(retVal_chrome.length > 0 || isOpera != null ) | ||||
|             { | ||||
|         // В Edge работаем через NativeMessage
 | ||||
|         if(browserSpecs.name == 'Edge') { | ||||
|             isEdge = true; | ||||
|             return true; | ||||
|         } | ||||
|         // В Chrome, Firefox и Opera работаем через асинхронную версию в зависимости от версии
 | ||||
|         if(browserSpecs.name == 'Opera') { | ||||
|             isOpera = true; | ||||
|             if(browserSpecs.version >= 33){ | ||||
|                 return true; | ||||
|             } | ||||
|             else{ | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         if(browserSpecs.name == 'Firefox') { | ||||
|             isFireFox = true; | ||||
|             if(browserSpecs.version >= 52){ | ||||
|                 return true; | ||||
|             } | ||||
|             else{ | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         if(browserSpecs.name == 'Chrome') { | ||||
|             if(browserSpecs.version >= 42){ | ||||
|                 return true; | ||||
|             } | ||||
|             else{ | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // Функция активации объектов КриптоПро ЭЦП Browser plug-in
 | ||||
| @ -251,7 +283,7 @@ | ||||
|                 return new ActiveXObject(name); | ||||
|             } | ||||
|         } | ||||
|         // В Firefox, Safari создаются объекты NPAPI
 | ||||
|         // создаются объекты NPAPI
 | ||||
|         return pluginObject.CreateObject(name); | ||||
|     } | ||||
| 
 | ||||
| @ -285,6 +317,11 @@ | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Функция для удаления созданных объектов
 | ||||
|     function ReleasePluginObjects() { | ||||
|         return cpcsp_chrome_nmcades.ReleasePluginObjects(); | ||||
|     } | ||||
| 
 | ||||
|     // Функция активации асинхронных объектов КриптоПро ЭЦП Browser plug-in
 | ||||
|     function CreateObjectAsync(name) { | ||||
|         return pluginObject.CreateObjectAsync(name); | ||||
| @ -343,6 +380,35 @@ | ||||
|         return tmpobj; | ||||
|     } | ||||
| 
 | ||||
|     function show_firefox_missing_extension_dialog() | ||||
|     { | ||||
|         if (!window.cadesplugin_skip_extension_install) | ||||
|         {   | ||||
|             var ovr = document.createElement('div'); | ||||
|             ovr.id = "cadesplugin_ovr"; | ||||
|             ovr.style = "visibility: hidden; position: fixed; left: 0px; top: 0px; width:100%; height:100%; background-color: rgba(0,0,0,0.7)"; | ||||
|             ovr.innerHTML = "<div id='cadesplugin_ovr_item' style='position:relative; width:400px; margin:100px auto; background-color:#fff; border:2px solid #000; padding:10px; text-align:center; opacity: 1; z-index: 1500'>" + | ||||
|                             "<button id='cadesplugin_close_install' style='float: right; font-size: 10px; background: transparent; border: 1; margin: -5px'>X</button>" + | ||||
|                             "<p>Для работы КриптоПро ЭЦП Browser plugin на данном сайте необходимо расширение для браузера. Убедитесь, что оно у Вас включено или установите его." + | ||||
|                             "<p><a href='https://www.cryptopro.ru/sites/default/files/products/cades/extensions/firefox_cryptopro_extension_latest.xpi'>Скачать расширение</a></p>" + | ||||
|                             "</div>"; | ||||
|             document.getElementsByTagName("Body")[0].appendChild(ovr); | ||||
|             document.getElementById("cadesplugin_close_install").addEventListener('click',function() | ||||
|                                     { | ||||
|                                         plugin_loaded_error("Плагин недоступен"); | ||||
|                                         document.getElementById("cadesplugin_ovr").style.visibility = 'hidden'; | ||||
|                                     }); | ||||
| 
 | ||||
|             ovr.addEventListener('click',function() | ||||
|                                 { | ||||
|                                     plugin_loaded_error("Плагин недоступен"); | ||||
|                                     document.getElementById("cadesplugin_ovr").style.visibility = 'hidden'; | ||||
|                                 }); | ||||
|             ovr.style.visibility="visible"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     //Выводим окно поверх других с предложением установить расширение для Opera.
 | ||||
|     //Если установленна переменная cadesplugin_skip_extension_install - не предлагаем установить расширение
 | ||||
|     function install_opera_extension() | ||||
| @ -391,7 +457,7 @@ | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function firefox_nmcades_onload() { | ||||
|     function firefox_or_edge_nmcades_onload() { | ||||
|         cpcsp_chrome_nmcades.check_chrome_plugin(plugin_loaded, plugin_loaded_error); | ||||
|     } | ||||
| 
 | ||||
| @ -400,7 +466,7 @@ | ||||
|         window.addEventListener("message", function (event){ | ||||
|             if (typeof(event.data) != "string" || !event.data.match("cadesplugin_loaded")) | ||||
|                return; | ||||
|             if(isFireFox) | ||||
|             if(isFireFox || isEdge) | ||||
|             { | ||||
|                 // Для Firefox вместе с сообщением cadesplugin_loaded прилетает url для загрузки nmcades_plugin_api.js
 | ||||
|                 var url = event.data.substring(event.data.indexOf("url:") + 4); | ||||
| @ -408,9 +474,10 @@ | ||||
|                 fileref.setAttribute("type", "text/javascript"); | ||||
|                 fileref.setAttribute("src", url); | ||||
|                 fileref.onerror = plugin_loaded_error; | ||||
|                 fileref.onload = firefox_nmcades_onload; | ||||
|                 fileref.onload = firefox_or_edge_nmcades_onload; | ||||
|                 document.getElementsByTagName("head")[0].appendChild(fileref); | ||||
| 
 | ||||
|                 // Для Firefox и Edge у нас только по одному расширению.
 | ||||
|                 failed_extensions++; | ||||
|             }else { | ||||
|                 cpcsp_chrome_nmcades.check_chrome_plugin(plugin_loaded, plugin_loaded_error); | ||||
|             } | ||||
| @ -421,7 +488,7 @@ | ||||
|     function load_extension() | ||||
|     { | ||||
| 
 | ||||
|         if(isFireFox){ | ||||
|         if(isFireFox || isEdge){ | ||||
|             // вызываем callback руками т.к. нам нужно узнать ID расширения. Он уникальный для браузера.
 | ||||
|             nmcades_api_onload(); | ||||
|             return; | ||||
| @ -509,6 +576,10 @@ | ||||
|     { | ||||
|         if(plugin_resolved == 1) | ||||
|             return; | ||||
|         if(isFireFox) | ||||
|         { | ||||
|             show_firefox_missing_extension_dialog(); | ||||
|         } | ||||
|         plugin_resolved = 1; | ||||
|         if(canPromise) | ||||
|         { | ||||
| @ -574,10 +645,15 @@ | ||||
|                 false); | ||||
|         }else | ||||
|         { | ||||
|             window.addEventListener("load", function (event) { | ||||
|             if(document.readyState === "complete"){ | ||||
|                 load_npapi_plugin(); | ||||
|                 check_npapi_plugin(); | ||||
|             }, false); | ||||
|             } else { | ||||
|                 window.addEventListener("load", function (event) { | ||||
|                     load_npapi_plugin(); | ||||
|                     check_npapi_plugin(); | ||||
|                 }, false); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -596,6 +672,7 @@ | ||||
|     if(isNativeMessageSupported()) | ||||
|     { | ||||
|         cadesplugin.CreateObjectAsync = CreateObjectAsync; | ||||
|         cadesplugin.ReleasePluginObjects = ReleasePluginObjects; | ||||
|     } | ||||
| 
 | ||||
|     if(!isNativeMessageSupported()) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 vgoma
						vgoma