How can I manage MSI session state within Javascript Custom Actions? - javascript

I have an ISAPI DLL, an add-on to IIS. I build the installer for it using WIX 3.0.
In the installer project, I have a number of custom actions implemented in Javascript. One of them, run at the initiation of the install, stops any IIS websites that are running. Another starts the IIS websites at the end of the install.
This stuff works, the CA's get invoked at the right times and under the right conditions. but the logic is naive. It stops all websites in the beginning (even if they are already stopped) and starts all websites at the end (even if they were previously stopped). This is obviously wrong.
What I'd like to do is keep track in the session of which websites required a stop at the beginning, and then, at the end, only try to restart those websites. Getting the state of a website is easy using the ServerState property on the CIM object. The question I have is, how should I store this information in the MSI session?
It's easy to stuff a single piece of information into a session Property, but what's the best way to store a set of N pieces of information, one for each website? In some cases there can be 1 website, in some cases, 51 websites.
I suppose I could use each distinct website name to create a distinct property name. Just not sure that is the best, most-efficient, most efficacious way to do things. Also, is it legal to use slashes in the name of an MSI Session property? (the website names will have slashes in them)
Suggestions?

You might want to check out:
VBScript (and Jscript) MSI CustomActions suck
C++ or C# is a much better choice. If your application already has dependencies on the framework then adding dependencies in your installer is a good logical choice. WiX has Deployment Tools Foundation ( DTF ) that has a custom action pattern that feels a lot jscript. You could then create a dictionary of websites and their run state and serialize it out to a single property. On the back side you could reconsitute that collection and then act upon it.
Not to mention the debugging story is MUCH better in DTF.

There's a simple solution. I was having a brain cramp.
All of the items I needed to store were strings - actually the names of websites that had been stopped during the installation. I just used the Javascript String.join method to create a single string, and the stuffed that into the session variable. Like this:
Session.Property("CA_STOPPEDSITES") = sitesThatWereStopped.join(",");
Then to retrieve that information later in another custom action, I do
var stoppedSites = Session.Property("CA_STOPPEDSITES");
if (stoppedSites != null) {
var sitesToStart = stoppedSites.split(",");
....
Simple, easy.

Related

My Shopify app replaces the product form - option_selection.js breaks: can't access its "parentNode" property

My Shopify app replaces the product pages 'Add To Cart' form / product form, with it's own form of sorts. It is Liquid logic that decides whether or not to render the entire <form> element.
This works great, but on some themes (like Jumpstart by Shopify), the product page bugs out completely, throwing me an error saying:
option_selection.js - can't access its "parentNode" property
Which I believe is the option_selection.js function where it is looking for the select box / variant ID somewhere on the page.
Of course, this variant ID / select box does not exist because it is not being rendered.
How can I replace the add to cart form while satisfying the option_selection.js functions?
Usually this wouldn't be a big deal, but Shopify's app review team will give me problems with this, and on the Jumpstart theme specifically, this error causes the product photos to not render; breaking the page completely.
Any ideas here? Much appreciated!
Axing the entire product form seems a bit extreme - there's no way to do what you need to do in a less invasive way?
Assuming not, you'll want to expand your install so that you can update any code in a theme that initializes the product form to take into account the possibility that you've defied the theme's simplistic assumptions.
For the option_selection.js compatibility, you'll be looking for where new Shopify.OptionSelectors is being invoked. If your code has set a variable through Javascript, that may be the easiest check to make. Example of an inline install that assumes your code creates a function named MyAppNamespace.isProdHidden:
Original:
new Shopify.OptionSelectors( ...
Updated:
!(window.MyAppNamespace && MyAppNamespace.isProdHidden({{ product.id | json }}) ) && new Shopify.OptionSelectors( ...
The added piece of code will evaluate to false if and only if your app has loaded properly and your isProdHidden function returns a truthy value. This scenario would prevent the new Shopify.OptionSelectors part from running, since we're using the && as a sort of short-circuit/emergency-stop operation.
If your app failed to load (or was uninstalled from the store without the liquid code being updated), or if MyAppNamespace.isProdHidden returns false, then the added block of code evaluates as true and the new Shopify.OptionSelectors happens as normal.
The above is equivalent to wrapping the entire new Shopify.OptionSelectors call in an if statement, with the install benefit that the party installing your app doesn't need to read the theme code to figure out where the OptionSelectors call ends. In most themes the OptionSelectors code is spread out over multiple lines and occasionally theme developers declare their onVariantChange function as an inline anonymous function - neither of which are big obstacles for experienced developers, but a huge complication for novices and store owners without this kind of expertise.
Making the status of your app available somehow through Javascript is probably the best thing for you to do as far as theme-install-compatibility goes. Some themes have their OptionSelectors call right in the product page, which can be affected by dynamic Liquid variables, but many have this code tucked away in a .js file in the assets folder instead. Still other themes don't use Shopify's OptionSelectors code at all and instead run their own thing, and thus your app could interfere in completely unexpected ways or places. Creating tools to make it easier to integrate your app into somebody else's code is therefore one of the best things you can do.
You'll also want to make sure that your code is able to handle multiple products, as many stores have quick-shops all through the site which can load arbitrary product forms. By making sure you have made the tools available, it's possible for you, your support team (if any) and theme devs can make the required updates to (almost!) any arbitrary theme.
Hope that helps!

non iframe html transition when using SCORM

i want to use SCORM (ver. 2004) using multiple html pages and i need to switch them using location.href
when im using only 1 html file its working as intended.
when using multiple files and switching them off with location.href, we get no connection on the new page and cannot initialize new connection because its already initialized.
Thank you very much for your help.
So the connection being Initialized isn't a big deal. But, each page loading and trying to initialize just generates a SCORM warning/error. That technically is a non-actionable error.
Cons of this approach
JavaScript has to instantiate on each page - each time. This means it has to pull back down (depending on the features your using) bookmarking, suspend data, etc...
So this is where mitigating all this becomes problematic.
When do you terminate?
How can you bookmark or support bookmarking?
What happens if curriculum adds or removes a page later?
Can I limit the number of times I try to initialize?
Will the LMS even allow this (since sometimes they salt and pepper values in the query string)?
The share-ability barometer on doing this I'd say is ripe with failure and I'd caution against it. Some LMS systems even detect the unload. Can you over come some of the above - sure. But will you be over taken by the rest... absolutely.
SCO = Shareable content object. And anything that diminishes the shareable part will hurt downstream.
Alternative
Use a single page SCO collection defined in a imsmanifest.xml. See https://github.com/cybercussion/SCOBot/wiki/Single-Pages-Managed-by-LMS-Navigation
Comment
Hope that helps. I was involved with a project a very long time ago where a architect wanted to do things simple like this, and it really requires some added elbow grease to either support single pages managed by the LMS, a AJAX or IFRAME approach to do it right.

How to create a truly hidden variable in Javascript

I am trying to build a puzzle game using HTML & JS. This is going to be a standalone HTML page. There isn't going to be a server side for this application.
Obviously, the game has an answer which the application will create at start time. Now, I wish to make this variable completely hidden i.e., not just hidden from user's view but also inaccessible to the user, even if he tries to read the page through Chrome's Developer Tools or such debug tools.
I'm looking for a solution using HTML5, JS ECMAScript 5+ & jQuery.
I remember reading something about Native HTML code (used for HTML File elements) which cannot be rendered/read even through Dev Tools. Is this any help?
Is there any way or strategy to achieve this?
NOTE: I am aware of <input type="hidden">. But that doesn't serve my purpose.
EDIT: As part of the game, the user makes attempts and the application needs to validate the user's input against this somehow-user-hidden answer variable. At this point, I believe there is no solution that's going to be completely airtight in the given constraints. Hence, I'm pursuing this from an academic interest. Does anyone have any other answers ?
Prehash your answer, hard code that into your page.
Then, when they submit their answer, run through whatever hashing pattern you did before hand, and compare the result.
It could theoretically be brute forced, of course.... if you had a few hundred years.
Javascript implementations of:
SHA-1: http://www.webtoolkit.info/javascript-sha1.html
SHA-256: http://www.webtoolkit.info/javascript-sha256.html
MD5: http://www.webtoolkit.info/javascript-md5.html
Edit:
An example would be:
Pattern: SHA-1(SHA-1(SHA-1(answer + salt)))
Salt: 982qx17wef7ddsbtxaewnsdufs (make something up, load it as an input type='hidden')
Result: (load it as an input type='hidden')
Request the answer
If SHA-1(SHA-1(SHA-1(attempt + salt))) === Result, they got it correct
Your can hash your values using MD5.
https://github.com/blueimp/JavaScript-MD5#client-side

Degrees of JS vulnerability

Never trust the client. It's my coding mantra. All javascript can, with enough effort, be overwritten or compromised. The thing I want to understand is how.
Let's say I wrote a function checkStep() for a game - each time the player moves one space, it polls the server to check for any events: HP regeneration, enter random battle, move to next map, etc. I asked myself "self, how would I go about rewriting or disabling this function?" Research turned up some conflicting results. Some sources say functions can be directly redefined from the console, others say it would be a much more involved process.
My question is this: what would a player have to do to rewrite or disable my checkStep() function? Can they simply redefine it from the console? Would they have to rip, modify, and re-host my code? How would you do it?
Please note, I'm not asking how to make this function secure.
The first person to leave an answer/comment along the lines of "you
can try minifying it, but it still wont be secure" or "put in some
server-side checks" is getting bludgeoned with a semicolon, as an
example to the rest.
You could use a web debugging proxy like Fiddler to do this for your local machine. Programs like this allow you to intercept content you download and fiddle with it. So you could write a new version of the function, then use the program to replace it with your version when the file is downloaded from the server. Then, for your local machine, the code would run with the new function in place. The web session manipulation page on the Fiddler site has a few more details.
There is no reason to use any Javascript or browser a even.
If a normal user can use their browser to play the game then any user can use any program to communicate with the server and send it anything they want. The server is not able to know if someone is using a browser to connect to it or not.
This applies to anything. A game server doesn't know if the user is connecting to it through the official game client. Since the official game is closed source it would be easy to fall into trusting it even though it is possible to reverse engineer the protocols used and use anything to connect to the server.
Complex things like creating a malicious game client, or using a proxy to alter content before it makes it to the browser are technically valid points, however that seems like a lot of effort for something which is very simple to do.
var checkStep = function() {
... // your original function
}
// later on
checkStep = function() {
alert('foo');
}
It is perfectly valid in JavaScript to change what function a variable holds. Any function you define can be redefined on the client side. This can be done by other script files loaded by the browser which use conflicting variable names, scripts injected via XSS, or by the user bringing up the console.

What is the reason behind the use of Javascript in Wikitude SDK for Android?

I've been comparing several SDKs in order to add some location-based AR in one of my Android Apps. So far I've really liked the overall simplicity of Wikitude, however there are things like them asking you to put some of the logic of the AR part in javascript files that confuse me.
What are you supposed to do with the javascript, what role does it serves in the overall flow between an Android Activity and the AR?
Also, as a side question, what sense is there to make out of this line in the Android documentation of Wikitude:
architectView.callJavascript(newData('" + poiDataAsJson +")')
at http://developer.wikitude.com/documentation/android. I assume there is a typo or mistake somewhere as newData is not defined anywhere in the Android code.
Thank you!
In order to enable cross platform augmented reality experiences, web technologies were chosen. The application flow is usually that the ArchtiectView is initialised and displayed by the native application. An AR experience is loaded which consists of an html file that executes javascript functions to create the objects in AR.
callJavascript method is used natively to communicate with the loaded AR exprience. It executes the passed javascript in the context of the loaded AR experience. Therefore it can be used to pass POI data as json to a function declared in the Javascript part.
There is an error in the posted java code
architectView.callJavascript(newData('" + poiDataAsJson +")')
should include 2 more double quotes
architectView.callJavascript("newData('" + poiDataAsJson +")'")
This executes the function newData declared globally in javascript and passes 1 parameter, the json encoded poi data.
Disclaimer: I work for Wikitude

Categories

Resources