Set HTML in Outlook Cached Mode via Javascript and EWS - javascript

My work Outlook environment is changing from online (continuous connection) to cached mode and that breaks the desktop component of an Outlook add-in designed to save and then forward draft emails to an in-house security check.
My original code would save the draft async, then use the Id and change key to then forward it. In cached mode, there is no Id until the account synchs with the Exchange.
Now broken code (does not work in cached mode)
//Save current item as draft
mailForward.SaveDraftIfNecessary = function SaveDraftIfNecessary() {
if (_item_id == null || _item_id == undefined) {
Office.context.mailbox.item.saveAsync(function (asyncResult) {
if (asyncResult.error) {
app.showNotification(_appName, "Error: " + asyncResult.error.message);
}
else {
_item_id = asyncResult.value;
}
});
}
};
I've been able to write code that can replicate the mail and send it, but I need to be able to insert the draft body into the new email body, but it does not accept it. It does not work for text or HTML.
The code for getting the body type and text is as follows:
item.body.getTypeAsync(
function (asyncResultGet) {
if (asyncResultGet.status === Office.AsyncResultStatus.Failed) {
statusUpdate("icon16", asyncResultGet.error.message);
stopSpinner();
}
else {
bodyType = asyncResultGet.value;
item.body.getAsync(bodyType,
function (asyncResultGet) {
if (asyncResultGet.status === Office.AsyncResultStatus.Failed) {
statusUpdate("icon16", asyncResultGet.error.message);
stopSpinner();
}
else {
bodyText = asyncResultGet.value;
The SOAP that I am trying to use to insert the body text. I have also tried t:NewBodyContent instead of t:Body:
' <t:Message>' +
' <t:Subject>' + _subject + '</t:Subject>' +
' <t:Body BodyType="'+ _bodyType +'">' + _bodyText + '</t:Body>' +
' <t:ToRecipients>' + _adddressesSoap + '</t:ToRecipients>' +
' </t:Message>' +

My issue was encoding. I had an inkling that might be the problem, but didn't test it out until I found this link:
HTML-encoding lost when attribute read from input field
The code I used is this:
var htmlEncode = function htmlEncode(s) {
var ntable = {
"&": "amp",
"<": "lt",
">": "gt",
"\"": "quot"
};
s = s.replace(/[&<>"]/g, function (ch) {
return "&" + ntable[ch] + ";";
});
s = s.replace(/[^ -\x7e]/g, function (ch) {
return "&#" + ch.charCodeAt(0).toString() + ";";
});
return s;
};

Related

Javascript: create dynamic js based on attribute from JSON read from a DB table

I hope someone can help me with some JavaScript that I am stuck on. I guess I would call this dynamic JavaScript. Here is what I'm trying to accomplish.
Overview of the app:
This is an entitlements app, where the user selects an application from a drop down that they need to be entitled to. Once they select the app, the system reads a db record for this app. In that record, there is JSON that defines what other information needs to be prompted for and the app will dynamically build the prompts and append to the HTML.
Read some JSON from a DB table using ajax (this works fine)
Using the 'variable' attribute from the JSON, create the following code substituting varname with the name defined in the variable attribute.
Code:
$('select[name="varname"]').on('change', function() {
var varname = $('select[name="varname"]').val(); });
JSON
{
"prompts": [{
"id": "1",
"enabled": "1",
"required": "1",
"prompt": "AWS Account Number ",
"variable": "aws_account_number",
"type": "select",
"value_list_type": "table",
"table_name": "cld_accounts",
"filter": "filter=accounttype,eq,aws&filter=accountstatus,eq,open&filter=rootaccountowner,eq,sts",
"order": "order=accountnumber",
"value_column": "record.accountnumber",
"dropdown_definition": "'record.accountnumber + \" - \" + record.clientid + \" - \" + record.alias'"
},
{
"id": "2",
"enabled": "1",
"required": "1",
"prompt": "Requested Permission ",
"variable": "permission",
"type": "select",
"value_list_type": "table",
"table_name": "aws_sso_mapping_from_ad",
"filter": "filter=accountnumber,eq,aws_account_number",
"order": "order=rolename",
"value_column": "record.rolename",
"dropdown_definition": "'record.rolename'"
}
]}
so, everywhere that 'varname' appears in that select function, it needs to be 'aws_account_number' so that this is the code that is generated:
$('select[name="aws_account_number"]').on('change', function() {
var aws_account_number = $('select[name="aws_account_number"]').val(); });
Below is my function code. Right after eval(ssrc1) (I know I shouldn't be using eval) is what I can't get to work. I have tried eval, string replace, template literals, etc., nothing seems to work.
Maybe there is a better way if anyone has any other suggestions. Basically what I need after the user completes all the prompts is to be able to send that data to handler that will entitle the user for the app. The problem is app 1 may have two prompts, app 2 may have four prompts.
// Get additional data based on selected application
$('select[name="application"]').on('change', function() {
var appId = $('select[name="application"]').val();
getApplicationConfig(appId);
});
function getApplicationConfig(appId) {
url = "/apiv1/api.php/records/ent_appconfig?filter=id,eq," + appId
console.log('getting application config, appId: ' + appId);
webix.ajax().headers({
"<?php echo $api_header_key?>":"<?php echo $api_header_value?>",
"Access-Control-Allow-Origin":"*"
}).get(url).then(function(data){
app_data = JSON.parse(data.text());
app_data.data[0].prompts_json.prompts.forEach(generateHTML);
function generateHTML(item) {
if ((item.type == 'select') && (item.enabled == '1')) {
console.log('generateHTML: ' + JSON.stringify(item));
html = gen_html_select(item.variable, item.prompt, item.required);
$('#additional_questions').append(html); // Append generated html to additional_questions div
// Select that uses table for options
if (item.value_list_type == 'table') {
vx = "var1";
ssrc1 = ''; // clear the variable
ssrc1 = 'url = "' + generateURL(item.table_name, item.filter, item.order) + '"; \
webix.ajax().headers({ "<?php echo $api_header_key?>":"<?php echo $api_header_value?>", \
"Access-Control-Allow-Origin":"*" \
}).get(url).then(function(data){ \
app_data = JSON.parse(data.text()); \
console.log(app_data.data); \
app_data.data.forEach(generateSelectOptions); \
});'
eval(ssrc1);
console.log("url: " + url);
window[item.variable] = "TEST123456";
console.log('window item.variable: ' + aws_account_number);
console.log('wiv: ' + window[item.variable]);
ssrc2 = '$(\'select[name="\' + item.variable + \'"]\').on(\'change\', function() { \
window[item.variable] = $(\'select[name="\' + item.variable + \'"]\').val(); \
console.log(\' accountnumber \' + aws_account_number); \
});'
console.log('ssrc2: ' + ssrc2);
//xxx = eval(ssrc2);
//var_dump(ssrc2);
//console.log('ssrc2: ' + xxx);
// var k = item.variable;
// console.log('item_variable: ' + k);
// //eval('var ' + k + '= ' + 'david;');
// //eval('var ' + k + ' = 10;');
// eval('var ' + k + ' = 100;');
// console.log('variable: ' + eval('item.variable;'));
} // End select table
// Select that uses the app JSON for options
if (item.value_list_type == 'list') {
console.log("select list");
console.log(item.list_values);
//app_data2 = JSON.parse(item.list_values);
app_data2 = item.list_values;
//console.log(app_data2);
app_data2.forEach(get_permission);
console.log("finished");
} // End select list
} // End if item.type = select and item.enabled = 1
function generateSelectOptions(record) {
// Needs to stay in generateHTML function to access the item object
option_template = 'newOption = new Option(<DISPLAY>, <VALUE>);'
// Replace placeholders in template with values from app JSON
var result = option_template.replace(/<VALUE>/gi, eval(item.value_column));
result = result.replace(/<DISPLAY>/gi, eval(item.dropdown_definition));
eval(result);
aws_account_number.add(newOption, undefined);
} // End generateSelectOptions
} // End generateHTML
$(".select2").select2();
// $('select[name="aws_account_number"]').on('change', function() {
// var accountnumber = $('select[name="aws_account_number"]').val();
// console.log('accountnumber ' + accountnumber);
// });
}); // End webix ajax call
} // End getApplicationConfig

sapui5 - javascript error handling - without try-catch in every callback

I am developing a SAPUI5-App. Is there a way to show all errors directly to the customer without having to put a try-catch-block into every callback of sapui5? He will use my app in a mobile device and wouldn´t be able to see the log.
I tried already the following code:
<script type="text/javascript">
window.onerror = function(msg, url, line, col, error) {
var extra = !col ? '' : '\ncolumn: ' + col;
extra += !error ? '' : '\nerror: ' + error;
alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);
return false; //true = suppress error alert
};
window.addEventListener("error", handleError, true);
function handleError(evt) {
if (evt.message) {
alert("error: "+evt.message +" at linenumber: "+evt.lineno+" of file: "+evt.filename);
} else {
alert("error: "+evt.type+" from element: "+(evt.srcElement || evt.target));
}
}
jQuery.sap.log.addLogListener({
onLogEntry : function(oLogEntry) {
if(oLogEntry.level == '1'){
alert(oLogEntry.details + ' - '+oLogEntry.message);
}
}});
</script>
But I like to actually copy the error-message from the log into an alert for the customer, so he can send me screenshots of the error in his device.
All my attempts did not show enough information or didn´t fire on every error in the console-log.

Check for an specific .js file being served in response

I need to detect whether an specific .js file was served in a http response and additionally, check the domain it came from, like this:
I need to automatically detect the lack of the js file and email the incidence
I tried Net::Http, rest-client, mechanize and a lot of gems, they just return the html header. It seems I need to monitor http traffic with tools like PhantomJS and checking for the file, but is there any rubyesque way of doing this?
Thanks in advance
I ended with the phantomjs approach. A ruby script iterate over a database table and then calls this phantomjs script for each record representing an URL
This is the phantomjs script
var page = require('webpage').create(),
system = require('system'),
address,
isScript = false;
var fs = require('fs');
// main
analizePage(system.args[1]);
//open page.
//onResourceRequested event, compares domain of each one with 'my.domain.net'
//append to a log file: -1 for failed url, 1 for script presence, 0 for no script presence
function analizePage(address){
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address ' + address);
fileWriter(-1, address);
}
else
{
if (!isScript){
fileWriter(0, address);
}
else
{
fileWriter(1, address);
}
console.log('Has script: ' + isScript);
}
phantom.exit(0);
});
page.onResourceRequested = function (req) {
try {
var link = document.createElement('a');
link.setAttribute('href', req.url); //extract asset's domain from URL
if (link.hostname == 'my.domain.net') {
isScript = true;
}
} catch(e) {
console.log("PAGE OPEN ERROR: " + e);
}
};
}
function fileWriter(type, line){
try {
fs.write("scriptlog.csv", type + ',' + line + ',' + Date.now() + ',' + system.args[2] + '\n', 'a');
} catch(e) {
console.log("FILE ERROR: " + e);
}
}

Audio shows 'Invalid source' when linking to a file on local machine using FileOpenPicker

I'm trying to write a JS Windows app. I have a button on the first page, and the click event handler code is as follows:
function pickSingleAudioFile(args) {
document.getElementById("output").innerText += "\n" + this.id + ": ";
// Create the picker object and set options
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.musicLibrary;
openPicker.fileTypeFilter.replaceAll([".mp3"]);
// Open the picker for the user to pick a file
openPicker.pickSingleFileAsync().then(function (file) {
if (file) {
// Application now has read/write access to the picked file
WinJS.log && WinJS.log("Picked file: " + file.name, "sample", "status");
document.getElementById("output").innerText += "You picked " + file.name + " from " + file.path;
// Save the file as an audio tag and load it
var audtag = document.createElement('audio');
audtag.setAttribute("id", "audtag");
audtag.setAttribute("controls", "true");
audtag.setAttribute("msAudioCategory", "backgroundcapablemedia");
audtag.setAttribute("src", "\"" + file.path + "\"");
document.getElementById("output").appendChild(audtag);
audtag.load();
} else {
// The picker was dismissed with no selected file
WinJS.log && WinJS.log("Operation cancelled.", "sample", "status");
}
});
}
The path is something like "D:\Songs\song1.mp3" or "\network-share\My Music\song name.mp3" I get the "Invalid Source" error when trying to load the file.
At first glance, this:
audtag.setAttribute("src", "\"" + file.path + "\"");
should instead be this:
audtag.setAttribute("src", file.path);
It's not clear why you are adding the backslashes. However, depending on what you are doing and based on samples I've seen, you'd be better off doing something like this:
var fileLocation = window.URL.createObjectURL(file, { oneTimeOnly: true });
audtag.setAttribute("src", fileLocation);
You might check out the "Playback Manager msAudioCategory Sample" from the Windows Dev Center for more ideas.

Is there any size limitation for ajax post?

I'm posting ckeditor content via Ajax to php. But getting 4-5 sentence of posted material in my db table. I wonder, Is there any size limitation for ajax post? is there any way to post big text contents via ajax?
My js looks like that
function postViaAjax(autosaveMode) {
var name = $("#name").val();
var title = $("#title").val();
var menu = $("#menu").val();
var parentcheck = $(".parentcheck:checked").val();
var id = $("#id").val();
if (parentcheck == 0) {
var parent = parentcheck;
} else {
var parent = $("#parent").val();
}
var content = CKEDITOR.instances['content'].getData();
var dataString = 'name=' + name + '&title=' + title + '&menu=' + menu + '&parentcheck=' + parentcheck + '&id=' + id + '&parent=' + parent + '&content=' + content;
$.ajax({
type: "POST",
url: "processor/dbadd.php",
data: dataString,
dataType: "json",
success: function (result, status, xResponse) {
var message = result.msg;
var err = result.err;
var now = new Date();
if (message != null) {
if (autosaveMode) {
$('#submit_btn').attr({
'value': 'Yadda saxlanıldı ' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds()
});
} else {
$.notifyBar({
cls: "success",
html: message + ' ' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds()
});
}
}
if (err != null) {
$.notifyBar({
cls: "error",
html: err
});
}
}
});
};
The HTTP specification doesn't impose a specific size limit for posts. They will usually be limited by either the web server or the programming technology used to process the form submission.
What kind of server do you use?
There isn't any size limitation for POSTs in HTTP.
Maybe you have an & in your content variable. Then everything after that would be stripped after that.
Other than that what type do you use for your data column in the database? Is it, by any chance, something like varchar(1000)? Then anything bigger would also get stripped.
Check what you actually receive on the server end, so you know if you've got a problem with the code or the database.
You have a limitation on the Apache server. Look for LimitRequestBody directive.
This may be helpful:
http://gallery.menalto.com/node/14870
In theory the limits on AJAX requests are the same on all the other requests, so it depends on your web server/app setup. See also Max length of send() data param on XMLHttpRequest Post

Categories