summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/samples/miles/miles-connect.html52
-rw-r--r--apps/samples/miles/miles-disconnect.html52
-rw-r--r--apps/samples/miles/miles.html27
-rw-r--r--apps/samples/miles/miles.js703
-rw-r--r--apps/samples/miles/miles.scxml63
-rw-r--r--apps/samples/miles/test1.jpegbin0 -> 10996 bytes
-rw-r--r--apps/samples/miles/test2.jpegbin0 -> 40332 bytes
-rw-r--r--src/uscxml/CMakeLists.txt7
-rw-r--r--src/uscxml/Factory.cpp4
-rw-r--r--src/uscxml/Message.h16
-rw-r--r--src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp58
-rw-r--r--src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h2
-rw-r--r--src/uscxml/util/Base64.cpp129
-rw-r--r--src/uscxml/util/Base64.h14
-rw-r--r--src/uscxml/util/MD5.cpp406
-rw-r--r--src/uscxml/util/MD5.h102
16 files changed, 873 insertions, 762 deletions
diff --git a/apps/samples/miles/miles-connect.html b/apps/samples/miles/miles-connect.html
deleted file mode 100644
index ae5f77e..0000000
--- a/apps/samples/miles/miles-connect.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
- <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dijit/themes/tundra/tundra.css">
- <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/layout/resources/FloatingPane.css">
- <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/layout/resources/ResizeHandle.css">
-
- <style type="text/css">
- </style>
-
- <script type="text/javascript">
- // dojoConfig = {
- // async : false,
- // isDebug : true,
- // debugAtAllCosts : true,
- // }
- </script>
-
- <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js"></script>
- <script type="text/javascript" src="viewer.js"></script>
-
- <script type="text/javascript">
- require(["dojo/domReady!", "dojo"], function(dom, dojo) {
- var jsonHere = {
- "email": "someone@here.com",
- "reflectorIP": "88.131.107.12",
- "problemName": "Fancy problem"
- }
- var xhr = dojo.require("dojo/_base/xhr");
- xhr.post({
- // The URL to request
- url: "http://localhost:8080/miles/connect",
- handleAs:"json",
- postData: dojo.toJson(jsonHere),
- headers:{
- "X-Requested-With": null,
- "Content-Type": "application/json",
- },
- load: function(result) {
-
- }
- });
- });
- </script>
- </head>
- <body class="tundra">
- <div style="width: 600px; height: 400px">
- <div id="scene1"></div>
- </div>
- </body>
-</html>
diff --git a/apps/samples/miles/miles-disconnect.html b/apps/samples/miles/miles-disconnect.html
deleted file mode 100644
index 30f5b39..0000000
--- a/apps/samples/miles/miles-disconnect.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
- <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dijit/themes/tundra/tundra.css">
- <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/layout/resources/FloatingPane.css">
- <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/layout/resources/ResizeHandle.css">
-
- <style type="text/css">
- </style>
-
- <script type="text/javascript">
- // dojoConfig = {
- // async : false,
- // isDebug : true,
- // debugAtAllCosts : true,
- // }
- </script>
-
- <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js"></script>
- <script type="text/javascript" src="viewer.js"></script>
-
- <script type="text/javascript">
- require(["dojo/domReady!", "dojo"], function(dom, dojo) {
- var jsonHere = {
- "email": "someone@here.com",
- "reflectorIP": "88.131.107.12",
- "problemName": "Fancy problem"
- }
- var xhr = dojo.require("dojo/_base/xhr");
- xhr.post({
- // The URL to request
- url: "http://localhost:8080/miles/disconnect",
- handleAs:"json",
- postData: dojo.toJson(jsonHere),
- headers:{
- "X-Requested-With": null,
- "Content-Type": "application/json",
- },
- load: function(result) {
-
- }
- });
- });
- </script>
- </head>
- <body class="tundra">
- <div style="width: 600px; height: 400px">
- <div id="scene1"></div>
- </div>
- </body>
-</html>
diff --git a/apps/samples/miles/miles.html b/apps/samples/miles/miles.html
new file mode 100644
index 0000000..019ead4
--- /dev/null
+++ b/apps/samples/miles/miles.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dijit/themes/tundra/tundra.css">
+
+ <style type="text/css">
+ </style>
+
+ <script type="text/javascript">
+ </script>
+
+ <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js"></script>
+ <script src="miles.js"></script>
+
+ <script type="text/javascript">
+ require(["dojo/domReady!"], function(dom) {
+ var milesSession = new Miles("miles1");
+ });
+ </script>
+ </head>
+ <body class="tundra">
+ <div style="width: 600px; height: 400px">
+ <div id="miles1"></div>
+ </div>
+ </body>
+</html>
diff --git a/apps/samples/miles/miles.js b/apps/samples/miles/miles.js
index a3cdcae..b9348e8 100644
--- a/apps/samples/miles/miles.js
+++ b/apps/samples/miles/miles.js
@@ -1,664 +1,131 @@
function Miles(element, params) {
-
// private attributes
var self = this;
// private instanceId
if (!Miles.instances)
Miles.instances = 0;
+
+ // public attributes
this.instanceId = Miles.instances++;
+ this.element = element;
+ this.connected = false;
+ this.imageIteration = 0;
+
+ // private attributes
+ var scxmlURL = "127.0.0.1:8080"
+ var reflectorIp = "127.0.0.1"
+ var email = "me@somehost.de";
+ var problemName = "some really hard problem";
- // public attributes
- this.reflectorURL = "127.0.0.1";
+ // override with parameters if given
this.params = params;
-
- // privileged public methods
- this.foo = function() {
- };
-
- // privileged private methods
- var bar = function(param1, param2) {
+ if (params && params.scxmlURL) scxmlURL = params.scxmlURL;
+ if (params && params.reflectorIp) reflectorIp = params.reflectorIp;
+ if (params && params.email) email = params.email;
+ if (params && params.problemName) problemName = params.problemName;
+
+ this.connect = function() {
+ self.xhr.post({
+ // The URL to request
+ url: "http://" + scxmlURL + "/miles/connect",
+ handleAs:"json",
+ postData: dojo.toJson({
+ reflectorIp: reflectorIp,
+ email: email,
+ problemName: problemName
+ }),
+ headers:{
+ "X-Requested-With": null,
+ "Content-Type": "application/json",
+ },
+ load: function(result) {
+ // we expect nothing in return
+ self.connected = true;
+ // trigger continuously loading the image
+ refreshImage();
+ }
+ });
+ }
+
+ var refreshImage = function() {
+ self.xhr.get({
+ // The URL to request
+ url: "http://" + scxmlURL + "/miles/image",
+ handleAs:"text",
+ postData: dojo.toJson({
+ reflectorIp: reflectorIp,
+ email: email,
+ problemName: problemName
+ }),
+ headers:{
+ "X-Requested-With": null,
+ "Content-Type": "application/json",
+ },
+ load: function(result) {
+ self.pictureElem.src = "data:image/jpeg;base64," + result;
+ if (self.connected) {
+ self.messageElem.innerHTML = self.imageIteration++;
+ refreshImage();
+ }
+ }
+ });
+
};
- // start of actual class after we fetched all dojo thingies
require(["dojo/dom-construct",
"dojo/_base/xhr",
- "dojo/dom",
- "dojo/on",
- "dojox/storage",
- "dojo/store/Memory",
- "dojo/store/Observable",
- "dijit/tree/ObjectStoreModel",
- "dijit/Tree",
- "dijit/form/TextBox",
- "dijit/form/Button",
- "dojox/widget/Standby",
+ "dojo/dom",
"dijit/form/DropDownButton",
"dijit/TooltipDialog",
- "dojo/dnd/Moveable",
- "dojo/ready",
- "dojo/dnd/Source",
- "dijit/form/HorizontalSlider",
- "dijit/form/Select",
- "dijit/form/NumberSpinner"],
+ "dojo/ready"],
function(domConst,
xhr,
- dom,
- on,
- storage,
- Memory,
- Observable,
- ObjectStoreModel,
- Tree,
- TextBox,
- Button,
- Standby,
+ dom,
DropDownButton,
TooltipDialog,
- Moveable,
- ready,
- Source,
- HorizontalSlider,
- Selector,
- NumberSpinner) {
-
+ ready) {
ready(function() {
+ self.xhr = xhr;
if (typeof(element) === 'string') {
element = dom.byId(element);
}
-
- self.element = element;
- self.xhr = xhr;
- self.localStorage = dojox.storage.manager.getProvider();
- self.localStorage.initialize();
-
- // establish our dom
+
element.appendChild(domConst.toDom('\
<table>\
<tr>\
<td valign="top">\
<div style="position: relative; padding: 0px">\
- <img class="model" src="' + self.resRoot + 'img/Tutorial.png" style="z-index: -1; width: ' + self.pose.width + 'px; height: ' + self.pose.height + 'px"></img>\
- <div style="z-index: 1; position: absolute; right: 45%; top: 45%">\
- <div class="progress"></div>\
- </div>\
+ <img class="picture" src="test.jpeg"></img>\
<div style="position: absolute; left: 10px; top: 10px">\
<table></tr>\
- <td class="filesDropDown" style="vertical-align: middle"></td>\
- <td>\
- <div class="movieDropDown" style="display: inline"></div>\
- <button type="button" class="movieAddButton"></button>\
- </td>\
- <td align="right"><button type="button" class="resetButton"></button></td>\
- <td class="dragHandler" style="vertical-align: middle; padding-top: 4px;"></td>\
+ <td class="control" style="vertical-align: middle"></td>\
</tr></table>\
</div>\
- <div style="position: absolute; right: 10px; top: 15%; height: 50%">\
- <div class="zoomSlide"></div>\
- </div>\
- <div style="position: absolute; right: 50%; top: 50%">\
- <div class="pitchRollHandler" style="font-size: 0.5em; background-color: rgba(255,255,255,0.5); border-radius: 5px; moz-border-radius: 5px;">\
- <table>\
- <tr>\
- <td><img class="pitchRollHandlerImg" src="' + self.resRoot + 'img/pitchRoll-handle.png" height="20px" style="padding: 2px 0px 0px 4px;" /></td>\
- <td><div class="pitchLabel"></div><div class="rollLabel"></div></td>\
- </tr>\
- </table>\
- </div>\
- </div>\
- <div style="position: absolute; right: 50%; top: 50%">\
- <div class="yawZoomHandler">\
- <div style="font-size: 0.5em; background-color: rgba(255,255,255,0.5); border-radius: 5px; moz-border-radius: 5px; position: absolute; left: -34px;">\
- <table>\
- <tr>\
- <td><img class="yawZoomHandlerImg" src="' + self.resRoot + 'img/yawZoom-handle.png" height="20px" style="padding: 2px 0px 0px 4px;" /></td>\
- <td><div class="yawLabel"></div><div class="zoomLabel"></div></td>\
- </tr>\
- </table>\
- </div>\
- </div>\
- </div>\
- <div style="position: absolute; right: 50%; top: 50%">\
- <div class="xyHandler" style="font-size: 0.5em; background-color: rgba(255,255,255,0.5); border-radius: 5px; moz-border-radius: 5px;">\
- <table>\
- <tr>\
- <td><img class="xyHandlerImg" src="' + self.resRoot + 'img/xy-handle.png" width="20px" style="padding: 2px 0px 0px 4px;" /></td>\
- <td><div class="xLabel"></div><div class="yLabel"></div></td>\
- </tr>\
- </table>\
- </div>\
- </div>\
</div>\
</td>\
- <td valign="top" height="100%">\
- </td>\
</tr>\
<tr>\
- <td colspan="2"><div class="messages"></div></td>\
+ <td valign="top">\
+ <div class="messages" style="position: relative; padding: 0px">\
+ </td>\
</tr>\
</table>\
'));
- // fetch special dom nodes for content
- self.messageBox = dojo.query("div.messages", element)[0];
- self.imgElem = dojo.query("img.model", element)[0];
-
- /**
- * === POSE MANIPULATION AND RESET ====================
- */
-
- self.resetButtonElem = dojo.query("button.resetButton", element)[0];
- self.progressElem = dojo.query("div.progress", element)[0];
- self.pitchRollHandlerElem = dojo.query(".pitchRollHandler", element)[0];
- self.yawZoomHandlerElem = dojo.query(".yawZoomHandler", element)[0];
- self.xyHandlerElem = dojo.query(".xyHandler", element)[0];
-
- self.pitchRollHandler = new Moveable(self.pitchRollHandlerElem);
- self.pitchRollHandler.onMoveStop = function(mover) {
- var handlerImg = dojo.query("img.pitchRollHandlerImg", mover.node)[0];
- var pitchLabel = dojo.query("div.pitchLabel", mover.node)[0];
- var rollLabel = dojo.query("div.rollLabel", mover.node)[0];
-
- pitchLabel.innerHTML = '';
- rollLabel.innerHTML = '';
-
- self.updateScene();
- };
- self.pitchRollHandler.onMoving = function(mover) {
- // mover.node.style.backgroundColor = "rgba(255,255,255,0.5)";
- // mover.node.style.borderRadius = "5px";
- // mover.node.style.mozBorderRadius = "5px";
- // mover.node.style.webkitBorderRadius = "5px";
- var handlerImg = dojo.query(".pitchRollHandlerImg", mover.node)[0];
- var pitchLabel = dojo.query(".pitchLabel", mover.node)[0];
- var rollLabel = dojo.query(".rollLabel", mover.node)[0];
- var offset = moverRelativeTo(handlerImg, self.element);
-
- offset.x += 30;
- offset.y += 20;
-
- self.xyHandlerElem.style.zIndex = 1;
- self.yawZoomHandlerElem.style.zIndex = 1;
- self.pitchRollHandlerElem.style.zIndex = 2;
-
- // self.pose.pitch = self.pose.pitch % (2 * 3.14159);
- // self.pose.roll = self.pose.roll % (2 * 3.14159);
- self.pose.roll = offset.x / self.pose.width - 0.5;
- self.pose.pitch = offset.y / self.pose.height - 0.5;
- self.pose.pitch *= -1;
- self.pose.roll *= 2 * 3.14159;
- self.pose.pitch *= 2 * 3.14159;
- self.pose.roll = Math.ceil((self.pose.roll) * 10) / 10;
- self.pose.pitch = Math.ceil((self.pose.pitch) * 10) / 10;
- pitchLabel.innerHTML = 'Pitch:' + self.pose.pitch;
- rollLabel.innerHTML = 'Roll:' + self.pose.roll;
- };
-
- self.yawZoomHandler = new Moveable(self.yawZoomHandlerElem);
- self.yawZoomHandler.onMoveStop = function(mover) {
- var handlerImg = dojo.query("img.yawZoomHandlerImg", mover.node)[0];
- var yawLabel = dojo.query("div.yawLabel", mover.node)[0];
- var zoomLabel = dojo.query("div.zoomLabel", mover.node)[0];
-
- yawLabel.innerHTML = '';
- zoomLabel.innerHTML = '';
-
- self.updateScene();
- };
- self.yawZoomHandler.onMoving = function(mover) {
- var handlerImg = dojo.query("img.yawZoomHandlerImg", mover.node)[0];
- var yawLabel = dojo.query("div.yawLabel", mover.node)[0];
- var zoomLabel = dojo.query("div.zoomLabel", mover.node)[0];
- var offset = moverRelativeTo(handlerImg, self.element);
-
- offset.x += 7;
- offset.y += 9;
-
- self.xyHandlerElem.style.zIndex = 1;
- self.yawZoomHandlerElem.style.zIndex = 2;
- self.pitchRollHandlerElem.style.zIndex = 1;
-
- // self.pose.pitch = self.pose.pitch % (2 * 3.14159);
- // self.pose.roll = self.pose.roll % (2 * 3.14159);
- self.pose.yaw = (self.pose.width - offset.x) / self.pose.width - 0.5;
- self.pose.zoom = offset.y / self.pose.height - 0.5;
- self.pose.yaw *= 2 * 3.14159;
- self.pose.zoom = self.pose.zoom * 3 + 1;
- self.pose.zoom = Math.ceil((self.pose.zoom) * 10) / 10;
- self.pose.yaw = Math.ceil((self.pose.yaw) * 10) / 10;
- yawLabel.innerHTML = 'Yaw:' + self.pose.yaw;
- zoomLabel.innerHTML = 'Zoom:' + self.pose.zoom;
- };
-
- self.xyHandler = new Moveable(self.xyHandlerElem);
- self.xyHandler.onMoveStop = function(mover) {
- var handlerImg = dojo.query("img.xyHandlerImg", mover.node)[0];
- var xLabel = dojo.query("div.xLabel", mover.node)[0];
- var yLabel = dojo.query("div.yLabel", mover.node)[0];
-
- xLabel.innerHTML = '';
- yLabel.innerHTML = '';
-
- self.updateScene();
- };
- self.xyHandler.onMoving = function(mover) {
- var handlerImg = dojo.query("img.xyHandlerImg", mover.node)[0];
- var xLabel = dojo.query("div.xLabel", mover.node)[0];
- var yLabel = dojo.query("div.yLabel", mover.node)[0];
- var offset = moverRelativeTo(handlerImg, self.element);
-
- offset.x += 3;
- offset.y += 13;
-
- self.xyHandlerElem.style.zIndex = 2;
- self.yawZoomHandlerElem.style.zIndex = 1;
- self.pitchRollHandlerElem.style.zIndex = 1;
-
- self.pose.x = offset.x / self.pose.width - 0.5;
- self.pose.y = offset.y / self.pose.height - 0.5;
- self.pose.x *= 100;
- self.pose.y *= 100;
- self.pose.y = Math.ceil((self.pose.y) * 10) / 10;
- self.pose.x = Math.ceil((self.pose.x) * 10) / 10;
- xLabel.innerHTML = 'X:' + self.pose.x;
- yLabel.innerHTML = 'Y:' + self.pose.y;
- };
-
- /**
- * === FILES DROPDOWN ====================
- */
-
- self.filesDropDownElem = dojo.query("td.filesDropDown", element)[0];
-
- self.createAvatar = function(item, mode) {
- if (mode == 'avatar') {
- // create your avatar if you want
- var avatar = dojo.create( 'div', { innerHTML: item.data });
- var avatarPose = dojo.clone(self.pose);
- avatarPose.width=60;
- avatarPose.height=60;
- var avatarImgUrl = urlSuffixForPose(avatarPose);
- avatar.innerHTML = '<img src=' + self.imageURL + avatarImgUrl + ' /> ';
- item.srcEcc = "VRMLViewer";
- item.iconPoseUrl = self.imageURL + avatarImgUrl;
- item.imageURL = self.imageURL;
- item.serverURL = self.serverURL;
- item.pose = avatarPose;
- return {node: avatar, data: item, type: item.type};
- }
- var handler = dojo.create( 'div', { innerHTML: '<img src="' + self.resRoot + 'img/drag.png" width="20px" />' });
- return {node: handler, data: item, type: item.type};
- };
-
- self.dragHandler = new Source(dojo.query("td.dragHandler", element)[0], {copyOnly: true, creator: self.createAvatar});
- self.dragHandler.insertNodes(false, [ { } ]);
-
- // setup fileStore for tree list
- self.fileStore = new Observable(new Memory({
- data: [ { id: 'root', name:'3D Models'} ],
- getChildren: function(object){
- return this.query({parent: object.id});
- }
- }));
- self.fileTreeModel = new ObjectStoreModel({
- store: self.fileStore,
- query: { id: "root" }
- });
-
- // setup actual tree dijit
- self.fileList = new dijit.Tree({
- id: "fileList" + self.instanceId,
- model: self.fileTreeModel,
- persist: false,
- showRoot: false,
- style: "height: 300px;",
- onClick: function(item){
- if ('url' in item) {
- self.imageURL = item.url;
- self.updateScene();
- }
- },
- getIconClass: function(item, opened) {
- return (!item || !('url' in item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf";
- },
- getIconStyle: function(item, opened){
- if('url' in item) {
- return { backgroundImage: "url('" + item.url + "?width=16&height=16')"};
- }
- }
- //return {backgroundImage: "url('" + item.url + "?width=16&height=16')"};
-
- });
-
- if (self.params && self.params.serverURL)
- self.serverURL = self.params.serverURL;
- var savedServerURL = self.localStorage.get("vrmlServer");
- if (savedServerURL && !self.serverURL) {
- self.serverURL = savedServerURL;
- self.refreshServer(savedServerURL);
- }
-
- self.serverBox = new TextBox({
- name: "Server",
- value: self.serverURL,
- style: "width: 65%",
-
- onKeyUp: function(e) {
- if (self.browseButton) {
- if (this.get("value") !== self.serverURL) {
- self.browseButton.setAttribute('label', 'Browse');
- } else {
- self.browseButton.setAttribute('label', 'Refresh');
- }
- }
- },
-
- onKeyDown: function(e) {
- var code = e.keyCode || e.which;
- if( code === 13 ) {
- e.preventDefault();
- self.refreshServer(this.get("value"));
- return false;
- }
- },
- });
-
- self.browseButton = new Button({
- label: "Browse",
- onClick: function(){
- self.refreshServer(self.serverBox.get("value"));
- }
- });
-
- self.filesDropDownContent = domConst.toDom('<div />');
- self.filesDropDownContent.appendChild(self.serverBox.domNode);
- self.filesDropDownContent.appendChild(self.browseButton.domNode);
- self.filesDropDownContent.appendChild(self.fileList.domNode);
-
- self.filesToolTip = new TooltipDialog({ content:self.filesDropDownContent, style:"max-height:320px"});
- self.filesDropDown = new DropDownButton({ label: "Files", dropDown: self.filesToolTip });
- self.filesDropDownElem.appendChild(self.filesDropDown.domNode);
-
- self.fileStandby = new Standby({target: self.filesDropDownContent });
- self.filesDropDownContent.appendChild(self.fileStandby.domNode);
-
- /**
- * === MOVIE DROPDOWN ====================
- */
-
- self.movieDropDownElem = dojo.query("div.movieDropDown", element)[0];
- self.movieAddButtonElem = dojo.query("button.movieAddButton", element)[0];
-
- self.movieDropDownContent = domConst.toDom(
- '<div style="overflow: auto; max-height: 420px;"> \
- <table><tr class="movieFormatLengthRow" /></tr><tr class="movieWidthHeightLengthRow" /></table> \
- <div class=\"dndArea\" /> \
- </div>'
- );
-
- self.movieFormatLengthRowElem = dojo.query("tr.movieFormatLengthRow", self.movieDropDownContent)[0];
- self.movieWidthHeightLengthRowElem = dojo.query("tr.movieWidthHeightLengthRow", self.movieDropDownContent)[0];
- self.movieDnDArea = dojo.query("div.dndArea", self.movieDropDownContent)[0];
+ self.pictureElem = dojo.query("img.picture", element)[0];
+ self.controlElem = dojo.query("td.control", element)[0];
+ self.messageElem = dojo.query("div.messages", element)[0];
- self.createMovieThumb = function(item, mode) {
- if (mode == 'avatar') {
- // when dragged
- var avatar = dojo.create( 'div', { innerHTML: item.data });
- var avatarPose = dojo.clone(self.pose);
- avatarPose.width = 60;
- avatarPose.height = 60;
- var avatarImgUrl = urlSuffixForPose(avatarPose);
- avatar.innerHTML = '<img src=' + self.imageURL + avatarImgUrl + ' /> ';
- item.srcEcc = "VRMLViewer";
- item.iconPoseUrl = self.imageURL + avatarImgUrl;
- item.imageURL = self.imageURL;
- item.serverURL = self.serverURL;
- item.pose = avatarPose;
- return {node: avatar, data: item, type: item.type};
- } else {
-
- // when added to list
- var thumb = domConst.toDom("\
- <div>\
- <table><tr><td>\
- <img class=\"movieThumb\"/>\
- <img class=\"removeThumb\" style=\"vertical-align: top; margin: -3px 0px 0px -8px; width: 20px; height: 20px;\"/>\
- </td><td align=\"left\">\
- <table><tr>\
- <td>Frame:</td><td><div class=\"relFrameLength\"/></td>\
- <td><div class=\"fillInSeries\" \></td>\
- </tr><tr>\
- <td>Transition:</td><td><div class=\"relTransitionLength\"/></td>\
- </tr></table>\
- </td></tr></table>\
- </div>\
- ");
- thumb = dojo.query("div", thumb)[0];
-
- var thumbImgElem = dojo.query("img.movieThumb", thumb)[0];
- var removeImgElem = dojo.query("img.removeThumb", thumb)[0];
- var relFrameLengthElem = dojo.query("div.relFrameLength", thumb)[0];
- var relTransitionLengthElem = dojo.query("div.relTransitionLength", thumb)[0];
- var fillInSeriesElem = dojo.query("div.fillInSeries", thumb)[0];
-
- item.getThisAndNeighborsFromDnD = function() {
- var thisAndNeighbors = {};
- self.addToMovieHandler.forInItems(function(obj, key, ctx) {
- if (obj.data === item) {
- thisAndNeighbors.this = { key: key, obj: obj };
- } else {
- thisAndNeighbors.before = { key: key, obj: obj };
- }
- if (thisAndNeighbors.this) {
- thisAndNeighbors.after = { key: key, obj: obj };
- return thisAndNeighbors;
- }
- });
- return thisAndNeighbors;
- };
-
- item.relFrameLengthSlider = new HorizontalSlider({
- value: 50,
- title: "Relative Duration of Frame",
- style: "width:150px;"
- }, relFrameLengthElem);
-
- item.relTransitionLengthSlider = new HorizontalSlider({
- value: 100,
- title: "Relative Duration of Transition",
- style: "width:150px;"
- }, relTransitionLengthElem);
-
- removeImgElem.onclick = function() {
- var thisItem = item.getThisAndNeighborsFromDnD();
- if (thisItem.this) {
- // haha - what a mess!
- self.addToMovieHandler.selectNone();
- self.addToMovieHandler.selection[thisItem.this.key] = thisItem.this.obj;
- self.addToMovieHandler.deleteSelectedNodes();
- }
- // disable create button if this was the last one
- if (!thisItem.after || !thisItem.before) {
- self.movieCreateButton.setAttribute('disabled', true);
- }
- }
-
- item.fillInSeriesButton = new Button({
- label: "Insert Series",
- style: "display: none;",
- onClick: function(){
- alert("foo");
- }
- }, fillInSeriesElem);
-
- removeImgElem.src = self.resRoot + "img/close.png";
-
- var thumbPose = dojo.clone(self.pose);
- thumbPose.width = self.pose.width / 10;
- thumbPose.height = self.pose.height / 10;
- var thumbImgUrl = urlSuffixForPose(thumbPose);
-
- thumbImgElem.src = self.imageURL + thumbImgUrl;
- // removeImgElem.src = self.resRoot + 'img/close.png';
-
- item.srcEcc = "VRMLViewer";
- item.iconPoseUrl = self.imageURL + thumbImgUrl;
- item.imageURL = self.imageURL;
- item.serverURL = self.serverURL;
- item.pose = thumbPose;
-
- return {node: thumb, data: item, type: item.type};
- }
- };
-
- self.addToMovieHandler = new Source(self.movieDnDArea, {copyOnly: true, creator: self.createMovieThumb});
-
- self.movieFormatSelection = new Selector({
- name: "movieFormat",
- style: "width: 320px",
- options: []
- });
- self.populateMovieCodecs(self.serverURL + '/movie/codecs', self.movieFormatSelection);
-
- self.movieFormatLengthRowElem.appendChild(dojo.create('td', { innerHTML: 'Format:'} ));
- self.movieFormatLengthRowElem.appendChild(dojo.create('td', { colspan: "2"}));
- self.movieFormatLengthRowElem.lastChild.appendChild(self.movieFormatSelection.domNode);
+ // the control dropdown button
+ self.controlDropDownContent = domConst.toDom('<div />');
+ self.controlToolTip = new TooltipDialog({ content:self.controlDropDownContent, style:"max-height:320px"});
+ self.controlDropDown = new DropDownButton({ label: "Connect", dropDown: self.controlToolTip });
+ self.controlElem.appendChild(self.controlDropDown.domNode);
- self.movieHeightSpinner = new NumberSpinner({
- value: 400,
- smallDelta: 1,
- style: "width: 60px",
- constraints: { min:40, places:0 },
- });
+ self.connect();
- self.movieWidthSpinner = new NumberSpinner({
- value: 600,
- smallDelta: 1,
- style: "width: 60px",
- constraints: { min:40, places:0 },
- });
-
- self.movieCreateButton = new Button({
- label: "Create",
- disabled: true,
- onClick: function(){
-
- var form = document.createElement("form");
-
- form.setAttribute("method", "post");
- form.setAttribute("action", self.serverURL + "/movie");
-
- var submitData = {};
- submitData.frames = [];
- submitData.movieLength = self.movieDurationSpinner.value;
- submitData.format = self.movieFormatSelection.value;
- submitData.width = self.movieWidthSpinner.value;
- submitData.height = self.movieHeightSpinner.value;
-
- self.addToMovieHandler.forInItems(function(obj, key, ctx) {
- var jsonData = {
- iconPoseUrl: obj.data.iconPoseUrl,
- imageURL: obj.data.imageURL,
- serverURL: obj.data.serverURL,
- pose: obj.data.pose,
- relFrameLength: obj.data.relFrameLengthSlider.value,
- relTransitionLength: obj.data.relTransitionLengthSlider.value,
- }
- submitData.frames.push(jsonData);
- });
-
- var hiddenField = document.createElement("input");
- hiddenField.setAttribute("type", "hidden");
- hiddenField.setAttribute("name", "data");
- hiddenField.setAttribute("value", JSON.stringify(submitData));
-
- form.appendChild(hiddenField);
-
- // this will not save the returned binary file
- // self.xhr.post({
- // form: form,
- // load: function(data){
- // alert("asd");
- // }
- // });
-
- document.body.appendChild(form);
- form.submit();
- document.body.removeChild(form);
- }
- });
-
- self.movieDurationSpinner = new NumberSpinner({
- value: 10,
- smallDelta: 1,
- style: "width: 40px",
- constraints: { min:0, places:0 },
- });
-
- // append format duration cell
- self.movieWidthHeightLengthRowElem.appendChild(dojo.create('td', { innerHTML: 'Size:'} ));
- var movieDimensionCell = dojo.create('td');
- movieDimensionCell.appendChild(self.movieWidthSpinner.domNode);
- movieDimensionCell.appendChild(dojo.create('span', { innerHTML: "x"} ));
- movieDimensionCell.appendChild(self.movieHeightSpinner.domNode);
- movieDimensionCell.appendChild(self.movieDurationSpinner.domNode);
- movieDimensionCell.appendChild(dojo.create('span', { innerHTML: "sec"} ));
- self.movieWidthHeightLengthRowElem.appendChild(movieDimensionCell);
-
- self.movieWidthHeightLengthRowElem.appendChild(dojo.create('td', { align: "right"}));
- self.movieWidthHeightLengthRowElem.lastChild.appendChild(self.movieCreateButton.domNode);
-
-
- self.movieToolTip = new TooltipDialog({ content:self.movieDropDownContent });
- self.movieDropDown = new DropDownButton({
- label: "Movie",
- style: "display: none;",
- dropDown: self.movieToolTip });
- self.movieDropDownElem.appendChild(self.movieDropDown.domNode);
-
- self.movieAddButton = new Button({
- label: "+",
- style: "margin-left: -10px; display: none;",
- onClick: function(){
- if (self.movieFormatSelection.options.length == 0) {
- self.populateMovieCodecs(self.serverURL + '/movie/codecs', self.movieFormatSelection);
- }
- // we could pass item.data here to creator
- self.addToMovieHandler.insertNodes(false, [ { } ]);
- self.movieCreateButton.setAttribute('disabled', false);
-
- }
- }, self.movieAddButtonElem);
-
-
- self.resetButton = new Button({
- label: "Reset",
- onClick: function(){
- self.pose.x = 0;
- self.pose.y = 0;
- self.pose.pitch = 0;
- self.pose.roll = 0;
- self.pose.yaw = 0;
- self.pose.zoom = 1;
-
- self.xyHandler.node.style.left = 0;
- self.xyHandler.node.style.top = 0;
- self.pitchRollHandler.node.style.left = 0;
- self.pitchRollHandler.node.style.top = 0;
- self.yawZoomHandler.node.style.left = 0;
- self.yawZoomHandler.node.style.top = 0;
-
- self.updateScene();
- }
- }, self.resetButtonElem);
-
- // do we have parameters for the initial pose?
- if(self.params && self.params.pose)
- self.setPose(self.params.imageURL, self.params.pose, self.params.serverURL);
-
- });
- });
-
-
+ })
+ });
}
diff --git a/apps/samples/miles/miles.scxml b/apps/samples/miles/miles.scxml
index 524729f..7014502 100644
--- a/apps/samples/miles/miles.scxml
+++ b/apps/samples/miles/miles.scxml
@@ -4,48 +4,55 @@
<invoke type="miles" id="miles">
<param name="foo" expr="'asdf'" />
<finalize>
- <script>
- </script>
+ <if cond="_event.data.origin">
+ <!-- log label="Reply-length" expr="_event.data.base64.length" / -->
+ <respond status="200" to="_event.data.origin">
+ <header name="Content-Type" value="text/ascii" />
+ <content expr="_event.data.base64" />
+ </respond>
+ </if>
</finalize>
</invoke>
<state id="idle">
- <!-- XHR CORS preflight response -->
+ <!-- XHR CORS preflight respond -->
<transition event="http.options" target="idle">
- <script>dump(_event);</script>
- <response status="200" requestexpr="_event.origin">
+ <script>//dump(_event);</script>
+ <respond status="200" to="_event.origin">
<header name="Access-Control-Allow-Origin" value="*" />
<header name="Access-Control-Allow-Methods" value="GET, OPTIONS" />
<header name="Access-Control-Allow-Headers" value="X-Requested-With" />
- </response>
+ </respond>
</transition>
- <transition event="http.post" target="idle">
- <script>dump(_event);</script>
+ <transition event="http.*" target="idle">
+ <script>//dump(_event);</script>
<if cond="_event.data.pathComponent[1] === 'session'">
- <response status="200" requestexpr="_event.origin" />
+ <respond status="200" to="_event.origin" />
+
+ <elseif cond="_event.data.pathComponent[1] === 'connect'" />
+ <send target="#_miles" event="connect">
+ <param name="reflectorIP" expr="_event.data.content.reflectorIP" />
+ <param name="email" expr="_event.data.content.email" />
+ <param name="problemName" expr="_event.data.content.problemName" />
+ </send>
+ <respond status="200" to="_event.origin" />
- <elseif cond="_event.data.pathComponent[1] === 'connect'">
- <send target="#_miles" event="connect">
- <param name="reflectorIP" expr="_event.data.content.reflectorIP" />
- <param name="email" expr="_event.data.content.email" />
- <param name="problemName" expr="_event.data.content.problemName" />
- </send>
- <response status="200" requestexpr="_event.origin" />
-
- </elseif>
- <elseif cond="_event.data.pathComponent[1] === 'disconnect'">
- <send target="#_miles" event="disconnect">
- <param name="reflectorIP" expr="_event.data.content.reflectorIP" />
- <param name="problemName" expr="_event.data.content.problemName" />
- </send>
- <response status="200" requestexpr="_event.origin" />
+ <elseif cond="_event.data.pathComponent[1] === 'disconnect'" />
+ <send target="#_miles" event="disconnect">
+ <param name="reflectorIP" expr="_event.data.content.reflectorIP" />
+ <param name="problemName" expr="_event.data.content.problemName" />
+ </send>
+ <respond status="200" to="_event.origin" />
- </elseif>
- <else>
- <response status="404" requestexpr="_event.origin" />
+ <elseif cond="_event.data.pathComponent[1] === 'image'" />
+ <send target="#_miles" event="image">
+ <param name="origin" expr="_event.origin" />
+ </send>
+
+ <else />
+ <respond status="404" to="_event.origin" />
- </else>
</if>
</transition>
</state>
diff --git a/apps/samples/miles/test1.jpeg b/apps/samples/miles/test1.jpeg
new file mode 100644
index 0000000..e174f89
--- /dev/null
+++ b/apps/samples/miles/test1.jpeg
Binary files differ
diff --git a/apps/samples/miles/test2.jpeg b/apps/samples/miles/test2.jpeg
new file mode 100644
index 0000000..aca2300
--- /dev/null
+++ b/apps/samples/miles/test2.jpeg
Binary files differ
diff --git a/src/uscxml/CMakeLists.txt b/src/uscxml/CMakeLists.txt
index cf52a77..20c9010 100644
--- a/src/uscxml/CMakeLists.txt
+++ b/src/uscxml/CMakeLists.txt
@@ -9,6 +9,13 @@ file(GLOB_RECURSE USCXML_SERVER
source_group("Interpreter" FILES ${USCXML_SERVER})
list (APPEND USCXML_FILES ${USCXML_SERVER})
+file(GLOB_RECURSE USCXML_UTIL
+ util/*.cpp
+ util/*.h
+)
+source_group("Interpreter" FILES ${USCXML_UTIL})
+list (APPEND USCXML_FILES ${USCXML_UTIL})
+
file(GLOB_RECURSE USCXML_CONCURRENCY
concurrency/*.cpp
concurrency/*.h
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index ae7af11..d73e25d 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -149,8 +149,8 @@ Factory::Factory() {
#ifdef MILES_FOUND
{
// eats 8MB of RAM!
-// MilesSessionInvoker* invoker = new MilesSessionInvoker();
-// registerInvoker(invoker);
+ MilesSessionInvoker* invoker = new MilesSessionInvoker();
+ registerInvoker(invoker);
}
{
SpatialAudio* invoker = new SpatialAudio();
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index bc92180..3008a99 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -16,6 +16,9 @@
#include "uscxml/Convenience.h"
+#include "uscxml/util/MD5.h"
+#include "uscxml/util/Base64.h"
+
#define TAGNAME(elem) ((Arabica::DOM::Element<std::string>)elem).getTagName()
#define LOCALNAME(elem) ((Arabica::DOM::Element<std::string>)elem).getLocalName()
#define ATTR(elem, attr) ((Arabica::DOM::Element<std::string>)elem).getAttribute(attr)
@@ -31,6 +34,19 @@ public:
char* data;
size_t size;
std::string mimetype;
+
+ std::string md5() {
+ return uscxml::md5(data, size);
+ }
+
+ std::string base64() {
+ return base64_encode((char* const)data, size);
+ }
+
+ Blob* fromBase64(const std::string base64) {
+ std::string decoded = base64_decode(base64);
+ return new Blob((void*)decoded.c_str(), decoded.length());
+ }
};
class Data {
diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
index 8d19019..80bcce8 100644
--- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
+++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
@@ -39,20 +39,57 @@ Data MilesSessionInvoker::getDataModelVariables() {
void MilesSessionInvoker::send(const SendRequest& req) {
// std::cout << req;
if (boost::iequals(req.name, "disconnect")) {
- std::string reflectorIP = req.params.find("reflectorip")->second;
- std::string problemName = req.params.find("problemname")->second;
+ std::string reflectorIP = "127.0.0.1";
+ Event::getParam(req.params, "reflectorip", reflectorIP);
+
+ std::string problemName = "Generic";
+ Event::getParam(req.params, "problemname", problemName);
+
int rv;
rv = miles_disconnect_reflector_session((char*)reflectorIP.c_str(), (char*)problemName.c_str());
if (!rv) {
LOG(ERROR) << "Could not disconnect from reflector session";
return;
}
-
- }
- if (boost::iequals(req.name, "connect")) {
- std::string email = req.params.find("email")->second;
- std::string reflectorIP = req.params.find("reflectorip")->second;
- std::string problemName = req.params.find("problemname")->second;
+ } else if (boost::iequals(req.name, "image")) {
+ // client wants an image
+ URL imageURL1("test1.jpeg");
+ URL imageURL2("test2.jpeg");
+
+ imageURL1.toAbsolute(_interpreter->getBaseURI());
+ imageURL2.toAbsolute(_interpreter->getBaseURI());
+
+ std::stringstream ssImage;
+
+ if (alternate) {
+ ssImage << imageURL1;
+ } else {
+ ssImage << imageURL2;
+ }
+ alternate = !alternate;
+
+ std::string imageContent = ssImage.str();
+
+ Event retEv;
+ retEv.data.compound["base64"] = Data(base64_encode(imageContent.data(), imageContent.size()), Data::VERBATIM);
+
+ std::string origin;
+ Event::getParam(req.params, "origin", origin);
+ retEv.data.compound["origin"] = origin;
+
+ tthread::this_thread::sleep_for(tthread::chrono::milliseconds(20));
+
+ returnEvent(retEv);
+
+ } else if (boost::iequals(req.name, "connect")) {
+ std::string email = "someSaneDefault";
+ Event::getParam(req.params, "email", email);
+
+ std::string reflectorIP = "127.0.0.1";
+ Event::getParam(req.params, "reflectorip", reflectorIP);
+
+ std::string problemName = "Generic";
+ Event::getParam(req.params, "problemname", problemName);
int rv;
rv = miles_connect_reflector_session((char*)reflectorIP.c_str(), (char*)problemName.c_str());
@@ -168,8 +205,9 @@ void MilesSessionInvoker::send(const SendRequest& req) {
// audio_transmitter(audio_dev, audio_encoder, out_rtp_audio_stream, out_rtcp_audio_stream);
// }
- _audioThread = new tthread::thread(MilesSessionInvoker::runAudio, this);
- _videoThread = new tthread::thread(MilesSessionInvoker::runVideo, this);
+ // don't start threads for mockup
+// _audioThread = new tthread::thread(MilesSessionInvoker::runAudio, this);
+// _videoThread = new tthread::thread(MilesSessionInvoker::runVideo, this);
}
}
diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
index d61dbfe..c28f2cc 100644
--- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
+++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
@@ -39,6 +39,8 @@ public:
virtual void invoke(const InvokeRequest& req);
protected:
+ bool alternate; // this is to alternate test1 an test2.jpeg and has no other use! remove me later ..
+
int video_rtp_in_socket, audio_rtp_in_socket;
int video_rtp_out_socket, audio_rtp_out_socket;
int video_rtcp_in_socket, audio_rtcp_in_socket;
diff --git a/src/uscxml/util/Base64.cpp b/src/uscxml/util/Base64.cpp
new file mode 100644
index 0000000..20cfbc3
--- /dev/null
+++ b/src/uscxml/util/Base64.cpp
@@ -0,0 +1,129 @@
+/*
+ base64.cpp and base64.h
+
+ Copyright (C) 2004-2008 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+
+ Moved to namespace umundo
+
+*/
+
+#include "Base64.h"
+#include <iostream>
+
+namespace uscxml {
+
+static const std::string base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+
+static inline bool is_base64(unsigned char c) {
+ return (isalnum(c) || (c == '+') || (c == '/'));
+}
+
+std::string base64_encode(char const* bytes_to_encode, unsigned int in_len) {
+ std::string ret;
+ int i = 0;
+ int j = 0;
+ unsigned char char_array_3[3];
+ unsigned char char_array_4[4];
+
+ while (in_len--) {
+ char_array_3[i++] = *(bytes_to_encode++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for(i = 0; (i <4) ; i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for(j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for (j = 0; (j < i + 1); j++)
+ ret += base64_chars[char_array_4[j]];
+
+ while((i++ < 3))
+ ret += '=';
+
+ }
+
+ return ret;
+
+}
+
+std::string base64_decode(std::string const& encoded_string) {
+ int in_len = encoded_string.size();
+ int i = 0;
+ int j = 0;
+ int in_ = 0;
+ unsigned char char_array_4[4], char_array_3[3];
+ std::string ret;
+
+ while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
+ char_array_4[i++] = encoded_string[in_];
+ in_++;
+ if (i ==4) {
+ for (i = 0; i <4; i++)
+ char_array_4[i] = base64_chars.find(char_array_4[i]);
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (i = 0; (i < 3); i++)
+ ret += char_array_3[i];
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for (j = i; j <4; j++)
+ char_array_4[j] = 0;
+
+ for (j = 0; j <4; j++)
+ char_array_4[j] = base64_chars.find(char_array_4[j]);
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
+ }
+
+ return ret;
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/util/Base64.h b/src/uscxml/util/Base64.h
new file mode 100644
index 0000000..eaa7cfc
--- /dev/null
+++ b/src/uscxml/util/Base64.h
@@ -0,0 +1,14 @@
+// taken from http://www.adp-gmbh.ch/cpp/common/base64.html
+#ifndef BASE64_H_5FKG12HF
+#define BASE64_H_5FKG12HF
+
+#include <string>
+
+namespace uscxml {
+
+std::string base64_encode(char const* , unsigned int len);
+std::string base64_decode(std::string const& s);
+
+}
+
+#endif /* end of include guard: BASE64_H_5FKG12HF */
diff --git a/src/uscxml/util/MD5.cpp b/src/uscxml/util/MD5.cpp
new file mode 100644
index 0000000..3fee55c
--- /dev/null
+++ b/src/uscxml/util/MD5.cpp
@@ -0,0 +1,406 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "MD5.h"
+#include <string.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+namespace uscxml {
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) {
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms) {
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) {
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16]) {
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
+
+std::string md5(const char* data, size_t length) {
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)data, length);
+ md5_finish(&state, digest);
+
+ std::ostringstream ss;
+ ss << std::hex << std::uppercase << std::setfill( '0' );
+ for (int i = 0; i < 16; i++) {
+ ss << std::setw( 2 ) << (int)digest[i];
+ }
+
+ return ss.str();
+}
+
+std::string md5(const std::string& data) {
+ return md5(data.data(), data.size());
+}
+
+}
diff --git a/src/uscxml/util/MD5.h b/src/uscxml/util/MD5.h
new file mode 100644
index 0000000..aebac78
--- /dev/null
+++ b/src/uscxml/util/MD5.h
@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/**
+ * C++ convinience
+ */
+#include <string>
+
+namespace uscxml {
+
+extern std::string md5(const char* data, size_t length);
+extern std::string md5(const std::string& data);
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* Initialize the algorithm. */
+ void md5_init(md5_state_t *pms);
+
+ /* Append a string to the message. */
+ void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+ /* Finish the message and return the digest. */
+ void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+}
+#endif /* md5_INCLUDED */