Parsing a Javascript object from online resource - javascript

I'm attempting to parse a Javscript object online using nodejs.
This file for example: http://www.google.com/recaptcha/api/challenge?k=6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU
This is not JSON, and is regular JavaScript. I have managed to parse out the JavaScript object using:
/* Data is the JS file above */
var j = data.substring(data.indexOf('{'), data.indexOf('}') + 1);
But, how do I parse that so I can read it as an object? JSON.parse doesn't work because its not JSON formatted.
Edit
As the challenge key is what I require, I ended up solving it with substring and indexOf:
var start = data.indexOf('\'');
var end = data.substring(start + 1).indexOf('\'');
var challenge = data.substring(start, (start + end) + 1);
But I'd still like to know a solution to the origional problem. And yes, I could use "'" but in this project we stuck to using single quotes and I'm a stickler for making sure everything is in line with the style guide. Silly I know, just a habbit.

well the simplest way is the following for this particular issue.
var x = JSON.stringify({
challenge : '03AHJ_VuuiaIB_izO6VJ6PifXI8A8i1yBeG6biCjadtaZHk5pbxfbW5JPpEXBEay-LPdCzSOI1bQgdnjq1tQVSqzQ63hMQB1Sjlho4LdzfZKLXuK3TKZD1YPr5bIjM-dYqHIkcYpaanchXOXLkHNoj0B6_ZrUk4rZg-o790H1LMNzoPGy3qkk6suYWs1CERFjkTO_mw9puMnYQNITPzBnRS-QMilbch2d_PeM2aDGToLSQiLn8mgHwP7fUHvCcE9VGzNZNXkDC8wF-YvUCxU354VqeSa8U7KKycg',
timeout : 1800,
lang : 'en',
server : 'http://www.google.com/recaptcha/api/',
site : '6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU',
error_message : '',
programming_error : '',
is_incorrect : false,
rtl : false,
t1 : 'Ly93d3cuZ29vZ2xlLmNvbS9qcy90aC9PejNvSUJCSlYxanlWSi13QTFqRndDd3dhbk5QVTh2TGd6SWVaNGc2TkxnLmpz',
t2 : '',
t3 : 'V3h0N3Vzd1cvWFR1d08yYmtyZG5HdDFoS1oyenNXMzBpS0dkRXVHUXc4anVBemtvemM2R1VhVDlPSmk0M0lRSWtMVVFUZ1JIWHlmUjE0VlBKQldOUVJuWG4ydXVzdjhJY2JZbHFCNGgxUGwvUzlzbE1reEpMcVcrbFRiS2JQWE9ZUXo5M3EwVDVPTFB4WVdHcTkzK0RuTXpjUTRtV0VhTUxOcDhqa2M2MitTT2w4dHVudHJ6NnlYdWdOVzFLMmlZOG8zOG5uUGNGZnp5ODcyZXZwTlIzRytJdkQyVFdsZFNzOXJ1amtDSkpRamtvQUdIYVpnRDBrODJxREdMSjhqRElQY1BqbTNUcno3TFQ4bG5jZ1pjbUM3NFpXdHlmVWhmYnNXRDNkMlBuaFdvM1lyUUp4Y1R5Z2F3elR2K3hpLzFyeisydU9SaTVJVk9MZFdpekQ3Y0NUQ0NDRlhVdDg1MElZalp4MkNYbkVWNkFmUDZ1UDNTOXhvaWxtaGdzWkg0OTZyQVFTai81RWdGelpLcFNVQnVtbGJGaFVLTWRDbHlGZ1orbGdRSVVubWk0WURTc2JMd1FaZkRhZlBZcjhJY0pyOWZSaU1leGpuMU9TNWk5UkZ2M0hLTG5jQzh3Y3plVzVKZjluYlZOWWdVY1l5U3FadmxOamF0Q3ozeXphNDhtazZwNHlIYUtWN1RvSGNvKzArWGpncm01YVd5cXpoYnRWb3Z5R2loUDNZeWswQmwwbXo0eEJUVm9HUjMzcGdtRHNYaFZRZ3lxRGJ3Wjl4YWxoN3NDQ21MVUVVOHZWWUtucGltNXpjSkU5RUlTaTk3NDBpcENxVGMrdytvRXJWTzU2VTczckZmM0FDbjlaeDFYbklueTF5SnU1TXBMaXAwSk5LSHB2R0lLb0poVjFnZ2M4bnRmNW1xQXJpWHByc1hJTk9pT20rdWIxZjFiWVBnRFJ1T3U2bjhwQm4wd2pqSStXck1ZU0xCMzZabW1taEZreWhEWTRBa0RzTWVWTG9ydzZSanJ2WURsc3NxY2wxZTAzT1k1aXl5T0o5dVVsR09DcDhaNHFoeFdYY0JiWk5ONndXTndXTnJGOGxkQkI3cHBhUVUySTFBZTk1ZXVRWHdRQjB4SWhqd3ZZQ2ZQU21DRFByTzhPYm9rK1BkeU5rTXhXODZxSnNWVUliU3U2ekZIYWdaV2xoaEx0Y1B6UFYrNXNvZVZXeVVpUXZKL2orVHNiYXJ3OFN4cDRMYTJvYWhFSUdybTlvaklTZHUxODhCS1ByakE5YWU5c2hITTRGczBreFU3a0tVbDI5d3JnT2NpcW1vVlptOTdsZnU1cWxGSXRTajdoVGlUZlV2V2s4NGEyOVpDcG9Xek91ZTZ1eFdFalJuMTVBb0FaTlFRWnhhQ3RkRlJJWTZ4U2p6TWRMNG9qZDFXbXhZNkFrK1I0Z3FkclhWQ090SEc0cnZITVN5ZWJCZ0pqcWIwWDJ4aTZNOVJTRlAwMUc1OTRvQ0hLb1h2TWcvTUxneEZtaUdGRkhPNnpNN2F1djl2bm1nb1IzbXF0Y1J3U2ZBaDNoQmxlWjV6dVg4ejdUQldhaUNDWHNuTEpnY1lxendaYTFZQWNFbjB1aWhtb0lwYzJmYXBHa0xPbWV2MlgyejJWeWJzdThpM3A2MlgyOXFxZklPLy9GdGdDZURsN0VXOTM4YzhRbEgwa1hqeUNhRStmU2dNVkl3MUZyMU9XVFNReVJXSVA4UXFyOTJVM1pHYm83cmtGeFU3dXBpWWU4eG1qSkt4R0FRMEdhY2J3aXdnL3RCQ2NsZHdZQ3lGNTdkRzY3T0p0SzdSNkdoZm1VQWlvOEF0UGI5WU1UYllJOWlhTytRK3FCS1NrakxWQlVWY1R3d2gxRlAvUkZWbm5XRmNrazdLUjVreTh0bjFYUVB4bWM0ZytSZUtXTnBYWlVrYnllSGF6M0w0dkNjYkRBT1B0aDFrNW41WEphNmwzcFlJM29NTXU4L0p2WW1TKzlaWUtsRExncXZZOEVDUEFFd05VS3ZEV2d1SlpobzZURVFkOGF0ekFHNHFidXpudXRLYmk3SXlVUDF5cHVqMVNFSTEvOFB6NHRTZ1kwRUZwOGFhbmVtNDRJaUlSeXUxYk5hZ2JPWlZVZTJUM0V4WUZncldjNk9VcEhscGE2UWY5d2FVNDJROWovTmJHMkJ5VndUcFNNZTZPMHUxeFhXTEFWRlpuMnk2SmtHN2xSZXFCTDFnaTZoMEpncmxzeWg4U3NibGRZWU1UMlNZWndYR3dNZUhpc1IyNHlFY3BZK1l6YlZ4aTRLOWRYSFhNRDJsUGlleEJsaUVEUTZtZ2dlSUJiZThpY2FITlY4Vy82MW10dmRVaGVCZnhuSk5FVTFQcm5aQm0ram9UZ3o2T1NVanYzaXA1S3E5dkZFcllDd091WFIwaC8zSFg2bENXc1grN2hBYXdFMU5WVW9icFBnWEUwTWlmVkV3eFhnR1p4TlQ1bkt5Y1o0ZzMxSm1lSkEzZ0o1RU5Zb1ZrZHViN21wSkJDeHo2T3R5cWhSR0tIcGpURElVSFlhMGNQeUtkM0poRjdxakF3eEFwSVJBNXoyRXhnZVN4RXFZVWNzaGVzNHZvSXA2bXo3U1JTb20wZkpJeXdVSFQ3THBTY0d5L1o3ZkRtVHBLemF0cCtrRmJZYzIvS1VGQ045RWFVdHZvN0I1aWxkVlRoeHpBdWVPbHZ5djBBVkNvZndGR1dVQlBmTmZVNVdwWkMvZkN4VWNXeG92Z1F0V21yTzI1Q1pzdWN6bnBobnhSMWYrLzRzZUJyckdZdWo3Q1YxaXJRcDhDZlJ6RTJudUpkWGlscWE1YXRyWmhRM2g3d1BEVXpFcDFqK2JSUjZyZmRQZ0t4K01teEVGUjJPNlNZTGlZamIrTDRhTVRrSEMrMzBycmFyMkVGMEhKd3MxOFlKWisyVXRnMXJsL3kyWC83akhieVBvbmNQdDNobUpKbW52OEVYTWdsdmtSNDE5VW5yNGkwY0d0amhpek1zZlh4TGtXai9tNlR4S3ZLQ2Q0SnhVa21DUllZVG12ZWw2RG1ubWtBVFdkTjFEZW9VOVAvMjVWak83Y3FIY3VQNTMrRjgzTk1VYmxiVzZ4VFRUMDY3SDJOemQ5S0VvSFpMcUgveVFmMDlwOVRUakRrcXZlQkk2aUx0WEZFdmQvdW9HTm4vSmNocEFQQ1hsbkhQbTlPbGI1YjVVejZhbVVPQ0U5OWhQTGlBcS9nVUFFSk9qdkZuYjFua3pxemxaWFVRSFpLRGxPUDhLNzlPMUNHSVNNUDZWRzNOVk4xRUJnSkx5dDN3NWMwemI3TDVGZ2oyZ1J4V2ZSUHpCRkFpb2hNR0RWS0QwN0JxN1Zib3lLeWxnWFpodjdqeXRLMmVSUVI0S1pUcXZ4cXpRWE1oMm9wVWk0V1Jhdis3amdsMlpPRlhSS2g0OGp2WGZKZW04NlIyRHJHcjVvNkMyaWFsWHBRWnAwWFE0UHNucEw4cDBGMVFFWCtHK1hhMFJrWERmTkNBV0FLQkoxTm5nNW9CdVFYR0JXWFVnL0Qxd0VHdk1Ub0M5ZGJ3YkE0enBISUtBRjQvWTRzSk5xTGY5L3RVUGhXSkRBa2NyWDNuNTR0ZWo5bGpqcGlpQmVxMlBGa0lBRG1nRzlzQ2hSdHAvKzBlZjhCTkNnTGQxVk1iNVRqaXdJS0dNdXkyb0VCa2FablNVbmZpWWVrMy8zTHRsSVVrZGdkZ3NYdWFNd2piSGhJcEhOQlF4Q25acWxYcDBMM2RWdUIwMkdTS2NXcEZrV01ZVy9lTlRnNkVwYWdYN1NhVjY3amUwQm4rTUdnMjdJdXlhZ2xQVlJ0NFZObk9EblBmQmpOZjNHdWZpS3ZkNHcvdlJ4NXFxYk9tNGtLTjFKQ3VDcVAzaFBhcWZveWVpamhWS0RuVW83MEpka3gzSjk2bFpBT2N2Z1NJaVNlM2h3MmlNM1V2WlpaVnpnOVJna3FXTUIxdVVlRXZTVkdxR2hKY0VaVllNMVdxOUVxMy9sZzZmSktzMitCanUzbXdsSGV0RUgzdUF1OHlQU2g0REhYYnU2VjkrYkpJOFZXK213b0YzT2xaNzYvMUZ0Q20xZ2QxdkJBOWM3RFdaU3VuVlByTnBldXFSa3VoODBBZVFQQTQ2SjAzOEQvMFNxZ2Z3cjRUWndDT1dPWEFkanFlUWdOWEdSc05iWjVSRFRxVlJSeWZCdTl1ZUVyRlF5bkthSEJFRTNxLzhtOWZSVXJkTE5jVW83VmhQYlQzWXVCNThGMjZxQ2o4L0U4WkZNVDlxbUtMb3BxT3lPUGJhMEhwSlkvSGxoZHZib3FMYkVkaFNjYXp4OEJDWXMvOVVEZ2JCemhXVnVJbTBsRzh5bEhuVTIyM1lRa2oweDhYeUpqZ0hlalJJL3hVUlJ2OGF0MGZINi9FbXM1ZlA3VE1zb3Y0MjVZUmFjeVpZajd1OGhGLzRSVFU0SXJKVGZrRm4xMkI2Q3FxOWF5dURpcjZkOHdnVy9BbExmT2g4OGxjQVh0WlJLaStzalIxYmhPY2crTFlGZXUwS2lKbnEzM1ZXL2VCSVNXSkpFdVpmaW1DWUlFQnc4T0huN3ZiT3BxZG9Cb0JrdmZjK3hsUDdwR25rM0NDaHNHNGliWjVSS0FxZ1dleTZZb0I3V1dhNWNya3VrbWRoYTlOZVV3R29kNVRUOEp3T2Y0MUo1SE5JQStSb3ZHZy96ZkxoUVMxYm52VUNCYWZzOW1xMmVBd1k0b2R6TGNFY1lZbFo1dlJmYkVSeS9MbFpEYmR1a3ZMczVQbVhFVGkzL2lHZElkREg5Vy9iNmFVenNnUE1UZGxzNU5taVJ2blNnSGtmR2hmdUhsUGtyclZUaTVCWGgwaFVRMERxbnlLT1c5SksxNHptZFNEcVZEQ0U2cUhVak1iMDlvK1RhRjZJcjQrVERLQS9LNlplWDdWem5nc1ZrOHVzdFY0bWxXbVNlQ3IxREV5V295WUtvRitjbWxFRlJPeEgwSnRwYlU2VENwRE9GSVIyNHdOdWtxT3pGeVFxTTZsZlpMUVkyWWE4ZjBINVh4WHQzYUhTajI4RlVLcjBOZEYvOElsb3NIZnpRUzNmT2R3b3Q0K2ZRVk5ReXlYK2U0QUlVTllqaDFJSi9GTkdER3IzTWVDd2ZRbTVCVVN0QkhVc0VualJCUXFmS0hVaU9WS1FYSWpMbklQM2tRYXMwWWtFYnFWUi9zcFYwKzUveFpXbmtuTkduZTBhd25DeVhNeW1qMU05cWlackp1UlJjUTk3VVVMeU54QXorWlJwcEJ5ZjBER3ROOTNyS2RTeEJmQ3JGd1dXUHY4YXIweWxiRi9WOHdiUklSb0tET2dHZjl5MWVoaEFYSmxsSFJBaGdUSjBvOVlkUFBvT2l1bGlNVTFScnZIVk8xaVFmcW96UklaV3p4U2JSWkJYYXRhVkRVSVlKTTR6Wjdoak8rSnRNb0VDQlBUVncwYVlRZHVEUEJYcFFSM2RlbTY0eFZXZHY1Tkk2MUxwazUvdVdqN29KckRZYXh1ODR0bTU5dkIrYjB6dHpibmlyYUhMa3ZwNXFXSnFqN3p2NEVPNnhYTm5pcnVLa3AxME5GeWhLQ3ZIajB5WmhxYkF5SUlBV0YyWGxuSU1mcVZsZ1czT3A1MFhHeGxOMnI2QjJhRXBvL0ttRktKN2wvRldsakwveDlBemExMzQzUHJ2WElncm01dGt2clh3QXU1M1Y0YXp0MXdaT1pNZGNPdEZWRlRLczZwMjZhcHBHb1gzcGxzUVQ1NFdwWTVSdVdVQ2tqeHM1dVJXdjVnaG1JTGZ2WlE5MmxoVStTWko0RUQxRk54UjhRRi9hRzZzdmRNZ21icXk4Y21VOFFCaUJtbG03akNjQnIzaHE3bThIcWFoUnliYmdKbFZIWkN5bk92bTMxc1JWTXNsVkxmOXNNYnhWR0VZNHZaYm5pWGZRYlg2ejZubHRoYVgvaXNSZWdKbkxLZUFYdWdQTHdxd0RDRit0MHRSY2V2aVV1MEYzdDhtdDhIRFFGd2ZFbVk1REVYdjZRZ2doNlhTY1ZzVzRIbnVtWTg1UnVTaGxRNVNTcmg5bXVBVTdvNEdnenZRNlhMVi9zcFNSbnBxVkUzRmJQaGxKd004TVkxaFhURUpEZWFIb0hHNzNXbG4yQksrcmRQR0dNV3pUeEJjbHB1aEZPRVViSHF2Z2ZFSE1BNWc1MlVxZG5JaVNJOGtqQ240YUM3Uk51c1gzanluMnVDVmQ2dlI3TDJJMURtTU51dmtJckQwQnNGc2NhSWNTMm9sY0dBYzhXVHc1U29ZRXFnRkovOU8yU3M1dy9IY3E3bmQ5MkpKQzQwd2Z0RHRzTVJaODlLdm1HNlBCUnZJZ3lHM0k5N2tOWEh2YTdQK1Q0NjE1cTUrVzhQZXZVNEVRM0dXa0dYMUhuMTlpbmZCNUtkQkphTGJMeEl1WTYyaWNWbU0rUUlpMmNyVmZ2YXN6SnJPSDBaN0hRaHJqcTVWdWFiY2tnSUpqQjZLUXVPSGVDQk95aVZobjQrUGJxQWl4Sk5DMDZuUDVLRzRTSkc1V0dTMHpxUmYyV2VRc0I3OFJPT1hpVnpwUll0ZEZQNGVVazVQUGo2NXFmVVJVZCtzUVFUNzZlczBocllyVFI3cDZpbGpzalZ6SGI5Q0NUbVJoYW1OejhQL2xnNFAxSUVrYUhlMElBNklLZUZXeFRwbWlFMytmWHl3K1hqbzF5WFZXUGgzaHZUTUhUbG1iUTF1SHpyaTUrb1lSaGpPQ2FLQTBYUzJNYkN4dXBzRVFTdUJYZmFQUDZEVVFIdnpxUjBDVXNBU1pEbU43NjVTczJDZTlneG9kbXJac1lXMEFsK0tQZ1V5bmd0bjA2Q1hyQlorWTQ5WVR2NFpFdlJ1WDNrdTJTazBTYjNRMXBHZDNjR2gxeW5scHpvM2hwWnRUZytDdDdtcFVKQURNdHdZa05QTG56TE5PdmNzbGIzNE5TbWdMREJEeTV0NGhOVFJCYWdGL0ZhK3JjdkNGK0lYWkdOZXNNclpMVmR5b29LTGRwNHptYk8yaEo1OUVlTE9RYUtZbkhtUWNLRU9oNjBBdktvZFZuMGVBbWxYc1YzRkRyZkp2ZE9QOURlOHk4OUV3VXpzc3U2MnE1aUJ2REs1SG90WDMybW9Jam1ncnRRcWQxaHRUeVlVMEJoTGFuRE5sSEtTdUp0UVlqQVl4MzN1UnZsZE8yQTA1cEpHdUd0UDRNQkhjTmFEUlV0WTNyamhOUnBnNDB2RndVNHZWSFVRVWZCVGdJNXNJY2pCOUlVUytpVWQ3VFg5ZUxhSnpaV3hGR2pRWm9JRVN3b0NrWlAwNnVKTmV1VGpMa3htWXBQcCtyVXpqdG5IU0Y4Q3ZhdWhtSkxsTVZyeEQxb3RDSXAzWkUxd0ZXVG9WV000Qjh5NlA2ZzB2ajJqSWw1RitYeG5RZzZaNVdqS1A3UjhGaWJMOVpNNEZMR1VoTzdlTWRzU1YxK1VNQytzZFJrVnM1ZjYyVys0T2Jld3FacTI3Qy8wdDJ4NEYrUG16QU92alpqcG1KbnI5RU5WZGZMVk1VZGNJeUJiMVhuVHJrRWw3UnNRQkxsa1FPOHM0cEt4eDdYazNTeCt6NGcxTm8xY1pXaHFWdFZ5bklkOXYxdU9jVklBYUE9'
});
console.log(JSON.parse(x).challenge);
//03AHJ_VuuiaIB_izO6VJ6PifXI8A8i1yBeG6biCjadtaZHk5pbxfbW5JPpEXBEay-LPdCzSOI1bQgdnjq1tQVSqzQ63hMQB1Sjlho4LdzfZKLXuK3TKZD1YPr5bIjM-dYqHIkcYpaanchXOXLkHNoj0B6_ZrUk4rZg-o790H1LMNzoPGy3qkk6suYWs1CERFjkTO_mw9puMnYQNITPzBnRS-QMilbch2d_PeM2aDGToLSQiLn8mgHwP7fUHvCcE9VGzNZNXkDC8wF-YvUCxU354VqeSa8U7KKycg

In the browser
This should work on client-side JavaScript :
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "http://www.google.com/recaptcha/api/challenge?k=6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU";
document.body.appendChild(js);
It adds the external file to your HTML. The JavaScript inside is run once it's been loaded.
Node.js
In node, I'd take this road :
Do an HTTP request to get the code
Save that code as a text file
require the file you just saved
If you take that road, your code should look something like this :
require("request")("http://www.google.com/recaptcha/api/challenge?k=6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU", function(error, response, body) {
require('fs').writeFile('./stuff.js', body, function(err) {
if(err) {
return console.log(err);
}
var stuffIJustLoaded = require('./stuff.js');
});
});

Related

How to get raw output from SHA1 using JS as PHP does?

I'm trying to dynamically generate a security header at Postman pre-request script. To do so, I need to transform the following code snippet from PHP to JS.
$password = "SECRETPASSWORD";
$nonce = random_bytes(32);
date_default_timezone_set("UTC");
$created = date(DATE_ATOM);
$encodedNonce = base64_encode($nonce);
$passwordHash = base64_encode(sha1($nonce . $created . sha1($password, true), true));
(Note the true flag at php's sha1() function, forcing raw output).
I've coded this code snippet so far:
var uuid = require('uuid');
var CryptoJS = require('crypto-js');
var moment = require('moment');
// Generate messageId
var messageId = uuid.v4();
pm.environment.set('messageId', messageId);
// Generate nonce
var nonce = uuid.v4();
var encodedNonce = CryptoJS.enc.Base64.stringify(
CryptoJS.enc.Utf8.parse(nonce)
);
pm.environment.set('nonce', encodedNonce);
// Generate created
var created = moment().utc().format();
pm.environment.set('created', created);
// Generate password hash
var password = 'SECRETPASSWORD';
var rawSha1Password = Buffer.from(CryptoJS.SHA1(password).toString(CryptoJS.enc.Base64), "base64").toString("utf8");
var passwordHash = CryptoJS.SHA1(nonce + created + rawSha1Password).toString(CryptoJS.enc.Base64);
pm.environment.set('passwordHash', passwordHash);
My JS script is almost working, the only problem seems to be the sha1 generation. Taking the following example values:
password: SECRETPASSWORD
nonce: 55d61876-f882-42f0-b390-dc662a7e7279
created: 2021-01-21T18:19:32Z
The output from PHP is:
encodedNonce: NTVkNjE4NzYtZjg4Mi00MmYwLWIzOTAtZGM2NjJhN2U3Mjc5
passwordHash: olI18mUowhmeCwjb1FJNHtTHYDA=
But, the output from JS is:
encodedNonce: NTVkNjE4NzYtZjg4Mi00MmYwLWIzOTAtZGM2NjJhN2U3Mjc5
passwordHash: tk/uYkL/3Uq0oIkYO0nlBGnV/0E=
As you can see, the encodedNonce is built correctly; however the passwordHash value is different. As I'm using Postman, I have a limited JS libraries available.
Taking this into account, how can I get the same result as the PHP one?
In the line
var rawSha1Password = Buffer.from(CryptoJS.SHA1(password).toString(CryptoJS.enc.Base64), "base64").toString("utf8");
the password hash is read into a buffer and then UTF-8 decoded. The UTF-8 decoding generally corrupts the data, see here. A possible solution is to concatenate the WordArrays instead of the strings:
function getPasswordHash(test){
// Generate nonce
var nonceWA = !test ? CryptoJS.lib.WordArray.random(32) : CryptoJS.enc.Utf8.parse('55d61876-f882-42f0-b390-dc662a7e7279');
console.log('nonce (Base64): ' + nonceWA.toString(CryptoJS.enc.Base64));
// Generate created
var created = !test ? moment().utc().format('YYYY-MM-DDTHH:mm:ss[Z]') : '2021-01-21T18:19:32Z';
var createdWA = CryptoJS.enc.Utf8.parse(created);
console.log('created: ' + created);
// Hash password
var pwd = 'SECRETPASSWORD';
var pwdHashWA = CryptoJS.SHA1(pwd);
// Hash nonce + created + pwd
var passwordHash = CryptoJS.SHA1(nonceWA.concat(createdWA).concat(pwdHashWA)).toString(CryptoJS.enc.Base64);
console.log('passwordHash: ' + passwordHash);
}
getPasswordHash(true); // with testdata
getPasswordHash(false); // without testdata
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
When the code is executed, the first call of getPasswordHash() uses the test data for nonce and date (test=true), the second call applies a random nonce and the current date (test=false) . The call with the test data returns the same result as the PHP code:
nonce (Base64): NTVkNjE4NzYtZjg4Mi00MmYwLWIzOTAtZGM2NjJhN2U3Mjc5
created: 2021-01-21T18:19:32Z
passwordHash: olI18mUowhmeCwjb1FJNHtTHYDA=
CryptoJS implements CryptoJS.lib.WordArray.random() as CSPRNG, which is the counterpart of the PHP method random_bytes(). The use of the uuid library is therefore actually not necessary. I have chosen CryptoJS.lib.WordArray.random() in my example because it is closest to the PHP code.

in javascript how to call powershell script

I have a powershell script and I run on powershell like :
.\download-packages-license.ps1
But I want to call the javascript file before these lines.
var json =fs.readFileSync('../../dev/licenses/AllLicenses.json', 'utf8');
var options = {compact: true, ignoreComment: true, spaces: 4};
var result = convert.json2xml(json, options);
I could not anything in stackoverflow except : How to run a powershell script from javascript?
So pls help thanks
I think this will work for you -
var spawn = require("child_process").spawn;
spawn("powershell.exe",[".\download-packages-license.ps1"]);
You can work with : Node-Powershell
Code Snippet :
const Shell = require('node-powershell');
const ps = new Shell({
executionPolicy: 'Bypass',
noProfile: true
});
ps.addCommand('echo node-powershell');
ps.invoke()
.then(output => {
console.log(output);
})
.catch(err => {
console.log(err);
});
JScript
Simple way.
Works great. Suitable for simple operations, but loses some data when receiving line feeds as a single \n instead of the expected \r\n. Split by \r\n misinterprets the array which leads to the need to reformat the array of strings. Basically, I just wrote this, so there may be other problems.
var codepage='windows-1251';/*US-Europe-1252 and Js file in that codepage*/
var toPStext='Hello.\nПроверка русских буковок.';
var shell=new ActiveXObject('WScript.Shell');
var std=shell.Exec("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -ExecutionPolicy Bypass -command \
$OutputEncoding = [Console]::outputEncoding = [System.Text.Encoding]::GetEncoding('"+codepage+"'); \
Write-Output '"+toPStext+"'");
var output = std.StdOut.ReadAll().split('\r\n');// split('\n') - leads to the loss of some data
if (output.length>0){WScript.echo(output)}
//var x=WScript.StdIn.ReadLine();
Line by line.
Unfortunately, powershell does not accept external data as sequences of lines, unlike cmd.exe with /q /k options, which simplifies this code, but will turn around problems with multiline output code. Of course, if necessary, you can transfer the code as a base64 string to powershell
var codepage='windows-1251';/*US-Europe-1252 and Js file in that codepage*/
var toPStext='Hello.\nПроверка русских буковок.';
var shell=new ActiveXObject('WScript.Shell');
var output=[],errors=[],WshRunning=0,WshFinished=1,WshFailed=2,i=0,tryCount=0;
var std=shell.Exec("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -ExecutionPolicy Bypass -command \
$OutputEncoding = [Console]::outputEncoding = [System.Text.Encoding]::GetEncoding('"+codepage+"'); \
Write-Output '"+toPStext+"'");
do{
if (std.Status==WshFailed){
errors.push('String '+i+' data read error: \n '+std.StdErr.ReadLine());
tryCount++
}
else if(std.Status==WshRunning){
output.push(std.StdOut.ReadLine());
tryCount=0;
WScript.Echo('Running ...')
}
else if(std.Status==WshFinished){
var last=std.StdOut.ReadLine();
if(last.length>0){output.push(last)};last=undefined;
tryCount=21;
WScript.Echo('Finished ...')
}i++;
}while(tryCount<21);
if (output.length>0){WScript.echo(output)}
if (errors.length>0){WScript.echo(errors)}
var x=WScript.StdIn.ReadLine();

MWS Post Request with Google Scripts

I am trying to make a post request through google scripts to amazon to collect information.
We are trying to get our orders to MWS and transfer them to sheets automatically.
I got to the last step which is signing the request.
A few things I wasnt sure about:
They say we use the secret key for hashing,I only see a client secret
and an access key id, which do I use?
Do I add the URL as part of whats getting signed? On the MWS Scratch pad they add this as shown:
POST
mws.amazonservices.com
/Orders/2013-09-01
Does it have to be on separate lines does it need post and the rest of the stuff. Its a little unclear.?
I read online that the sha256 byte code gets base64 encoded, not the string literal, is that true?
I tried to hash the string that amazon gave to me with an online tool and compare it to the hash they provided and the base64 encode, thing matched. I tried decoding as well, nothing matched
Can someone please send me an example that works, so I can understand what happens and how it works?
Thank you!
Below is what I have so far:
function POSTRequest() {
var url = 'https:mws.amazonservices.com/Orders/2013-09-01?';
var today = new Date();
var todayTime = ISODateString(today);
var yesterday = new Date();
yesterday.setDate(today.getDate() - 1);
yesterday.setHours(0,0,0,0);
var yesterdayTime = ISODateString(yesterday);
var dayBeforeYesterday = new Date();
dayBeforeYesterday.setDate(today.getDate() - 2);
dayBeforeYesterday.setHours(0,0,0,0);
var dayBeforeYesterdayTime = ISODateString(dayBeforeYesterday);
var unsignedURL =
'POST\r\nhttps:mws.amazonservices.com\r\n/Orders/2013-09-01\r\n'+
'AWSAccessKeyId=xxxxxxxxxxx' +
'&Action=ListOrders'+
'&CreatedAfter=' + dayBeforeYesterdayTime +
'&CreatedBefore' + yesterdayTime +
'&FulfillmentChannel.Channel.1=AFN' +
'&MWSAuthToken=xxxxxxxxxxxx'+
'&MarketplaceId.Id.1=ATVPDKIKX0DER' +
'&SellerId=xxxxxxxxxxx'+
'&SignatureMethod=HmacSHA256'+
'&SignatureVersion=2'+
'&Timestamp='+ ISODateString(new Date) +
'&Version=2013-09-0';
var formData = {
'AWSAccessKeyId' : 'xxxxxxxxx',
'Action' : "ListOrders",
'CreatedAfter' : dayBeforeYesterdayTime,
'CreatedBefore' : yesterdayTime,
'FulfillmentChannel.Channel.1' : 'AFN',
'MWSAuthToken' : 'xxxxxxxxxxxx',
'MarketplaceId.Id.1' : 'ATVPDKIKX0DER',
'SellerId' : 'xxxxxxxxxx',
'SignatureMethod' : 'HmacSHA256',
'SignatureVersion' : '2',
'Timestamp' : ISODateString(new Date),
'Version' : '2013-09-01',
'Signature' : calculatedSignature(unsignedURL)
};
var options = {
"method" : "post",
"muteHttpExceptions" : true,
"payload" : formData
};
var result = UrlFetchApp.fetch(url, options);
writeDataToXML(result);
Logger.log(result);
if (result.getResponseCode() == 200) {
writeDataToXML(result);
}
}
function calculatedSignature(url) {
var urlToSign = url;
var secret = "xxxxxxxxxxxxxxxxxxx";
var accesskeyid = 'xxxxxxxxxxxxxxx';
var byteSignature = Utilities.computeHmacSha256Signature(urlToSign, secret);
// convert byte array to hex string
var signature = byteSignature.reduce(function(str,chr){
chr = (chr < 0 ? chr + 256 : chr).toString(16);
return str + (chr.length==1?'0':'') + chr;
},'');
Logger.log("URL to sign: " + urlToSign);
Logger.log("");
Logger.log("byte " + byteSignature);
Logger.log("");
Logger.log("reg " + signature);
var byte64 = Utilities.base64Encode(byteSignature)
Logger.log("base64 byte " + Utilities.base64Encode(byteSignature));
Logger.log("");
Logger.log("base64 reg " + Utilities.base64Encode(signature));
return byte64;
}
Step 1, creating the string to be signed
The string_to_sign is the combination of the following:
The string POST followed by a NEWLINE character
The name of the host, mws.amazonservices.com, followed by a NEWLINE
The API URL, often just /, or somthing like /Orders/2013-09-01, followed by a NEWLINE
An alphabetical list of all parameters except Signature in URL encoding, like a=1&b=2, not followed by anything
The minimum parameters seem to be the following:
AWSAccessKeyId is a 20-character code provided by Amazon
Action is the name of your API call, like GetReport
SellerId is your 14-character seller ID
SignatureMethod is HmacSHA256
SignatureVersion is 2
Timestamp is a date like 20181231T23:59:59Z for one second before new year UTC
Version is the API version like 2013-09-01
additional parameters may be needed for your call, depending on the value of Action
Please note:
The NEWLINE character is just "\n", not "\r\n"
The name of the host should not include "https://" or "http://"
The Signature parameter is necessary for the actual call later (see step 3), but is not part of the string_to_sign.
Your string_to_sign should now look somewhat like this:
POST
mws.amazonservices.com
/Orders/2013-09-01
AWSAccessKeyId=12345678901234567890&Action=ListOrders&CreatedAfter .... &Version=2013-09-01
Step 2, signing that string
Calculate a SHA256 hash of above string using the 40-character Secret Key
Encode this hash using Base64
In Pseudocode: signature = Base64encode( SHA256( string_to_sign, secret_key ))
Step 3, send the call
Send a HTTPS POST request, using the full alphabetical list of parameters, now including above signature as Signature somewhere in the middle, because you need to keep ascending alphabetical order.
https://mws.amazonservices.com/Orders/2013-09-01?AWSAccessKeyId....Version=2013-09-01
Step 4, processing the result
You should be getting two things back: a response header and a XML document. Be sure to evaluate the HTTP status in the header as well as all contents of the XML document. Some error messages are hidden deeply in XML while HTTP returns "200 OK".
Step 5, Advanced Stuff
If you use calls that require you to send a document, like SendFeed, you need to do the following additional steps:
Calculate the MD5 hash of your document
Encode this hash using Base64
In Pseudocode: contentmd5= Base64encode( MD5( document ))
Add Content-Type: text/xml (or whatever fits your document) as HTTP header
Add Content-MD5: plus the base64 encoded hash as HTTP header
This code was a great help for building a similar application. I corrected some small issues to bring it up to work:
before signing the ISODate need to be worked out to replace the ":" chars
var todayTime = ISODateString(today);
var todayISO = todayTime;
var todayTime_ = todayTime.replace(":", "%3A");
todayTime = todayTime_.replace(":","%3A");
The same for the calculated signature (quick & dirty solution, replace only 3 appearences and need to updated for more chars)
Logger.log(unsignedURL);
var tmpsignature = calculatedSignature(unsignedURL);
var orsignature = tmpsignature;
// encode special chars
tmpsignature = encodeURIComponent(orsignature);
}
I added a header and dropped the form, put all parameters in the url
var header = {
"x-amazon-user-agent": "GoogleSheets/1.0 (Language=Javascript)",
"Content-Type": "application/x-www-form-urlencoded"
// "Content-Type": "text/xml"
};
var options = {
"method" : "post",
"muteHttpExceptions" : true,
// "payload" : formData,
"header":header
};
And changed the call to url encoded (Form was not working, do not know why)
var url = 'https:mws-eu.amazonservices.com/Orders/2013-09-01?'+
'AWSAccessKeyId=<your stuff>'+
'&Action=GetOrder'+
'&SellerId=<your stuff>+
'&MWSAuthToken=<your token>'+
'&SignatureVersion=2'+
'&Timestamp='+todayTime'+ // remember to replace the ":" thru hex
'&Version=2013-09-01'+
'&Signature='+ tmpsignature+
'&SignatureMethod=HmacSHA256'+
'&AmazonOrderId.Id.1='+<your order;
parsed the response:
var result = UrlFetchApp.fetch(url, options);
//writeDataToXML(result);
Logger.log(result);
var xml = result.getContentText();
var document = XmlService.parse(xml);
This worked! :-)
I checked the signature also with
https://mws-eu.amazonservices.com/scratchpad/index.html

Display thumbnailPhoto from Active Directory using Javascript only - Base64 encoding issue

Here's what I'm trying to do:
From an html page using only Javascript I'm trying to query the Active Directory and retrieve some user's attributes.
Which I succeded to do (thanks to some helpful code found around that I just cleaned up a bit).
I can for example display on my html page the "displayName" of the user I provided the "samAccountName" in my code, which is great.
But I also wanted to display the "thumbnailPhoto" and here I'm getting some issues...
I know that the AD provide the "thumbnailPhoto" as a byte array and that I should be able to display it in a tag as follow:
<img src="data:image/jpeg;base64," />
including base64 encoded byte array at the end of the src attribute.
But I cannot manage to encode it at all.
I tried to use the following library for base64 encoding:
https://github.com/beatgammit/base64-js
But was unsuccesful, it's acting like nothing is returned for that AD attribute, but the photo is really there I can see it over Outlook or Lync.
Also when I directly put that returned value in the console I can see some weird charaters so I guess there's something but not sure how it should be handled.
Tried a typeof to find out what the variable type is but it's returning "undefined".
I'm adding here the code I use:
var ADConnection = new ActiveXObject( "ADODB.connection" );
var ADCommand = new ActiveXObject( "ADODB.Command" );
ADConnection.Open( "Data Source=Active Directory Provider;Provider=ADsDSOObject" );
ADCommand.ActiveConnection = ADConnection;
var ou = "DC=XX,DC=XXXX,DC=XXX";
var where = "objectCategory = 'user' AND objectClass='user' AND samaccountname='XXXXXXXX'";
var orderby = "samaccountname ASC";
var fields = "displayName,thumbnailPhoto";
var queryType = fields.match( /,(memberof|member),/ig ) ? "LDAP" : "GC";
var path = queryType + "://" + ou;
ADCommand.CommandText = "select '" + fields + "' from '" + path + "' WHERE " + where + " ORDER BY " + orderby;
var recordSet = ADCommand.Execute;
fields = fields.split( "," );
var data = [];
while(!recordSet.EOF)
{
var rowResult = { "length" : fields.length };
var i = fields.length;
while(i--)
{
var fieldName = fields[i];
if(fieldName == "directReports" && recordSet.Fields(fieldName).value != null)
{
rowResult[fieldName] = true;
}
else
{
rowResult[fieldName] = recordSet.Fields(fieldName).value;
}
}
data.push(rowResult);
recordSet.MoveNext;
}
recordSet.Close();
console.log(rowResult["displayName"]);
console.log(rowResult["thumbnailPhoto"]);
(I replaced db information by Xs)
(There's only one entry returned that's why I'm using the rowResult in the console instead of data)
And here's what the console returns:
LOG: Lastname, Firstname
LOG: 񏳿က䙊䙉Āā怀怀
(same here Lastname & Firstname returned are the correct value expected)
This is all running on IE9 and unfortunetly have to make this compatible with IE9 :/
Summary:
I need to find a solution in Javascript only
I know it should be returning a byte array and I need to base64 encode it, but all my attempts failed and I'm a bit clueless on the reason why
I'm not sure if the picture is getting returned at all here, the thing in the console seems pretty small... or if I'm nothing doing the encoding correctly
If someone could help me out with this it would be awesome, I'm struggling with this for so long now :/
Thanks!

Localize Strings in Javascript

I'm currently using .resx files to manage my server side resources for .NET.
the application that I am dealing with also allows developers to plugin JavaScript into various event handlers for client side validation, etc.. What is the best way for me to localize my JavaScript messages and strings?
Ideally, I would like to store the strings in the .resx files to keep them with the rest of the localized resources.
I'm open to suggestions.
A basic JavaScript object is an associative array, so it can easily be used to store key/value pairs. So using JSON, you could create an object for each string to be localized like this:
var localizedStrings={
confirmMessage:{
'en/US':'Are you sure?',
'fr/FR':'Est-ce que vous êtes certain?',
...
},
...
}
Then you could get the locale version of each string like this:
var locale='en/US';
var confirm=localizedStrings['confirmMessage'][locale];
Inspired by SproutCore You can set properties of
strings:
'Hello'.fr = 'Bonjour';
'Hello'.es = 'Hola';
and then simply spit out the proper localization based on your locale:
var locale = 'en';
alert( message[locale] );
After Googling a lot and not satisfied with the majority of solutions presented, I have just found an amazing/generic solution that uses T4 templates. The complete post by Jochen van Wylick you can read here:
Using T4 for localizing JavaScript resources based on .resx files
Main advantages are:
Having only 1 place where resources are managed ( namely the .resx
files )
Support for multiple cultures
Leverage IntelliSense - allow for code completion
Disadvantages:
The shortcomings of this solution are of course that the size of the
.js file might become quite large. However, since it's cached by the
browser, we don't consider this a problem for our application. However
- this caching can also result in the browser not finding the resource called from code.
How this works?
Basically he defined a T4 template that points to your .resx files. With some C# code he traverses each and every resource string and add it to JavaScript pure key value properties that then are output in a single JavaScript file called Resources.js (you can tweak the names if you wish).
T4 template [ change accordingly to point to your .resx files location ]
<## template language="C#" debug="false" hostspecific="true"#>
<## assembly name="System.Windows.Forms" #>
<## import namespace="System.Resources" #>
<## import namespace="System.Collections" #>
<## import namespace="System.IO" #>
<## output extension=".js"#>
<#
var path = Path.GetDirectoryName(Host.TemplateFile) + "/../App_GlobalResources/";
var resourceNames = new string[1]
{
"Common"
};
#>
/**
* Resources
* ---------
* This file is auto-generated by a tool
* 2012 Jochen van Wylick
**/
var Resources = {
<# foreach (var name in resourceNames) { #>
<#=name #>: {},
<# } #>
};
<# foreach (var name in resourceNames) {
var nlFile = Host.ResolvePath(path + name + ".nl.resx" );
var enFile = Host.ResolvePath(path + name + ".resx" );
ResXResourceSet nlResxSet = new ResXResourceSet(nlFile);
ResXResourceSet enResxSet = new ResXResourceSet(enFile);
#>
<# foreach (DictionaryEntry item in nlResxSet) { #>
Resources.<#=name#>.<#=item.Key.ToString()#> = {
'nl-NL': '<#= ("" + item.Value).Replace("\r\n", string.Empty).Replace("'","\\'")#>',
'en-GB': '<#= ("" + enResxSet.GetString(item.Key.ToString())).Replace("\r\n", string.Empty).Replace("'","\\'")#>'
};
<# } #>
<# } #>
In the Form/View side
To have the correct translation picked up, add this in your master if you're using WebForms:
<script type="text/javascript">
var locale = '<%= System.Threading.Thread.CurrentThread.CurrentCulture.Name %>';
</script>
<script type="text/javascript" src="/Scripts/Resources.js"></script>
If you're using ASP.NET MVC (like me), you can do this:
<script type="text/javascript">
// Setting Locale that will be used by JavaScript translations
var locale = $("meta[name='accept-language']").attr("content");
</script>
<script type="text/javascript" src="/Scripts/Resources.js"></script>
The MetaAcceptLanguage helper I got from this awesome post by Scott Hanselman:
Globalization, Internationalization and Localization in ASP.NET MVC 3, JavaScript and jQuery - Part 1
public static IHtmlString MetaAcceptLanguage<T>(this HtmlHelper<T> html)
{
var acceptLanguage =
HttpUtility.HtmlAttributeEncode(
Thread.CurrentThread.CurrentUICulture.ToString());
return new HtmlString(
String.Format("<meta name=\"{0}\" content=\"{1}\">", "accept-language",
acceptLanguage));
}
Use it
var msg = Resources.Common.Greeting[locale];
alert(msg);
With a satellite assembly (instead of a resx file) you can enumerate all strings on the server, where you know the language, thus generating a Javascript object with only the strings for the correct language.
Something like this works for us (VB.NET code):
Dim rm As New ResourceManager([resource name], [your assembly])
Dim rs As ResourceSet =
rm.GetResourceSet(Thread.CurrentThread.CurrentCulture, True, True)
For Each kvp As DictionaryEntry In rs
[Write out kvp.Key and kvp.Value]
Next
However, we haven't found a way to do this for .resx files yet, sadly.
JSGettext does an excellent job -- dynamic loading of GNU Gettext .po files using pretty much any language on the backend. Google for "Dynamic Javascript localization with Gettext and PHP" to find a walkthrough for JSGettext with PHP (I'd post the link, but this silly site won't let me, sigh...)
Edit: this should be the link
I would use an object/array notation:
var phrases={};
phrases['fatalError'] ='On no!';
Then you can just swap the JS file, or use an Ajax call to redefine your phrase list.
There's a library for localizing JavaScript applications:
https://github.com/wikimedia/jquery.i18n
It can do parameter replacement, supports gender (clever he/she handling), number (clever plural handling, including languages that have more than one plural form), and custom grammar rules that some languages need.
The strings are stored in JSON files.
The only requirement is jQuery.
I did the following to localize JavaScript for a mobile app running HTML5:
1.Created a set of resource files for each language calling them like "en.js" for English. Each contained the different strings the app as follows:
var localString = {
appName: "your app name",
message1: "blah blah"
};
2.Used Lazyload to load the proper resource file based on the locale language of the app: https://github.com/rgrove/lazyload
3.Pass the language code via a Query String (As I am launching the html file from Android using PhoneGap)
4.Then I wrote the following code to load dynamically the proper resource file:
var lang = getQueryString("language");
localization(lang);
function localization(languageCode) {
try {
var defaultLang = "en";
var resourcesFolder = "values/";
if(!languageCode || languageCode.length == 0)
languageCode = defaultLang;
// var LOCALIZATION = null;
LazyLoad.js(resourcesFolder + languageCode + ".js", function() {
if( typeof LOCALIZATION == 'undefined') {
LazyLoad.js(resourcesFolder + defaultLang + ".js", function() {
for(var propertyName in LOCALIZATION) {
$("#" + propertyName).html(LOCALIZATION[propertyName]);
}
});
} else {
for(var propertyName in LOCALIZATION) {
$("#" + propertyName).html(LOCALIZATION[propertyName]);
}
}
});
} catch (e) {
errorEvent(e);
}
}
function getQueryString(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
5.From the html file I refer to the strings as follows:
span id="appName"
Well, I think that you can consider this. English-Spanish example:
Write 2 Js Scripts, like that:
en-GB.js
lang = {
date_message: 'The start date is incorrect',
...
};
es-ES.js
lang = {
date_message: 'Fecha de inicio incorrecta',
...
};
Server side - code behind:
Protected Overrides Sub InitializeCulture()
Dim sLang As String
sLang = "es-ES"
Me.Culture = sLang
Me.UICulture = sLang
Page.ClientScript.RegisterClientScriptInclude(sLang & ".js", "../Scripts/" & sLang & ".js")
MyBase.InitializeCulture()
End Sub
Where sLang could be "en-GB", you know, depending on current user's selection ...
Javascript calls:
alert (lang.date_message);
And it works, very easy, I think.
Expanding on diodeus.myopenid.com's answer: Have your code write out a file containing a JS array with all the required strings, then load the appropriate file/script before the other JS code.
The MSDN way of doing it, basically is:
You create a separate script file for each supported language and culture. In each script file, you include an object in JSON format that contains the localized resources values for that language and culture.
I can't tell you the best solution for your question, but IMHO this is the worst way of doing it. At least now you know how NOT to do it.
We use MVC and have simply created a controller action to return a localized string. We maintain the user's culture in session and set the thread culture before any call to retrieve a language string, AJAX or otherwise. This means we always return a localized string.
I'll admit, it isn't the most efficient method but getting a localised string in javascript is seldom required as most localization is done in our partial views.
Global.asax.cs
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
// Set the current thread's culture
var culture = (CultureInfo)Session["CultureInfo"];
if (culture != null)
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
}
Controller Action
public string GetString(string key)
{
return Language.ResourceManager.GetString(key);
}
Javascript
/*
Retrieve a localized language string given a lookup key.
Example use:
var str = language.getString('MyString');
*/
var language = new function () {
this.getString = function (key) {
var retVal = '';
$.ajax({
url: rootUrl + 'Language/GetString?key=' + key,
async: false,
success: function (results) {
retVal = results;
}
});
return retVal;
}
};

Categories

Resources