├── .gitignore ├── LICENSE ├── README.md ├── browserst └── browserst.js ├── cmanager ├── cmanager-bg.js ├── cmanager.js ├── credential.html └── credential.js ├── css ├── HoldOn.min.css ├── common.css ├── font-awesome.min.css ├── jquery.dataTables.css ├── jquery.tour.css ├── materialize.css ├── proxy-settings.css └── sweetalert2.min.css ├── debugreq ├── debugreq-bg.js ├── debugreq-details.js ├── debugreq-history.html ├── debugreq-history.js └── debugreq.js ├── fastpurge ├── fastpurge-bg.js ├── fastpurge-details.js ├── fastpurge-history.html ├── fastpurge-history.js └── fastpurge.js ├── fonts ├── FontAwesome.otf ├── fontawesome-webfont.eot ├── fontawesome-webfont.svg ├── fontawesome-webfont.ttf ├── fontawesome-webfont.woff ├── fontawesome-webfont.woff2 ├── materialicons.css ├── materialize.woff2 └── roboto │ ├── Roboto-Bold.eot │ ├── Roboto-Bold.ttf │ ├── Roboto-Bold.woff │ ├── Roboto-Bold.woff2 │ ├── Roboto-Light.eot │ ├── Roboto-Light.ttf │ ├── Roboto-Light.woff │ ├── Roboto-Light.woff2 │ ├── Roboto-Medium.eot │ ├── Roboto-Medium.ttf │ ├── Roboto-Medium.woff │ ├── Roboto-Medium.woff2 │ ├── Roboto-Regular.eot │ ├── Roboto-Regular.ttf │ ├── Roboto-Regular.woff │ ├── Roboto-Regular.woff2 │ ├── Roboto-Thin.eot │ ├── Roboto-Thin.ttf │ ├── Roboto-Thin.woff │ └── Roboto-Thin.woff2 ├── img ├── akamai-black-logo.png ├── akamai-blue-logo.png ├── akamai-grey-logo.png ├── akamai-orange-logo.jpg ├── akamai-orange-logo.png ├── akamai.png ├── akamai.svg ├── akamai_logo.svg ├── datatable │ ├── back_disabled.png │ ├── back_enabled.png │ ├── back_enabled_hover.png │ ├── forward_disabled.png │ ├── forward_enabled.png │ ├── forward_enabled_hover.png │ ├── sort_asc.png │ ├── sort_asc_disabled.png │ ├── sort_both.png │ ├── sort_desc.png │ └── sort_desc_disabled.png ├── dev-icons-128.png ├── dev_tools_marquee.png ├── dev_tools_wallpaper1.png ├── dev_tools_wallpaper2.png ├── dev_tools_wallpaper3.png ├── dev_tools_wallpaper4.png ├── email_header_background.png ├── email_header_banner_dev.png ├── email_header_devpops_title.png ├── email_header_devpops_withbg.png ├── email_header_title.png ├── fail_icon.png ├── icon-128.png ├── icons-128.png ├── info_icon.png ├── spring_devops_icon.png └── success_icon.png ├── js ├── HoldOn.min.js ├── aes.js ├── background.js ├── cipher-core.js ├── common.js ├── core.js ├── edgegrid.js ├── enc-base64.js ├── encdec.js ├── endpoints.js ├── evpkdf.js ├── flush.js ├── google-analytics.js ├── hmac-sha256.js ├── http-request.js ├── jquery-3.1.1.min.js ├── jquery.dataTables.js ├── jquery.tour.js ├── materialize.min.js ├── md5.js ├── modal.js ├── moment.js ├── popup.js ├── sha256.js ├── socketflush.js ├── sweetalert2.min.js └── twitter-widgets.js ├── manifest.json ├── openapitester ├── openapitester-bg.js ├── openapitester-details.js ├── openapitester-history.html ├── openapitester-history.js └── openapitester.js ├── papiviz ├── css │ └── papiviz.css ├── img │ └── d.png ├── js │ ├── jquery.json2html.js │ └── json2html.js └── lib │ └── index.js └── popup.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Akhil Jay 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Banner image](/img/dev_tools_marquee.png) 2 | 3 | Over the past few months I have had very interesting discussions with developers around what tools define their workspace and how can Akamai be part of that workspace. A recurring theme was the ability to instantly perform actions like purge, debugging errors, pull Akamai logs and debug ESI errors right from the browser or from their code editor. 4 | 5 | After a few brainstorming sessions with [Ricky Yu](https://github.com/ricky840) and his experience with building tools/extensions we decided to create a chrome extension that provides Akamai developer features directly within a browser. Below is a quick summary of the features available for testing within the chrome extension. 6 | 7 | Here is a link the [extension](https://chrome.google.com/webstore/detail/akamai-developer-toolkit/oeekflkhfpllpepjdkpodopelgaebeed/) 8 | 9 | Here is a link to our [roadmap](https://trello.com/b/NMa7Qyn7/akamai-developer-toolkit-project-backlog-and-dashboard) 10 | 11 | ### Akamai API Manager: 12 | Manage your API credentials and toggle between different kinds of API tokens based on the service you are trying to access. 13 | - Ability to add and manage API credentials Ability to manage up to 20 API credentials. Developers tend to have multiple API tokens within a single Akamai account, this extensions helps you toggle between the multiple API endpoints depending on the Akamai service you have access to. 14 | 15 | ### Fast Purge: 16 | ![Fast Purge img](/img/dev_tools_wallpaper2.png) 17 | Manage and make invalidate/delete requests 18 | - Make fast purge requests by entering URL or multiple URLs or CP codes or Cache Tags 19 | - Purge history and manager: Keep a record of all the purges that you have issued using the extension 20 | - Issue purges directly from the extension or even from the context menu (right click on an image you want to purge). Pretty useful when you are working on a dev page. 21 | 22 | ### Debug Requests 23 | ![Debug Requests img](/img/dev_tools_wallpaper3.png) 24 | "Debug Requests" section, helps translate error reference code and pull logs for the error and transactions you make on Akamai, be it a WAF error or an IM error, the tools helps you translate the error code and save the error details as a PDF and share with colleagues OR pull logs and share with Akatec. 25 | - Ability to translate Error Reference Codes View history of all the Error translations you did 26 | - Notifies you when the translation is complete 27 | - To fetch Akamai logs, you will need a ghost IP and the hostname associated to the logs you are interested in, we pull the logs for the past 30 mins from the time you click on "fetch logs" within the extension. 28 | - Debug history and manager: keeps a record of all the debugging you have done and can download and save it in case you need it for further debugging. 29 | 30 | ### Browser Settings 31 | ![Browser Settings img](/img/dev_tools_wallpaper4.png) 32 | "Browser Settings", helps you manage your chrome browser configurations like proxy settings, flush DNS/socket pools and enablement of Akamai pragma headers. 33 | - Ability to add multiple proxy configs Ability to support proxies with Auth headers 34 | - Supports up to 10 proxy configs. Once a proxy config is selected the user can open up a new tab OR a new window OR reload their current tab to make requests go through the proxy. Developers can configure & save multiple proxy profiles within this extension based on their dev pipelines. 35 | - When a proxy config is selected the extension icon lights up GREEN notifying the user that they are on a proxy connection. 36 | 37 | 38 | # Call for Feedback 39 | Please download the extension here [Akamai Developer Toolkit - Chrome Web Store](https://chrome.google.com/webstore/detail/akamai-developer-toolkit/oeekflkhfpllpepjdkpodopelgaebeed/) and tell us what features you would like to see within the extension using the feedback button within the extension. 40 | 41 | 42 | #### Change Log: 43 | > Update: 07/18/18: Support added to pruge content using CP codes or Cache Tags
44 | > Update: 07/16/18: Support added to a) Translate error reference codes and b) Fetch logs from Akamai servers using Hostname and Ghost IP address
45 | > Update: 07/07/18: Support added for proxying HTTP requests, flush DNS cache and enabling Akamai debug headers
46 | > Version 1: API credentials manager, ability to issue fast purge request directly from the page you are working on
47 | 48 | #### Interested in our roadmap or found an issue? 49 | - Here is a link to our [Roadmap and Backlog](https://trello.com/b/NMa7Qyn7/akamai-developer-toolkit-project-backlog-and-dashboard)
50 | - If you have feedback or bugs you would like to report please create an issue in this repo
51 | 52 | #### Code Contributors 53 | - Ricky Yu 54 | - Ishika Sachdeva 55 | - Akhil Jayaprakash 56 | > Would you like your name here too? If you wish to contribute code to the extension, please email: ajayapra@akamai.com
57 | 58 | 59 | #### Disclaimer: 60 | This is an unofficial extension and there will be no Akamai engineering or Akamai Technical support provided in case the tool fails or throws errors, that being said please report all issues using the feedback button within the extension. All API tokens and credentials are stored locally in your laptop and not beamed up to the internet, we run edgegrid within the extension and pass the computed authorization headers with the API requests. 61 | 62 | 63 | -------------------------------------------------------------------------------- /cmanager/cmanager-bg.js: -------------------------------------------------------------------------------- 1 | var activatedTokenCache = {}; 2 | 3 | var initCmanagerStorageState = function() { 4 | console.log("initializing Cmanager Storage"); 5 | chrome.storage.local.get("active_token", function(result) { 6 | if(result['active_token'] == undefined) { 7 | activatedTokenCache = {}; 8 | chrome.storage.local.set({'active_token': ""}); 9 | } else { 10 | var active_token = b(result['active_token']); 11 | if(active_token) { 12 | activatedTokenCache = active_token; 13 | } 14 | } 15 | }); 16 | chrome.storage.local.get("tokens", function(result) { 17 | if(result['tokens'] == undefined) { 18 | chrome.storage.local.set({'tokens': []}); 19 | } 20 | }); 21 | } 22 | 23 | var updateActiveTokenCache = function(token) { 24 | var urlparser = document.createElement('a'); 25 | urlparser.href = token.baseurl; 26 | activatedTokenCache = token; 27 | activatedTokenCache.baseurl = urlparser.origin; 28 | //send msg to cmanager.js about active token cache being updated 29 | chrome.runtime.sendMessage({ 30 | msg: "activecachetokenupdated", 31 | data: { 32 | subject: "Activecacheupdated", 33 | content: "yes" 34 | } 35 | }); 36 | console.log("ActiveTokenCache updated"); 37 | } 38 | 39 | var updateActiveToken = function(token) { 40 | var en_token = a(token); 41 | chrome.storage.local.get("active_token", function(data) { 42 | if (data['active_token'] != "") { 43 | var active_token = b(data['active_token']); 44 | if (active_token && active_token.uniqid != token.uniqid) { 45 | if (en_token) { 46 | chrome.storage.local.set({'active_token': en_token}, function() { 47 | updateActiveTokenCache(token); 48 | console.log('Active Token Updated: ' + token.desc); 49 | }); 50 | } 51 | } 52 | } else { 53 | if (en_token) { 54 | chrome.storage.local.set({'active_token': en_token}, function() { 55 | updateActiveTokenCache(token); 56 | console.log('Active Token Updated: ' + token.desc); 57 | }); 58 | } 59 | } 60 | }); 61 | } 62 | 63 | var downloadToken = function(objToken) { 64 | var body = ""; 65 | var field_names = { 66 | baseurl: "host", 67 | clienttoken: "client_token", 68 | accesstoken: "access_token", 69 | secret: "client_secret", 70 | desc: "credential_desc", 71 | tokentype: "credential_type" 72 | }; 73 | for (var each in field_names) { 74 | if (each === "baseurl") { 75 | var url = objToken[each].replace('https://', ''); 76 | body += field_names[each] + " = " + url + "\n\n"; 77 | } else { 78 | body += field_names[each] + " = " + objToken[each] + "\n\n"; 79 | } 80 | } 81 | var filename = objToken.desc.replace(/\s+/g, '-'); 82 | var atag = document.createElement('a'); 83 | atag.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(body)); 84 | atag.setAttribute('download', filename); 85 | atag.style.display = 'none'; 86 | document.body.appendChild(atag); 87 | atag.click(); 88 | document.body.removeChild(atag); 89 | } 90 | 91 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 92 | if (message.type === "cmanager") { 93 | var token_id = message.token_id; 94 | switch(message.action) { 95 | case "delete": 96 | chrome.storage.local.get(['tokens'], function(data) { 97 | var arr_tokens = data['tokens']; 98 | var token_index_to_delete; 99 | // for the case when decryption failed. token_id is index of token list 100 | var num_token_id = parseInt(token_id); 101 | if (num_token_id < 1000) { 102 | token_index_to_delete = num_token_id; 103 | } else { 104 | for (var i=0; i < arr_tokens.length; i++) { 105 | var de_token = b(arr_tokens[i]); 106 | if (de_token.uniqid == token_id) { 107 | token_index_to_delete = i; 108 | } 109 | // delete token == current active token 110 | if (!jQuery.isEmptyObject(activatedTokenCache)) { 111 | if (token_id == activatedTokenCache.uniqid) { 112 | activatedTokenCache = {}; 113 | chrome.storage.local.set({'active_token': ""}); 114 | chrome.runtime.sendMessage({ 115 | msg: "activecachetokenupdated", 116 | data: { 117 | subject: "Activecacheupdated", 118 | content: "yes" 119 | } 120 | }); 121 | } 122 | } 123 | } 124 | } 125 | if (typeof token_index_to_delete == 'number') { 126 | arr_tokens.splice(token_index_to_delete, 1); 127 | if (arr_tokens.length == 0){ 128 | chrome.storage.local.set({ 129 | 'active_token': "", 130 | 'tokens': [] 131 | }); 132 | } else { 133 | chrome.storage.local.set({'tokens': arr_tokens}); 134 | } 135 | } 136 | }); 137 | 138 | break; 139 | case "activate": 140 | chrome.storage.local.get('tokens', function(tokens) { 141 | var arr_tokens = tokens['tokens']; 142 | for (var i = 0; i < arr_tokens.length; i++) { 143 | var de_token = b(arr_tokens[i]); 144 | if (de_token) { 145 | if (de_token.uniqid == token_id) { 146 | updateActiveToken(de_token); 147 | break; 148 | } 149 | } 150 | } 151 | }); 152 | break; 153 | case "download": 154 | chrome.storage.local.get('tokens', function(tokens) { 155 | var arr_tokens = tokens['tokens']; 156 | for (var i = 0; i < arr_tokens.length; i++) { 157 | var de_token = b(arr_tokens[i]); 158 | if (de_token) { 159 | if (de_token.uniqid == token_id) { 160 | downloadToken(de_token); 161 | break; 162 | } 163 | } 164 | } 165 | }); 166 | break; 167 | case "deleteall": 168 | activatedTokenCache = {}; 169 | chrome.storage.local.set({ 170 | 'active_token': "", 171 | 'tokens': [] 172 | }); 173 | chrome.runtime.sendMessage({ 174 | msg: "activecachetokenupdated", 175 | data: { 176 | subject: "Activecacheupdated", 177 | content: "yes" 178 | } 179 | }); 180 | break; 181 | default: 182 | break; 183 | } 184 | } 185 | }); 186 | -------------------------------------------------------------------------------- /cmanager/cmanager.js: -------------------------------------------------------------------------------- 1 | var loadCredentialList = function () { 2 | $('#tokenlist').empty().hide(); 3 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 4 | chrome.storage.local.get('tokens', function(data) { 5 | var arr_tokens = data['tokens']; 6 | if (arr_tokens.length > 0) { 7 | for (i = 0; i < arr_tokens.length; i++) { 8 | var api_credential = backgroundpage.b(arr_tokens[i]); 9 | if (!api_credential) { api_credential = {desc: "Failed to load", tokentype: "Please delete and register again", uniqid: i}; } 10 | var list_html = '
  • '; 11 | list_html += ''; 12 | list_html += '' + api_credential.desc + ''; 13 | list_html += '

    ' + api_credential.tokentype + '

    '; 14 | list_html += '

    Click on Activate to enable this credential for your requests

    '; 15 | list_html += '
    '; 16 | list_html += '
    Activate
    '; 17 | list_html += '
    Edit
    '; 18 | list_html += '
    Download
    '; 19 | list_html += '
    Delete
    '; 20 | list_html += '
  • '; 21 | $('#tokenlist').append(list_html); 22 | } 23 | // if (arr_tokens.length == 1) {$('[action=activate]').trigger('click')}; 24 | $("#apitab-nocredential").hide(); 25 | $('#tokenlist').show(); 26 | markActiveToken(); 27 | } else { 28 | $("#apitab-nocredential").show(); 29 | return false; 30 | } 31 | }); 32 | }); 33 | } 34 | 35 | var loadActiveCredentiallist = function () { 36 | $('#activetoken_inuse').empty().hide(); 37 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 38 | chrome.storage.local.get('tokens', function(data) { 39 | var arr_tokens = data['tokens']; 40 | var activetokenid = backgroundpage.activatedTokenCache.uniqid; 41 | // console.log(activetokenid); 42 | //console.log(arr_tokens.length); 43 | if (arr_tokens.length >0 ){ 44 | if (activetokenid !== undefined) { 45 | // var activetokenid = backgroundpage.activatedTokenCache.uniqid; 46 | //console.log(activetokenid); 47 | var api_credential1 = backgroundpage.activatedTokenCache; 48 | // console.log(api_credential1); 49 | if (!api_credential1) { api_credential1 = {desc: "Failed to load", tokentype: "Please delete and register again", uniqid: activetokenid}; } 50 | var list_html1 = '
    '; 51 | list_html1 += '
  • '; 52 | list_html1 += ''; 53 | list_html1 += '
    ' + api_credential1.desc + '
    '; 54 | list_html1 += '

    ' + api_credential1.tokentype + '

    '; 55 | list_html1 += '

    This is the credential that is currently active across the extension. This credential will be used for any OPEN api call the extension has to make.

  • '; 56 | list_html1 += '
    '; 57 | list_html1 += 'Switch Akamai API credentials'; 58 | list_html1 += '
    '; 59 | $('#activetoken_inuse').append(list_html1); 60 | // $("#apitab-nocredential").hide(); 61 | $('#activetoken_inuse').show(); 62 | 63 | // $(".key-img").hide(); 64 | // $("#activetoken_inuse").closest("li.avatar").find(".key-img").fadeToggle(); 65 | // $('.collection-item.avatar').addClass("disabled"); 66 | //$("#activetoken_inuse").closest("li.avatar").removeClass("disabled"); 67 | // markActiveToken(); 68 | } 69 | else { 70 | var list_html2 = '
  • '; 71 | // list_html2 += ''; 72 | list_html2 += '

    Congrats on adding your first Akamai API credential! You need to activate the credential in order to use it across the extension

    '; 73 | list_html2 += '

    Activate Akamai API credentials

    '; 74 | list_html2 += '
  • '; 75 | $('#activetoken_inuse').append(list_html2); 76 | $('#activetoken_inuse').show(); 77 | } 78 | } 79 | else { 80 | $("#apitab-nocredential").show(); 81 | return false; 82 | } 83 | }); 84 | }); 85 | } 86 | 87 | //receive message that active token has been updated 88 | chrome.runtime.onMessage.addListener( 89 | function(request, sender, sendResponse) { 90 | if (request.msg === "activecachetokenupdated") { 91 | // To do something 92 | loadActiveCredentiallist(); 93 | } 94 | } 95 | ); 96 | 97 | // Mark current active_token 98 | var markActiveToken = function() { 99 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 100 | $("a[tokenid='" + backgroundpage.activatedTokenCache.uniqid + "'][action='activate']").trigger('click'); 101 | }); 102 | } 103 | 104 | $('#deletealltoken').click(function() { 105 | chrome.runtime.sendMessage({type: "gaq", target: "Delete_all_tokens", behavior: "clicked"}); 106 | chrome.runtime.sendMessage({type: "cmanager", action: "deleteall",}); 107 | $("#tokenlist").hide(); 108 | $("#apitab-nocredential").show(); 109 | }); 110 | 111 | $('#addnewtoken, #addnewtokenlink').click(function() { 112 | chrome.runtime.sendMessage({type: "gaq", target: "Add_new_credential", behavior: "clicked"}); 113 | // chrome.tabs.create({ 114 | // url: 'cmanager/credential.html' 115 | // }); 116 | $('.addingapitoken').empty(); 117 | $('.addingapitoken').append('
    Adding an API Credential
    Upload a credential file
    File
    '); 118 | 119 | loadcredentialaddition(); 120 | 121 | }); 122 | 123 | $(document).on('click', '#tokenlist li a', function(event) { 124 | var button_type = $(this).attr('action'); 125 | var token_id = $(this).attr('tokenid'); 126 | switch (button_type) { 127 | case "edit": 128 | chrome.tabs.create({url: 'cmanager/credential.html?id=' + token_id}); 129 | chrome.runtime.sendMessage({type: "gaq", target: "Editing_an_api_token", behavior: "clicked"}); 130 | break; 131 | case "delete": 132 | $(this).closest("li.avatar").fadeOut("normal", function() { 133 | if ($(this).parent("ul").children().length === 1) { 134 | $("#tokenlist").hide(); 135 | $("#apitab-nocredential").show(); 136 | } 137 | $(this).remove(); 138 | }); 139 | //loadActiveCredentiallist(); 140 | 141 | chrome.runtime.sendMessage({type: "cmanager", action: "delete", token_id: token_id}); 142 | chrome.runtime.sendMessage({type: "gaq", target: "Deleting_an_api_token", behavior: "clicked"}); 143 | break; 144 | case "activate": 145 | $(".key-img").hide(); 146 | $(this).closest("li.avatar").find(".key-img").fadeToggle(); 147 | $('.collection-item.avatar').addClass("disabled"); 148 | $(this).closest("li.avatar").removeClass("disabled"); 149 | 150 | chrome.runtime.sendMessage({type: "cmanager", action: "activate", token_id: token_id}); 151 | chrome.runtime.sendMessage({type: "gaq", target: "Activating_an_api_token", behavior: "clicked"}); 152 | break; 153 | case "download": 154 | chrome.runtime.sendMessage({type: "cmanager", action: "download", token_id: token_id}); 155 | chrome.runtime.sendMessage({type: "gaq", target: "Downloading_an_api_token", behavior: "clicked"}); 156 | break; 157 | default: 158 | break; 159 | } 160 | }); 161 | -------------------------------------------------------------------------------- /cmanager/credential.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Add/Edit API Credentials 4 | 5 | 6 | 7 |
    8 |
    9 | 10 |
    11 |
    12 |
    13 | Adding an API Credential 14 |
    15 |
    16 | 17 | 18 |
    19 |
    20 |
    21 |
    22 | 23 | 24 |
    25 |
    26 |
    27 |
    28 | 29 | 30 |
    31 |
    32 |
    33 |
    34 | 35 | 36 |
    37 |
    38 |
    39 |
    40 | 41 | 42 |
    43 |
    44 |
    45 |
    46 | 52 | 53 |
    54 |
    55 |
    56 |
    57 |
    58 |
    59 | Close 60 | Save & Add Another 61 | Save & Close 62 | Reset 63 |
    64 |
    65 |
    66 |
    67 |
    68 | 69 |
    70 |
    71 |
    72 | Upload a credential file 73 |
    74 |
    75 |
    76 | File 77 | 78 |
    79 |
    80 | 81 |
    82 |
    83 |
    84 |
    85 |
    86 |
    87 | 88 |
    89 |
    90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /cmanager/credential.js: -------------------------------------------------------------------------------- 1 | function loadcredentialaddition(){ 2 | console.log('credential.js loaded'); 3 | // $('select').material_select(); 4 | // $('.initialized').hide(); // materialize bug 5 | 6 | 7 | chrome.runtime.sendMessage({type: "gaq", target: "Add_new_credentials_page", behavior: "loaded"}); 8 | 9 | var credentialType = function(domain) { 10 | if (domain.match(/.*\.luna\.akamaiapis\.net\/?$/i)) { 11 | return "luna"; 12 | } else if (domain.match(/.*\.purge\.akamaiapis\.net\/?$/i)) { 13 | return "purge"; 14 | } else { 15 | return "others"; 16 | } 17 | return null; 18 | } 19 | 20 | var apiTokenIds = ['credential_desc', 'baseurl', 'accesstoken', 'clienttoken', 'secret', 'tokentype']; 21 | var passedId = getUrlParameter('id'); 22 | var edit_mode = false; 23 | 24 | if (passedId != '') { 25 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 26 | chrome.storage.local.get('tokens', function(tokens) { 27 | var arr_tokens = tokens['tokens']; 28 | var edit_token = ""; 29 | for(var i=0; i < arr_tokens.length; i++) { 30 | var de_token = backgroundpage.b(arr_tokens[i]); 31 | if (de_token) { 32 | if (de_token.uniqid == passedId) { 33 | edit_token = de_token; 34 | edit_mode = true; 35 | break; 36 | } 37 | } else { 38 | alert("Failed to load the credential"); 39 | return; 40 | } 41 | } 42 | for (var i=0; i < apiTokenIds.length; i++) { 43 | $('#'+apiTokenIds[i]).val(edit_token[apiTokenIds[i]]); 44 | if (apiTokenIds[i] == 'credential_desc') { 45 | $('#credential_desc').val(edit_token.desc); 46 | } 47 | } 48 | $('select').material_select(); 49 | }); 50 | }); 51 | } 52 | 53 | $('#submitButton, #submitButton-add').click(function() { 54 | chrome.runtime.sendMessage({type: "gaq", target: "New_credentials_page_save_btn", behavior: "clicked"}); 55 | 56 | var button_id = $(this).attr('id'); 57 | var desc = $("#credential_desc").val().trim(); 58 | var baseurl = $("#baseurl").val().trim(); 59 | var accesstoken = $("#accesstoken").val().trim(); 60 | var clienttoken = $("#clienttoken").val().trim(); 61 | var secret = $("#secret").val().trim(); 62 | var tokentype = $("#tokentype").val(); 63 | 64 | for (var i=0; i < apiTokenIds.length; i++) { 65 | var obj_input = $('#'+apiTokenIds[i]); 66 | if (obj_input.val() != null) { 67 | var user_input_text = obj_input.val().trim().replace(/\s+/g, ''); 68 | } else { 69 | var user_input_text = obj_input.val(); 70 | } 71 | if (user_input_text == null || user_input_text == "") { 72 | switch(apiTokenIds[i]) { 73 | case 'credential_desc': 74 | alert('Please enter Credential Description'); 75 | obj_input.focus(); 76 | break; 77 | case 'baseurl': 78 | alert('Please enter Host'); 79 | obj_input.focus(); 80 | break; 81 | case 'accesstoken': 82 | alert('Please enter Access Token'); 83 | obj_input.focus(); 84 | break; 85 | case 'clienttoken': 86 | alert('Please enter Client Token'); 87 | obj_input.focus(); 88 | break; 89 | case 'secret': 90 | alert('Please enter Client Secret'); 91 | obj_input.focus(); 92 | break; 93 | case 'tokentype': 94 | alert('Please select Credential Type'); 95 | obj_input.focus(); 96 | break; 97 | default: 98 | break; 99 | } 100 | return false; 101 | } 102 | } 103 | 104 | var urlparser = document.createElement('a'); 105 | urlparser.href = baseurl; 106 | if (urlparser.protocol !== 'https:') { 107 | alert('Host should start with https://'); 108 | $("#baseurl").focus(); 109 | return false; 110 | } 111 | 112 | var domainre = /^https:\/\/[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]+\.(?:purge|luna|imaging|imaging-staging|luna-dev|purge-dev|imaging-dev|cloudsecurity|cloudsecurity-staging|cloudsecurity-dev)\.akamaiapis\.net\/?$/i; 113 | if (!baseurl.match(domainre)) { 114 | alert('Please check if Host is in right format'); 115 | $("#baseurl").focus(); 116 | return false; 117 | } 118 | 119 | var token_data = { 120 | 'desc': desc, 121 | 'baseurl': baseurl, 122 | 'accesstoken': accesstoken, 123 | 'clienttoken': clienttoken, 124 | 'secret': secret, 125 | 'tokentype': tokentype, 126 | 'uniqid': new Date().getTime().toString() 127 | } 128 | 129 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 130 | 131 | // edit mode, update active_token if it was active. 132 | if (edit_mode) { 133 | if (backgroundpage.activatedTokenCache.uniqid == passedId) { 134 | backgroundpage.updateActiveToken(token_data); 135 | } 136 | } 137 | 138 | var en_token_data = backgroundpage.a(token_data); 139 | if (!en_token_data) { 140 | alert("Encryption failed. Please try again"); 141 | return false; 142 | } 143 | 144 | chrome.storage.local.get('tokens', function(tokens) { 145 | var arr_tokens = tokens['tokens']; 146 | if (arr_tokens.length != 0) { 147 | if (edit_mode) { 148 | for (var i=0; i < arr_tokens.length; i++) { 149 | var de_token = backgroundpage.b(arr_tokens[i]); 150 | if (de_token) { 151 | if(de_token.uniqid == passedId) { 152 | arr_tokens[i] = en_token_data; 153 | } 154 | } 155 | } 156 | } else { 157 | arr_tokens.unshift(en_token_data); 158 | } 159 | } else if (arr_tokens.length > 20) { 160 | alert("You can only add up to 20 credentials"); 161 | return false; 162 | } else { 163 | arr_tokens = [en_token_data]; 164 | } 165 | 166 | chrome.storage.local.set({'tokens': arr_tokens} , function() { 167 | // alert('Saved Successfully'); 168 | swal({ 169 | title: 'Success!', 170 | text: 'Your credential has been successfully saved and encrypted locally', 171 | type: 'success', 172 | }) 173 | chrome.runtime.sendMessage({type: "gaq", target: "New_credentials_page_save_successful", behavior: "yes"}); 174 | if (button_id == "submitButton-add") { 175 | $("#clearButton").trigger('click'); 176 | loadCredentialList(); 177 | loadActiveCredentiallist(); 178 | } else if (button_id == "submitButton") { 179 | $('.addingapitoken').empty(); 180 | loadCredentialList(); 181 | loadActiveCredentiallist(); 182 | } 183 | }); 184 | }); 185 | }); 186 | }); 187 | 188 | 189 | 190 | $('#clearButton').click(function() { 191 | chrome.runtime.sendMessage({type: "gaq", target: "New_credentials_page_reset_btn", behavior: "clicked"}); 192 | for (var i=0; i < apiTokenIds.length; i++) { 193 | obj_input = $('#'+apiTokenIds[i]).val(null); 194 | } 195 | $(".file-path").val(''); 196 | $(":file").val(''); 197 | Materialize.updateTextFields(); 198 | $('select').material_select(); 199 | }); 200 | 201 | $('#closed_api_Button').click(function(){ 202 | $('.addingapitoken').empty(); 203 | loadCredentialList(); 204 | loadActiveCredentiallist(); 205 | }); 206 | 207 | $(":file").change(function(){ 208 | console.log('file uploaded'); 209 | var uploaded_file = this.files[0]; 210 | if (!uploaded_file) { 211 | alert("Failed to load file"); 212 | } else if (!uploaded_file.type.match('text.*')) { 213 | alert(uploaded_file.name + " is not a valid text file"); 214 | } else { 215 | var read = new FileReader(); 216 | read.onload = function(frObj) { 217 | var f_body = frObj.target.result; 218 | var arr_fline = f_body.split('\n'); 219 | var split_re = /secret=|host=|token=/i; 220 | var arr_tokens = []; 221 | for (var i=0; i < arr_fline.length; i++) { 222 | var fline_trimed = arr_fline[i].replace(/\s+/g, ''); 223 | if (fline_trimed.match(/.*host.*akamaiapis\.net.*|.*akamaiapis\.net.*host.*/i)) { 224 | arr_tokens.push({ token_type: "host", token_value: fline_trimed.split(split_re)[1] }); 225 | } else if (fline_trimed.match(/.*client.*secret.*|.*secret.*client.*/i)) { 226 | arr_tokens.push({ token_type: "client_secret", token_value: fline_trimed.split(split_re)[1] }); 227 | } else if (fline_trimed.match(/.*client.*token.*|.*token.*client.*/i)) { 228 | arr_tokens.push({ token_type: "client_token", token_value: fline_trimed.split(split_re)[1] }); 229 | } else if (fline_trimed.match(/.*access.*token.*|.*token.*access.*/i)) { 230 | arr_tokens.push({ token_type: "access_token", token_value: fline_trimed.split(split_re)[1] }); 231 | } else { 232 | // 233 | } 234 | } 235 | for (var i=0; i < arr_tokens.length; i++) { 236 | switch (arr_tokens[i].token_type) { 237 | case "host": 238 | $("#baseurl").val("https://" + arr_tokens[i].token_value); 239 | $("#baseurl").trigger("change"); 240 | break; 241 | case "client_secret": 242 | $("#secret").val(arr_tokens[i].token_value); 243 | break; 244 | case "client_token": 245 | $("#clienttoken").val(arr_tokens[i].token_value); 246 | break; 247 | case "access_token": 248 | $("#accesstoken").val(arr_tokens[i].token_value); 249 | break; 250 | default: 251 | break; 252 | } 253 | } 254 | } 255 | read.readAsText(uploaded_file); 256 | } 257 | }); 258 | 259 | $('#baseurl').on("change paste keyup", function() { 260 | var credential_type = credentialType($(this).val()); 261 | if (credential_type === "purge") { 262 | $("#tokentype").val("Fast Purge APIs"); 263 | $('select').material_select(); 264 | } else if (credential_type === "luna") { 265 | $("#tokentype").val("General OPEN APIs"); 266 | $('select').material_select(); 267 | } else { 268 | $("#tokentype").val("Other OPEN APIs"); 269 | $('select').material_select(); 270 | } 271 | }); 272 | 273 | } // document ready 274 | -------------------------------------------------------------------------------- /css/common.css: -------------------------------------------------------------------------------- 1 | .secondary-content a:hover { 2 | text-decoration: underline; 3 | } 4 | 5 | .see-more-link a:hover { 6 | text-decoration: underline; 7 | } 8 | 9 | li.disabled { 10 | color: #D3D3D3; 11 | } 12 | 13 | .secondary-content { 14 | top: 4px !important; 15 | font-size: 13px; 16 | width: 100px; 17 | line-height: 19px; 18 | } 19 | 20 | .submit-button { 21 | width: 150px; 22 | padding-left: 15px; 23 | padding-right: 15px; 24 | } 25 | 26 | #joblist .collection-item { 27 | padding-left: 20px; 28 | } 29 | 30 | /* general */ 31 | .row-stacked { 32 | margin-top: 0px !important; 33 | margin-bottom: 0px !important; 34 | } 35 | 36 | /* token list */ 37 | #tokenlist.collection { 38 | font-size: 11.5px; 39 | border-left: unset; 40 | border-right: unset; 41 | } 42 | 43 | /* history list */ 44 | #historylist.collapsible { 45 | border-left: unset; 46 | border-right: unset; 47 | box-shadow: unset; 48 | font-size: 13px; 49 | } 50 | 51 | /* tabs */ 52 | .tabs .tab a.active { 53 | color: #21a5d2; 54 | } 55 | 56 | .tabs .tab a:hover { 57 | color: #21a5d2; 58 | } 59 | 60 | .tabs .tab a { 61 | color: #969696; 62 | } 63 | 64 | .tabs .indicator { 65 | background-color: #f38b00; 66 | } 67 | 68 | /* switch button */ 69 | .switch label input[type=checkbox]:checked+.lever:after { 70 | background-color: #f38b00 !important; 71 | } 72 | .switch label input[type=checkbox]:checked+.lever { 73 | background-color: #ffd092 !important; 74 | } 75 | 76 | /* Tutorial Video Icon */ 77 | .tutorial-video-icon { 78 | vertical-align: top; 79 | } 80 | 81 | /* padding top */ 82 | .padding-top { 83 | padding-top: 15px; 84 | } 85 | 86 | /* materilize overriding */ 87 | textarea.materialize-textarea { 88 | padding: 1.5rem 0 0 0 !important; 89 | } 90 | 91 | /* card alert */ 92 | .card-alert { 93 | margin: 0.5rem 0 0rem 0; 94 | } 95 | .card-content.card-alert-content { 96 | padding: 10px; 97 | display: table; 98 | } 99 | .card-alert p { 100 | top: 16px; 101 | font-size: 14px; 102 | padding-left: 6px; 103 | display: table-cell; 104 | vertical-align: middle; 105 | } 106 | .card-alert i { 107 | font-size: 30px; 108 | display: table-cell; 109 | vertical-align: middle; 110 | } 111 | .card-alert .clearmark { 112 | background: none; 113 | border: none; 114 | font-size: 18px; 115 | color: #03a9f4; 116 | cursor: pointer; 117 | position: absolute; 118 | top: 15px; 119 | right: 10px; 120 | } 121 | 122 | /* twitter button */ 123 | .twitter-wjs { 124 | /* display: inline; */ 125 | } 126 | 127 | /* table inside table - history table */ 128 | tr.shown:hover { 129 | background-color: unset !important; 130 | } 131 | .history-table { 132 | font-size: 14px; 133 | margin-top: 10px; 134 | margin-bottom: 10px; 135 | } 136 | .history-table tbody tr { 137 | background-color: #E7F2FE !important; 138 | } 139 | .history-table td { 140 | text-align: left !important; 141 | padding-left: 20px !important; 142 | } 143 | .show-more { 144 | width: 1%; 145 | } 146 | .delete-record { 147 | width: 1%; 148 | } 149 | 150 | /* debug request */ 151 | .debug-card-btn { 152 | margin-top: 20px; 153 | width: 100%; 154 | } 155 | 156 | /* for wrapping text in datatable */ 157 | table pre { 158 | white-space: pre-wrap; /* css-3 */ 159 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 160 | white-space: -pre-wrap; /* Opera 4-6 */ 161 | white-space: -o-pre-wrap; /* Opera 7 */ 162 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 163 | word-break: break-all; 164 | font-size: 15px; 165 | font-family: Consolas; 166 | } 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /css/jquery.tour.css: -------------------------------------------------------------------------------- 1 | .tour_item.active { 2 | z-index: 9998; 3 | position: relative; 4 | } 5 | #tour_mask { 6 | background-color: rgb(0, 0, 0); 7 | display: block; 8 | height: 100%; 9 | left: 0; 10 | opacity: 0.7; 11 | position: fixed; 12 | top: 0; 13 | width: 100%; 14 | z-index: 20; 15 | } 16 | #tour_dialog { 17 | background-color: #363636; 18 | border: 1px solid #000000; 19 | border-radius: 5px 5px 5px 5px; 20 | box-shadow: 0 0 10px 2px #367ABB, 0 2px 0 0 rgba(255, 255, 255, 0.3) inset; 21 | color: #FFFFFF; 22 | display: none; 23 | line-height: 20px; 24 | padding: 15px; 25 | position: absolute !important; 26 | text-shadow: 0 1px 0 #000000; 27 | z-index: 9999; 28 | text-align: left; 29 | max-width: 380px; 30 | font-size: 14px 31 | } 32 | #tour_dialog:hover a { 33 | opacity: 1; 34 | transition: opacity 1s; 35 | -moz-transition: opacity 1s; 36 | -webkit-transition: opacity 1s; 37 | -o-transition: opacity 1s; 38 | } 39 | #tour_dialog hr { 40 | background-color: rgba(255, 255, 255, 0.2); 41 | border: medium none; 42 | border-top: 1px solid #000; 43 | height: 2px; 44 | margin: 15px 0; 45 | } 46 | 47 | #tour_dialog #exit_tour_dialog_btn.button { 48 | border-radius: 4px; 49 | display: inline-block; 50 | font-size: 14px; 51 | padding: 6px 14px; 52 | position: relative; 53 | vertical-align: top; 54 | cursor: pointer; 55 | float: right; 56 | border: 1px solid #000; 57 | background-color: #9e9e9e !important; 58 | } 59 | 60 | #tour_dialog #exit_tour_dialog_btn.button:hover { 61 | background: -moz-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 62 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #44a4c7), color-stop(100%, #2136bf)); 63 | background: -webkit-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 64 | background: -o-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 65 | background: -ms-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 66 | background: linear-gradient(top, #44a4c7 0%, #2136bf 100%); 67 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='44a4c7', endColorstr='2136bf', GradientType=0); 68 | color: #fff !important; 69 | } 70 | #tour_dialog #tour_dialog_btn.button { 71 | border-radius: 4px; 72 | -webkit-border-radius: 4px; 73 | -moz-border-radius: 4px; 74 | border: 1px solid #000; 75 | background: #3f9abc; 76 | background: -moz-linear-gradient(top, #3f9abc 0%, #1f32b3 100%); 77 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #3f9abc), color-stop(100%, #1f32b3)); 78 | background: -webkit-linear-gradient(top, #3f9abc 0%, #1f32b3 100%); 79 | background: -o-linear-gradient(top, #3f9abc 0%, #1f32b3 100%); 80 | background: -ms-linear-gradient(top, #3f9abc 0%, #1f32b3 100%); 81 | background: linear-gradient(top, #3f9abc 0%, #1f32b3 100%); 82 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='@start', endColorstr='@end', GradientType=0); 83 | -moz-box-shadow: 0 0 1px 1px rgba(255, 255, 255, 0.1), 0 1px 0 0 #99DBF8 inset; 84 | -webkit-box-shadow: 0 0 1px 1px rgba(255, 255, 255, 0.1), 0 1px 0 0 #99DBF8 inset; 85 | box-shadow: 0 0 1px 1px rgba(255, 255, 255, 0.1), 0 1px 0 0 #99DBF8 inset; 86 | color: #eee; 87 | display: inline-block; 88 | font-size: 14px; 89 | padding: 6px 14px; 90 | position: relative; 91 | text-decoration: none; 92 | vertical-align: top; 93 | text-shadow: 0 -1px 1px #000000; 94 | cursor: pointer; 95 | float: right; 96 | } 97 | #tour_dialog #tour_dialog_btn.button:hover { 98 | background: -moz-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 99 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #44a4c7), color-stop(100%, #2136bf)); 100 | background: -webkit-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 101 | background: -o-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 102 | background: -ms-linear-gradient(top, #44a4c7 0%, #2136bf 100%); 103 | background: linear-gradient(top, #44a4c7 0%, #2136bf 100%); 104 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='44a4c7', endColorstr='2136bf', GradientType=0); 105 | color: #fff !important; 106 | } 107 | #tour_dialog .arrow { 108 | position: absolute; 109 | width: 0; 110 | height: 0; 111 | } 112 | #tour_dialog .arrow.top { 113 | border-left: 10px solid transparent; 114 | border-right: 10px solid transparent; 115 | border-top: 10px solid #363636; 116 | bottom: -10px; 117 | left: 48%; 118 | } 119 | #tour_dialog .arrow.bottom { 120 | border-bottom: 10px solid #363636; 121 | border-left: 10px solid transparent; 122 | border-right: 10px solid transparent; 123 | left: 48%; 124 | top: -8px; 125 | } 126 | #tour_dialog .arrow.right { 127 | border-bottom: 10px solid transparent; 128 | border-right: 10px solid #363636; 129 | border-top: 10px solid transparent; 130 | left: -10px; 131 | top: 8px; 132 | } 133 | #tour_dialog .arrow.left { 134 | border-bottom: 10px solid transparent; 135 | border-left: 10px solid #363636; 136 | border-top: 10px solid transparent; 137 | right: -10px; 138 | top: 8px; 139 | } 140 | body { 141 | font-family: helvetica; 142 | background: #cedce7; 143 | /* Old browsers */ 144 | background: -moz-radial-gradient(center, ellipse cover, #fff 0%, #dbdbdb 100%); 145 | /* FF3.6+ */ 146 | background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #fff), color-stop(100%, #dbdbdb)); 147 | /* Chrome,Safari4+ */ 148 | background: -webkit-radial-gradient(center, ellipse cover, #fff 0%, #dbdbdb 100%); 149 | /* Chrome10+,Safari5.1+ */ 150 | background: -o-radial-gradient(center, ellipse cover, #fff 0%, #dbdbdb 100%); 151 | /* Opera 12+ */ 152 | background: -ms-radial-gradient(center, ellipse cover, #fff 0%, #dbdbdb 100%); 153 | /* IE10+ */ 154 | background: radial-gradient(center, ellipse cover, #fff 0%, #dbdbdb 100%); 155 | /* W3C */ 156 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff', endColorstr='#dbdbdb', GradientType=1); 157 | /* IE6-9 fallback on horizontal gradient */ 158 | } 159 | .demo_container { 160 | margin: auto; 161 | text-align: center; 162 | width: 330px; 163 | } 164 | .demo_item { 165 | background-color: #fff; 166 | border: 1px solid #B1B1B1; 167 | border-radius: 10px; 168 | box-shadow: 0 3px 0 0 rgba(0, 0, 0, 0.2); 169 | display: inline-block; 170 | margin: 75px; 171 | padding: 15px; 172 | } -------------------------------------------------------------------------------- /css/proxy-settings.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 5px 10px 10px; 3 | } 4 | 5 | h1 { 6 | color: #53637D; 7 | font: 26px/1.2 Helvetica, sans-serif; 8 | font-size: 200%; 9 | margin: 0; 10 | padding-bottom: 4px; 11 | text-shadow: white 0 1px 2px; 12 | } 13 | 14 | div[role='main'] { 15 | border-radius: 5px; 16 | background: #EAEEF3; 17 | font: 14px/1 Arial,Sans Serif; 18 | padding: 10px; 19 | width: 563px; 20 | box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5); 21 | overflow: hidden; 22 | transition: background-color 0.5s ease-out; 23 | } 24 | 25 | div[role='main'].incognito { 26 | background: #496281 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAhCAYAAABeD2IVAAAFz0lEQVRYw8VYC0xcRRQtUEprERQ1VkohSGNpwaCYYNBUjS2K+KEVTUkDiqY0hWD5xxhDINgQqIZviRAkSiiWNDRxWypNpaatEQk/CwvlWyks3+XPAssu7I7nbmabx+suPzfrTU7yljfz5sy95947w5YtpjcLwBLYBuzgsAGs+DuzGZGwBh4BHIDdwHPA8xxuwBOcnIWpPUAL7wQeB54CngYcAWdO4kXgDeBoWFhYSk5OTtmFCxeuxsbGpuBv3sCTwFZTkrLmXtgH+AJ+QAAQCBzz8/P7MiUl5aebN29Kh4eHFVNTU2xoaIgNDAywe/fusYyMjO858R2mJEUe2ldZWfljd3f3P+3t7bK2trZBuVyuYCJbXFxkXV1drLOzU4e7d++yzMzMasz3AexMSYq89CoRYuuwvr6+B6Q6OjpYUVFRG+Yf4iE0iZYoc5woVK2trUPrIUXh05Mir9XW1qow/33gmf8idj0ZypjHuIgj5ubm1OshpdFoVoTwzp07zMbGJsTb23s/16fFZlKcyDjY29u7+fr6HoJFV1dXt7EN2MjIyANSUqmUubq6Jtna2r7OvWW7kUy04IR2+fj4HDx+/HhUYmJiIQQuhZ5mN0JKqVSuEHtWVlbd6dOns+3s7N7h9YtKynbuhFWNQuYQGBh4ODs7u2B0dHRauNDMzIx2eXmZabXadRG7f/++jhSylV25ckXOk2D4yJEjSVjnNV7ntq9Fily6Jzg4+CTEOqf/OJFoampSFRQUjDc3Ny+QF9RqtU47hozGE3mUDIbxOtTX1ytQt5T6MQipFGu9zDPbYq0i+ey5c+dyxAvBSxrsXHXixIlmVOsOaGykp6dnYXZ2lt49BHhIWVdXN1VaWipLS0trCQ8P/xseUwrD6+HhEUJO4BFa3VMREREx4+PjCkNhunjx4iAWuI0x16KjowlVYkA7uncYczUyMpJ+3z579mzXwsLCA9fimcXHx6djvb3cGatmHrnTBxr4jSZShaYwCQnC89PQXFNUVNSvMTExv6C/XYqLi6sg0DMISRISEq7h+QY81dHY2DgpDq9CoWCYm8Fbl8FmLaxLROoA8OGpU6dKL1++LCMdGdIPEkF569atIYlE0oNNdGFsNz03NDTI0QOVhrRG31GpVCR4JcrEV1jnFWOZaMVrBx07vIDDQBiQil3XQENDMplseWlpiW3WBOLXovWoy8vLBxA+CTT6NdZ5gR9vtooFvis1NfWTioqKn6uqqv6ihius4NCYZn5+Xuf2zRAi4OSgQQIsT05OrnA71qrmR6BtQlL0wwVpL1nPIqQzCgFpzlB50HuFxlF2TkxMUKiXxBKgb4Dooqen5zHeX63FWUfl/22k/aix+qM3IkEeS05Obs7Pz6+vqakZgAcUY2Njur8T2cHBwSXobbSwsPCPgICAAny7QJgstAaVjry8vEquKwexpiz5WccrJCTkDO1yLWIILcP474DPgQ8oMahpA9+C0FxJSUk7nr/h2vwMSAfhJWFJQAKN8Xku4tCJveWP3d8gb6zWToh0aGjoJYz/FHgToGYbTMmBUM0RnJyccvE7GkiEVlv1cylhpqenGbI7l4v8UWNVfRsn5efs7Jxx/vz5fr0+VvGWuqysrMbNzS0R88KDgoLyEMo+/XvyDI4tcmHC6GsUSkgL5rxFCWbsxGDFY/oSdn+mt7d3gj5w/fp15VrENmokbvRANTbyBdbbz8/tBgsn1agD/v7+cUh7lfAj2KmGmdAoI9PT0//kOnQ01vesedF8t7+/X27oQ0hbrSmJoXBKucD3GAsd3VS8cDIoY2YykgM6RS4/Zj8kckt+sfTDeaeHmdFwHxzj98Y94qKpOz+5u7ufZGY28haOyOX89rzCW9SZ3YuLi39g/4Mhy4ex/kHejFeQ2tvS0vI79ShqE+YEmjxLSkoK5aQsheGjW6snv8EeBT42Az4C3uP/l3DhyWYhvuPZ84PWbt6tzQFH7pCdvCzoSP0LtBi6oflBr2wAAAAASUVORK5CYII=') no-repeat 533px bottom; 27 | } 28 | 29 | form { 30 | transition: transform 0.25s ease; 31 | width: 563px; 32 | } 33 | 34 | form.offscreen { 35 | transform: translateX(-600px); 36 | } 37 | 38 | fieldset { 39 | border: 0; 40 | margin: 0; 41 | padding: 0; 42 | position: relative; 43 | } 44 | 45 | legend { 46 | position: absolute; 47 | left: -999em; 48 | } 49 | 50 | form > fieldset { 51 | border-radius: 5px; 52 | border: 1px solid transparent; 53 | padding: 10px 10px 10px 30px; 54 | margin: 5px 0; 55 | transition: all 0.5s ease; 56 | } 57 | 58 | form > fieldset:hover { 59 | background: rgba(255,255,255,0.1); 60 | border-color: rgba(0,0,0,0.1); 61 | } 62 | 63 | form > fieldset.active { 64 | background: rgba(255,255,255,0.25); 65 | border-color: rgba(0,0,0,0.25); 66 | } 67 | 68 | form > fieldset > input { 69 | margin-left: -20px; 70 | } 71 | 72 | section { 73 | margin: 5px 0 0; 74 | } 75 | 76 | section fieldset:not(:first-child):not(:last-child) { 77 | max-height: 1.6em; 78 | overflow: hidden; 79 | transition: all 0.5s ease; 80 | } 81 | 82 | section.single fieldset:not(:first-child):not(:last-child) { 83 | max-height: 0px; 84 | } 85 | 86 | section fieldset:last-child { 87 | margin-top: 5px; 88 | } 89 | 90 | section fieldset:last-child label { 91 | display: block; 92 | } 93 | 94 | section fieldset:last-child textarea { 95 | width: 412px; 96 | } 97 | 98 | section > fieldset { 99 | position: relative; 100 | padding-left: 60px; 101 | } 102 | 103 | section > fieldset > legend { 104 | left: 0; 105 | top: 4px; 106 | width: 53px; 107 | text-align: right; 108 | } 109 | 110 | input[type='url']:invalid:not(:active):not(:focus) { 111 | border-color: rgba(255,0,0,0.5); 112 | background: rgba(255,0,0,0.25); 113 | } 114 | 115 | input:invalid:not(:active):not(:focus):after { 116 | content: "This isn't a valid URL!"; 117 | display:block; 118 | } 119 | 120 | input[type="checkbox"] { 121 | margin: 5px 0 5px 35px; 122 | } 123 | 124 | input[type="text"] { 125 | width: 200px; 126 | margin: 0 10px 0 0; 127 | } 128 | 129 | input.port { 130 | width: 50px; 131 | margin: 2px 10px 0 5px; 132 | } 133 | 134 | section label, 135 | section legend { 136 | color: #999; 137 | transition: color 0.5s ease; 138 | } 139 | 140 | .incognito section label, 141 | .incognito section legend { 142 | color: #BBB; 143 | } 144 | 145 | .active section label, 146 | .active section legend, 147 | form > fieldset > label { 148 | color: #000; 149 | transition: color 0.5s ease; 150 | } 151 | 152 | .incognito .active section label, 153 | .incognito .active section legend, 154 | .incognito form > fieldset > label { 155 | color: #FFF; 156 | } 157 | 158 | input[type="submit"], 159 | button { 160 | border-radius: 2px; 161 | box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); 162 | -webkit-user-select: none; 163 | background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5); 164 | border: 1px solid #AAA; 165 | color: #444; 166 | margin-bottom: 0; 167 | min-width: 4em; 168 | padding: 3px 12px; 169 | margin-top: 0; 170 | font-size: 1.1em; 171 | } 172 | 173 | .overlay { 174 | display: block; 175 | text-align: center; 176 | position: absolute; 177 | left: 50%; 178 | top: 50%; 179 | width: 500px; 180 | padding: 20px; 181 | margin: -80px 0 0 -270px; 182 | opacity: 0; 183 | background: rgba(0, 0, 0, 0.75); 184 | border-radius: 5px; 185 | color: #FFF; 186 | font: 1.5em/1.2 Helvetica Neue, sans-serif; 187 | transform: scale(0); 188 | transition: all 1.0s ease; 189 | } 190 | 191 | .overlay a { 192 | color: #FFF; 193 | } 194 | 195 | .overlay.visible { 196 | opacity: 1; 197 | transform: scale(1); 198 | } 199 | -------------------------------------------------------------------------------- /debugreq/debugreq-bg.js: -------------------------------------------------------------------------------- 1 | var initDebugReqStorage = function() { 2 | console.log("initializing DebugReq Storage"); 3 | chrome.storage.local.get(['translateErrorCodeHistory', 'fetchLogByIpHistory'], function(result) { 4 | if(result['translateErrorCodeHistory'] == undefined) { 5 | chrome.storage.local.set({'translateErrorCodeHistory': {}}); 6 | } 7 | if(result['fetchLogByIpHistory'] == undefined) { 8 | chrome.storage.local.set({'fetchLogByIpHistory': {}}); 9 | } 10 | }); 11 | } 12 | 13 | function translateErrorCode(errorcode, callback) { 14 | if(!checkActiveCredential("luna")) { 15 | callback(); 16 | return; 17 | } 18 | var reference_code = errorcode.replace('#',''); 19 | var endpoint = getApiEndPoint("debug-translate-errorcode", {errorcode: reference_code}); 20 | var obj_request = { 21 | url: activatedTokenCache.baseurl + endpoint, 22 | auth_header: authorizationHeader({method: "GET", tokens: activatedTokenCache, endpoint: endpoint}), 23 | requestId: "DebugErrCode" + new Date().getTime().toString(), 24 | token_desc: activatedTokenCache.desc, 25 | errorcode: reference_code, 26 | requestedTime: getCurrentDatetimeUTC() 27 | } 28 | sendGetReq(obj_request, onTranslateSuccess, onTranslateError); 29 | showBasicNotification("ErrorCode Translatation Requested", "You will get notified shortly"); 30 | sleep(Math.floor((Math.random() * 1000) + 100), callback); 31 | } 32 | 33 | function getLogLinesFromIP(obj_debug_data, callback) { 34 | if(!checkActiveCredential("luna")) { 35 | callback(); 36 | return; 37 | } 38 | var querystring = "?endTime=" + encodeURIComponent(getCurrentDatetimeUTC("ISO-8601")) + "&hostHeader=" + obj_debug_data.hostname; 39 | var endpoint = getApiEndPoint("debug-fetchlog-by-ip", {ipaddr: obj_debug_data.ipaddr, querystring: querystring}); 40 | var obj_request = { 41 | url: activatedTokenCache.baseurl + endpoint, 42 | auth_header: authorizationHeader({method: "GET", tokens: activatedTokenCache, endpoint: endpoint}), 43 | requestId: "DebugFetchLog" + new Date().getTime().toString(), 44 | ipaddr: obj_debug_data.ipaddr, 45 | hostname: obj_debug_data.hostname, 46 | token_desc: activatedTokenCache.desc, 47 | requestedTime: getCurrentDatetimeUTC() 48 | } 49 | sendGetReq(obj_request, onGetLogLinesSuccess, onGetLogLinesError); 50 | showBasicNotification("Fetching Logs Requested", "You will get notified shortly"); 51 | sleep(Math.floor((Math.random() * 1000) + 100), callback); 52 | } 53 | 54 | var onTranslateSuccess = function(response, status, obj_request) { 55 | var translate_result = { 56 | 'lastupdated': getCurrentDatetimeUTC(), 57 | 'requestedTime': obj_request.requestedTime, 58 | 'raw_response': response, 59 | 'token_desc': obj_request.token_desc, 60 | 'requestId': obj_request.requestId, 61 | 'errorcode': obj_request.errorcode, 62 | 'status': 'success', 63 | 'debug_type': 'errorcode' 64 | }; 65 | saveDebugReqResult(translate_result); 66 | showListNotification("debug-errorcode", "ErrorCode Translation Success", translate_result, img_success); 67 | } 68 | 69 | var onTranslateError = function(xhr, status, error, obj_request) { 70 | var translate_result = { 71 | 'lastupdated': getCurrentDatetimeUTC(), 72 | 'requestedTime': obj_request.requestedTime, 73 | 'raw_response': '', 74 | 'token_desc': obj_request.token_desc, 75 | 'requestId': obj_request.requestId, 76 | 'errorcode': obj_request.errorcode, 77 | 'status': 'fail', 78 | 'debug_type': 'errorcode' 79 | }; 80 | try { 81 | translate_result['raw_response'] = JSON.parse(xhr.responseText); 82 | } catch (err) { 83 | translate_result['raw_response'] = {detail: 'Could not make API request'}; 84 | } 85 | saveDebugReqResult(translate_result); 86 | showListNotification("debug-errorcode", "ErrorCode Translation Failed", translate_result, img_fail); 87 | } 88 | 89 | var onGetLogLinesSuccess = function(response, status, obj_request) { 90 | var getlogline_result = { 91 | 'lastupdated': getCurrentDatetimeUTC(), 92 | 'requestedTime': obj_request.requestedTime, 93 | 'raw_response': response, 94 | 'token_desc': obj_request.token_desc, 95 | 'requestId': obj_request.requestId, 96 | 'ipaddr': obj_request.ipaddr, 97 | 'hostname': obj_request.hostname, 98 | 'status': 'success', 99 | 'debug_type': 'fetchlog' 100 | }; 101 | saveDebugReqResult(getlogline_result); 102 | showListNotification("debug-fetchlog", "Fetch Log Success", getlogline_result, img_success); 103 | } 104 | 105 | var onGetLogLinesError = function(xhr, status, error, obj_request) { 106 | var getlogline_result = { 107 | 'lastupdated': getCurrentDatetimeUTC(), 108 | 'requestedTime': obj_request.requestedTime, 109 | 'raw_response': '', 110 | 'token_desc': obj_request.token_desc, 111 | 'requestId': obj_request.requestId, 112 | 'ipaddr': obj_request.ipaddr, 113 | 'hostname': obj_request.hostname, 114 | 'status': 'fail', 115 | 'debug_type': 'fetchlog' 116 | }; 117 | try { 118 | getlogline_result['raw_response'] = JSON.parse(xhr.responseText); 119 | } catch (err) { 120 | getlogline_result['raw_response'] = {detail: 'Could not make API request'}; 121 | } 122 | saveDebugReqResult(getlogline_result); 123 | showListNotification("debug-fetchlog", "Fetch Log Failed", getlogline_result, img_fail); 124 | } 125 | 126 | function saveDebugReqResult(result) { 127 | if (result.debug_type == 'errorcode') { 128 | chrome.storage.local.get('translateErrorCodeHistory', function(records) { 129 | var translate_history = records['translateErrorCodeHistory']; 130 | translate_history[result.requestId] = result; 131 | chrome.storage.local.set({ translateErrorCodeHistory: translate_history }); 132 | console.log("New " + result.debug_type + " record added"); 133 | }); 134 | } 135 | if (result.debug_type == 'fetchlog') { 136 | chrome.storage.local.get('fetchLogByIpHistory', function(records) { 137 | var fetchlog_history = records['fetchLogByIpHistory']; 138 | fetchlog_history[result.requestId] = result; 139 | chrome.storage.local.set({ fetchLogByIpHistory: fetchlog_history }); 140 | console.log("New " + result.debug_type + " record added"); 141 | }); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /debugreq/debugreq-details.js: -------------------------------------------------------------------------------- 1 | function loadDebugReqResultDetails(debug_req_id, callback) { 2 | var loadTarget = ""; 3 | 4 | if(debug_req_id.startsWith("DebugErrCode")) { 5 | loadTarget = "translateErrorCodeHistory"; 6 | } else if(debug_req_id.startsWith("DebugFetchLog")) { 7 | loadTarget = "fetchLogByIpHistory"; 8 | } 9 | 10 | chrome.storage.local.get(loadTarget, function(data) { 11 | var obj_records = data[loadTarget]; 12 | var history_data = obj_records[debug_req_id]; 13 | 14 | var html = ''; 15 | html += ''; 16 | html += ''; 17 | html += ''; 18 | 19 | var better_title = { 20 | lastupdated: "Last Updated", 21 | raw_response: "Raw Response", 22 | requestId: "Request Id", 23 | requestedTime: "Request Time", 24 | token_desc: "Credential Used", 25 | errorcode: "ErrorCode", 26 | status: "Status", 27 | debug_type: "DebugReqType", 28 | ipaddr: "IP address", 29 | hostname: "Hostname" 30 | } 31 | 32 | var arr_keys = Object.keys(history_data).reverse(); 33 | 34 | for(var i=0; i < arr_keys.length; i++) { 35 | let key = arr_keys[i]; 36 | var text = ""; 37 | if (jQuery.type(history_data[key]) == 'object') { 38 | text = "
    " + JSON.stringify(history_data[key], null, 2) + "
    "; 39 | } else if (jQuery.type(history_data[key]) == 'array') { 40 | for(var k=0; k < history_data[key].length; k++) { 41 | text += "

    " + history_data[key][k] + "

    "; 42 | } 43 | } else { 44 | text = history_data[key]; 45 | } 46 | html += ""; 47 | } 48 | html += '
    " + better_title[key] + "" + text + "
    '; 49 | html += ''; 50 | html += ''; 51 | 52 | callback(html); 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /debugreq/debugreq-history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug Request Results 4 | 5 | 6 | 7 | 8 | 20 | 21 | 22 |
    23 |
    24 |
    25 |
    26 |
    27 | 28 |
    29 | Debug Request Results 30 |
    31 | 32 |
    33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
    Time(GMT)DebugTypeCredentialErrorCode or Hostname, IPStatus
    48 |
    49 | 50 |
    51 |
    52 | Clear All 53 | Close Tab 54 |
    55 |
    56 | 57 |
    58 |
    59 |
    60 |
    61 |
    62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /debugreq/debugreq-history.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | chrome.runtime.sendMessage({type: "gaq", target: "Debug_errorcode_result_page", behavior: "loaded"}); 3 | 4 | $('#clearDebugRecordButton').click(function(){ 5 | chrome.runtime.sendMessage({type: "gaq", target: "Debug_errorcode_page_clearhistory", behavior: "clicked"}); 6 | removeDebugReqRecord(); 7 | }); 8 | 9 | loadDebugReqResult(function(){ 10 | initDataTable(); 11 | var passedId = getUrlParameter('id'); 12 | if (passedId){ 13 | $(".show-more [requestId="+passedId+"]").trigger('click'); 14 | } 15 | }); 16 | 17 | 18 | $('#closeButton').click(function(){ 19 | chrome.runtime.sendMessage({type: "gaq", target: "Debug_errorcode_page_closebtn", behavior: "clicked"}); 20 | closeCurrentTab(); 21 | }); 22 | 23 | $('body').on('click', '.show-more [requestId]', function() { 24 | var td = $(this); 25 | var tr = td.closest('tr'); 26 | var tr_next = tr.next('tr'); 27 | var debug_req_id = td.attr('requestId'); 28 | td.children("i").text("expand_less"); 29 | loadDebugReqResultDetails(debug_req_id, function(data){ 30 | if (tr_next.attr('class') == "shown") { 31 | td.children("i").text("expand_more"); 32 | tr_next.hide(); 33 | tr_next.remove(); 34 | } else { 35 | tr.after(data); 36 | } 37 | }); 38 | }); 39 | 40 | $('body').on('click', '.delete-record [requestId]', function() { 41 | var td = $(this); 42 | var tr = td.closest('tr'); 43 | var debug_req_id = td.attr('requestId'); 44 | removeDebugReqRecord(debug_req_id); 45 | tr.hide(); 46 | }); 47 | }); 48 | 49 | function loadDebugReqResult(callback) { 50 | $("#debugreqlist").empty(); 51 | chrome.storage.local.get(['translateErrorCodeHistory', 'fetchLogByIpHistory'], function(debugdata) { 52 | var obj_results_errorcode = debugdata['translateErrorCodeHistory']; 53 | var obj_results_fetchlog = debugdata['fetchLogByIpHistory']; 54 | var obj_results_merged = Object.assign({}, obj_results_fetchlog, obj_results_errorcode); 55 | for (var debugReqId in obj_results_merged) { 56 | var obj_result = obj_results_merged[debugReqId]; 57 | tbody_html = ""; 58 | tbody_html += ""; 59 | tbody_html += "expand_more"; 60 | tbody_html += "" + obj_result.requestedTime + ""; 61 | tbody_html += "" + obj_result.debug_type.capitalize() + ""; 62 | tbody_html += "" + obj_result.token_desc + ""; 63 | tbody_html += "" + (obj_result.errorcode == undefined ? obj_result.hostname + ", " + obj_result.ipaddr : obj_result.errorcode) + ""; 64 | tbody_html += "" + obj_result.status.capitalize() + ""; 65 | tbody_html += ""; 66 | tbody_html += "delete"; 67 | tbody_html += ""; 68 | $("#debugreqlist").append(tbody_html); 69 | } 70 | callback(); 71 | }); 72 | } 73 | 74 | function initDataTable() { 75 | $('#debug-request-table').DataTable({ 76 | "columnDefs": [ { 77 | "targets" : 'no-sort', 78 | "orderable": false 79 | }], 80 | "order":[ 81 | [1, 'dsc'] 82 | ] 83 | }); 84 | } 85 | 86 | function removeDebugReqRecord(debugReqRecordId) { 87 | if (debugReqRecordId != null) { 88 | chrome.storage.local.get(['translateErrorCodeHistory', 'fetchLogByIpHistory'], function(debugdata) { 89 | if(debugReqRecordId.startsWith("DebugErrCode")) { 90 | target = "translateErrorCodeHistory"; 91 | } else if (debugReqRecordId.startsWith("DebugFetchLog")) { 92 | target = "fetchLogByIpHistory"; 93 | } 94 | var obj_results = debugdata[target]; 95 | delete obj_results[debugReqRecordId]; 96 | var beforeSave = {}; 97 | beforeSave[target] = obj_results; 98 | chrome.storage.local.set(beforeSave, function(){ 99 | if (Object.keys(debugdata['translateErrorCodeHistory']).length == 0 && 100 | Object.keys(debugdata['fetchLogByIpHistory'].length == 0)) { 101 | destoryAndInitDataTable(); 102 | } 103 | }); 104 | }); 105 | } else if (debugReqRecordId == null) { 106 | chrome.storage.local.set({translateErrorCodeHistory: {}, fetchLogByIpHistory: {}}, function() { 107 | destoryAndInitDataTable(); 108 | }); 109 | } 110 | } 111 | 112 | function destoryAndInitDataTable() { 113 | $('#debug-request-table').DataTable().clear().destroy(); 114 | initDataTable(); 115 | } 116 | -------------------------------------------------------------------------------- /debugreq/debugreq.js: -------------------------------------------------------------------------------- 1 | chrome.storage.local.get('akamaiDebugHeaderSwitch', function(data) { 2 | var type = data['akamaiDebugHeaderSwitch']; 3 | $("#updatetype-debugheaders").prop('checked', (type == 'OFF') ? false : true); 4 | }); 5 | 6 | $("#updatetype-debugheaders").change(function() { 7 | chrome.runtime.sendMessage({type: "gaq", target: "toggle_debug_headers", behavior: "clicked"}); 8 | var type = $(this).prop("checked") ? "ON" : "OFF"; 9 | chrome.runtime.sendMessage({ 10 | type: "browser-akamaidebugheaderswitch", 11 | body: type 12 | }); 13 | }); 14 | 15 | $('#debughistorydetails').click(function() { 16 | chrome.runtime.sendMessage({type: "gaq", target: "View_debug_history", behavior: "clicked"}); 17 | chrome.tabs.create({ 18 | url: 'debugreq/debugreq-history.html' 19 | }); 20 | }); 21 | 22 | $('#debug-errorcode-btn').click(function() { 23 | var errorcode = $('#debug-errorcode').val().trim(); 24 | if (errorcode.split(".").length != 4) { 25 | Materialize.toast('Error Reference Code is not in the right format', 1500); 26 | $('#debug-errorcode').focus(); 27 | return false; 28 | } 29 | var this_obj = $(this); 30 | var this_html = $(this).html(); 31 | this_obj.addClass("disabled"); 32 | this_obj.html(''); 33 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 34 | backgroundpage.translateErrorCode(errorcode, function(request_result) { 35 | this_obj.removeClass("disabled").blur(); 36 | this_obj.html(this_html); 37 | }); 38 | }); 39 | }); 40 | 41 | $('#debug-fetchlog-btn').click(function() { 42 | var debug_ipaddr = $("#debug-ipaddr").val().trim(); 43 | var debug_hostname = $("#debug-hostname").val().trim(); 44 | 45 | if(isEmpty(debug_ipaddr) || !isValidIPv4(debug_ipaddr)) { 46 | Materialize.toast('Please enter valid IP address', 1500); 47 | $("#debug-ipaddr").focus(); 48 | return false; 49 | } else if(isEmpty(debug_hostname) || !isValidDomain(debug_hostname)) { 50 | Materialize.toast('Please enter valid Hostname', 1500); 51 | $("#debug-hostname").focus(); 52 | return false; 53 | } 54 | 55 | var this_obj = $(this); 56 | var this_html = $(this).html(); 57 | this_obj.addClass("disabled"); 58 | this_obj.html(''); 59 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 60 | backgroundpage.getLogLinesFromIP({ipaddr: debug_ipaddr, hostname: debug_hostname}, function(request_result) { 61 | this_obj.removeClass("disabled").blur(); 62 | this_obj.html(this_html); 63 | }); 64 | }); 65 | }); 66 | 67 | -------------------------------------------------------------------------------- /fastpurge/fastpurge-bg.js: -------------------------------------------------------------------------------- 1 | var purgeUpdateTypeCache = ""; 2 | 3 | var initFastPurgeStorage = function() { 4 | console.log("initializing FastPurge Storage"); 5 | chrome.storage.local.get(["purgeHistory", "update_type"], function(result) { 6 | if(result['purgeHistory'] == undefined) { 7 | chrome.storage.local.set({'purgeHistory': {}}); 8 | } 9 | if(result['update_type'] == undefined) { 10 | chrome.storage.local.set({update_type: 'invalidate'}, function() { 11 | purgeUpdateTypeCache = 'invalidate'; 12 | }); 13 | } else { 14 | purgeUpdateTypeCache = result['update_type']; 15 | } 16 | }); 17 | } 18 | 19 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 20 | if (message.type == "fastpurge") { 21 | if (message.update_type != undefined) 22 | chrome.storage.local.set({'update_type': message.update_type}, function() { 23 | purgeUpdateTypeCache = message.update_type; 24 | console.log("Fastpurge: update_type was updated to " + message.update_type); 25 | }); 26 | } 27 | }); 28 | 29 | function createPostBody(arr_objects) { 30 | post_data = { 'objects': new Array() }; 31 | for(var i=0; i < arr_objects.length; i++) { 32 | post_data['objects'].push(arr_objects[i]); 33 | } 34 | return JSON.stringify(post_data); 35 | } 36 | 37 | function savePurgeResult(purge_result) { 38 | chrome.storage.local.get('purgeHistory', function(records) { 39 | var purge_history = records['purgeHistory']; 40 | purge_history[purge_result.requestId] = purge_result; 41 | chrome.storage.local.set({ purgeHistory: purge_history }); 42 | console.log("New purge record added"); 43 | }); 44 | } 45 | 46 | var onPurgeSuccess = function(response, status, obj_request) { 47 | _gaq.push(['_trackEvent', 'Purge_req_successful', 'yes']); 48 | var purge_result = { 49 | 'lastupdated': getCurrentDatetimeUTC(), 50 | 'requestedTime': obj_request.requestedTime, 51 | 'purge_request_accepted': 'success', 52 | 'purge_type': obj_request.purge_type, 53 | 'purgeId': response.purgeId, 54 | 'network': obj_request.purge_network, 55 | 'purge_objects': JSON.parse(obj_request.body_data).objects, 56 | 'raw_response': response, 57 | 'token_used': obj_request.token_desc, 58 | 'update_type': obj_request.purge_update_type, 59 | 'requestId': obj_request.requestId 60 | }; 61 | savePurgeResult(purge_result); 62 | showListNotification("purge", "Purge Success", purge_result, img_success); 63 | } 64 | 65 | var onPurgeError = function(xhr, status, error, obj_request) { 66 | _gaq.push(['_trackEvent', 'Purge_req_successful', 'no']); 67 | var purge_result = { 68 | 'lastupdated': getCurrentDatetimeUTC(), 69 | 'requestedTime': obj_request.requestedTime, 70 | 'purge_request_accepted': '', 71 | 'purge_type': obj_request.purge_type, 72 | 'purgeId': 'Purge Request Error', 73 | 'network': obj_request.purge_network, 74 | 'purge_objects': JSON.parse(obj_request.body_data).objects, 75 | 'raw_response': '', 76 | 'token_used': obj_request.token_desc, 77 | 'update_type': obj_request.purge_update_type, 78 | 'requestId': obj_request.requestId 79 | }; 80 | var title = ""; 81 | try { 82 | purge_result['raw_response'] = JSON.parse(xhr.responseText); 83 | purge_result['purge_request_accepted'] = "fail"; 84 | var title = "Purge Failed"; 85 | _gaq.push(['_trackEvent', 'Purge_req_failure_reason', 'Purge_failed']); 86 | } catch (err) { 87 | purge_result['raw_response'] = {detail: 'Could not make API call'}; 88 | purge_result['purge_request_accepted'] = "connect-fail"; 89 | var title = "Request Failed"; 90 | _gaq.push(['_trackEvent', 'Purge_req_failure_reason', 'Request Failed']); 91 | } 92 | savePurgeResult(purge_result); 93 | showListNotification("purge", title, purge_result, img_fail); 94 | } 95 | 96 | function inputParser(arr_purge_targets) { 97 | var urlchecker = document.createElement('a'); 98 | var re_cpcode = /^\d\d\d\d\d\d$/g; 99 | var arr_urls = [], arr_cpcodes = [], arr_tags = []; 100 | 101 | for(var i=0; i < arr_purge_targets.length; i++) { 102 | urlchecker.href = arr_purge_targets[i]; 103 | if (urlchecker.protocol == "http:" || urlchecker.protocol == "https:") { 104 | arr_urls.push(arr_purge_targets[i]); 105 | } else if (arr_purge_targets[i].match(re_cpcode) != null) { 106 | arr_cpcodes.push(arr_purge_targets[i]); 107 | } else { 108 | arr_tags.push(arr_purge_targets[i]); 109 | } 110 | } 111 | 112 | var purge_targets = { 113 | urls: arr_urls, 114 | cpcodes: arr_cpcodes, 115 | tags: arr_tags, 116 | }; 117 | 118 | return purge_targets; 119 | } 120 | 121 | function makePurgeRequest(arr_purge_targets, network, callback) { 122 | if(!checkActiveCredential("purge")) { 123 | callback(); 124 | return; 125 | } 126 | 127 | var obj_purge_targets = inputParser(arr_purge_targets); 128 | var purge_requests = []; 129 | 130 | if (obj_purge_targets.urls.length > 0) { 131 | var endpoint = getApiEndPoint("purge-url", {updatetype: purgeUpdateTypeCache, network: network}); 132 | purge_requests.push({ 133 | url: activatedTokenCache.baseurl + endpoint, 134 | body_data: createPostBody(obj_purge_targets.urls), 135 | auth_header: authorizationHeader({method: "POST", body: createPostBody(obj_purge_targets.urls), tokens: activatedTokenCache, endpoint: endpoint}), 136 | purge_type: 'url', 137 | requestId: "PurgeURL_r" + new Date().getTime().toString(), 138 | purge_update_type: purgeUpdateTypeCache, 139 | token_desc: activatedTokenCache.desc, 140 | purge_network: network, 141 | requestedTime: getCurrentDatetimeUTC() 142 | }); 143 | } 144 | 145 | if (obj_purge_targets.cpcodes.length > 0) { 146 | var endpoint = getApiEndPoint("purge-cpcode", {updatetype: purgeUpdateTypeCache, network: network}); 147 | purge_requests.push({ 148 | url: activatedTokenCache.baseurl + endpoint, 149 | body_data: createPostBody(obj_purge_targets.cpcodes), 150 | auth_header: authorizationHeader({method: "POST", body: createPostBody(obj_purge_targets.cpcodes), tokens: activatedTokenCache, endpoint: endpoint}), 151 | purge_type: 'cpcode', 152 | requestId: "PurgeCPCode_r" + new Date().getTime().toString(), 153 | purge_update_type: purgeUpdateTypeCache, 154 | token_desc: activatedTokenCache.desc, 155 | purge_network: network, 156 | requestedTime: getCurrentDatetimeUTC() 157 | }); 158 | } 159 | 160 | if (obj_purge_targets.tags.length > 0) { 161 | var endpoint = getApiEndPoint("purge-tag", {updatetype: purgeUpdateTypeCache, network: network}); 162 | purge_requests.push({ 163 | url: activatedTokenCache.baseurl + endpoint, 164 | body_data: createPostBody(obj_purge_targets.tags), 165 | auth_header: authorizationHeader({method: "POST", body: createPostBody(obj_purge_targets.tags), tokens: activatedTokenCache, endpoint: endpoint}), 166 | purge_type: 'tag', 167 | requestId: "PurgeTag_r" + new Date().getTime().toString(), 168 | purge_update_type: purgeUpdateTypeCache, 169 | token_desc: activatedTokenCache.desc, 170 | purge_network: network, 171 | requestedTime: getCurrentDatetimeUTC() 172 | }); 173 | } 174 | 175 | if (purge_requests.length > 0) { 176 | for (i=0; i < purge_requests.length; i++) { 177 | sendPostReq(purge_requests[i], onPurgeSuccess, onPurgeError, callback); 178 | } 179 | } else { 180 | showBasicNotification('Input Error', 'Please check entered purge targets are correct', img_fail); 181 | callback("fail"); 182 | return false; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /fastpurge/fastpurge-details.js: -------------------------------------------------------------------------------- 1 | function loadDetails(purge_req_id, callback) { 2 | chrome.storage.local.get('purgeHistory', function(data) { 3 | var obj_records = data['purgeHistory']; 4 | var history_data = obj_records[purge_req_id]; 5 | 6 | var html = ''; 7 | html += ''; 8 | html += ''; 9 | html += ''; 10 | 11 | var better_title = { 12 | lastupdated: "Last Updated", 13 | network: "Network", 14 | purgeId: "Purge Id", 15 | purge_objects: "Purge Objects", 16 | purge_request_accepted: "Purge Request Status", 17 | purge_type: "Purge Type", 18 | raw_response: "Raw Response", 19 | requestId: "Request Id", 20 | requestedTime: "Request Time", 21 | token_used: "Credential Used", 22 | update_type: "Purge Update Type" 23 | } 24 | 25 | var arr_keys = Object.keys(history_data).reverse(); 26 | 27 | for(var i=0; i < arr_keys.length; i++) { 28 | let key = arr_keys[i]; 29 | var text = ""; 30 | if (jQuery.type(history_data[key]) == 'object' && key != 'token_used') { 31 | text = "
    " + JSON.stringify(history_data[key], null, 2) + "
    "; 32 | } else if (jQuery.type(history_data[key]) == 'array') { 33 | for(var k=0; k < history_data[key].length; k++) { 34 | text += "

    " + history_data[key][k] + "

    "; 35 | } 36 | } else { 37 | text = history_data[key]; 38 | } 39 | html += ""; 40 | } 41 | html += '
    " + better_title[key] + "" + text + "
    '; 42 | html += ''; 43 | html += ''; 44 | 45 | callback(html); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /fastpurge/fastpurge-history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Purge History 4 | 5 | 6 | 7 | 8 | 20 | 21 | 22 |
    23 |
    24 |
    25 |
    26 |
    27 | 28 |
    29 | Purge History 30 |
    31 | 32 |
    33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
    Time(GMT)CredentialUpdateTypePurgeTypePurgeIdObjectNumNetworkStatus
    51 |
    52 | 53 |
    54 |
    55 | Clear History 56 | Close Tab 57 |
    58 |
    59 | 60 |
    61 |
    62 |
    63 |
    64 |
    65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /fastpurge/fastpurge-history.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | chrome.runtime.sendMessage({type: "gaq", target: "Purge_history_page", behavior: "loaded"}); 3 | 4 | loadHistory(function(){ 5 | initDataTable(); 6 | var passedId = getUrlParameter('id'); 7 | if (passedId){ 8 | $(".show-more [requestId="+passedId+"]").trigger('click'); 9 | } 10 | }); 11 | 12 | $('#clearHistoryButton').click(function(){ 13 | chrome.runtime.sendMessage({type: "gaq", target: "Purge_history_page_clearhistory", behavior: "clicked"}); 14 | removeHistoryRecord(); 15 | }); 16 | 17 | $('#closeButton').click(function(){ 18 | chrome.runtime.sendMessage({type: "gaq", target: "Purge_history_page_closebtn", behavior: "clicked"}); 19 | closeCurrentTab(); 20 | }); 21 | 22 | $('body').on('click', '.show-more [requestId]', function () { 23 | var td = $(this); 24 | var tr = td.closest('tr'); 25 | var tr_next = tr.next('tr'); 26 | var purge_req_id = td.attr('requestId'); 27 | td.children("i").text("expand_less"); 28 | loadDetails(purge_req_id, function(data){ 29 | if (tr_next.attr('class') == "shown") { 30 | td.children("i").text("expand_more"); 31 | tr_next.hide(); 32 | tr_next.remove(); 33 | } else { 34 | tr.after(data); 35 | } 36 | }); 37 | }); 38 | 39 | $('body').on('click', '.delete-record [requestId]', function () { 40 | var td = $(this); 41 | var tr = td.closest('tr'); 42 | var purge_req_id = td.attr('requestId'); 43 | removeHistoryRecord(purge_req_id); 44 | tr.hide(); 45 | }); 46 | }); 47 | 48 | function initDataTable() { 49 | $('#purge-table').DataTable({ 50 | "columnDefs": [ { 51 | "targets" : 'no-sort', 52 | "orderable": false 53 | }], 54 | "order":[ 55 | [1, 'dsc'] 56 | ] 57 | }); 58 | } 59 | 60 | function loadHistory(callback) { 61 | $("#historylist").empty(); 62 | chrome.storage.local.get('purgeHistory', function(purgedata) { 63 | var obj_records = purgedata['purgeHistory']; 64 | for (var purgeReqId in obj_records) { 65 | var obj_history = obj_records[purgeReqId]; 66 | tbody_html = ""; 67 | tbody_html += ""; 68 | tbody_html += "expand_more"; 69 | tbody_html += "" + obj_history.requestedTime + ""; 70 | tbody_html += "" + obj_history.token_used.capitalize() + ""; 71 | tbody_html += "" + obj_history.update_type.capitalize() + ""; 72 | tbody_html += "" + obj_history.purge_type.toUpperCase() + ""; 73 | tbody_html += "" + obj_history.purgeId + ""; 74 | tbody_html += "" + obj_history.purge_objects.length + ""; 75 | tbody_html += "" + obj_history.network.capitalize() + ""; 76 | tbody_html += "" + obj_history.purge_request_accepted.capitalize() + ""; 77 | tbody_html += ""; 78 | tbody_html += "delete"; 79 | tbody_html += ""; 80 | $("#historylist").append(tbody_html); 81 | } 82 | callback(); 83 | }); 84 | } 85 | 86 | function removeHistoryRecord(purgeRecordId) { 87 | console.log('remove record was called') 88 | chrome.storage.local.get('purgeHistory', function(data) { 89 | var obj_records = data['purgeHistory']; 90 | if (purgeRecordId == null) { 91 | for (key in obj_records) { 92 | delete obj_records[key]; 93 | } 94 | } else { 95 | delete obj_records[purgeRecordId]; 96 | } 97 | chrome.storage.local.set({'purgeHistory': obj_records}, function(){ 98 | if (Object.keys(obj_records).length == 0) { 99 | $('#purge-table').DataTable().clear().destroy(); 100 | initDataTable(); 101 | } 102 | }); 103 | }); 104 | } 105 | -------------------------------------------------------------------------------- /fastpurge/fastpurge.js: -------------------------------------------------------------------------------- 1 | chrome.storage.local.get('update_type', function(data) { 2 | $("#updatetype-switch").prop('checked', (data['update_type'] == 'invalidate') ? false : true); 3 | }); 4 | 5 | $('#purgehistorydetails, #purgehistorydetailslink').click(function() { 6 | chrome.runtime.sendMessage({type: "gaq", target: "View_purge_history", behavior: "clicked"}); 7 | chrome.tabs.create({ 8 | url: 'fastpurge/fastpurge-history.html' 9 | }); 10 | }); 11 | 12 | $("#updatetype-switch").change(function() { 13 | chrome.runtime.sendMessage({type: "gaq", target: "toggle_purge_type", behavior: "clicked"}); 14 | var type = $(this).prop("checked") ? "delete" : "invalidate"; 15 | chrome.runtime.sendMessage({type: "fastpurge", update_type: type}); 16 | }); 17 | 18 | $('#submitButton-stg, #submitButton-pro').click(function(obj) { 19 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 20 | backgroundpage._gaq.push(['_trackEvent', 'Submit_purge_req', 'clicked']); 21 | }); 22 | var arr_purge_targets = $('#purgeurls').val().split("\n"); 23 | var network = $(this).attr('network'); 24 | for (i = 0; i < arr_purge_targets.length; i++) { 25 | arr_purge_targets[i] = arr_purge_targets[i].trim().replace(/\s+/g, ''); 26 | } 27 | if (arr_purge_targets.filter(Boolean).length == 0) { 28 | Materialize.toast('Please enter Cpcode/Tag/URL to purge', 1500); 29 | return false; 30 | } else { 31 | var submit_buttons = $('#submitButton-stg, #submitButton-pro'); 32 | var this_obj = $(this); 33 | var this_html = $(this).html(); 34 | submit_buttons.addClass("disabled"); 35 | this_obj.html(''); 36 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 37 | backgroundpage.makePurgeRequest(arr_purge_targets.filter(Boolean), network, function(request_result) { 38 | submit_buttons.removeClass("disabled").blur(); 39 | this_obj.html(this_html); 40 | }); 41 | }); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /fonts/materialicons.css: -------------------------------------------------------------------------------- 1 | /* fallback */ 2 | @font-face { 3 | font-family: 'Material Icons'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: url(materialize.woff2) format('woff2'); 7 | } 8 | 9 | .material-icons { 10 | font-family: 'Material Icons'; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: 'liga'; 22 | -webkit-font-smoothing: antialiased; 23 | } -------------------------------------------------------------------------------- /fonts/materialize.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/materialize.woff2 -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Bold.eot -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Bold.ttf -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Light.eot -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Light.ttf -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Medium.eot -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Medium.ttf -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Regular.eot -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Regular.ttf -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Thin.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Thin.eot -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Thin.ttf -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /fonts/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/fonts/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /img/akamai-black-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/akamai-black-logo.png -------------------------------------------------------------------------------- /img/akamai-blue-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/akamai-blue-logo.png -------------------------------------------------------------------------------- /img/akamai-grey-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/akamai-grey-logo.png -------------------------------------------------------------------------------- /img/akamai-orange-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/akamai-orange-logo.jpg -------------------------------------------------------------------------------- /img/akamai-orange-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/akamai-orange-logo.png -------------------------------------------------------------------------------- /img/akamai.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/akamai.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/akamai_logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/datatable/back_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/back_disabled.png -------------------------------------------------------------------------------- /img/datatable/back_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/back_enabled.png -------------------------------------------------------------------------------- /img/datatable/back_enabled_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/back_enabled_hover.png -------------------------------------------------------------------------------- /img/datatable/forward_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/forward_disabled.png -------------------------------------------------------------------------------- /img/datatable/forward_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/forward_enabled.png -------------------------------------------------------------------------------- /img/datatable/forward_enabled_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/forward_enabled_hover.png -------------------------------------------------------------------------------- /img/datatable/sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/sort_asc.png -------------------------------------------------------------------------------- /img/datatable/sort_asc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/sort_asc_disabled.png -------------------------------------------------------------------------------- /img/datatable/sort_both.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/sort_both.png -------------------------------------------------------------------------------- /img/datatable/sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/sort_desc.png -------------------------------------------------------------------------------- /img/datatable/sort_desc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/datatable/sort_desc_disabled.png -------------------------------------------------------------------------------- /img/dev-icons-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/dev-icons-128.png -------------------------------------------------------------------------------- /img/dev_tools_marquee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/dev_tools_marquee.png -------------------------------------------------------------------------------- /img/dev_tools_wallpaper1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/dev_tools_wallpaper1.png -------------------------------------------------------------------------------- /img/dev_tools_wallpaper2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/dev_tools_wallpaper2.png -------------------------------------------------------------------------------- /img/dev_tools_wallpaper3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/dev_tools_wallpaper3.png -------------------------------------------------------------------------------- /img/dev_tools_wallpaper4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/dev_tools_wallpaper4.png -------------------------------------------------------------------------------- /img/email_header_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/email_header_background.png -------------------------------------------------------------------------------- /img/email_header_banner_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/email_header_banner_dev.png -------------------------------------------------------------------------------- /img/email_header_devpops_title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/email_header_devpops_title.png -------------------------------------------------------------------------------- /img/email_header_devpops_withbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/email_header_devpops_withbg.png -------------------------------------------------------------------------------- /img/email_header_title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/email_header_title.png -------------------------------------------------------------------------------- /img/fail_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/fail_icon.png -------------------------------------------------------------------------------- /img/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/icon-128.png -------------------------------------------------------------------------------- /img/icons-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/icons-128.png -------------------------------------------------------------------------------- /img/info_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/info_icon.png -------------------------------------------------------------------------------- /img/spring_devops_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/spring_devops_icon.png -------------------------------------------------------------------------------- /img/success_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/img/success_icon.png -------------------------------------------------------------------------------- /js/HoldOn.min.js: -------------------------------------------------------------------------------- 1 | 2 | (function(b){function a(){if("undefined"==typeof jQuery){throw new Error("HoldOn.js requires jQuery")}var c={};c.open=function(e){$("#holdon-overlay").remove();var h="sk-rect";var g="";var f="";if(e){if(e.hasOwnProperty("theme")){h=e.theme}if(e.hasOwnProperty("message")){f=e.message}}switch(h){case"custom":g='
    '+e.content+"
    ";break;case"sk-dot":g='
    ';break;case"sk-rect":g='
    ';break;case"sk-cube":g='
    ';break;case"sk-bounce":g='
    ';break;case"sk-circle":g='
    ';break;case"sk-cube-grid":g='
    ';break;case"sk-folding-cube":g='
    ';break;case"sk-fading-circle":g='
    ';break;default:g='
    ';console.warn(h+" doesn't exist for HoldOn.js");break}var d='";$(d).appendTo("body").fadeIn(300);if(e){if(e.backgroundColor){$("#holdon-overlay").css("backgroundColor",e.backgroundColor)}if(e.backgroundColor){$("#holdon-message").css("color",e.textColor)}}};c.close=function(){$("#holdon-overlay").fadeOut(300,function(){$(this).remove()})};return c}if(typeof(HoldOn)==="undefined"){b.HoldOn=a()}})(window); -------------------------------------------------------------------------------- /js/aes.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function () { 8 | // Shortcuts 9 | var C = CryptoJS; 10 | var C_lib = C.lib; 11 | var BlockCipher = C_lib.BlockCipher; 12 | var C_algo = C.algo; 13 | 14 | // Lookup tables 15 | var SBOX = []; 16 | var INV_SBOX = []; 17 | var SUB_MIX_0 = []; 18 | var SUB_MIX_1 = []; 19 | var SUB_MIX_2 = []; 20 | var SUB_MIX_3 = []; 21 | var INV_SUB_MIX_0 = []; 22 | var INV_SUB_MIX_1 = []; 23 | var INV_SUB_MIX_2 = []; 24 | var INV_SUB_MIX_3 = []; 25 | 26 | // Compute lookup tables 27 | (function () { 28 | // Compute double table 29 | var d = []; 30 | for (var i = 0; i < 256; i++) { 31 | if (i < 128) { 32 | d[i] = i << 1; 33 | } else { 34 | d[i] = (i << 1) ^ 0x11b; 35 | } 36 | } 37 | 38 | // Walk GF(2^8) 39 | var x = 0; 40 | var xi = 0; 41 | for (var i = 0; i < 256; i++) { 42 | // Compute sbox 43 | var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); 44 | sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; 45 | SBOX[x] = sx; 46 | INV_SBOX[sx] = x; 47 | 48 | // Compute multiplication 49 | var x2 = d[x]; 50 | var x4 = d[x2]; 51 | var x8 = d[x4]; 52 | 53 | // Compute sub bytes, mix columns tables 54 | var t = (d[sx] * 0x101) ^ (sx * 0x1010100); 55 | SUB_MIX_0[x] = (t << 24) | (t >>> 8); 56 | SUB_MIX_1[x] = (t << 16) | (t >>> 16); 57 | SUB_MIX_2[x] = (t << 8) | (t >>> 24); 58 | SUB_MIX_3[x] = t; 59 | 60 | // Compute inv sub bytes, inv mix columns tables 61 | var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); 62 | INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); 63 | INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); 64 | INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); 65 | INV_SUB_MIX_3[sx] = t; 66 | 67 | // Compute next counter 68 | if (!x) { 69 | x = xi = 1; 70 | } else { 71 | x = x2 ^ d[d[d[x8 ^ x2]]]; 72 | xi ^= d[d[xi]]; 73 | } 74 | } 75 | }()); 76 | 77 | // Precomputed Rcon lookup 78 | var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; 79 | 80 | /** 81 | * AES block cipher algorithm. 82 | */ 83 | var AES = C_algo.AES = BlockCipher.extend({ 84 | _doReset: function () { 85 | // Shortcuts 86 | var key = this._key; 87 | var keyWords = key.words; 88 | var keySize = key.sigBytes / 4; 89 | 90 | // Compute number of rounds 91 | var nRounds = this._nRounds = keySize + 6 92 | 93 | // Compute number of key schedule rows 94 | var ksRows = (nRounds + 1) * 4; 95 | 96 | // Compute key schedule 97 | var keySchedule = this._keySchedule = []; 98 | for (var ksRow = 0; ksRow < ksRows; ksRow++) { 99 | if (ksRow < keySize) { 100 | keySchedule[ksRow] = keyWords[ksRow]; 101 | } else { 102 | var t = keySchedule[ksRow - 1]; 103 | 104 | if (!(ksRow % keySize)) { 105 | // Rot word 106 | t = (t << 8) | (t >>> 24); 107 | 108 | // Sub word 109 | t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; 110 | 111 | // Mix Rcon 112 | t ^= RCON[(ksRow / keySize) | 0] << 24; 113 | } else if (keySize > 6 && ksRow % keySize == 4) { 114 | // Sub word 115 | t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; 116 | } 117 | 118 | keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; 119 | } 120 | } 121 | 122 | // Compute inv key schedule 123 | var invKeySchedule = this._invKeySchedule = []; 124 | for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { 125 | var ksRow = ksRows - invKsRow; 126 | 127 | if (invKsRow % 4) { 128 | var t = keySchedule[ksRow]; 129 | } else { 130 | var t = keySchedule[ksRow - 4]; 131 | } 132 | 133 | if (invKsRow < 4 || ksRow <= 4) { 134 | invKeySchedule[invKsRow] = t; 135 | } else { 136 | invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ 137 | INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; 138 | } 139 | } 140 | }, 141 | 142 | encryptBlock: function (M, offset) { 143 | this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); 144 | }, 145 | 146 | decryptBlock: function (M, offset) { 147 | // Swap 2nd and 4th rows 148 | var t = M[offset + 1]; 149 | M[offset + 1] = M[offset + 3]; 150 | M[offset + 3] = t; 151 | 152 | this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); 153 | 154 | // Inv swap 2nd and 4th rows 155 | var t = M[offset + 1]; 156 | M[offset + 1] = M[offset + 3]; 157 | M[offset + 3] = t; 158 | }, 159 | 160 | _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { 161 | // Shortcut 162 | var nRounds = this._nRounds; 163 | 164 | // Get input, add round key 165 | var s0 = M[offset] ^ keySchedule[0]; 166 | var s1 = M[offset + 1] ^ keySchedule[1]; 167 | var s2 = M[offset + 2] ^ keySchedule[2]; 168 | var s3 = M[offset + 3] ^ keySchedule[3]; 169 | 170 | // Key schedule row counter 171 | var ksRow = 4; 172 | 173 | // Rounds 174 | for (var round = 1; round < nRounds; round++) { 175 | // Shift rows, sub bytes, mix columns, add round key 176 | var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; 177 | var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; 178 | var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; 179 | var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; 180 | 181 | // Update state 182 | s0 = t0; 183 | s1 = t1; 184 | s2 = t2; 185 | s3 = t3; 186 | } 187 | 188 | // Shift rows, sub bytes, add round key 189 | var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; 190 | var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; 191 | var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; 192 | var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; 193 | 194 | // Set output 195 | M[offset] = t0; 196 | M[offset + 1] = t1; 197 | M[offset + 2] = t2; 198 | M[offset + 3] = t3; 199 | }, 200 | 201 | keySize: 256/32 202 | }); 203 | 204 | /** 205 | * Shortcut functions to the cipher's object interface. 206 | * 207 | * @example 208 | * 209 | * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); 210 | * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); 211 | */ 212 | C.AES = BlockCipher._createHelper(AES); 213 | }()); 214 | -------------------------------------------------------------------------------- /js/common.js: -------------------------------------------------------------------------------- 1 | String.prototype.capitalize = function(lower) { 2 | return (lower ? this.toLowerCase() : this).replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); }); 3 | }; 4 | 5 | function isEmpty(val) { 6 | return val === null || val === '' || jQuery.isEmptyObject(val); 7 | } 8 | 9 | function sleep(milisec, callback) { 10 | setTimeout(function(){ 11 | if (typeof callback != 'undefined') { 12 | callback(); 13 | } 14 | }, milisec); 15 | } 16 | 17 | function getUrlParameter(name) { 18 | name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); 19 | var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); 20 | var results = regex.exec(location.search); 21 | return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); 22 | } 23 | 24 | function closeCurrentTab() { 25 | chrome.tabs.getCurrent(function(tab) { 26 | chrome.tabs.remove(tab.id); 27 | }); 28 | } 29 | 30 | function getCurrentDatetimeUTC(format) { 31 | obj_date = new Date(); 32 | year = obj_date.getUTCFullYear(); 33 | month = obj_date.getUTCMonth() + 1; 34 | date = obj_date.getUTCDate(); 35 | hours = obj_date.getUTCHours(); 36 | minutes = obj_date.getUTCMinutes(); 37 | seconds = obj_date.getUTCSeconds(); 38 | temp_arr = [year, month, date, hours, minutes, seconds] 39 | for (i = 0; i < temp_arr.length; i++) { 40 | if (temp_arr[i] < 10) { 41 | temp_arr[i] = '0' + temp_arr[i]; 42 | } 43 | } 44 | if(format == "ISO-8601") { 45 | return temp_arr[0] + '-' + temp_arr[1] + '-' + temp_arr[2] + 'T' + temp_arr[3] + ':' + temp_arr[4] + ':' + temp_arr[5] + 'Z'; 46 | } else { 47 | return temp_arr[0] + '/' + temp_arr[1] + '/' + temp_arr[2] + ' ' + temp_arr[3] + ':' + temp_arr[4] + ':' + temp_arr[5]; 48 | } 49 | } 50 | 51 | function isValidIPv4(ip) { 52 | var ipre = /^(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$/g; 53 | return ipre.test(ip); 54 | } 55 | 56 | function isValidDomain(domain) { 57 | var domainre= /^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,}\.?((xn--)?([a-z0-9\-.]{1,61}|[a-z0-9-]{1,30})\.?[a-zA-Z0-9]{2,})$/i; 58 | return domainre.test(domain); 59 | } 60 | -------------------------------------------------------------------------------- /js/edgegrid.js: -------------------------------------------------------------------------------- 1 | function getTimeStampInUtc() { 2 | //obj_date = new Date(); 3 | obj_date = moment.utc().format("YYYYMMDDTHH:mm:ss+0000"); 4 | console.log(obj_date); 5 | return obj_date; 6 | /*year = moment().year(obj_date); 7 | console.log(year); 8 | month = moment().month(obj_date) + 1; 9 | date = moment().date(obj_date); 10 | hours = moment().hour(obj_date); 11 | minutes = moment().minute(obj_date); 12 | seconds = moment().seconds(obj_date); 13 | temp_arr = [year, month, date, hours, minutes, seconds] 14 | for (i = 0; i < temp_arr.length; i++) { 15 | if (temp_arr[i] < 10) { 16 | temp_arr[i] = '0' + temp_arr[i]; 17 | } 18 | } 19 | return temp_arr[0] + temp_arr[1] + temp_arr[2] + 'T' + temp_arr[3] + ':' + temp_arr[4] + ':' + temp_arr[5] + '+0000'; 20 | */ 21 | 22 | } 23 | 24 | function authHeaderValueWithOutSignature(apiTokens, timestamp) { 25 | var without_signature = 'EG1-HMAC-SHA256 client_token=' + apiTokens['clienttoken'] + ';'; 26 | without_signature += 'access_token=' + apiTokens['accesstoken'] + ';'; 27 | without_signature += 'timestamp=' + timestamp + ';'; 28 | without_signature += 'nonce=0ffd2fa-cede-43ea-befc-c5b6ea33f32b;'; 29 | return without_signature; 30 | } 31 | 32 | function dataToSign(apiTokens, without_signature, timestamp, body, method) { 33 | var parser = document.createElement('a'); 34 | parser.href = apiTokens['baseurl']; 35 | arr_t = [method, parser.protocol.replace(":", ""), parser.hostname, parser.pathname + parser.search].join('\t'); 36 | var hash_body_in_base64 = ""; 37 | if (body != "") {hash_body_in_base64 = CryptoJS.enc.Base64.stringify(CryptoJS.SHA256(body));} 38 | data_to_sign = arr_t + '\t\t' + hash_body_in_base64 + '\t' + without_signature; 39 | return data_to_sign; 40 | } 41 | 42 | function authorizationHeader(ingredient) { 43 | var method = ingredient.method; 44 | var tokens = jQuery.extend(true, {}, ingredient.tokens); 45 | tokens.baseurl += ingredient.endpoint; 46 | var body = (method == 'POST') ? ingredient.body : ""; 47 | var timestamp = getTimeStampInUtc(); 48 | var auth_header_without_signature = authHeaderValueWithOutSignature(tokens, timestamp); 49 | var data_to_sign = dataToSign(tokens, auth_header_without_signature, timestamp, body, method); 50 | var signing_key_hash_in_base64 = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(timestamp, tokens['secret'])); 51 | var signature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(data_to_sign, signing_key_hash_in_base64)); 52 | return authorization_header = auth_header_without_signature + 'signature=' + signature; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /js/enc-base64.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function () { 8 | // Shortcuts 9 | var C = CryptoJS; 10 | var C_lib = C.lib; 11 | var WordArray = C_lib.WordArray; 12 | var C_enc = C.enc; 13 | 14 | /** 15 | * Base64 encoding strategy. 16 | */ 17 | var Base64 = C_enc.Base64 = { 18 | /** 19 | * Converts a word array to a Base64 string. 20 | * 21 | * @param {WordArray} wordArray The word array. 22 | * 23 | * @return {string} The Base64 string. 24 | * 25 | * @static 26 | * 27 | * @example 28 | * 29 | * var base64String = CryptoJS.enc.Base64.stringify(wordArray); 30 | */ 31 | stringify: function (wordArray) { 32 | // Shortcuts 33 | var words = wordArray.words; 34 | var sigBytes = wordArray.sigBytes; 35 | var map = this._map; 36 | 37 | // Clamp excess bits 38 | wordArray.clamp(); 39 | 40 | // Convert 41 | var base64Chars = []; 42 | for (var i = 0; i < sigBytes; i += 3) { 43 | var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 44 | var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; 45 | var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; 46 | 47 | var triplet = (byte1 << 16) | (byte2 << 8) | byte3; 48 | 49 | for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { 50 | base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); 51 | } 52 | } 53 | 54 | // Add padding 55 | var paddingChar = map.charAt(64); 56 | if (paddingChar) { 57 | while (base64Chars.length % 4) { 58 | base64Chars.push(paddingChar); 59 | } 60 | } 61 | 62 | return base64Chars.join(''); 63 | }, 64 | 65 | /** 66 | * Converts a Base64 string to a word array. 67 | * 68 | * @param {string} base64Str The Base64 string. 69 | * 70 | * @return {WordArray} The word array. 71 | * 72 | * @static 73 | * 74 | * @example 75 | * 76 | * var wordArray = CryptoJS.enc.Base64.parse(base64String); 77 | */ 78 | parse: function (base64Str) { 79 | // Shortcuts 80 | var base64StrLength = base64Str.length; 81 | var map = this._map; 82 | 83 | // Ignore padding 84 | var paddingChar = map.charAt(64); 85 | if (paddingChar) { 86 | var paddingIndex = base64Str.indexOf(paddingChar); 87 | if (paddingIndex != -1) { 88 | base64StrLength = paddingIndex; 89 | } 90 | } 91 | 92 | // Convert 93 | var words = []; 94 | var nBytes = 0; 95 | for (var i = 0; i < base64StrLength; i++) { 96 | if (i % 4) { 97 | var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2); 98 | var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2); 99 | words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8); 100 | nBytes++; 101 | } 102 | } 103 | 104 | return WordArray.create(words, nBytes); 105 | }, 106 | 107 | _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' 108 | }; 109 | }()); 110 | -------------------------------------------------------------------------------- /js/encdec.js: -------------------------------------------------------------------------------- 1 | const enkey = '1655959604103034488113670823001292669092'; 2 | const possible_keys = [enkey, 3 | "piez-im-simple", 4 | "piez-im-advanced", 5 | "piez-a2", 6 | "piez-ro-simple", 7 | "piez-ro-advanced", 8 | "piez-3pm", 9 | "piez-off" 10 | ]; 11 | 12 | function a(obj) { 13 | if (jQuery.isEmptyObject(obj)) { 14 | return false; 15 | } else { 16 | try { 17 | var str = JSON.stringify(obj) 18 | var encrypted = CryptoJS.AES.encrypt(str, enkey); 19 | } catch (err) { 20 | console.log(err); 21 | return false; 22 | } 23 | return encrypted.toString(); 24 | } 25 | } 26 | 27 | function b(enstr) { 28 | if (enstr == undefined || enstr == null || enstr == '') { 29 | return false; 30 | } else { 31 | for(var y=0; y < possible_keys.length; y++) { 32 | var de_result = pleaseDecrypt(enstr, possible_keys[y]); 33 | if (typeof de_result == "object") { 34 | return de_result; 35 | } 36 | } 37 | return false; 38 | } 39 | } 40 | 41 | function pleaseDecrypt(encrypted_str, possible_key) { 42 | try { 43 | var decrypted = CryptoJS.AES.decrypt(encrypted_str, possible_key); 44 | var str = decrypted.toString(CryptoJS.enc.Utf8); 45 | } catch (err) { 46 | // console.log("Trying different key " + possible_key); 47 | console.log(err); 48 | return false; 49 | } 50 | return JSON.parse(str); 51 | } -------------------------------------------------------------------------------- /js/endpoints.js: -------------------------------------------------------------------------------- 1 | var getApiEndPoint = function(name, obj_params) { 2 | switch(name) { 3 | case "purge-url": 4 | return '/ccu/v3/' + obj_params.updatetype + '/url/' + obj_params.network; 5 | case "purge-cpcode": 6 | return '/ccu/v3/' + obj_params.updatetype + '/cpcode/' + obj_params.network; 7 | case "purge-tag": 8 | return '/ccu/v3/' + obj_params.updatetype + '/tag/' + obj_params.network; 9 | case "debug-translate-errorcode": 10 | return '/diagnostic-tools/v2/errors/' + obj_params.errorcode + "/translated-error"; 11 | case "debug-fetchlog-by-ip": 12 | return '/diagnostic-tools/v2/ip-addresses/' + obj_params.ipaddr + "/log-lines" + obj_params.querystring; 13 | default: 14 | return ''; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /js/evpkdf.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function () { 8 | // Shortcuts 9 | var C = CryptoJS; 10 | var C_lib = C.lib; 11 | var Base = C_lib.Base; 12 | var WordArray = C_lib.WordArray; 13 | var C_algo = C.algo; 14 | var MD5 = C_algo.MD5; 15 | 16 | /** 17 | * This key derivation function is meant to conform with EVP_BytesToKey. 18 | * www.openssl.org/docs/crypto/EVP_BytesToKey.html 19 | */ 20 | var EvpKDF = C_algo.EvpKDF = Base.extend({ 21 | /** 22 | * Configuration options. 23 | * 24 | * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) 25 | * @property {Hasher} hasher The hash algorithm to use. Default: MD5 26 | * @property {number} iterations The number of iterations to perform. Default: 1 27 | */ 28 | cfg: Base.extend({ 29 | keySize: 128/32, 30 | hasher: MD5, 31 | iterations: 1 32 | }), 33 | 34 | /** 35 | * Initializes a newly created key derivation function. 36 | * 37 | * @param {Object} cfg (Optional) The configuration options to use for the derivation. 38 | * 39 | * @example 40 | * 41 | * var kdf = CryptoJS.algo.EvpKDF.create(); 42 | * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); 43 | * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); 44 | */ 45 | init: function (cfg) { 46 | this.cfg = this.cfg.extend(cfg); 47 | }, 48 | 49 | /** 50 | * Derives a key from a password. 51 | * 52 | * @param {WordArray|string} password The password. 53 | * @param {WordArray|string} salt A salt. 54 | * 55 | * @return {WordArray} The derived key. 56 | * 57 | * @example 58 | * 59 | * var key = kdf.compute(password, salt); 60 | */ 61 | compute: function (password, salt) { 62 | // Shortcut 63 | var cfg = this.cfg; 64 | 65 | // Init hasher 66 | var hasher = cfg.hasher.create(); 67 | 68 | // Initial values 69 | var derivedKey = WordArray.create(); 70 | 71 | // Shortcuts 72 | var derivedKeyWords = derivedKey.words; 73 | var keySize = cfg.keySize; 74 | var iterations = cfg.iterations; 75 | 76 | // Generate key 77 | while (derivedKeyWords.length < keySize) { 78 | if (block) { 79 | hasher.update(block); 80 | } 81 | var block = hasher.update(password).finalize(salt); 82 | hasher.reset(); 83 | 84 | // Iterations 85 | for (var i = 1; i < iterations; i++) { 86 | block = hasher.finalize(block); 87 | hasher.reset(); 88 | } 89 | 90 | derivedKey.concat(block); 91 | } 92 | derivedKey.sigBytes = keySize * 4; 93 | 94 | return derivedKey; 95 | } 96 | }); 97 | 98 | /** 99 | * Derives a key from a password. 100 | * 101 | * @param {WordArray|string} password The password. 102 | * @param {WordArray|string} salt A salt. 103 | * @param {Object} cfg (Optional) The configuration options to use for this computation. 104 | * 105 | * @return {WordArray} The derived key. 106 | * 107 | * @static 108 | * 109 | * @example 110 | * 111 | * var key = CryptoJS.EvpKDF(password, salt); 112 | * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); 113 | * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); 114 | */ 115 | C.EvpKDF = function (password, salt, cfg) { 116 | return EvpKDF.create(cfg).compute(password, salt); 117 | }; 118 | }()); 119 | -------------------------------------------------------------------------------- /js/flush.js: -------------------------------------------------------------------------------- 1 | var script_tag = document.createElement('script'); 2 | script_tag.type = 'text/javascript'; 3 | script_tag.text = 'window.g_browser.sendClearHostResolverCache();window.g_browser.sendFlushSocketPools();'; 4 | document.body.appendChild(script_tag); 5 | -------------------------------------------------------------------------------- /js/google-analytics.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Adding google analytics to track only clicks within the extension, 3 | * this will help us improve services that are most used, feel free to email ajayapra@akamai.com in case 4 | * you would like to get a non-analytics version of our extension 5 | * Source https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/tutorials/analytics/popup.js 6 | */ 7 | 8 | // dev analytics tracker 9 | // var _AnalyticsCode = 'UA-116652320-3'; 10 | var _AnalyticsCode = 'UA-185910390-1'; 11 | 12 | var _gaq = _gaq || []; 13 | _gaq.push(['_setAccount', _AnalyticsCode]); 14 | _gaq.push(['_trackPageview']); 15 | 16 | (function() { 17 | var ga = document.createElement('script'); 18 | ga.type = 'text/javascript'; 19 | ga.async = true; 20 | ga.src = 'https://ssl.google-analytics.com/ga.js'; 21 | var s = document.getElementsByTagName('script')[0]; 22 | s.parentNode.insertBefore(ga, s); 23 | })(); 24 | 25 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 26 | if (message.type === "gaq") { 27 | _gaq.push(['_trackEvent', message.target, message.behavior]); 28 | console.log("Tracking Event - " + message.target + " : " + message.behavior); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /js/hmac-sha256.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | var CryptoJS=CryptoJS||function(h,s){var f={},g=f.lib={},q=function(){},m=g.Base={extend:function(a){q.prototype=this;var c=new q;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, 8 | r=g.WordArray=m.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=s?c:4*a.length},toString:function(a){return(a||k).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< 9 | 32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>3]|=parseInt(a.substr(b, 10 | 2),16)<<24-4*(b%8);return new r.init(d,c/2)}},n=l.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new r.init(d,c)}},j=l.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}}, 11 | u=g.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var g=0;gn;){var j;a:{j=k;for(var u=h.sqrt(j),t=2;t<=u;t++)if(!(j%t)){j=!1;break a}j=!0}j&&(8>n&&(m[n]=l(h.pow(k,0.5))),r[n]=l(h.pow(k,1/3)),n++);k++}var a=[],f=f.SHA256=q.extend({_doReset:function(){this._hash=new g.init(m.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],g=b[2],j=b[3],h=b[4],m=b[5],n=b[6],q=b[7],p=0;64>p;p++){if(16>p)a[p]= 15 | c[d+p]|0;else{var k=a[p-15],l=a[p-2];a[p]=((k<<25|k>>>7)^(k<<14|k>>>18)^k>>>3)+a[p-7]+((l<<15|l>>>17)^(l<<13|l>>>19)^l>>>10)+a[p-16]}k=q+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&m^~h&n)+r[p]+a[p];l=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&g^f&g);q=n;n=m;m=h;h=j+k|0;j=g;g=f;f=e;e=k+l|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+g|0;b[3]=b[3]+j|0;b[4]=b[4]+h|0;b[5]=b[5]+m|0;b[6]=b[6]+n|0;b[7]=b[7]+q|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; 16 | d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=q.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=q._createHelper(f);s.HmacSHA256=q._createHmacHelper(f)})(Math); 17 | (function(){var h=CryptoJS,s=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(f,g){f=this._hasher=new f.init;"string"==typeof g&&(g=s.parse(g));var h=f.blockSize,m=4*h;g.sigBytes>m&&(g=f.finalize(g));g.clamp();for(var r=this._oKey=g.clone(),l=this._iKey=g.clone(),k=r.words,n=l.words,j=0;j
    '); 25 | if (var_exit === false){ 26 | this.showStep(); 27 | } 28 | 29 | }, 30 | 31 | // increment steps or pause if we're waiting on a trigger to advance 32 | nextStep: function () { 33 | var latent = TourSteps[this.startFrom].waitForTrigger; // should we proceed? 34 | this.startFrom += 1; 35 | this[this.startFrom < TourSteps.length && !latent ? 'showStep' : 'tourComplete'](); 36 | }, 37 | 38 | // build dialog content, set focus on elements, and finally fade in the step 39 | showStep: function () { 40 | var parent = this; 41 | this.setupSelectorsLive(); 42 | 43 | $('.tour_item').removeClass('active'); 44 | this.getContent(); 45 | this.setDialogPos(TourSteps[this.startFrom].position); 46 | $('*').bind('click', { 47 | stop: this.startFrom 48 | }, this.tourClickHandler); 49 | 50 | 51 | if (!$('#tour_mask').is(":visible")) { 52 | $('#tour_mask').fadeIn(); 53 | } 54 | 55 | $(TourSteps[this.startFrom].selector).addClass('active').fadeIn(); 56 | $('#tour_dialog').fadeIn(function () { 57 | parent.dialogVisible(); 58 | }); 59 | $('#exit_tour_dialog_btn').on('click', function(e){ 60 | Tour.tourComplete(); 61 | TourSteps.length = 0; 62 | var_exit = true; 63 | return; 64 | }); 65 | }, 66 | 67 | stepComplete: function () { 68 | this.mpEvent(TourSteps[this.startFrom].actionName); 69 | $('*').unbind('click', this.tourClickHandler); 70 | var parent = this; 71 | $('#tour_dialog').fadeOut(function () { 72 | parent.nextStep(); 73 | this.inProgress = true; 74 | }); 75 | }, 76 | 77 | tourComplete: function () { 78 | $('#tour_dialog').fadeOut(); 79 | // sipmle check to see if we're pausing or at the end of our tour step 80 | // if we're just pausing, we want to keep focus on the area until we move forward 81 | if (this.startFrom == TourSteps.length) { 82 | $('#tour_mask').fadeOut(function () { 83 | $('.tour_item').removeClass('active'); 84 | if (typeof TourCompleteCallback == 'function') { 85 | TourCompleteCallback.call(); 86 | } 87 | }); 88 | } 89 | $('#tour_mask').fadeOut(function () { 90 | $('.tour_item').removeClass('active'); 91 | if (typeof TourCompleteCallback == 'function') { 92 | TourCompleteCallback.call(); 93 | } 94 | }); 95 | }, 96 | 97 | // To use: include MixPanel js (see mixpanel.com). Set identity or person info *before* the tour starts. 98 | // Add a "actionName" string to each step and upon user completion it will be automatically sent to MixPanel for funnel tracking 99 | mpEvent: function (eventName) { 100 | if (eventName) { 101 | mixpanel.track(eventName, { 102 | "funnelVersion": this.funnelID 103 | }); 104 | } 105 | }, 106 | 107 | getContent: function () { 108 | var message = TourSteps[this.startFrom].msg; 109 | message += TourSteps[this.startFrom].btnMsg ? "
    " + TourSteps[this.startFrom].btnMsg + "
    " : ""; 110 | message += TourSteps[this.startFrom].exitbtnMsg ? "
    " + TourSteps[this.startFrom].exitbtnMsg + "
    " : ""; 111 | message += TourSteps[this.startFrom].exit1btnMsg ? "
    " + TourSteps[this.startFrom].exit1btnMsg + "
    " : ""; 112 | $('#tour_dialog .msg').html(message); 113 | }, 114 | 115 | setDialogPos: function (position) { 116 | 117 | // @todo - need to calculate arrow position in px instead of % 118 | 119 | var selArray = TourSteps[this.startFrom].selector.split(","); 120 | var target = $(selArray[0]); 121 | var dialog = $('#tour_dialog'); 122 | var top, left; 123 | 124 | // added check to see if the target exists if not go to next step 125 | if (target.length === 0) 126 | { 127 | this.nextStep(); 128 | } else { 129 | 130 | switch (position) { 131 | case "top": 132 | top = target.offset().top - dialog.outerHeight() - this.offsetFudge; 133 | left = target.offset().left + target.outerWidth() / 2 - dialog.outerWidth() / 2; 134 | break; 135 | case "right": 136 | top = target.offset().top; 137 | left = target.offset().left + target.outerWidth() + this.offsetFudge; 138 | break; 139 | case "bottom": 140 | top = target.offset().top + target.outerHeight() + this.offsetFudge; 141 | left = target.offset().left + target.outerWidth() / 2 - dialog.outerWidth() / 2; 142 | break; 143 | case "left": 144 | top = target.offset().top; 145 | left = target.offset().left - dialog.outerWidth() - this.offsetFudge; 146 | break; 147 | case "center": 148 | // screen center hor & vert 149 | top = Math.max(0, (($(window).height() - dialog.outerHeight()) / 2) + $(window).scrollTop()); 150 | left = Math.max(0, (($(window).width() - dialog.outerWidth()) / 2) + $(window).scrollLeft()); 151 | break; 152 | } 153 | 154 | dialog.children('.arrow').attr('class', 'arrow ' + position); 155 | dialog.css({ 156 | top: top, 157 | left: left 158 | }); 159 | } 160 | 161 | 162 | }, 163 | 164 | // Is our next tour item visible on screen? If not, scroll to it! 165 | dialogVisible: function () { 166 | var dialog = $('#tour_dialog'), 167 | scrollTop = $(window).scrollTop(), 168 | scrollBottom = scrollTop + $(window).height(), 169 | 170 | elemTop = $(dialog).offset().top, 171 | elemBottom = elemTop + $(dialog).height(); 172 | 173 | if (!((elemBottom >= scrollTop) && (elemTop <= scrollBottom) && (elemBottom <= scrollBottom) && (elemTop >= scrollTop))) { 174 | $('html, body').animate({ 175 | scrollTop: $(dialog).offset().top - 25 176 | }, 500); 177 | } 178 | }, 179 | 180 | setupSelectorsLive: function () { 181 | // tour item class allows us to pull an element up the z-index and focus on it 182 | // if we pass more than one selector, loop through and add the class to all of them 183 | var selArray = TourSteps[this.startFrom].selector.split(","); 184 | for (var i = 0; i < selArray.length; i++) { 185 | $(selArray[i]).addClass('tour_item'); 186 | } 187 | 188 | // setup triggers for latent actions - use .trigger() to fire these off once the user has complete a custom action in your app 189 | var trigger = TourSteps[this.startFrom].waitForTrigger; 190 | if (trigger) { 191 | $('body').append(''); 192 | $(trigger).bind('click.tour', { 193 | selector: trigger 194 | }, this.resumeClickHandler); 195 | } 196 | }, 197 | 198 | // namespaced for tour resume triggers 199 | // if a trigger has been activated let's resume the tour where we left off 200 | resumeClickHandler: function (e) { 201 | $(e.data.selector).unbind('click.tour', this.resumeClickHandler); 202 | Tour.showStep(); 203 | }, 204 | 205 | // custom click handler when tour is active. 206 | // Check to see if the next action was clicked to advance the tour (nextSelector) 207 | tourClickHandler: function (e) { 208 | var nextSel = TourSteps[e.data.stop].nextSelector; 209 | if (nextSel) { // we only proceed when THIS selector is clicked i.e. #ok_button 210 | if ($(e.currentTarget).is(nextSel) || $(nextSel).find(e.currentTarget).length > 0) { 211 | Tour.stepComplete(); 212 | } 213 | } 214 | 215 | else { // no next selector specified. Any click or action will continue the tour 216 | Tour.stepComplete(); 217 | // Tour.tourComplete(); 218 | } 219 | } 220 | }; 221 | Tour.init(); // kickoff our tour 222 | 223 | 224 | 225 | }; 226 | }(jQuery, window)); -------------------------------------------------------------------------------- /js/md5.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function (Math) { 8 | // Shortcuts 9 | var C = CryptoJS; 10 | var C_lib = C.lib; 11 | var WordArray = C_lib.WordArray; 12 | var Hasher = C_lib.Hasher; 13 | var C_algo = C.algo; 14 | 15 | // Constants table 16 | var T = []; 17 | 18 | // Compute constants 19 | (function () { 20 | for (var i = 0; i < 64; i++) { 21 | T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; 22 | } 23 | }()); 24 | 25 | /** 26 | * MD5 hash algorithm. 27 | */ 28 | var MD5 = C_algo.MD5 = Hasher.extend({ 29 | _doReset: function () { 30 | this._hash = new WordArray.init([ 31 | 0x67452301, 0xefcdab89, 32 | 0x98badcfe, 0x10325476 33 | ]); 34 | }, 35 | 36 | _doProcessBlock: function (M, offset) { 37 | // Swap endian 38 | for (var i = 0; i < 16; i++) { 39 | // Shortcuts 40 | var offset_i = offset + i; 41 | var M_offset_i = M[offset_i]; 42 | 43 | M[offset_i] = ( 44 | (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | 45 | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) 46 | ); 47 | } 48 | 49 | // Shortcuts 50 | var H = this._hash.words; 51 | 52 | var M_offset_0 = M[offset + 0]; 53 | var M_offset_1 = M[offset + 1]; 54 | var M_offset_2 = M[offset + 2]; 55 | var M_offset_3 = M[offset + 3]; 56 | var M_offset_4 = M[offset + 4]; 57 | var M_offset_5 = M[offset + 5]; 58 | var M_offset_6 = M[offset + 6]; 59 | var M_offset_7 = M[offset + 7]; 60 | var M_offset_8 = M[offset + 8]; 61 | var M_offset_9 = M[offset + 9]; 62 | var M_offset_10 = M[offset + 10]; 63 | var M_offset_11 = M[offset + 11]; 64 | var M_offset_12 = M[offset + 12]; 65 | var M_offset_13 = M[offset + 13]; 66 | var M_offset_14 = M[offset + 14]; 67 | var M_offset_15 = M[offset + 15]; 68 | 69 | // Working varialbes 70 | var a = H[0]; 71 | var b = H[1]; 72 | var c = H[2]; 73 | var d = H[3]; 74 | 75 | // Computation 76 | a = FF(a, b, c, d, M_offset_0, 7, T[0]); 77 | d = FF(d, a, b, c, M_offset_1, 12, T[1]); 78 | c = FF(c, d, a, b, M_offset_2, 17, T[2]); 79 | b = FF(b, c, d, a, M_offset_3, 22, T[3]); 80 | a = FF(a, b, c, d, M_offset_4, 7, T[4]); 81 | d = FF(d, a, b, c, M_offset_5, 12, T[5]); 82 | c = FF(c, d, a, b, M_offset_6, 17, T[6]); 83 | b = FF(b, c, d, a, M_offset_7, 22, T[7]); 84 | a = FF(a, b, c, d, M_offset_8, 7, T[8]); 85 | d = FF(d, a, b, c, M_offset_9, 12, T[9]); 86 | c = FF(c, d, a, b, M_offset_10, 17, T[10]); 87 | b = FF(b, c, d, a, M_offset_11, 22, T[11]); 88 | a = FF(a, b, c, d, M_offset_12, 7, T[12]); 89 | d = FF(d, a, b, c, M_offset_13, 12, T[13]); 90 | c = FF(c, d, a, b, M_offset_14, 17, T[14]); 91 | b = FF(b, c, d, a, M_offset_15, 22, T[15]); 92 | 93 | a = GG(a, b, c, d, M_offset_1, 5, T[16]); 94 | d = GG(d, a, b, c, M_offset_6, 9, T[17]); 95 | c = GG(c, d, a, b, M_offset_11, 14, T[18]); 96 | b = GG(b, c, d, a, M_offset_0, 20, T[19]); 97 | a = GG(a, b, c, d, M_offset_5, 5, T[20]); 98 | d = GG(d, a, b, c, M_offset_10, 9, T[21]); 99 | c = GG(c, d, a, b, M_offset_15, 14, T[22]); 100 | b = GG(b, c, d, a, M_offset_4, 20, T[23]); 101 | a = GG(a, b, c, d, M_offset_9, 5, T[24]); 102 | d = GG(d, a, b, c, M_offset_14, 9, T[25]); 103 | c = GG(c, d, a, b, M_offset_3, 14, T[26]); 104 | b = GG(b, c, d, a, M_offset_8, 20, T[27]); 105 | a = GG(a, b, c, d, M_offset_13, 5, T[28]); 106 | d = GG(d, a, b, c, M_offset_2, 9, T[29]); 107 | c = GG(c, d, a, b, M_offset_7, 14, T[30]); 108 | b = GG(b, c, d, a, M_offset_12, 20, T[31]); 109 | 110 | a = HH(a, b, c, d, M_offset_5, 4, T[32]); 111 | d = HH(d, a, b, c, M_offset_8, 11, T[33]); 112 | c = HH(c, d, a, b, M_offset_11, 16, T[34]); 113 | b = HH(b, c, d, a, M_offset_14, 23, T[35]); 114 | a = HH(a, b, c, d, M_offset_1, 4, T[36]); 115 | d = HH(d, a, b, c, M_offset_4, 11, T[37]); 116 | c = HH(c, d, a, b, M_offset_7, 16, T[38]); 117 | b = HH(b, c, d, a, M_offset_10, 23, T[39]); 118 | a = HH(a, b, c, d, M_offset_13, 4, T[40]); 119 | d = HH(d, a, b, c, M_offset_0, 11, T[41]); 120 | c = HH(c, d, a, b, M_offset_3, 16, T[42]); 121 | b = HH(b, c, d, a, M_offset_6, 23, T[43]); 122 | a = HH(a, b, c, d, M_offset_9, 4, T[44]); 123 | d = HH(d, a, b, c, M_offset_12, 11, T[45]); 124 | c = HH(c, d, a, b, M_offset_15, 16, T[46]); 125 | b = HH(b, c, d, a, M_offset_2, 23, T[47]); 126 | 127 | a = II(a, b, c, d, M_offset_0, 6, T[48]); 128 | d = II(d, a, b, c, M_offset_7, 10, T[49]); 129 | c = II(c, d, a, b, M_offset_14, 15, T[50]); 130 | b = II(b, c, d, a, M_offset_5, 21, T[51]); 131 | a = II(a, b, c, d, M_offset_12, 6, T[52]); 132 | d = II(d, a, b, c, M_offset_3, 10, T[53]); 133 | c = II(c, d, a, b, M_offset_10, 15, T[54]); 134 | b = II(b, c, d, a, M_offset_1, 21, T[55]); 135 | a = II(a, b, c, d, M_offset_8, 6, T[56]); 136 | d = II(d, a, b, c, M_offset_15, 10, T[57]); 137 | c = II(c, d, a, b, M_offset_6, 15, T[58]); 138 | b = II(b, c, d, a, M_offset_13, 21, T[59]); 139 | a = II(a, b, c, d, M_offset_4, 6, T[60]); 140 | d = II(d, a, b, c, M_offset_11, 10, T[61]); 141 | c = II(c, d, a, b, M_offset_2, 15, T[62]); 142 | b = II(b, c, d, a, M_offset_9, 21, T[63]); 143 | 144 | // Intermediate hash value 145 | H[0] = (H[0] + a) | 0; 146 | H[1] = (H[1] + b) | 0; 147 | H[2] = (H[2] + c) | 0; 148 | H[3] = (H[3] + d) | 0; 149 | }, 150 | 151 | _doFinalize: function () { 152 | // Shortcuts 153 | var data = this._data; 154 | var dataWords = data.words; 155 | 156 | var nBitsTotal = this._nDataBytes * 8; 157 | var nBitsLeft = data.sigBytes * 8; 158 | 159 | // Add padding 160 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 161 | 162 | var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); 163 | var nBitsTotalL = nBitsTotal; 164 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( 165 | (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | 166 | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) 167 | ); 168 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( 169 | (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | 170 | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) 171 | ); 172 | 173 | data.sigBytes = (dataWords.length + 1) * 4; 174 | 175 | // Hash final blocks 176 | this._process(); 177 | 178 | // Shortcuts 179 | var hash = this._hash; 180 | var H = hash.words; 181 | 182 | // Swap endian 183 | for (var i = 0; i < 4; i++) { 184 | // Shortcut 185 | var H_i = H[i]; 186 | 187 | H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | 188 | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); 189 | } 190 | 191 | // Return final computed hash 192 | return hash; 193 | }, 194 | 195 | clone: function () { 196 | var clone = Hasher.clone.call(this); 197 | clone._hash = this._hash.clone(); 198 | 199 | return clone; 200 | } 201 | }); 202 | 203 | function FF(a, b, c, d, x, s, t) { 204 | var n = a + ((b & c) | (~b & d)) + x + t; 205 | return ((n << s) | (n >>> (32 - s))) + b; 206 | } 207 | 208 | function GG(a, b, c, d, x, s, t) { 209 | var n = a + ((b & d) | (c & ~d)) + x + t; 210 | return ((n << s) | (n >>> (32 - s))) + b; 211 | } 212 | 213 | function HH(a, b, c, d, x, s, t) { 214 | var n = a + (b ^ c ^ d) + x + t; 215 | return ((n << s) | (n >>> (32 - s))) + b; 216 | } 217 | 218 | function II(a, b, c, d, x, s, t) { 219 | var n = a + (c ^ (b | ~d)) + x + t; 220 | return ((n << s) | (n >>> (32 - s))) + b; 221 | } 222 | 223 | /** 224 | * Shortcut function to the hasher's object interface. 225 | * 226 | * @param {WordArray|string} message The message to hash. 227 | * 228 | * @return {WordArray} The hash. 229 | * 230 | * @static 231 | * 232 | * @example 233 | * 234 | * var hash = CryptoJS.MD5('message'); 235 | * var hash = CryptoJS.MD5(wordArray); 236 | */ 237 | C.MD5 = Hasher._createHelper(MD5); 238 | 239 | /** 240 | * Shortcut function to the HMAC's object interface. 241 | * 242 | * @param {WordArray|string} message The message to hash. 243 | * @param {WordArray|string} key The secret key. 244 | * 245 | * @return {WordArray} The HMAC. 246 | * 247 | * @static 248 | * 249 | * @example 250 | * 251 | * var hmac = CryptoJS.HmacMD5(message, key); 252 | */ 253 | C.HmacMD5 = Hasher._createHmacHelper(MD5); 254 | }(Math)); -------------------------------------------------------------------------------- /js/modal.js: -------------------------------------------------------------------------------- 1 | var link = document.createElement('link'); 2 | link.href = chrome.extension.getURL("css/HoldOn.min.css"); 3 | link.rel = "stylesheet"; 4 | link.type = "text/css"; 5 | link.id = "inject"; 6 | 7 | if ($("#inject").length == 0) { 8 | $("body").append(link); 9 | } 10 | 11 | chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 12 | if (request.action == "open") { 13 | HoldOn.open({ 14 | theme:"sk-fading-circle", 15 | textColor:"white", 16 | message:'Requesting Purge..' 17 | }); 18 | } else { 19 | HoldOn.close(); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /js/sha256.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function (Math) { 8 | // Shortcuts 9 | var C = CryptoJS; 10 | var C_lib = C.lib; 11 | var WordArray = C_lib.WordArray; 12 | var Hasher = C_lib.Hasher; 13 | var C_algo = C.algo; 14 | 15 | // Initialization and round constants tables 16 | var H = []; 17 | var K = []; 18 | 19 | // Compute constants 20 | (function () { 21 | function isPrime(n) { 22 | var sqrtN = Math.sqrt(n); 23 | for (var factor = 2; factor <= sqrtN; factor++) { 24 | if (!(n % factor)) { 25 | return false; 26 | } 27 | } 28 | 29 | return true; 30 | } 31 | 32 | function getFractionalBits(n) { 33 | return ((n - (n | 0)) * 0x100000000) | 0; 34 | } 35 | 36 | var n = 2; 37 | var nPrime = 0; 38 | while (nPrime < 64) { 39 | if (isPrime(n)) { 40 | if (nPrime < 8) { 41 | H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); 42 | } 43 | K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); 44 | 45 | nPrime++; 46 | } 47 | 48 | n++; 49 | } 50 | }()); 51 | 52 | // Reusable object 53 | var W = []; 54 | 55 | /** 56 | * SHA-256 hash algorithm. 57 | */ 58 | var SHA256 = C_algo.SHA256 = Hasher.extend({ 59 | _doReset: function () { 60 | this._hash = new WordArray.init(H.slice(0)); 61 | }, 62 | 63 | _doProcessBlock: function (M, offset) { 64 | // Shortcut 65 | var H = this._hash.words; 66 | 67 | // Working variables 68 | var a = H[0]; 69 | var b = H[1]; 70 | var c = H[2]; 71 | var d = H[3]; 72 | var e = H[4]; 73 | var f = H[5]; 74 | var g = H[6]; 75 | var h = H[7]; 76 | 77 | // Computation 78 | for (var i = 0; i < 64; i++) { 79 | if (i < 16) { 80 | W[i] = M[offset + i] | 0; 81 | } else { 82 | var gamma0x = W[i - 15]; 83 | var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ 84 | ((gamma0x << 14) | (gamma0x >>> 18)) ^ 85 | (gamma0x >>> 3); 86 | 87 | var gamma1x = W[i - 2]; 88 | var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ 89 | ((gamma1x << 13) | (gamma1x >>> 19)) ^ 90 | (gamma1x >>> 10); 91 | 92 | W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; 93 | } 94 | 95 | var ch = (e & f) ^ (~e & g); 96 | var maj = (a & b) ^ (a & c) ^ (b & c); 97 | 98 | var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); 99 | var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); 100 | 101 | var t1 = h + sigma1 + ch + K[i] + W[i]; 102 | var t2 = sigma0 + maj; 103 | 104 | h = g; 105 | g = f; 106 | f = e; 107 | e = (d + t1) | 0; 108 | d = c; 109 | c = b; 110 | b = a; 111 | a = (t1 + t2) | 0; 112 | } 113 | 114 | // Intermediate hash value 115 | H[0] = (H[0] + a) | 0; 116 | H[1] = (H[1] + b) | 0; 117 | H[2] = (H[2] + c) | 0; 118 | H[3] = (H[3] + d) | 0; 119 | H[4] = (H[4] + e) | 0; 120 | H[5] = (H[5] + f) | 0; 121 | H[6] = (H[6] + g) | 0; 122 | H[7] = (H[7] + h) | 0; 123 | }, 124 | 125 | _doFinalize: function () { 126 | // Shortcuts 127 | var data = this._data; 128 | var dataWords = data.words; 129 | 130 | var nBitsTotal = this._nDataBytes * 8; 131 | var nBitsLeft = data.sigBytes * 8; 132 | 133 | // Add padding 134 | dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); 135 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); 136 | dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; 137 | data.sigBytes = dataWords.length * 4; 138 | 139 | // Hash final blocks 140 | this._process(); 141 | 142 | // Return final computed hash 143 | return this._hash; 144 | }, 145 | 146 | clone: function () { 147 | var clone = Hasher.clone.call(this); 148 | clone._hash = this._hash.clone(); 149 | 150 | return clone; 151 | } 152 | }); 153 | 154 | /** 155 | * Shortcut function to the hasher's object interface. 156 | * 157 | * @param {WordArray|string} message The message to hash. 158 | * 159 | * @return {WordArray} The hash. 160 | * 161 | * @static 162 | * 163 | * @example 164 | * 165 | * var hash = CryptoJS.SHA256('message'); 166 | * var hash = CryptoJS.SHA256(wordArray); 167 | */ 168 | C.SHA256 = Hasher._createHelper(SHA256); 169 | 170 | /** 171 | * Shortcut function to the HMAC's object interface. 172 | * 173 | * @param {WordArray|string} message The message to hash. 174 | * @param {WordArray|string} key The secret key. 175 | * 176 | * @return {WordArray} The HMAC. 177 | * 178 | * @static 179 | * 180 | * @example 181 | * 182 | * var hmac = CryptoJS.HmacSHA256(message, key); 183 | */ 184 | C.HmacSHA256 = Hasher._createHmacHelper(SHA256); 185 | }(Math)); 186 | -------------------------------------------------------------------------------- /js/socketflush.js: -------------------------------------------------------------------------------- 1 | var script_tag = document.createElement('script'); 2 | script_tag.type = 'text/javascript'; 3 | script_tag.text = 'window.g_browser.sendFlushSocketPools();'; 4 | document.body.appendChild(script_tag); 5 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "background":{ 3 | "persistent":true, 4 | "scripts":[ 5 | "js/jquery-3.1.1.min.js", 6 | "js/core.js", 7 | "js/enc-base64.js", 8 | "js/sha256.js", 9 | "js/hmac-sha256.js", 10 | "js/md5.js", 11 | "js/evpkdf.js", 12 | "js/cipher-core.js", 13 | "js/materialize.min.js", 14 | "js/aes.js", 15 | "js/encdec.js", 16 | "js/common.js", 17 | "js/edgegrid.js", 18 | "js/background.js", 19 | "js/endpoints.js", 20 | "js/moment.js", 21 | "js/http-request.js", 22 | "js/google-analytics.js", 23 | "cmanager/cmanager-bg.js", 24 | "fastpurge/fastpurge-bg.js", 25 | "debugreq/debugreq-bg.js", 26 | "openapitester/openapitester-bg.js", 27 | "openapitester/openapitester.js" 28 | ] 29 | }, 30 | "browser_action":{ 31 | "default_icon":"img/icons-128.png", 32 | "default_title":"Akamai Developer Toolkit" 33 | }, 34 | "description":"A chrome extension that provide developers access to Akamai developer tools including testing OPEN APIs right within their workspace", 35 | "devtools_page": "/piez/devtools/devtools.html", 36 | "icons":{ 37 | "128":"img/icons-128.png", 38 | "16":"img/icons-128.png", 39 | "48":"img/icons-128.png" 40 | }, 41 | "manifest_version":2, 42 | "content_security_policy": "script-src 'self' https://ssl.google-analytics.com https://platform.twitter.com https://www.gstatic.com ; object-src 'self'", 43 | "name":"Akamai Developer Toolkit", 44 | "permissions":[ 45 | "notifications", 46 | "tabs", 47 | "activeTab", 48 | "storage", 49 | "webNavigation", 50 | "contextMenus", 51 | "management", 52 | "https://*/*", 53 | "http://*/*" 54 | ], 55 | "update_url":"https://clients2.google.com/service/update2/crx", 56 | "version":"2.0.45", 57 | "web_accessible_resources":[ 58 | "fonts/*.*", 59 | "js/jquery-3.1.1.min.js", 60 | "css/font-awesome.min.css", 61 | "css/HoldOn.min.css", 62 | "js/HoldOn.min.js" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /openapitester/openapitester-bg.js: -------------------------------------------------------------------------------- 1 | 2 | var initOpenAPIStorage = function() { 3 | console.log("initializing OPENAPI Storage"); 4 | chrome.storage.local.get("openapiHistory", function(result) { 5 | if(result['openapiHistory'] == undefined) { 6 | chrome.storage.local.set({'openapiHistory': {}}); 7 | } 8 | }); 9 | } 10 | 11 | 12 | function saveOpenAPIResult(openapi_result) { 13 | chrome.storage.local.get('openapiHistory', function(records) { 14 | var openapi_history = records['openapiHistory']; 15 | openapi_history[openapi_result.requestId] = openapi_result; 16 | chrome.storage.local.set({ openapiHistory: openapi_history }); 17 | console.log("New OpenAPI record added"); 18 | loadHistory1(); 19 | }); 20 | } 21 | 22 | 23 | 24 | 25 | var OnRequestSuccess = function(response, status, obj_request, jqappxhr, respp_time) { 26 | _gaq.push(['_trackEvent', 'OpenAPI_req_successful', 'yes']); 27 | var openapireq_result = { 28 | 'lastupdated': getCurrentDatetimeUTC(), 29 | 'requestedTime': obj_request.requestedTime, 30 | 'endpoint': obj_request.endpoint, 31 | 'method': obj_request.method, 32 | 'body_data': obj_request.body_data, 33 | 'response_headers': jqappxhr.getAllResponseHeaders(), 34 | 'raw_response': response, 35 | 'token_desc': obj_request.token_desc, 36 | 'requestId': obj_request.requestId, 37 | 'status': 'success', 38 | 'respreq_time': respp_time 39 | }; 40 | //console.log(openapireq_result.respreq_time); 41 | saveOpenAPIResult(openapireq_result); 42 | loadOpenAPIResults(openapireq_result); 43 | var loadresp_status = '

    | Request Status:



    ' 44 | //message to send success notification to popup.js 45 | chrome.runtime.sendMessage({ 46 | msg: "openapi_notfify", 47 | data: { 48 | subject: "MSG", 49 | content: loadresp_status 50 | } 51 | }); 52 | 53 | //showListNotification("OpenAPI", "Request Success", openapireq_result, img_success); 54 | } 55 | 56 | var OnRequestError = function(xhr, status, error, obj_request, respe_time) { 57 | var openapireqerror_result = { 58 | 'lastupdated': getCurrentDatetimeUTC(), 59 | 'requestedTime': obj_request.requestedTime, 60 | 'endpoint': obj_request.endpoint, 61 | 'method': obj_request.method, 62 | 'body_data': obj_request.body_data, 63 | 'response_headers': xhr.getAllResponseHeaders(), 64 | 'raw_response': '', 65 | 'token_desc': obj_request.token_desc, 66 | 'requestId': obj_request.requestId, 67 | 'status': 'fail', 68 | 'respreq_time': respe_time 69 | }; 70 | try { 71 | openapireqerror_result['raw_response'] = JSON.parse(xhr.responseText); 72 | } catch (err) { 73 | openapireqerror_result['raw_response'] = {detail: 'Could not make API request'}; 74 | } 75 | saveOpenAPIResult(openapireqerror_result); 76 | loadOpenAPIResults(openapireqerror_result); 77 | var loadresp_status = '

    | Request Status:



    ' 78 | //message to send success notification to popup.js 79 | chrome.runtime.sendMessage({ 80 | msg: "openapi_notfify", 81 | data: { 82 | subject: "MSG", 83 | content: loadresp_status 84 | } 85 | }); 86 | // $.notify("OPEN API request unsuccessful", "error"); 87 | // showListNotification("OpenAPI", "Request Failed", openapireqerror_result, img_fail); 88 | } 89 | 90 | 91 | function makeOpenAPIReq(arr_openapiendpoint, arr_method, arr_headersname, arr_headerspresent, arr_headersvalue, arr_addpostbody, callback) { 92 | // console.log(arr_method); 93 | // console.log(arr_openapiendpoint); 94 | // console.log(arr_addpostbody); 95 | // console.log(arr_headersname); 96 | // console.log(arr_headersvalue); 97 | 98 | // if(!checkActiveCredential("luna")){ 99 | // callback(); 100 | // return; 101 | //} 102 | var arr_headernamevalue = {}; 103 | arr_headernamevalue [arr_headersname] = arr_headersvalue; 104 | console.log(arr_headersname); 105 | console.log(arr_headersvalue); 106 | if (arr_method == "GET"){ 107 | var obj_request = { 108 | url: activatedTokenCache.baseurl + arr_openapiendpoint, 109 | endpoint: arr_openapiendpoint, 110 | method: arr_method, 111 | headerpresent: arr_headerspresent, 112 | headernamevalue: arr_headernamevalue, 113 | headername: arr_headersname, 114 | headervalue: arr_headersvalue, 115 | auth_header: authorizationHeader({method: "GET", tokens: activatedTokenCache, endpoint: arr_openapiendpoint}), 116 | requestId: "OpenAPI_" + new Date().getTime().toString(), 117 | token_desc: activatedTokenCache.desc, 118 | requestedTime: getCurrentDatetimeUTC() 119 | } 120 | sendGetReq(obj_request, OnRequestSuccess, OnRequestError); 121 | //showBasicNotification("OPEN API GET Requested", "You will get notified shortly"); 122 | sleep(Math.floor((Math.random() * 1000) + 100), callback); 123 | } 124 | if(arr_method == "POST"){ 125 | var obj_request = { 126 | url: activatedTokenCache.baseurl + arr_openapiendpoint, 127 | endpoint: arr_openapiendpoint, 128 | method: arr_method, 129 | headerpresent: arr_headerspresent, 130 | headernamevalue: arr_headernamevalue, 131 | headername: arr_headersname, 132 | headervalue: arr_headersvalue, 133 | body_data: arr_addpostbody, 134 | auth_header: authorizationHeader({method: "POST", body: arr_addpostbody, tokens: activatedTokenCache, endpoint: arr_openapiendpoint}), 135 | requestId: "OpenAPI_" + new Date().getTime().toString(), 136 | token_desc: activatedTokenCache.desc, 137 | requestedTime: getCurrentDatetimeUTC() 138 | } 139 | 140 | sendPostReq(obj_request, OnRequestSuccess, OnRequestError, callback); 141 | //showBasicNotification("OPEN API POST Requested", "You will get notified shortly"); 142 | sleep(Math.floor((Math.random() * 1000) + 100), callback); 143 | 144 | } 145 | if(arr_method == "PUT"){ 146 | var obj_request = { 147 | url: activatedTokenCache.baseurl + arr_openapiendpoint, 148 | endpoint: arr_openapiendpoint, 149 | method: arr_method, 150 | headerpresent: arr_headerspresent, 151 | headernamevalue: arr_headernamevalue, 152 | headername: arr_headersname, 153 | headervalue: arr_headersvalue, 154 | body_data: arr_addpostbody, 155 | auth_header: authorizationHeader({method: "PUT", body: arr_addpostbody, tokens: activatedTokenCache, endpoint: arr_openapiendpoint}), 156 | requestId: "OpenAPI_" + new Date().getTime().toString(), 157 | token_desc: activatedTokenCache.desc, 158 | requestedTime: getCurrentDatetimeUTC() 159 | } 160 | 161 | sendPutReq(obj_request, OnRequestSuccess, OnRequestError, callback); 162 | //showBasicNotification("OPEN API POST Requested", "You will get notified shortly"); 163 | sleep(Math.floor((Math.random() * 1000) + 100), callback); 164 | 165 | } 166 | 167 | if(arr_method == "DELETE"){ 168 | var obj_request = { 169 | url: activatedTokenCache.baseurl + arr_openapiendpoint, 170 | endpoint: arr_openapiendpoint, 171 | method: arr_method, 172 | headerpresent: arr_headerspresent, 173 | headernamevalue: arr_headernamevalue, 174 | headername: arr_headersname, 175 | headervalue: arr_headersvalue, 176 | auth_header: authorizationHeader({method: "DELETE", tokens: activatedTokenCache, endpoint: arr_openapiendpoint}), 177 | requestId: "OpenAPI_" + new Date().getTime().toString(), 178 | token_desc: activatedTokenCache.desc, 179 | requestedTime: getCurrentDatetimeUTC() 180 | } 181 | sendDeleteReq(obj_request, OnRequestSuccess, OnRequestError, callback); 182 | // showBasicNotification("OPEN API POST Requested", "You will get notified shortly"); 183 | sleep(Math.floor((Math.random() * 1000) + 100), callback); 184 | 185 | } 186 | 187 | 188 | } 189 | 190 | 191 | function loadHistory1() { 192 | chrome.runtime.sendMessage({ 193 | msg: "reload_history", 194 | data: { 195 | subject: "XHR5 response", 196 | content: "history reloaded" 197 | } 198 | }); 199 | } -------------------------------------------------------------------------------- /openapitester/openapitester-details.js: -------------------------------------------------------------------------------- 1 | function loadDetails(openapireq_req_id, callback) { 2 | chrome.storage.local.get('openapiHistory', function(data) { 3 | var obj_records = data['openapiHistory']; 4 | var history_data = obj_records[openapireq_req_id]; 5 | 6 | var html = ''; 7 | html += ''; 8 | html += ''; 9 | 10 | var better_title = { 11 | raw_response: "Raw Response", 12 | lastupdated: "Last Updated", 13 | requestedTime: "Request Time", 14 | token_desc: "Credential Used", 15 | requestId: "Request Id", 16 | status: "Response Status", 17 | method: "HTTP Method", 18 | endpoint: "API Endpoint", 19 | body_data: "POST Payload", 20 | response_headers: "Response Headers", 21 | respreq_time: "Total Time For Response" 22 | 23 | } 24 | 25 | var arr_keys = Object.keys(history_data).reverse(); 26 | 27 | for(var i=0; i < arr_keys.length; i++) { 28 | let key = arr_keys[i]; 29 | var text = ""; 30 | if (jQuery.type(history_data[key]) == 'object' && key != 'token_desc') { 31 | text = "
    " + JSON.stringify(history_data[key], null, 2) + "
    "; 32 | } else if (jQuery.type(history_data[key]) == 'object Object'){ 33 | text += "

    " + history_data[key] + "

    "; 34 | } 35 | else if (jQuery.type(history_data[key]) == 'array') { 36 | for(var k=0; k < history_data[key].length; k++) { 37 | text += "
    " + JSON.stringify(history_data[key][k], null, 2) + "
    "; 38 | } 39 | } else if (key == 'token_desc') { 40 | text = history_data[key]; 41 | } else { 42 | text = history_data[key]; 43 | } 44 | html += ""; 45 | } 46 | html += '
    " + better_title[key] + "" + text + "
    '; 47 | html += ''; 48 | html += ''; 49 | 50 | callback(html); 51 | }); 52 | } 53 | -------------------------------------------------------------------------------- /openapitester/openapitester-history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Open API History 4 | 5 | 6 | 7 | 8 | 20 | 21 | 22 | 23 |
    24 |
    25 |
    26 |
    27 |
    28 |
    29 |
    30 | 31 |
    32 | OPEN API History 33 |
    34 | 35 |
    36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
    Time(GMT)OPEN API CredHTTP MethodAPI Endpoint RequestedResponse Status
    51 |
    52 | 53 |
    54 |
    55 | Clear History 56 | Close Tab 57 |
    58 |
    59 | 60 |
    61 |
    62 |
    63 |
    64 |
    65 |
    66 | 67 |
    68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /openapitester/openapitester-history.js: -------------------------------------------------------------------------------- 1 | var tableapis = {}; 2 | $(document).ready(function() { 3 | 4 | //chrome.runtime.sendMessage({type: "gaq", target: "OpenAPI_history_page", behavior: "loaded"}); 5 | 6 | loadHistory(function(){ 7 | initDataTable(); 8 | var passedId = getUrlParameter('id'); 9 | if (passedId){ 10 | $(".show-more [requestId="+passedId+"]").trigger('click'); 11 | } 12 | }); 13 | 14 | $('#clearHistoryButton').click(function(){ 15 | chrome.runtime.sendMessage({type: "gaq", target: "OpenAPI_history_page_clearhistory", behavior: "clicked"}); 16 | removeHistoryRecord(); 17 | }); 18 | 19 | $('#closeButton').click(function(){ 20 | chrome.runtime.sendMessage({type: "gaq", target: "OpenAPI_history_page_closebtn", behavior: "clicked"}); 21 | closeCurrentTab(); 22 | }); 23 | 24 | $('body').on('click', '.show-more [requestId]', function () { 25 | var td = $(this); 26 | var tr = td.closest('tr'); 27 | var tr_next = tr.next('tr'); 28 | var openapi_req_id = td.attr('requestId'); 29 | td.children("i").text("expand_less"); 30 | loadDetails(openapi_req_id, function(data){ 31 | if (tr_next.attr('class') == "shown") { 32 | td.children("i").text("expand_more"); 33 | tr_next.hide(); 34 | tr_next.remove(); 35 | } else { 36 | tr.after(data); 37 | } 38 | }); 39 | }); 40 | 41 | $('body').on('click', '.delete-record [requestId]', function () { 42 | var td = $(this); 43 | var tr = td.closest('tr'); 44 | var openapi_req_id = td.attr('requestId'); 45 | removeHistoryRecord(openapi_req_id); 46 | tr.hide(); 47 | }); 48 | }); 49 | 50 | function initDataTable(){ 51 | tableapis = $('#openapi-table').DataTable({ 52 | "columnDefs": [ { 53 | "targets" : 'no-sort', 54 | "orderable": false 55 | }], 56 | "order":[ 57 | [1, 'dsc'] 58 | ] 59 | }); 60 | } 61 | 62 | 63 | function loadHistory(callback) { 64 | $("#historylist").empty(); 65 | chrome.storage.local.get('openapiHistory', function(openapidata) { 66 | var obj_records = openapidata['openapiHistory']; 67 | for (var openapiReqId in obj_records) { 68 | var obj_history = obj_records[openapiReqId]; 69 | tbody_html = ""; 70 | tbody_html += ""; 71 | tbody_html += "expand_more"; 72 | tbody_html += "" + obj_history.requestedTime + ""; 73 | tbody_html += "" + obj_history.token_desc + ""; 74 | tbody_html += "" + obj_history.method + ""; 75 | tbody_html += "" + obj_history.endpoint + ""; 76 | tbody_html += "" + obj_history.status + ""; 77 | tbody_html += ""; 78 | tbody_html += "delete"; 79 | tbody_html += ""; 80 | $("#historylist").append(tbody_html); 81 | } 82 | callback(); 83 | }); 84 | } 85 | 86 | function removeHistoryRecord(openapiRecordId) { 87 | console.log('remove record was called') 88 | chrome.storage.local.get('openapiHistory', function(data) { 89 | var obj_records = data['openapiHistory']; 90 | if (openapiRecordId == null) { 91 | for (key in obj_records) { 92 | delete obj_records[key]; 93 | } 94 | } else { 95 | delete obj_records[openapiRecordId]; 96 | } 97 | chrome.storage.local.set({'openapiHistory': obj_records}, function(){ 98 | if (Object.keys(obj_records).length == 0) { 99 | $('#openapi-table').DataTable().clear().destroy(); 100 | initDataTable(); 101 | } 102 | }); 103 | }); 104 | } 105 | 106 | 107 | 108 | function addRecordintoHistory(){ 109 | $('#openapi-table').DataTable().clear().destroy(); 110 | loadHistory(function(){ 111 | initDataTable(); 112 | }); 113 | } 114 | -------------------------------------------------------------------------------- /openapitester/openapitester.js: -------------------------------------------------------------------------------- 1 | $('#openapitesterhistorydetails, #openapitesterhistorydetailslink').click(function() { 2 | chrome.runtime.sendMessage({type: "gaq", target: "View_openapitester_history", behavior: "clicked"}); 3 | chrome.tabs.create({ 4 | url: 'openapitester/openapitester-history.html' 5 | }); 6 | }); 7 | 8 | 9 | 10 | function loadOpenAPIResults(openapi_result){ 11 | $("#openapiresults-js").empty(); 12 | $('.openapiresppayload-js').empty(); 13 | $('.openapirespheaders-js').empty(); 14 | $('.openapireqheaders-js').empty(); 15 | $('.openapireqpayload-js').empty(); 16 | 17 | 18 | // console.log(openapi_result.requestId); 19 | //console.log(openapi_result.raw_response); 20 | 21 | 22 | var html1 = '
    '; 23 | html1 += ''; 24 | html1 += ''; 82 | html1 += ''; 83 | html1 += '
    '; 25 | html1 += ''; 26 | 27 | var better1_title = { 28 | raw_response: "Raw Response", 29 | lastupdated: "Last Updated", 30 | requestedTime: "Request Time", 31 | token_desc: "Credential Used", 32 | requestId: "Request Id", 33 | status: "Response Status", 34 | method: "HTTP Method", 35 | endpoint: "API endpoint", 36 | body_data: "POST Payload", 37 | response_headers: "Response Headers", 38 | respreq_time: "Total time for request response" 39 | 40 | } 41 | 42 | var loadresponse_payload = '
    ' + JSON.stringify(openapi_result.raw_response, null, 2) + '
    '; 43 | 44 | 45 | var loadresponse_headers = '
    ' + openapi_result.response_headers.replace('\r\n', '
    ') + '
    '; 46 | 47 | var loadrequest_payload = '
    ' + openapi_result.body_data + '
    '; 48 | 49 | var loadresp_time = '

    | Time taken for response:'+ openapi_result.respreq_time + '



    ' 50 | 51 | //need to define this 52 | // var loadrequest_headers ={ 53 | // body_data: "Request Payload" 54 | // } 55 | 56 | //defining HTML for detailed view 57 | var arr1_keys = Object.keys(openapi_result).reverse(); 58 | for(var i=0; i < arr1_keys.length; i++) { 59 | let key1 = arr1_keys[i]; 60 | var text1 = ""; 61 | 62 | if (jQuery.type(openapi_result[key1]) == 'object'|| jQuery.type(openapi_result[key1]) == 'array' && key1 != 'token_desc') { 63 | 64 | text1 = "
    " + JSON.stringify(openapi_result[key1], null, 2) + "
    "; 65 | 66 | } else if (jQuery.type(openapi_result[key1]) == 'array') { 67 | for(var k=0; k < openapi_result[key1].length; k++) { 68 | text1 += "

    " + openapi_result[key1][k] + "

    "; 69 | 70 | } 71 | } else if (key1 == 'token_desc') { 72 | text1 = openapi_result[key1]; 73 | 74 | } else { 75 | text1 = openapi_result[key1]; 76 | 77 | } 78 | html1 += ""; 79 | } 80 | html1 += '
    " + better1_title[key1] + "" + text1 + "
    '; 81 | html1 += '
    '; 84 | 85 | //defining html for response payload 86 | var html2 = '
    '; 87 | html2 += ''+ loadresponse_payload + '
    '; 88 | //console.log(html2); 89 | 90 | //defining html for response headers 91 | var html3 = '
    '; 92 | html3 += ''+ loadresponse_headers + '
    '; 93 | 94 | //defining html for request payload 95 | var html4 = '
    '; 96 | html4 += ''+ loadrequest_payload + '
    '; 97 | 98 | //message to send detailed response to popup.js 99 | chrome.runtime.sendMessage({ 100 | msg: "openapi_response_completed", 101 | data: { 102 | subject: "XHR response", 103 | content: html1 104 | } 105 | }); 106 | 107 | //message to send detailed response payload to popup.js 108 | chrome.runtime.sendMessage({ 109 | msg: "openapi_response_payload", 110 | data: { 111 | subject: "XHR1 response", 112 | content: html2 113 | } 114 | }); 115 | //message to send detailed response headers to popup.js 116 | chrome.runtime.sendMessage({ 117 | msg: "openapi_response_headers", 118 | data: { 119 | subject: "XHR2 response", 120 | content: html3 121 | } 122 | }); 123 | //message to send detailed request payload to popup.js 124 | chrome.runtime.sendMessage({ 125 | msg: "openapi_request_payload", 126 | data: { 127 | subject: "XHR3 response", 128 | content: html4 129 | } 130 | }); 131 | //message to send total time to popup.js 132 | chrome.runtime.sendMessage({ 133 | msg: "openapi_response_time", 134 | data: { 135 | subject: "XHR4 response", 136 | content: loadresp_time 137 | } 138 | }); 139 | 140 | // loadHistory1(); 141 | 142 | } 143 | 144 | $('#openapitester-submitButton').click(function(obj) { 145 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 146 | backgroundpage._gaq.push(['_trackEvent', 'Submit_openapitester_req', 'clicked']); 147 | }); 148 | var arr_target_headerspresent = false; 149 | var arr_target_openapiendpoint = $('#openapiendpoint').val().split("\n"); 150 | var arr_target_method = $('#openAPImethod').prop('value'); 151 | var arr_target_headersname = $('#addheadersname').val().split("\n"); 152 | var arr_target_headersvalue = $('#addheadersvalue').val().split("\n"); 153 | var arr_target_headersnamelngth = $('#addheadersname').val().length; 154 | console.log(arr_target_headersnamelngth); 155 | //var arr_target_headersvaluelngth = $('#addheadersvalue').val().length; 156 | if (arr_target_headersnamelngth >0){ 157 | arr_target_headerspresent = true; 158 | } 159 | var arr_target_addpostbody = $('#addpostbody').val(); 160 | body_data = arr_target_addpostbody.replace(/\n/g,""); 161 | //console.log(body_data); 162 | var submit_buttons = $('#openapitester-submitButton'); 163 | if (arr_target_openapiendpoint.filter(Boolean).length == 0) { 164 | Materialize.toast('Please enter an API endpoint', 1500); 165 | return false; 166 | } else { 167 | //empty previous response request results from div 168 | $('.openapiresults-js').empty(); 169 | $('.openapiresppayload-js').empty(); 170 | $('.openapirespheaders-js').empty(); 171 | $('.openapireqheaders-js').empty(); 172 | $('.openapireqpayload-js').empty(); 173 | $('.responsestatus-js').empty(); 174 | $('.responsetime-js').empty(); 175 | //inject spinner into div 176 | $('.openapiresults-js').append('
    '); 177 | $('.openapiresppayload-js').append('
    '); 178 | $('.openapirespheaders-js').append('
    '); 179 | $('.openapireqheaders-js').append('
    '); 180 | $('.openapireqpayload-js').append('
    '); 181 | 182 | 183 | var submit_buttons = $('#openapitester-submitButton'); 184 | var this_obj = $(this); 185 | var this_html = $(this).html(); 186 | submit_buttons.addClass("disabled"); 187 | this_obj.html(''); 188 | chrome.runtime.getBackgroundPage(function(backgroundpage) { 189 | backgroundpage.makeOpenAPIReq(arr_target_openapiendpoint.filter(Boolean), arr_target_method, arr_target_headersname, arr_target_headerspresent, arr_target_headersvalue, body_data, function(request_result) { 190 | submit_buttons.removeClass("disabled").blur(); 191 | this_obj.html(this_html); 192 | }); 193 | }); 194 | } 195 | }); 196 | 197 | 198 | -------------------------------------------------------------------------------- /papiviz/css/papiviz.css: -------------------------------------------------------------------------------- 1 | #page {min-height:600px;} 2 | .package {padding:3px;border-radius:2px;margin-top:3px;} 3 | .header {cursor:pointer;} 4 | 5 | .name {color:gray;} 6 | 7 | .array {background-color:#FFD8BB;border:thin solid #FFB780;} 8 | .object {background-color:#E7F1FE;border:thin solid #7DA2CE;} 9 | .string {color:red;} 10 | .number {color:blue;} 11 | .function {color:green;} 12 | 13 | .open .children {display:block;} 14 | .closed .children {display:none;} 15 | 16 | .arrow {background-image:url("../img/d.png"); background-repeat:no-repeat; background-color:transparent; height:15px; width:15px; display:inline-block;} 17 | 18 | .open .arrow {background-position:-20px 0;} 19 | .closed .arrow {background-position:0 0;} 20 | 21 | .type {color:gray;font-size:8pt;float:right;} 22 | 23 | .hide {display:none;} 24 | 25 | #main {width:100%;height:500px;overflow-y:scroll;} -------------------------------------------------------------------------------- /papiviz/img/d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akamai/akamai_developer_toolkit/0c0464d8b8d189bf751b8ca87f84899d7e5c5546/papiviz/img/d.png -------------------------------------------------------------------------------- /papiviz/js/jquery.json2html.js: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2013 Crystalline Technologies 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), 4 | // to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 5 | // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | // 7 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | // 9 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 11 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | 13 | (function($){ 14 | 15 | //Main method 16 | $.fn.json2html = function(json, transform, _options){ 17 | 18 | //Make sure we have the json2html base loaded 19 | if(typeof json2html === 'undefined') return(undefined); 20 | 21 | //Default Options 22 | var options = { 23 | 'append':true, 24 | 'replace':false, 25 | 'prepend':false, 26 | 'eventData':{} 27 | }; 28 | 29 | //Extend the options (with defaults) 30 | if( _options !== undefined ) $.extend(options, _options); 31 | 32 | //Insure that we have the events turned (Required) 33 | options.events = true; 34 | 35 | //Make sure to take care of any chaining 36 | return this.each(function(){ 37 | 38 | //let json2html core do it's magic 39 | var result = json2html.transform(json, transform, options); 40 | 41 | //Attach the html(string) result to the DOM 42 | var dom = $(document.createElement('i')).html(result.html); 43 | 44 | //Determine if we have events 45 | for(var i = 0; i < result.events.length; i++) { 46 | 47 | var event = result.events[i]; 48 | 49 | //find the associated DOM object with this event 50 | var obj = $(dom).find("[json2html-event-id-"+event.type+"='" + event.id + "']"); 51 | 52 | //Check to see if we found this element or not 53 | if(obj.length === 0) throw 'jquery.json2html was unable to attach event ' + event.id + ' to DOM'; 54 | 55 | //remove the attribute 56 | $(obj).removeAttr('json2html-event-id-'+event.type); 57 | 58 | //attach the event 59 | $(obj).on(event.type,event.data,function(e){ 60 | //attach the jquery event 61 | e.data.event = e; 62 | 63 | //call the appropriate method 64 | e.data.action.call($(this),e.data); 65 | }); 66 | } 67 | 68 | //Append it to the appropriate element 69 | if (options.replace) $.fn.replaceWith.call($(this),$(dom).children()); 70 | else if (options.prepend) $.fn.prepend.call($(this),$(dom).children()); 71 | else $.fn.append.call($(this),$(dom).children()); 72 | }); 73 | }; 74 | })(jQuery); 75 | -------------------------------------------------------------------------------- /papiviz/lib/index.js: -------------------------------------------------------------------------------- 1 | 2 | //three types of objects 3 | // array 4 | // object 5 | // function 6 | 7 | var json2 = { "rules": { "name": "default", "children": [ { "name": "Performance", "children": [ { "name": "Compressible Objects", "children": [], "behaviors": [ { "name": "gzipResponse", "options": { "behavior": "ALWAYS" } } ], "criteria": [ { "name": "contentType", "options": { "matchCaseSensitive": false, "matchOperator": "IS_ONE_OF", "matchWildcard": true, "values": [ "text/*", "application/javascript", "application/x-javascript", "application/x-javascript*", "application/json", "application/x-json", "application/*+json", "application/*+xml", "application/text", "application/vnd.microsoft.icon", "application/vnd-ms-fontobject", "application/x-font-ttf", "application/x-font-opentype", "application/x-font-truetype", "application/xmlfont/eot", "application/xml", "font/opentype", "font/otf", "font/eot", "image/svg+xml", "image/vnd.microsoft.icon" ] } } ], "criteriaMustSatisfy": "all", "comments": "Compresses content to improve performance of clients with slow connections. Applies Last Mile Acceleration to requests when the returned object supports gzip compression." } ], "behaviors": [ { "name": "enhancedAkamaiProtocol", "options": { "display": "" } }, { "name": "allowTransferEncoding", "options": { "enabled": true } }, { "name": "removeVary", "options": { "enabled": true } } ], "criteria": [], "criteriaMustSatisfy": "all", "comments": "Improves the performance of delivering objects to end users. Behaviors in this rule are applied to all requests as appropriate." }, { "name": "Offload", "children": [ { "name": "CSS and JavaScript", "children": [], "behaviors": [ { "name": "caching", "options": { "behavior": "MAX_AGE", "mustRevalidate": false, "ttl": "1d" } }, { "name": "prefreshCache", "options": { "enabled": true, "prefreshval": 90 } } ], "criteria": [ { "name": "fileExtension", "options": { "matchCaseSensitive": false, "matchOperator": "IS_ONE_OF", "values": [ "css", "js" ] } } ], "criteriaMustSatisfy": "any", "comments": "Overrides the default caching behavior for CSS and JavaScript objects that are cached on the edge server. Because these object types are dynamic, the TTL is brief." }, { "name": "Static Objects", "children": [], "behaviors": [ { "name": "caching", "options": { "behavior": "MAX_AGE", "mustRevalidate": false, "ttl": "7d" } }, { "name": "prefreshCache", "options": { "enabled": true, "prefreshval": 90 } } ], "criteria": [ { "name": "fileExtension", "options": { "matchCaseSensitive": false, "matchOperator": "IS_ONE_OF", "values": [ "aif", "aiff", "au", "avi", "bin", "bmp", "cab", "carb", "cct", "cdf", "class", "doc", "dcr", "dtd", "exe", "flv", "gcf", "gff", "gif", "grv", "hdml", "hqx", "ico", "ini", "jpeg", "jpg", "mov", "mp3", "nc", "pct", "pdf", "png", "ppc", "pws", "swa", "swf", "txt", "vbs", "w32", "wav", "wbmp", "wml", "wmlc", "wmls", "wmlsc", "xsd", "zip", "pict", "tif", "tiff", "mid", "midi", "ttf", "eot", "woff", "woff2", "otf", "svg", "svgz", "webp", "jxr", "jar", "jp2" ] } } ], "criteriaMustSatisfy": "any", "comments": "Overrides the default caching behavior for images, music, and similar objects that are cached on the edge server. Because these object types are static, the TTL is long." }, { "name": "Uncacheable Responses", "children": [], "behaviors": [ { "name": "downstreamCache", "options": { "behavior": "TUNNEL_ORIGIN" } } ], "criteria": [ { "name": "cacheability", "options": { "matchOperator": "IS_NOT", "value": "CACHEABLE" } } ], "criteriaMustSatisfy": "all", "comments": "Overrides the default downstream caching behavior for uncacheable object types. Instructs the edge server to pass Cache-Control and/or Expire headers from the origin to the client." } ], "behaviors": [ { "name": "caching", "options": { "behavior": "NO_STORE" } }, { "name": "cacheError", "options": { "enabled": true, "preserveStale": true, "ttl": "10s" } }, { "name": "downstreamCache", "options": { "allowBehavior": "LESSER", "behavior": "ALLOW", "sendHeaders": "CACHE_CONTROL_AND_EXPIRES", "sendPrivate": false } } ], "criteria": [], "criteriaMustSatisfy": "all", "comments": "Controls caching, which offloads traffic away from the origin. Most objects types are not cached. However, the child rules override this behavior for certain subsets of requests." }, { "name": "Image Manager", "children": [], "behaviors": [ { "name": "caching", "options": { "behavior": "MAX_AGE", "mustRevalidate": false, "ttl": "30d" } } ], "criteria": [ { "name": "fileExtension", "options": { "matchCaseSensitive": false, "matchOperator": "IS_ONE_OF", "values": [ "jpg", "gif", "jpeg", "png", "imviewer" ] } } ], "criteriaMustSatisfy": "all", "comments": "Enable Scale for Mobile to serve the best available size for the requesting device. (Careful testing is highly recommended.) Enable Use Best File Type to serve the image format that works best for the requesting client. To configure breakpoint widths, derivative image quality, and artistic transformations, save and activate this configuration; then, create policies for this policy set via either Image Manager Policy Manager or the OPEN Image Manager API." } ], "behaviors": [ { "name": "origin", "options": { "cacheKeyHostname": "ORIGIN_HOSTNAME", "compress": true, "enableTrueClientIp": false, "forwardHostHeader": "ORIGIN_HOSTNAME", "httpPort": 80, "originType": "CUSTOMER", "hostname": "origin.akamaideveloper.net" } }, { "name": "cpCode", "options": { "value": { "id": 755127, "name": "DEV-POPS-RESERVED-123081", "description": "DevPoPs internal CPCODE" } } }, { "name": "allowPost", "options": { "allowWithoutContentLength": false, "enabled": true } }, { "name": "realUserMonitoring", "options": { "enabled": true } } ], "options": { "is_secure": false }, "variables": [], "comments": "The behaviors in the Default Rule apply to all requests for the property hostname(s) unless another rule overrides the Default Rule settings." } }; 8 | 9 | var transforms = { 10 | 'object':{'tag':'div','class':'package ${show} ${type}','children':[ 11 | {'tag':'div','class':'header','children':[ 12 | {'tag':'div','class':function(obj){ 13 | 14 | var classes = ["arrow"]; 15 | 16 | if( getValue(obj.value) !== undefined ) classes.push("hide"); 17 | 18 | return(classes.join(' ')); 19 | }}, 20 | {'tag':'span','class':'name','html':'${name}'}, 21 | {'tag':'span','class':'value','html':function(obj) { 22 | var value = getValue(obj.value); 23 | if( value !== undefined ) return(" : " + value); 24 | else return(''); 25 | }}, 26 | {'tag':'span','class':'type','html':'${type}'} 27 | ]}, 28 | {'tag':'div','class':'children','children':function(obj){return(children(obj.value));}} 29 | ]} 30 | }; 31 | 32 | $(function(){ 33 | 34 | $('#inputJSON').val(JSON.stringify(json2)); 35 | 36 | //Visualize sample 37 | visualize(json2); 38 | 39 | $('#btnVisualize').click(function() { 40 | 41 | //Get the value from the input field 42 | var json_string = $('#inputJSON').val(); 43 | 44 | //Parse the json string 45 | try 46 | { 47 | //json 48 | var json = JSON.parse(json_string); 49 | 50 | //eval 51 | //eval("var json=" + json_string); 52 | 53 | visualize(json); 54 | } 55 | catch (e) 56 | { 57 | alert("Sorry error in json string, please correct and try again: " + e.message); 58 | } 59 | }); 60 | 61 | }); 62 | 63 | function visualize(json) { 64 | 65 | $('#top').html(''); 66 | 67 | $('#top').json2html(convert('json',json,'open'),transforms.object); 68 | 69 | regEvents(); 70 | } 71 | 72 | function getValue(obj) { 73 | var type = $.type(obj); 74 | 75 | //Determine if this object has children 76 | switch(type) { 77 | case 'array': 78 | case 'object': 79 | return(undefined); 80 | break; 81 | 82 | case 'function': 83 | //none 84 | return('function'); 85 | break; 86 | 87 | case 'string': 88 | return("'" + obj + "'"); 89 | break; 90 | 91 | default: 92 | return(obj); 93 | break; 94 | } 95 | } 96 | 97 | //Transform the children 98 | function children(obj){ 99 | var type = $.type(obj); 100 | 101 | //Determine if this object has children 102 | switch(type) { 103 | case 'array': 104 | case 'object': 105 | return(json2html.transform(obj,transforms.object)); 106 | break; 107 | 108 | default: 109 | //This must be a litteral 110 | break; 111 | } 112 | } 113 | 114 | function convert(name,obj,show) { 115 | 116 | var type = $.type(obj); 117 | 118 | if(show === undefined) show = 'closed'; 119 | 120 | var children = []; 121 | 122 | //Determine the type of this object 123 | switch(type) { 124 | case 'array': 125 | //Transform array 126 | //Itterrate through the array and add it to the elements array 127 | var len=obj.length; 128 | for(var j=0;j