Index: /trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- /trunk/FACT++/src/InterpreterV8.cc	(revision 14740)
+++ /trunk/FACT++/src/InterpreterV8.cc	(revision 14741)
@@ -433,4 +433,35 @@
 }
 
+Handle<Value> InterpreterV8::FuncGetStates(const Arguments& args)
+{
+    if (args.Length()>1)
+        return ThrowException(String::New("getStates must not take more than one arguments."));
+
+    if (args.Length()==1 && !args[0]->IsString())
+        return ThrowException(String::New("Argument must be an string."));
+
+    const string server = args.Length()==1 ? *String::AsciiValue(args[0]) : "DIM_CONTROL";
+
+    const vector<State> states = JsGetStates(server);
+
+    HandleScope handle_scope;
+
+    Handle<Object> list = Object::New();
+    if (list.IsEmpty())
+        return Undefined();
+
+    for (auto it=states.begin(); it!=states.end(); it++)
+    {
+        Handle<Value> entry = StringObject::New(String::New(it->name.c_str()));
+        if (entry.IsEmpty())
+            return Undefined();
+
+        StringObject::Cast(*entry)->Set(String::New("description"), String::New(it->comment.c_str()), ReadOnly);
+        list->Set(Integer::New(it->index), entry, ReadOnly);
+    }
+
+    return handle_scope.Close(list);
+}
+
 // ==========================================================================
 //                             Internal functions
@@ -441,5 +472,5 @@
 // function is called.  Prints its arguments on stdout separated by
 // spaces and ending with a newline.
-Handle<Value> InterpreterV8::FuncPrint(const Arguments& args)
+Handle<Value> InterpreterV8::FuncLog(const Arguments& args)
 {
     for (int i=0; i<args.Length(); i++)
@@ -1926,10 +1957,11 @@
     // Create a template for the global object.
     Handle<ObjectTemplate> dim = ObjectTemplate::New();
-    dim->Set(String::New("print"),   FunctionTemplate::New(WrapPrint), ReadOnly);
-    dim->Set(String::New("alarm"),   FunctionTemplate::New(WrapAlarm), ReadOnly);
-    dim->Set(String::New("wait"),    FunctionTemplate::New(WrapWait),  ReadOnly);
-    dim->Set(String::New("send"),    FunctionTemplate::New(WrapSend),  ReadOnly);
-    dim->Set(String::New("state"),   FunctionTemplate::New(WrapState), ReadOnly);
-    dim->Set(String::New("version"), Integer::New(DIM_VERSION_NUMBER), ReadOnly);
+    dim->Set(String::New("log"),       FunctionTemplate::New(WrapLog),       ReadOnly);
+    dim->Set(String::New("alarm"),     FunctionTemplate::New(WrapAlarm),     ReadOnly);
+    dim->Set(String::New("wait"),      FunctionTemplate::New(WrapWait),      ReadOnly);
+    dim->Set(String::New("send"),      FunctionTemplate::New(WrapSend),      ReadOnly);
+    dim->Set(String::New("state"),     FunctionTemplate::New(WrapState),     ReadOnly);
+    dim->Set(String::New("version"),   Integer::New(DIM_VERSION_NUMBER),     ReadOnly);
+    dim->Set(String::New("getStates"), FunctionTemplate::New(WrapGetStates), ReadOnly);
 
     Handle<ObjectTemplate> dimctrl = ObjectTemplate::New();
Index: /trunk/FACT++/src/InterpreterV8.h
===================================================================
--- /trunk/FACT++/src/InterpreterV8.h	(revision 14740)
+++ /trunk/FACT++/src/InterpreterV8.h	(revision 14741)
@@ -67,5 +67,5 @@
     v8::Handle<v8::Value> FuncThread(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncKill(const v8::Arguments& args);
-    v8::Handle<v8::Value> FuncPrint(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncLog(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncAlarm(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncOut(const v8::Arguments& args);
@@ -76,4 +76,5 @@
     v8::Handle<v8::Value> FuncSetState(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncGetState(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncGetStates(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncNewState(const v8::Arguments& args);
     //v8::Handle<v8::Value> FuncOpen(const v8::Arguments& args);
@@ -113,5 +114,5 @@
     static v8::Handle<v8::Value> WrapInclude(const v8::Arguments &args)  { if (This) return This->FuncInclude(args);  else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapFile(const v8::Arguments &args)     { if (This) return This->FuncFile(args);     else return v8::Undefined(); }
-    static v8::Handle<v8::Value> WrapPrint(const v8::Arguments &args)    { if (This) return This->FuncPrint(args);    else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapLog(const v8::Arguments &args)      { if (This) return This->FuncLog(args);      else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapAlarm(const v8::Arguments &args)    { if (This) return This->FuncAlarm(args);    else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapOut(const v8::Arguments &args)      { if (This) return This->FuncOut(args);      else return v8::Undefined(); }
@@ -126,4 +127,5 @@
     static v8::Handle<v8::Value> WrapSetState(const v8::Arguments &args) { if (This) return This->FuncSetState(args); else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapGetState(const v8::Arguments &args) { if (This) return This->FuncGetState(args); else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapGetStates(const v8::Arguments &args){ if (This) return This->FuncGetStates(args);else return v8::Undefined(); }
     //static v8::Handle<v8::Value> WrapOpen(const v8::Arguments &args)     { if (This) return This->FuncOpen(args);     else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapSubscription(const v8::Arguments &args){ if (This) return This->FuncSubscription(args);else return v8::Undefined(); }
@@ -181,4 +183,5 @@
     virtual int   JsGetState(const std::string &) const { return -2; }
     virtual State JsGetCurrentState() const { return State(); }
+    virtual std::vector<State> JsGetStates(const std::string &) { return std::vector<State>(); }
 
     virtual std::vector<Description> JsDescription(const std::string &) { return std::vector<Description>(); };
Index: /trunk/FACT++/src/RemoteControl.h
===================================================================
--- /trunk/FACT++/src/RemoteControl.h	(revision 14740)
+++ /trunk/FACT++/src/RemoteControl.h	(revision 14741)
@@ -174,4 +174,5 @@
     bool  JsSetState(int s)                   { if (!fImp || fImp->GetCurrentState()<2) return false; SetSection(s-4); return true; }
     int   JsGetState(const string &n) const   { return fImp ? fImp->GetStateIndex(n) : StateMachineImp::kSM_NotAvailable; }
+    vector<State> JsGetStates(const string &server) { return fImp ? fImp->GetStates(server) : vector<State>(); }
     State JsGetCurrentState() const
     {
@@ -186,5 +187,4 @@
         return fImp && fImp->AddStateName(s, n, c);
     }
-
 
     /*
Index: /trunk/FACT++/src/StateMachineDimControl.cc
===================================================================
--- /trunk/FACT++/src/StateMachineDimControl.cc	(revision 14740)
+++ /trunk/FACT++/src/StateMachineDimControl.cc	(revision 14741)
@@ -445,4 +445,21 @@
 }
 
+vector<State> StateMachineDimControl::GetStates(const string &server)
+{
+    const lock_guard<mutex> guard(fMutex);
+
+    vector<State> rc;
+
+    for (auto it=fStateDescriptionList.begin(); it!=fStateDescriptionList.end(); it++)
+    {
+        if (it->first.first!=server)
+            continue;
+
+        rc.push_back(State(it->first.second, it->second.first, it->second.second));
+    }
+
+    return rc;
+}
+
 
 int StateMachineDimControl::HandleAddService(const Service &svc)
@@ -506,4 +523,6 @@
     fScriptUser = fUser;
 
+    // FIXME: Check fUser for quotes!
+
     const map<string, string> &js = conf.GetOptions<string>("JavaScript.");
     for (auto it=js.begin(); it!=js.end(); it++)
@@ -555,8 +574,8 @@
 
     if (conf.Has("start"))
-        return Dim::SendCommand("DIM_CONTROL/START", conf.Get<string>("start")+" user="+fUser) + 1;
+        return Dim::SendCommand("DIM_CONTROL/START", conf.Get<string>("start")+" user='"+fUser+"'") + 1;
 
     if (conf.Has("batch"))
-        return Dim::SendCommand("DIM_CONTROL/EXECUTE", conf.Get<string>("batch")+" user="+fUser) + 1;
+        return Dim::SendCommand("DIM_CONTROL/EXECUTE", conf.Get<string>("batch")+" user='"+fUser+"'") + 1;
 
     if (conf.Has("msg"))
Index: /trunk/FACT++/src/StateMachineDimControl.h
===================================================================
--- /trunk/FACT++/src/StateMachineDimControl.h	(revision 14740)
+++ /trunk/FACT++/src/StateMachineDimControl.h	(revision 14741)
@@ -60,4 +60,6 @@
     std::vector<std::string> GetCommandList();
     std::vector<Description> GetDescription(const std::string &service);
+    std::vector<State>       GetStates(const std::string &server);
+
 
     int PrintStates(std::ostream &out, const std::string &serv="");
