Modify specific text with value - javascript

I Read a text document with readFile method ,and I got the current string.
I need to modify some specific fields inside and save the file and keep the original format
in the read file I got the following "string"
\r\nAPP_HOST=mo-d6fa.corp\r\nAPP_PORT=5000\r\nINS_PORT=50100\r\nPORT=66000\r\n
and I need to change just the number for properties
PORT=4000
APP_PORT =4000
I use the fs.readFile(filePath, 'utf8') and the response is this file

You can modify it turning into an object, setting values and then get back to string using Array.prototype.reduce:
var rawValues = "\r\nAPP_HOST=mo-d6fa.corp\r\nAPP_PORT=5000\r\nINS_PORT=50100\r\nPORT=66000\r\n";
// #1 You need to turn raw string into an array using String.prototype.split
// #2 It's time to reduce the array into an object to be able to access
// config values as a key-value pair store
var values = rawValues.trim().split("\r\n").reduce(
function(result, next, index, sourceArray) {
var keyValuePair = sourceArray[index].split("=");
result[keyValuePair[0]] = keyValuePair[1];
return result;
}, {});
// Now you can alter config values like a dictionary:
values["PORT"] = "9995";
values["APP_PORT"] = "9999";
// or using dot syntax if possible settings have valid JavaScript
// variable names...
values.PORT = "9995";
values.APP_PORT = "9999";
// ...more settings...
// #3 Once you've edited your settings, it's time to reduce each property
// as part of a new raw string containing all configurations.
rawValues = Object.keys(values).reduce(function(previousValue, property, index) {
previousValue += property + "=" + values[property] + "\r\n";
return previousValue;
}, "");
// Now PORT and APP_PORT contain their new values...
document.getElementById("rawResult").textContent = JSON.stringify(rawValues);
<div id="rawResult"></div>
Suggestion
IMHO, if you can turn your configuration into a valid JSON life can be even easier.
For example, your raw config can be { "APP_HOST": "mo-d6fa.corp", "APP_PORT": 5000, "INS_PORT": 50100, "PORT": 66000 }. See how this simplifies your problem:
var rawConfig = '{ "APP_HOST": "mo-d6fa.corp", "APP_PORT": 5000, "INS_PORT": 50100, "PORT": 66000 }';
var config = JSON.parse(rawConfig);
config["APP_PORT"] = 6000;
config["PORT"] = 7000;
rawConfig = JSON.stringify(config);
document.getElementById("result").textContent = rawConfig;
<div id="result"></div>
Instead of rolling your own configuration parser, you can just use JSON which is a well-known pattern and it has a built-in, out-of-the-box parser as part of every Web browser in the earth, NodeJS and even non-JavaScript platforms like .NET, Java...

The regexes for both these will be pretty similar. Here's a stab:
var portRegex = /\nPORT=\d+/g;
var appPortRegex = /\nAPP_PORT=\d+/g;
var fileStr = fs.readFile(filePath, 'utf8');
fileStr = fileStr
.replace(portRegex, '\nPORT=' + 4000)
.replace(appPortRegex, '\nAPP_PORT=' + 4000);

The problem with finding the exact PORT entry can be resolved by matching it at the beginning of a line only with /m modifier (in a multiline mode) that forces ^ to match at the beginning of a line:
/^(PORT\s*=\s*)\d+/m
/^(APP_PORT\s*=\s*)\d+/m
var re = /^(APP_PORT\s*=\s*)\d+/m;
var re2 = /^(PORT\s*=\s*)\d+/m;
var str = 'APP_HOST=mo-d6fa.corp\nAPP_PORT=5000\nINS_PORT=50100\nPORT=66000';
var result = str.replace(re, '$1NEWVALUE').replace(re2, '$1ANOTHERVALUE');
document.write(result);

Related

How can I extract alternative names data from a CSR?

I have a CSR and I can parse all the data with pkijs.org lib, but I have no luck to parse alternative names data. How is it possible to do with a javascript? Some other libs can be in use, I guess, do you know one?
Following the docs of CertificationRequest class provided by pkijs here https://pkijs.org/docs/classes/CertificationRequest.html. We can see that the structure of a CSR. The subject alternative name will be stored in attributes propery of CertificationRequest object. But the structure inside of attributes is quite complex to make it as plain text. This is my code used to print out the subject alternative name
const pkijs = require('pkijs');
const utils = require("pvtsutils");
const asn1js = require("asn1js");
let base64 = "<your_csr_in_base64>"
let csrraw = utils.Convert.FromBase64(base64);
console.log(csrraw)
const pkcs10 = pkijs.CertificationRequest.fromBER(csrraw);
let seq = pkcs10.attributes[0].values[0];
let exts = pkijs.Extensions.fromBER(seq.toBER(false));
console.log(exts);
var san = getExtentionsForSANFromExtensions(exts);
console.log(san)
if (san != undefined) {
san.names.forEach(element => {
console.log(element.type + " = " + element.value)
});
}
function getExtentionsForSANFromExtensions(exts){
for (var i = 0 ; i< exts.extensions.length; i++) {
var ext = exts.extensions[i];
if(ext.extnID == '2.5.29.17') {
var octetString = asn1js.fromBER(ext.extnValue.toBER(false)).result;
return pkijs.GeneralNames.fromBER(octetString.getValue());
}
}
}
I've tested this code and it works properly with CSR generated by Keystore Explorer. Have not tested with another tool to generate CSR that supports subject alternative names.
Cheers!
If you have a CSR and need to extract the alternative names data from it, you can use the following command:
openssl req -in csr.pem -noout -text
This will print out the entire CSR, including the alternative names data.

is there a way to use newlines in xdmp.eval()

Hi I want to write clean code that I can read and have a good overview.
So I wrote this:
var id = '12345';
var coll = ['scc-roles','scc-proj-' + id];
var spm = 'some-role';
var data = {role : spm, roleNames : 'sccss-user', collection : coll}
var spmRoleId = xdmp.eval('declareUpdate();
var sec = require("/MarkLogic/security.xqy");
var roleId = sec.createRole(role, "Generated project member", roleNames, null, collection,null,null);
var uri = "http://marklogic.com/xdmp/roles/" + roleId;
xdmp.documentAddCollections(uri,collection)',data,{"database" : xdmp.securityDatabase()})
But apparently a newline is not allowed in xdmp.eval() ?
[javascript] JS-JAVASCRIPT: + 'var sec = require("/MarkLogic/security.xqy"); -- Error running JavaScript request: SyntaxError: Unexpected token ILLEGAL
I tried using a '+' sign to generate a strng over more then one line, swapping single and double quotes but no luck.
Being able to test this code (copy paste) to the security database makes a lot of sense to me...
If I wrap it all in one unreadable line , it works ok.
hugo
The way to effectively create a new line in a JavaScrit string is to escape the new line char like this
var str = "I'm displayed\
in two line";
In the final file, you will see effectively a new line.
If you want see in the dist output the new line but not in your src string you could just insert the \n equivalent of a return to line.
var str = "I'm displayed\n in two line";
In es6 you will be able to use ` char to achieve the same thing without \
var str = `I'm displayed
in two line`;
Maybe you would like the strange, yet useful array-notation way of doing this:
var multiline1 = [
'the lazy fox',
'jumped over',
'the dead chicken',
].join('\n');
and the result:
the lazy fox
jumped over
the dead chicken
In general, you should avoid string concatenation to build code for eval. Strings make it difficult to spot bugs and are a great vector for injection attacks. Instead, I'd advise you to write a proper function in XQuery or JavaScript and use xdmp.invokeFunction to evaluate it. invokeFunction takes all of the same options as xdmp.eval.
Here's an example that gets roles in the context of a security database. The applyAs function returns a function that wraps the function provided by the caller, evaluating it with the eval options provided.
function applyAs(fct, options) {
return function() {
var params = Array.prototype.slice.call(arguments);
// Curry the function to include the params by closure.
// xdmp.invokeFunction requires that invoked functions have
// an arity of zero.
var f = (function() {
return fct.apply(null, params);
}).bind(this);
// Allow passing in user name, rather than id
if(options.user) { options.userId = xdmp.user(options.user); delete options.user; }
// Allow the functions themselves to declare their transaction mode
if(fct.transactionMode && !(options.transactionMode)) { options.transactionMode = fct.transactionMode; }
return xdmp.invokeFunction(f, options); // xdmp.invokeFunction returns a ValueIterator
}
}
/**
* Gets an Array of id-name Objects. Requires privileged access to security.
*
* #param names An optional Array of role IDs as strings used to filter
* #return An Array of Objects with role ID keys and role name values
*/
function getRoles(names) {
var sec = require('/MarkLogic/security.xqy');
var db = {database: xdmp.securityDatabase()};
var roleIDs = applyAs(sec.getRoleIds, db);
var rolesItr;
if(Array.isArray(names)) {
rolesItr = roleIDs(xdmp.arrayValues(names));
} else {
rolesItr = roleIDs();
}
var roleNames = applyAs(sec.getRoleNames, db)(rolesItr).toArray().map(function(el) { return el.textContent; });
var roles = [];
var i = 0;
for(var role of rolesItr) {
var r = {}
r[role.textContent] = roleNames[i++];
roles.push(r);
}
return roles;
}
getRoles();
Originally from a gist.

Parsing a localstorage object gives uncaught syntax error?

I'm trying to save numbers given by Math.random. I save them in array which gets saved into localStorage. I then want to append each new array of numbers when Math.random is used. It's easier if you view the code I tried wrting.
var nums = [];
for (var i = 0; i < 5; i++) {
var num = Math.floor(Math.random() * 50);
nums.push(" " + num);
}
console.log(nums);
function appendToStorage(name, data) {
var old = localStorage.getItem(name);
if (old === null) old = "";
localStorage.setItem(name, old + JSON.stringify(data));
}
if (localStorage.num) {
appendToStorage('num', nums);
} else {
localStorage.setItem("num", JSON.stringify(nums));
}
var nums2 = localStorage.getItem("num");
console.log(nums2);
document.getElementById("test").innerHTML = JSON.parse(nums2);
This doesn't work, though. Console says Uncaught SyntaxError: Unexpected token [
This error will work if you remove the JSON.parse on getElementById. I want it to be parsed, though, so the numbers are more easily viewed. How can I do this?
If you simply append a valid JSON string to another valid JSON string you don't get a valid JSON string. For example:
var myJSON = '{"thing": "data"}'; // valid
myJSON = myJSON + myJSON; // myJSON is now '{"thing": "data"}{"thing": "data"}', not valid
To do this reliably you'll need to parse your retrieved JSON, update the result, then stringify it again before storing it in localStorage.
function appendToStorage(name, data) {
var old = localStorage.getItem(name);
if (old === null) old = "[]";
var newData = JSON.parse(old);
newData.push(data);
localStorage.setItem(name, JSON.stringify(newData));
}
Note that this will return an array when you parse it, and that will cause you a problem when you try to set innerHTML. You'll need to unpack the array to some sort of text format first (thanks to jibsales for that).
Element.innerHTML takes a string as valid input, not an Array. May I suggest using JSON.parse(nums).join("");
Using this method would also allow you to not add the leading white space in your for loop and instead add the white space as the first parameter to the Array.join method. If you want each number on a new line, pass "\n".

javascript regular expression match only returning last match

I have a small node application that takes some input, applies a regular expression to extract some info and should return an array of matches. All of it it pretty straight forward but the behavior I am seeing is not expected. My understanding was that if I have input with multiple lines that match this regex then each line would be an element in the array that the match returns. Unfortunately it looks like the array only contains the match groups for the last line. Is there a way to rewrite this, without iterating through the input twice, so that I can populate a nested array with the matched data per line? It would be great to return the match groups as elements, but I need to do this for each line. The end goal is to turn all this into formatted JSON for a downstream application.
Thanks for taking a look...
Now the CODE
Also available for experimentation here in a cloud 9 ide.
var util = require('util');
var re = /(processed)(.*?)\((.*?)\)(.*?)([0-9]\.[0-9]+[0-9])/g;
var data;
var returnData = [];
var Parser = function(input) {
util.log("Instantiating Parser");
this.data = input;
};
Parser.prototype.parse = function(callback) {
util.log("In the parser");
this.returnData = re.exec(this.data);
callback(this.returnData);
}
exports.Parser = Parser;
And a test file:
var Parser = require("./parser.js").Parser;
var util = require('util');
var fs = require('fs');
var data = "worker[0] processed packet (0x2000000, 1200358, t) in 0.000021 seconds\n" +
"worker[0] processed packet (0x2000000, 400115, b) in 0.000030 seconds\n"+
" (0) Registration Stats: (1387305947, 0x3d00000a, 17024, 2504, 0, 400109, 400116, b)\n"+
"worker[0] processed packet (0x1000000, 400116, b) in 0.000045 seconds\n"+
"worker[0] processed packet (0x1000000, 1200369, t) in 0.000024 seconds\n";
util.log("creating new parser");
var Parser = new Parser(data);
util.log("calling parse");
Parser.parse(function(data) {
for (var i=0; i < data.length; i++)
util.log(data[i]);
});
Here is the debuggex for the regular expression.
re.exec only returns one match each time it is executed. If you want an array of all the matches, you need to do something like this:
var matchedData = [];
var match;
while (match = re.exec(this.data)) {
matchedData.push(match);
}

Get Query String with Dojo

Users will be hitting up against a URL that contains a query string called inquirytype. For a number of reasons, I need to read in this query string with javascript (Dojo) and save its value to a variable. I've done a fair amount of research trying to find how to do this, and I've discovered a few possibilities, but none of them seem to actually read in a query string that isn't hard-coded somewhere in the script.
You can access parameters from the url using location.search without Dojo Can a javascript attribute value be determined by a manual url parameter?
function getUrlParams() {
var paramMap = {};
if (location.search.length == 0) {
return paramMap;
}
var parts = location.search.substring(1).split("&");
for (var i = 0; i < parts.length; i ++) {
var component = parts[i].split("=");
paramMap [decodeURIComponent(component[0])] = decodeURIComponent(component[1]);
}
return paramMap;
}
Then you could do the following to extract id from the url /hello.php?id=5&name=value
var params = getUrlParams();
var id = params['id']; // or params.id
Dojo provides http://dojotoolkit.org/reference-guide/dojo/queryToObject.html which is a bit smarter than my simple implementation and creates arrays out of duplicated keys.
var uri = "http://some.server.org/somecontext/?foo=bar&foo=bar2&bit=byte";
var query = uri.substring(uri.indexOf("?") + 1, uri.length);
var queryObject = dojo.queryToObject(query);
//The structure of queryObject will be:
// {
// foo: ["bar", "bar2],
// bit: "byte"
// }
In new dojo it's accessed with io-query:
require([
"dojo/io-query",
], function (ioQuery) {
GET = ioQuery.queryToObject(decodeURIComponent(dojo.doc.location.search.slice(1)));
console.log(GET.id);
});
Since dojo 0.9, there is a better option, queryToObject.
dojo.queryToObject(query)
See this similar question with what I think is a cleaner answer.

Categories