SMS driver for websms.ru service; Config class refactoring
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 8 Apr 2014 16:32:09 +0000 (19:32 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 8 Apr 2014 16:32:09 +0000 (19:32 +0300)
24 files changed:
ChangeLog
configure.ac
include/nxconfig.h
netxms.sln
src/agent/core/policy.cpp
src/agent/subagents/java/ConfigHelper.cpp
src/agent/subagents/netsvc/main.cpp
src/agent/subagents/netsvc/netsvc.h
src/libnetxms/config.cpp
src/libnxmap/element.cpp
src/server/core/dcitem.cpp
src/server/core/dcithreshold.cpp
src/server/core/dcobject.cpp
src/server/core/dctcolumn.cpp
src/server/core/dctthreshold.cpp
src/server/core/epp.cpp
src/server/core/import.cpp
src/server/core/template.cpp
src/server/smsdrv/Makefile.am
src/server/smsdrv/dummy/dummy.vcproj
src/server/smsdrv/dummy/main.cpp
src/server/smsdrv/websms/Makefile.am [new file with mode: 0644]
src/server/smsdrv/websms/main.cpp [new file with mode: 0644]
src/server/smsdrv/websms/websms.vcproj [copied from src/server/smsdrv/dummy/dummy.vcproj with 92% similarity]

index c5ccc20..46ba259 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@
   enableIcmp, enableSnmp, enableStatusPoll, enableTopologyPoll
 - Fixed server crash if SNMP proxy unavailable
 - New MIBs: FROGFOOT-RESOURCES-MIB, MIKROTIK-MIB
+- SMS driver for websms.ru service
 - Management console:
    - DCI values can be shown on network map links
    - Colored background for DCIs with active thresholds in DCI summary tables
index 10c1da6..656e0af 100644 (file)
@@ -57,6 +57,7 @@ SUBAGENT_LIBS=""
 SERVER_LIBS=""
 SERVER_TOOLS=""
 SERVER_INCLUDE=""
+SMSDRV_DIRS=""
 TOP_LEVEL_MODULES=""
 CONTRIB_MODULES=""
 CLIENT_COMPONENTS=""
@@ -413,6 +414,7 @@ AC_ARG_WITH(dist,
        DB_DRIVERS=" mysql pgsql odbc mssql sqlite oracle db2 informix"
        MODULES="libexpat libstrophe libtre zlib libnetxms install sqlite snmp libnxsl libnxlp db server agent libnxmap libnxcl client nxscript nxcproxy tools"
        SUBAGENT_DIRS="linux freebsd openbsd netbsd sunos aix ipso hpux odbcquery informix oracle lmsensors darwin rpi java netsvc db2"
+       SMSDRV_DIRS="websms"
        NXCONFIG="nxconfig"
        TOP_LEVEL_MODULES="include sql images"
        SERVER_INCLUDE="include"
@@ -1379,6 +1381,7 @@ if test "x$HAVE_LIBCURL" = "xyes"; then
 fi
 if test "x$HAVE_LIBCURL" = "xyes"; then
   SUBAGENT_DIRS="$SUBAGENT_DIRS netsvc"
+  SMSDRV_DIRS="$SMSDRV_DIRS websms"
 fi
 
 #--------------------------------------------------------------------
@@ -2303,6 +2306,7 @@ AC_SUBST(SUBAGENT_DIRS)
 AC_SUBST(SERVER_INCLUDE)
 AC_SUBST(SERVER_LIBS)
 AC_SUBST(SERVER_TOOLS)
+AC_SUBSR(SMSDRV_DIRS)
 AC_SUBST(TOP_LEVEL_MODULES)
 AC_SUBST(CONTRIB_MODULES)
 AC_SUBST(CLIENT_COMPONENTS)
index d5ed340..202fd9d 100644 (file)
@@ -61,33 +61,44 @@ public:
        int getConcatenatedValuesLength();
        
        const TCHAR *getValue(int index = 0);
-       INT32 getValueInt(int index = 0, INT32 defaultValue = 0);
-       UINT32 getValueUInt(int index = 0, UINT32 defaultValue = 0);
-       INT64 getValueInt64(int index = 0, INT64 defaultValue = 0);
-       UINT64 getValueUInt64(int index = 0, UINT64 defaultValue = 0);
-       bool getValueBoolean(int index = 0, bool defaultValue = false);
-       bool getValueUUID(int index, uuid_t uuid);
+       INT32 getValueAsInt(int index = 0, INT32 defaultValue = 0);
+       UINT32 getValueAsUInt(int index = 0, UINT32 defaultValue = 0);
+       INT64 getValueAsInt64(int index = 0, INT64 defaultValue = 0);
+       UINT64 getValueAsUInt64(int index = 0, UINT64 defaultValue = 0);
+       bool getValueAsBoolean(int index = 0, bool defaultValue = false);
+       bool getValueAsUUID(int index, uuid_t uuid);
+
+       void addValue(const TCHAR *value);
+       void setValue(const TCHAR*value);
 
        const TCHAR *getSubEntryValue(const TCHAR *name, int index = 0, const TCHAR *defaultValue = NULL);
-       INT32 getSubEntryValueInt(const TCHAR *name, int index = 0, INT32 defaultValue = 0);
-       UINT32 getSubEntryValueUInt(const TCHAR *name, int index = 0, UINT32 defaultValue = 0);
-       INT64 getSubEntryValueInt64(const TCHAR *name, int index = 0, INT64 defaultValue = 0);
-       UINT64 getSubEntryValueUInt64(const TCHAR *name, int index = 0, UINT64 defaultValue = 0);
-       bool getSubEntryValueBoolean(const TCHAR *name, int index = 0, bool defaultValue = false);
-       bool getSubEntryValueUUID(const TCHAR *name, uuid_t uuid, int index = 0);
+       INT32 getSubEntryValueAsInt(const TCHAR *name, int index = 0, INT32 defaultValue = 0);
+       UINT32 getSubEntryValueAsUInt(const TCHAR *name, int index = 0, UINT32 defaultValue = 0);
+       INT64 getSubEntryValueAsInt64(const TCHAR *name, int index = 0, INT64 defaultValue = 0);
+       UINT64 getSubEntryValueAsUInt64(const TCHAR *name, int index = 0, UINT64 defaultValue = 0);
+       bool getSubEntryValueAsBoolean(const TCHAR *name, int index = 0, bool defaultValue = false);
+       bool getSubEntryValueAsUUID(const TCHAR *name, uuid_t uuid, int index = 0);
 
    const TCHAR *getAttribute(const TCHAR *name) { return m_attributes.get(name); }
+       INT32 getAttributeAsInt(const TCHAR *name, INT32 defaultValue = 0);
+       UINT32 getAttributeAsUInt(const TCHAR *name, UINT32 defaultValue = 0);
+       INT64 getAttributeAsInt64(const TCHAR *name, INT64 defaultValue = 0);
+       UINT64 getAttributeAsUInt64(const TCHAR *name, UINT64 defaultValue = 0);
+       bool getAttributeAsBoolean(const TCHAR *name, bool defaultValue = false);
+
    void setAttribute(const TCHAR *name, const TCHAR *value) { m_attributes.set(name, value); }
    void setAttributePreallocated(TCHAR *name, TCHAR *value) { m_attributes.setPreallocated(name, value); }
+   void setAttribute(const TCHAR *name, INT32 value);
+   void setAttribute(const TCHAR *name, UINT32 value);
+   void setAttribute(const TCHAR *name, INT64 value);
+   void setAttribute(const TCHAR *name, UINT64 value);
+   void setAttribute(const TCHAR *name, bool value);
 
        const TCHAR *getFile() { return m_file; }
        int getLine() { return m_line; }
 
        void setName(const TCHAR *name);
 
-       void addValue(const TCHAR *value);
-       void setValue(const TCHAR*value);
-
        ConfigEntry *createEntry(const TCHAR *name);
        ConfigEntry *findEntry(const TCHAR *name);
        ObjectArray<ConfigEntry> *getSubEntries(const TCHAR *mask);
@@ -134,12 +145,12 @@ public:
 
        ConfigEntry *getEntry(const TCHAR *path);
        const TCHAR *getValue(const TCHAR *path, const TCHAR *defaultValue = NULL);
-       INT32 getValueInt(const TCHAR *path, INT32 defaultValue);
-       UINT32 getValueUInt(const TCHAR *path, UINT32 defaultValue);
-       INT64 getValueInt64(const TCHAR *path, INT64 defaultValue);
-       UINT64 getValueUInt64(const TCHAR *path, UINT64 defaultValue);
-       bool getValueBoolean(const TCHAR *path, bool defaultValue);
-       bool getValueUUID(const TCHAR *path, uuid_t uuid);
+       INT32 getValueAsInt(const TCHAR *path, INT32 defaultValue);
+       UINT32 getValueAsUInt(const TCHAR *path, UINT32 defaultValue);
+       INT64 getValueAsInt64(const TCHAR *path, INT64 defaultValue);
+       UINT64 getValueAsUInt64(const TCHAR *path, UINT64 defaultValue);
+       bool getValueAsBoolean(const TCHAR *path, bool defaultValue);
+       bool getValueAsUUID(const TCHAR *path, uuid_t uuid);
        ObjectArray<ConfigEntry> *getSubEntries(const TCHAR *path, const TCHAR *mask);
        ObjectArray<ConfigEntry> *getOrderedSubEntries(const TCHAR *path, const TCHAR *mask);
 
index 3656c81..15880cd 100644 (file)
@@ -586,6 +586,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "devemu", "src\agent\subagen
                {B1745870-F3ED-4ACB-B813-0C4F47EF0793} = {B1745870-F3ED-4ACB-B813-0C4F47EF0793}
        EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "websms", "src\server\smsdrv\websms\websms.vcproj", "{60BB5936-BF12-423F-9276-26F179E9C231}"
+       ProjectSection(ProjectDependencies) = postProject
+               {CB89D905-C8BE-4027-B2D8-F96C245E9160} = {CB89D905-C8BE-4027-B2D8-F96C245E9160}
+               {B1745870-F3ED-4ACB-B813-0C4F47EF0793} = {B1745870-F3ED-4ACB-B813-0C4F47EF0793}
+       EndProjectSection
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Win32 = Debug|Win32
@@ -1354,6 +1360,14 @@ Global
                {BBE9028E-725C-45C6-97C9-BFC443F19DB7}.Release|Win32.Build.0 = Release|Win32
                {BBE9028E-725C-45C6-97C9-BFC443F19DB7}.Release|x64.ActiveCfg = Release|x64
                {BBE9028E-725C-45C6-97C9-BFC443F19DB7}.Release|x64.Build.0 = Release|x64
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Debug|Win32.ActiveCfg = Debug|Win32
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Debug|Win32.Build.0 = Debug|Win32
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Debug|x64.ActiveCfg = Debug|x64
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Debug|x64.Build.0 = Debug|x64
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Release|Win32.ActiveCfg = Release|Win32
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Release|Win32.Build.0 = Release|Win32
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Release|x64.ActiveCfg = Release|x64
+               {60BB5936-BF12-423F-9276-26F179E9C231}.Release|x64.Build.0 = Release|x64
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
@@ -1426,6 +1440,7 @@ Global
                {7D0A15A1-7F6E-480D-9926-13BB6DAA0E10} = {5818CCA9-B585-44B8-B29E-98B1DC278A3C}
                {912783D2-CF6F-4040-B564-4E2436EB0827} = {5818CCA9-B585-44B8-B29E-98B1DC278A3C}
                {60BB5936-BF12-423F-9276-26F179E9C230} = {5818CCA9-B585-44B8-B29E-98B1DC278A3C}
+               {60BB5936-BF12-423F-9276-26F179E9C231} = {5818CCA9-B585-44B8-B29E-98B1DC278A3C}
                {BECC966D-AFC8-48F6-97B1-2FE92062D7B4} = {69EC5B74-D466-422E-B8D1-1386B0421D54}
                {23F22F68-D562-4E80-8267-9F1DD9398357} = {69EC5B74-D466-422E-B8D1-1386B0421D54}
                {169A4446-A035-4CF7-8377-3C517ADF0C50} = {69EC5B74-D466-422E-B8D1-1386B0421D54}
index 572984b..b79418c 100644 (file)
@@ -74,7 +74,7 @@ static int GetPolicyType(uuid_t guid)
 
        _sntprintf(path, 256, POLICY_REGISTRY_PATH _T("/policy-%s/type"), uuid_to_string(guid, buffer));
        Config *registry = OpenRegistry();
-       type = registry->getValueInt(path, -1);
+       type = registry->getValueAsInt(path, -1);
        CloseRegistry(false);
        return type;
 }
@@ -268,7 +268,7 @@ UINT32 GetPolicyInventory(CommSession *session, CSCPMessage *msg)
                        {
                                uuid_parse(&(e->getName()[7]), guid);
                                msg->SetVariable(varId++, guid, UUID_LENGTH);
-                               msg->SetVariable(varId++, (WORD)e->getSubEntryValueInt(_T("type")));
+                               msg->SetVariable(varId++, (WORD)e->getSubEntryValueAsInt(_T("type")));
                                msg->SetVariable(varId++, e->getSubEntryValue(_T("server")));
                        }
                }
index 1944c7a..962d9c9 100644 (file)
@@ -316,7 +316,7 @@ namespace org_netxms_agent
       if ((config != NULL) && (jpath != NULL))
       {
          TCHAR *path = CStringFromJavaString(jenv, jpath);
-         INT32 result = config->getValueInt(path, (INT32)jvalue);
+         INT32 result = config->getValueAsInt(path, (INT32)jvalue);
          free(path);
          return (jint) result;
       }
@@ -334,7 +334,7 @@ namespace org_netxms_agent
       if ((config != NULL) && (jpath != NULL))
       {
          TCHAR *path = CStringFromJavaString(jenv, jpath);
-         INT64 result = config->getValueInt64(path, (long)jvalue);
+         INT64 result = config->getValueAsInt64(path, (long)jvalue);
          free(path);
          return (jlong)result;
       }
@@ -352,7 +352,7 @@ namespace org_netxms_agent
       if ((config != NULL) && (jpath != NULL))
       {
          TCHAR *path = CStringFromJavaString(jenv, jpath);
-         bool result = config->getValueBoolean(path, jvalue ? true : false);
+         bool result = config->getValueAsBoolean(path, jvalue ? true : false);
          free(path);
          return (jboolean) result;
       }
@@ -788,7 +788,7 @@ namespace org_netxms_agent
       {
          return jdefaultValue;
       }
-      return (jint) configEntry->getValueInt((INT32) jindex, (INT32) jdefaultValue);
+      return (jint) configEntry->getValueAsInt((INT32) jindex, (INT32) jdefaultValue);
    }
 
    /*
@@ -803,7 +803,7 @@ namespace org_netxms_agent
       {
          return jdefaultValue;
       }
-      return (jlong) configEntry->getValueInt64((INT32) jindex, (INT64) jdefaultValue);
+      return (jlong) configEntry->getValueAsInt64((INT32) jindex, (INT64) jdefaultValue);
    }
 
    /*
@@ -818,7 +818,7 @@ namespace org_netxms_agent
       {
          return jdefaultValue;
       }
-      return (jboolean)configEntry->getValueBoolean((INT32) jindex, jdefaultValue ? true : false);
+      return (jboolean)configEntry->getValueAsBoolean((INT32) jindex, jdefaultValue ? true : false);
    }
 
    /*
@@ -846,7 +846,7 @@ namespace org_netxms_agent
       if (jname != NULL)
       {
          TCHAR *name = CStringFromJavaString(jenv, jname);
-         jresult = (jint) configEntry->getSubEntryValueInt(name, (int) jindex, (INT32) jdefaultValue );
+         jresult = (jint) configEntry->getSubEntryValueAsInt(name, (int) jindex, (INT32) jdefaultValue );
          free(name);
       }
       return jresult;
@@ -868,7 +868,7 @@ namespace org_netxms_agent
       if (jname != NULL)
       {
          TCHAR *name = CStringFromJavaString(jenv, jname);
-         jresult = (jlong) configEntry->getSubEntryValueInt64(name, (int) jindex, (INT64) jdefaultValue );
+         jresult = (jlong) configEntry->getSubEntryValueAsInt64(name, (int) jindex, (INT64) jdefaultValue );
          free(name);
       }
       return jresult;
@@ -890,7 +890,7 @@ namespace org_netxms_agent
       if (jname != NULL)
       {
          TCHAR *name = CStringFromJavaString(jenv, jname);
-         jresult = (jboolean) configEntry->getSubEntryValueBoolean(name, (int)jindex, jdefaultValue ? true : false);
+         jresult = (jboolean) configEntry->getSubEntryValueAsBoolean(name, (int)jindex, jdefaultValue ? true : false);
          free(name);
       }
       return jresult;
index 68c4504..993aed0 100644 (file)
@@ -52,11 +52,9 @@ static NX_CFG_TEMPLATE m_cfgTemplate[] =
  */
 static size_t OnCurlDataReceived(char *ptr, size_t size, size_t nmemb, void *userdata)
 {
-   // TODO: it assumed that size * nmemb will always fit into size_t
    RequestData *data = (RequestData *)userdata;
    if ((data->allocated - data->size) < (size * nmemb))
    {
-      // TODO: add check for realloc == NULL
       char *newData = (char *)realloc(data->data, data->allocated + CURL_MAX_HTTP_HEADER);
       if (newData == NULL)
       {
@@ -158,6 +156,8 @@ static LONG H_CheckService(const TCHAR *parameters, const TCHAR *arg, TCHAR *val
                   retCode = PC_ERR_CONNECT;
                }
             }
+            safe_free(data->data);
+            free(data);
             curl_easy_cleanup(curl);
          }
          else
@@ -194,7 +194,7 @@ static BOOL SubagentInit(Config *config)
    if (ret)
    {
       AgentWriteDebugLog(3, _T("cURL version: %hs"), curl_version());
-#if HAVE_DECL_CURL_VERSION_INFO
+#if defined(_WIN32) || HAVE_DECL_CURL_VERSION_INFO
       curl_version_info_data *version = curl_version_info(CURLVERSION_NOW);
       char protocols[1024] = {0};
       const char * const *p = version->protocols;
index a1d158e..5fcb5c7 100644 (file)
@@ -29,13 +29,15 @@ enum
        PC_ERR_INTERNAL
 };
 
-
-typedef struct
+/**
+ * Request data for cURL call
+ */
+struct RequestData
 {
    size_t size;
    size_t allocated;
    char *data;
-} RequestData;
+};
 
 #define NETSVC_AF_VERIFYPEER 1
 
index 0f67942..4db2f8d 100644 (file)
@@ -189,7 +189,7 @@ const TCHAR* ConfigEntry::getValue(int index)
 /**
  * Get entry value as integer
  */
-INT32 ConfigEntry::getValueInt(int index, INT32 defaultValue)
+INT32 ConfigEntry::getValueAsInt(int index, INT32 defaultValue)
 {
    const TCHAR *value = getValue(index);
    return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
@@ -198,7 +198,7 @@ INT32 ConfigEntry::getValueInt(int index, INT32 defaultValue)
 /**
  * Get entry value as unsigned integer
  */
-UINT32 ConfigEntry::getValueUInt(int index, UINT32 defaultValue)
+UINT32 ConfigEntry::getValueAsUInt(int index, UINT32 defaultValue)
 {
    const TCHAR *value = getValue(index);
    return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
@@ -207,7 +207,7 @@ UINT32 ConfigEntry::getValueUInt(int index, UINT32 defaultValue)
 /**
  * Get entry value as 64 bit integer
  */
-INT64 ConfigEntry::getValueInt64(int index, INT64 defaultValue)
+INT64 ConfigEntry::getValueAsInt64(int index, INT64 defaultValue)
 {
    const TCHAR *value = getValue(index);
    return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
@@ -216,7 +216,7 @@ INT64 ConfigEntry::getValueInt64(int index, INT64 defaultValue)
 /**
  * Get entry value as 64 bit unsigned integer
  */
-UINT64 ConfigEntry::getValueUInt64(int index, UINT64 defaultValue)
+UINT64 ConfigEntry::getValueAsUInt64(int index, UINT64 defaultValue)
 {
    const TCHAR *value = getValue(index);
    return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
@@ -226,7 +226,7 @@ UINT64 ConfigEntry::getValueUInt64(int index, UINT64 defaultValue)
  * Get entry value as boolean
  * (consider non-zero numerical value or strings "yes", "true", "on" as true)
  */
-bool ConfigEntry::getValueBoolean(int index, bool defaultValue)
+bool ConfigEntry::getValueAsBoolean(int index, bool defaultValue)
 {
    const TCHAR *value = getValue(index);
    if (value != NULL)
@@ -243,7 +243,7 @@ bool ConfigEntry::getValueBoolean(int index, bool defaultValue)
 /**
  * Get entry value as GUID
  */
-bool ConfigEntry::getValueUUID(int index, uuid_t uuid)
+bool ConfigEntry::getValueAsUUID(int index, uuid_t uuid)
 {
    const TCHAR *value = getValue(index);
    if (value != NULL)
@@ -307,37 +307,40 @@ const TCHAR* ConfigEntry::getSubEntryValue(const TCHAR *name, int index, const T
    return (value != NULL) ? value : defaultValue;
 }
 
-INT32 ConfigEntry::getSubEntryValueInt(const TCHAR *name, int index, INT32 defaultValue)
+INT32 ConfigEntry::getSubEntryValueAsInt(const TCHAR *name, int index, INT32 defaultValue)
 {
    const TCHAR *value = getSubEntryValue(name, index);
    return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
 }
 
-UINT32 ConfigEntry::getSubEntryValueUInt(const TCHAR *name, int index, UINT32 defaultValue)
+UINT32 ConfigEntry::getSubEntryValueAsUInt(const TCHAR *name, int index, UINT32 defaultValue)
 {
    const TCHAR *value = getSubEntryValue(name, index);
    return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
 }
 
-INT64 ConfigEntry::getSubEntryValueInt64(const TCHAR *name, int index, INT64 defaultValue)
+INT64 ConfigEntry::getSubEntryValueAsInt64(const TCHAR *name, int index, INT64 defaultValue)
 {
    const TCHAR *value = getSubEntryValue(name, index);
    return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
 }
 
-UINT64 ConfigEntry::getSubEntryValueUInt64(const TCHAR *name, int index, UINT64 defaultValue)
+UINT64 ConfigEntry::getSubEntryValueAsUInt64(const TCHAR *name, int index, UINT64 defaultValue)
 {
    const TCHAR *value = getSubEntryValue(name, index);
    return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
 }
 
-bool ConfigEntry::getSubEntryValueBoolean(const TCHAR *name, int index, bool defaultValue)
+/**
+ * Get sub-entry value as boolean
+ * (consider non-zero numerical value or strings "yes", "true", "on" as true)
+ */
+bool ConfigEntry::getSubEntryValueAsBoolean(const TCHAR *name, int index, bool defaultValue)
 {
    const TCHAR *value = getSubEntryValue(name, index);
    if (value != NULL)
    {
-      return !_tcsicmp(value, _T("yes")) || !_tcsicmp(value, _T("true")) || !_tcsicmp(value, _T("on"))
-         || (_tcstol(value, NULL, 0) != 0);
+      return !_tcsicmp(value, _T("yes")) || !_tcsicmp(value, _T("true")) || !_tcsicmp(value, _T("on")) || (_tcstol(value, NULL, 0) != 0);
    }
    else
    {
@@ -345,7 +348,10 @@ bool ConfigEntry::getSubEntryValueBoolean(const TCHAR *name, int index, bool def
    }
 }
 
-bool ConfigEntry::getSubEntryValueUUID(const TCHAR *name, uuid_t uuid, int index)
+/**
+ * Get sub-entry value as UUID
+ */
+bool ConfigEntry::getSubEntryValueAsUUID(const TCHAR *name, uuid_t uuid, int index)
 {
    const TCHAR *value = getSubEntryValue(name, index);
    if (value != NULL)
@@ -358,6 +364,107 @@ bool ConfigEntry::getSubEntryValueUUID(const TCHAR *name, uuid_t uuid, int index
    }
 }
 
+/**
+ * Get attribute as integer
+ */
+INT32 ConfigEntry::getAttributeAsInt(const TCHAR *name, INT32 defaultValue)
+{
+   const TCHAR *value = getAttribute(name);
+   return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
+}
+
+/**
+ * Get attribute as unsigned integer
+ */
+UINT32 ConfigEntry::getAttributeAsUInt(const TCHAR *name, UINT32 defaultValue)
+{
+   const TCHAR *value = getAttribute(name);
+   return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
+}
+
+/**
+ * Get attribute as 64 bit integer
+ */
+INT64 ConfigEntry::getAttributeAsInt64(const TCHAR *name, INT64 defaultValue)
+{
+   const TCHAR *value = getAttribute(name);
+   return (value != NULL) ? _tcstoll(value, NULL, 0) : defaultValue;
+}
+
+/**
+ * Get attribute as unsigned 64 bit integer
+ */
+UINT64 ConfigEntry::getAttributeAsUInt64(const TCHAR *name, UINT64 defaultValue)
+{
+   const TCHAR *value = getAttribute(name);
+   return (value != NULL) ? _tcstoull(value, NULL, 0) : defaultValue;
+}
+
+/**
+ * Get attribute as boolean
+ * (consider non-zero numerical value or strings "yes", "true", "on" as true)
+ */
+bool ConfigEntry::getAttributeAsBoolean(const TCHAR *name, bool defaultValue)
+{
+   const TCHAR *value = getAttribute(name);
+   if (value != NULL)
+   {
+      return !_tcsicmp(value, _T("yes")) || !_tcsicmp(value, _T("true")) || !_tcsicmp(value, _T("on")) || (_tcstol(value, NULL, 0) != 0);
+   }
+   else
+   {
+      return defaultValue;
+   }
+}
+
+/**
+ * Set attribute
+ */
+void ConfigEntry::setAttribute(const TCHAR *name, INT32 value)
+{
+   TCHAR buffer[64];
+   _sntprintf(buffer, 64, _T("%d"), (int)value);
+   setAttribute(name, buffer);
+}
+
+/**
+ * Set attribute
+ */
+void ConfigEntry::setAttribute(const TCHAR *name, UINT32 value)
+{
+   TCHAR buffer[64];
+   _sntprintf(buffer, 64, _T("%u"), (unsigned int)value);
+   setAttribute(name, buffer);
+}
+
+/**
+ * Set attribute
+ */
+void ConfigEntry::setAttribute(const TCHAR *name, INT64 value)
+{
+   TCHAR buffer[64];
+   _sntprintf(buffer, 64, INT64_FMT, value);
+   setAttribute(name, buffer);
+}
+
+/**
+ * Set attribute
+ */
+void ConfigEntry::setAttribute(const TCHAR *name, UINT64 value)
+{
+   TCHAR buffer[64];
+   _sntprintf(buffer, 64, UINT64_FMT, value);
+   setAttribute(name, buffer);
+}
+
+/**
+ * Set attribute
+ */
+void ConfigEntry::setAttribute(const TCHAR *name, bool value)
+{
+   setAttribute(name, value ? _T("true") : _T("false"));
+}
+
 /**
  * Print config entry
  */
@@ -580,31 +687,31 @@ const TCHAR *Config::getValue(const TCHAR *path, const TCHAR *defaultValue)
    return value;
 }
 
-INT32 Config::getValueInt(const TCHAR *path, INT32 defaultValue)
+INT32 Config::getValueAsInt(const TCHAR *path, INT32 defaultValue)
 {
    const TCHAR *value = getValue(path);
    return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
 }
 
-UINT32 Config::getValueUInt(const TCHAR *path, UINT32 defaultValue)
+UINT32 Config::getValueAsUInt(const TCHAR *path, UINT32 defaultValue)
 {
    const TCHAR *value = getValue(path);
    return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
 }
 
-INT64 Config::getValueInt64(const TCHAR *path, INT64 defaultValue)
+INT64 Config::getValueAsInt64(const TCHAR *path, INT64 defaultValue)
 {
    const TCHAR *value = getValue(path);
    return (value != NULL) ? _tcstol(value, NULL, 0) : defaultValue;
 }
 
-UINT64 Config::getValueUInt64(const TCHAR *path, UINT64 defaultValue)
+UINT64 Config::getValueAsUInt64(const TCHAR *path, UINT64 defaultValue)
 {
    const TCHAR *value = getValue(path);
    return (value != NULL) ? _tcstoul(value, NULL, 0) : defaultValue;
 }
 
-bool Config::getValueBoolean(const TCHAR *path, bool defaultValue)
+bool Config::getValueAsBoolean(const TCHAR *path, bool defaultValue)
 {
    const TCHAR *value = getValue(path);
    if (value != NULL)
@@ -621,7 +728,7 @@ bool Config::getValueBoolean(const TCHAR *path, bool defaultValue)
 /**
  * Get value at given path as UUID
  */
-bool Config::getValueUUID(const TCHAR *path, uuid_t uuid)
+bool Config::getValueAsUUID(const TCHAR *path, uuid_t uuid)
 {
    const TCHAR *value = getValue(path);
    if (value != NULL)
index acc20cf..46a663e 100644 (file)
@@ -41,9 +41,9 @@ NetworkMapElement::NetworkMapElement(UINT32 id, UINT32 flags)
 NetworkMapElement::NetworkMapElement(UINT32 id, Config *config, UINT32 flags)
 {
        m_id = id;
-       m_type = config->getValueInt(_T("/type"), MAP_ELEMENT_GENERIC);
-       m_posX = config->getValueInt(_T("/posX"), 0);
-       m_posY = config->getValueInt(_T("/posY"), 0);
+       m_type = config->getValueAsInt(_T("/type"), MAP_ELEMENT_GENERIC);
+       m_posX = config->getValueAsInt(_T("/posX"), 0);
+       m_posY = config->getValueAsInt(_T("/posY"), 0);
        m_flags = flags;
 }
 
@@ -117,7 +117,7 @@ NetworkMapObject::NetworkMapObject(UINT32 id, UINT32 objectId, UINT32 flags) : N
 
 NetworkMapObject::NetworkMapObject(UINT32 id, Config *config, UINT32 flags) : NetworkMapElement(id, config, flags)
 {
-       m_objectId = config->getValueUInt(_T("/objectId"), 0);
+       m_objectId = config->getValueAsUInt(_T("/objectId"), 0);
 }
 
 
@@ -181,11 +181,11 @@ NetworkMapDecoration::NetworkMapDecoration(UINT32 id, LONG decorationType, UINT3
  */
 NetworkMapDecoration::NetworkMapDecoration(UINT32 id, Config *config, UINT32 flags) : NetworkMapElement(id, config, flags)
 {
-       m_decorationType = config->getValueInt(_T("/decorationType"), 0);
-       m_color = config->getValueUInt(_T("/color"), 0);
+       m_decorationType = config->getValueAsInt(_T("/decorationType"), 0);
+       m_color = config->getValueAsUInt(_T("/color"), 0);
        m_title = _tcsdup(config->getValue(_T("/title"), _T("")));
-       m_width = config->getValueInt(_T("/width"), 0);
-       m_height = config->getValueInt(_T("/height"), 0);
+       m_width = config->getValueAsInt(_T("/width"), 0);
+       m_height = config->getValueAsInt(_T("/height"), 0);
 }
 
 /**
index 9d64545..2f5330a 100644 (file)
@@ -191,9 +191,9 @@ DCItem::DCItem(UINT32 dwId, const TCHAR *szName, int iSource, int iDataType,
 DCItem::DCItem(ConfigEntry *config, Template *owner) : DCObject(config, owner)
 {
    nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
-   m_dataType = (BYTE)config->getSubEntryValueInt(_T("dataType"));
-   m_deltaCalculation = (BYTE)config->getSubEntryValueInt(_T("delta"));
-   m_sampleCount = (BYTE)config->getSubEntryValueInt(_T("samples"));
+   m_dataType = (BYTE)config->getSubEntryValueAsInt(_T("dataType"));
+   m_deltaCalculation = (BYTE)config->getSubEntryValueAsInt(_T("delta"));
+   m_sampleCount = (BYTE)config->getSubEntryValueAsInt(_T("samples"));
    m_dwCacheSize = 0;
    m_ppValueCache = NULL;
    m_tPrevValueTimeStamp = 0;
@@ -201,17 +201,17 @@ DCItem::DCItem(ConfigEntry *config, Template *owner) : DCObject(config, owner)
        m_nBaseUnits = DCI_BASEUNITS_OTHER;
        m_nMultiplier = 1;
        m_customUnitName = NULL;
-       m_snmpRawValueType = (WORD)config->getSubEntryValueInt(_T("snmpRawValueType"));
-       m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueInt(_T("instanceDiscoveryMethod"));
+       m_snmpRawValueType = (WORD)config->getSubEntryValueAsInt(_T("snmpRawValueType"));
+       m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
        const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
        m_instanceDiscoveryData = (value != NULL) ? _tcsdup(value) : NULL;
        m_instanceFilterSource = NULL;
        m_instanceFilter = NULL;
        setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
 
-       if (config->getSubEntryValueInt(_T("allThresholds")))
+       if (config->getSubEntryValueAsInt(_T("allThresholds")))
                m_flags |= DCF_ALL_THRESHOLDS;
-       if (config->getSubEntryValueInt(_T("rawValueInOctetString")))
+       if (config->getSubEntryValueAsInt(_T("rawValueInOctetString")))
                m_flags |= DCF_RAW_VALUE_OCTET_STRING;
 
        ConfigEntry *thresholdsRoot = config->findEntry(_T("thresholds"));
index 7d8e003..922fb8f 100644 (file)
@@ -137,18 +137,18 @@ Threshold::Threshold(ConfigEntry *config, DCItem *parentItem)
    m_targetId = parentItem->getTarget()->Id();
    m_eventCode = EventCodeFromName(config->getSubEntryValue(_T("activationEvent"), 0, _T("SYS_THRESHOLD_REACHED")));
    m_rearmEventCode = EventCodeFromName(config->getSubEntryValue(_T("deactivationEvent"), 0, _T("SYS_THRESHOLD_REARMED")));
-   m_function = (BYTE)config->getSubEntryValueInt(_T("function"), 0, F_LAST);
-   m_operation = (BYTE)config->getSubEntryValueInt(_T("condition"), 0, OP_EQ);
+   m_function = (BYTE)config->getSubEntryValueAsInt(_T("function"), 0, F_LAST);
+   m_operation = (BYTE)config->getSubEntryValueAsInt(_T("condition"), 0, OP_EQ);
    m_dataType = parentItem->getDataType();
        m_value = config->getSubEntryValue(_T("value"), 0, _T(""));
-   m_sampleCount = (config->getSubEntryValue(_T("sampleCount")) != NULL) ? config->getSubEntryValueInt(_T("sampleCount"), 0, 1) : config->getSubEntryValueInt(_T("param1"), 0, 1);
+   m_sampleCount = (config->getSubEntryValue(_T("sampleCount")) != NULL) ? config->getSubEntryValueAsInt(_T("sampleCount"), 0, 1) : config->getSubEntryValueAsInt(_T("param1"), 0, 1);
    m_scriptSource = NULL;
    m_script = NULL;
    const TCHAR *script = config->getSubEntryValue(_T("script"));
    setScript((script != NULL) ? _tcsdup(script) : NULL);
    m_isReached = FALSE;
        m_currentSeverity = SEVERITY_NORMAL;
-       m_repeatInterval = config->getSubEntryValueInt(_T("repeatInterval"), 0, -1);
+       m_repeatInterval = config->getSubEntryValueAsInt(_T("repeatInterval"), 0, -1);
        m_lastEventTimestamp = 0;
        m_numMatches = 0;
 }
index 4837ac3..468a87c 100644 (file)
@@ -154,9 +154,9 @@ DCObject::DCObject(ConfigEntry *config, Template *owner)
        nx_strncpy(m_szName, config->getSubEntryValue(_T("name"), 0, _T("unnamed")), MAX_ITEM_NAME);
    nx_strncpy(m_szDescription, config->getSubEntryValue(_T("description"), 0, m_szName), MAX_DB_STRING);
        nx_strncpy(m_systemTag, config->getSubEntryValue(_T("systemTag"), 0, _T("")), MAX_DB_STRING);
-       m_source = (BYTE)config->getSubEntryValueInt(_T("origin"));
-   m_iPollingInterval = config->getSubEntryValueInt(_T("interval"));
-   m_iRetentionTime = config->getSubEntryValueInt(_T("retention"));
+       m_source = (BYTE)config->getSubEntryValueAsInt(_T("origin"));
+   m_iPollingInterval = config->getSubEntryValueAsInt(_T("interval"));
+   m_iRetentionTime = config->getSubEntryValueAsInt(_T("retention"));
    m_status = ITEM_STATUS_ACTIVE;
    m_busy = 0;
        m_scheduledForDeletion = 0;
@@ -170,7 +170,7 @@ DCObject::DCObject(ConfigEntry *config, Template *owner)
        m_dwProxyNode = 0;
    const TCHAR *perfTabSettings = config->getSubEntryValue(_T("perfTabSettings"));
    m_pszPerfTabSettings = (perfTabSettings != NULL) ? _tcsdup(perfTabSettings) : NULL;
-       m_snmpPort = (WORD)config->getSubEntryValueInt(_T("snmpPort"));
+       m_snmpPort = (WORD)config->getSubEntryValueAsInt(_T("snmpPort"));
    m_dwNumSchedules = 0;
    m_ppScheduleList = NULL;
 
@@ -178,7 +178,7 @@ DCObject::DCObject(ConfigEntry *config, Template *owner)
        m_transformationScript = NULL;
        setTransformationScript(config->getSubEntryValue(_T("transformation")));
    
-       if (config->getSubEntryValueInt(_T("advancedSchedule")))
+       if (config->getSubEntryValueAsInt(_T("advancedSchedule")))
                m_flags |= DCF_ADVANCED_SCHEDULE;
 
        ConfigEntry *schedules = config->findEntry(_T("schedules"));
index b32eb68..a4e191f 100644 (file)
@@ -101,7 +101,7 @@ DCTableColumn::DCTableColumn(DB_RESULT hResult, int row)
 DCTableColumn::DCTableColumn(ConfigEntry *e)
 {
    nx_strncpy(m_name, e->getSubEntryValue(_T("name"), 0, _T("")), MAX_COLUMN_NAME);
-   m_flags = (UINT16)e->getSubEntryValueUInt(_T("flags"));
+   m_flags = (UINT16)e->getSubEntryValueAsUInt(_T("flags"));
    m_displayName = _tcsdup(e->getSubEntryValue(_T("displayName"), 0, _T("")));
 
    const TCHAR *oid = e->getSubEntryValue(_T("snmpOid"));
index d6402e7..78d2245 100644 (file)
@@ -253,7 +253,7 @@ DCTableConditionGroup::DCTableConditionGroup(ConfigEntry *e)
          ConfigEntry *c = conditions->get(i);
          const TCHAR *column = c->getSubEntryValue(_T("column"), 0, _T(""));
          const TCHAR *value = c->getSubEntryValue(_T("value"), 0, _T(""));
-         int op = c->getSubEntryValueInt(_T("operation"));
+         int op = c->getSubEntryValueAsInt(_T("operation"));
                        m_conditions->add(new DCTableCondition(column, op, value));
                }
                delete conditions;
index ed34ce1..d951e97 100644 (file)
@@ -54,8 +54,8 @@ EPRule::EPRule(UINT32 dwId)
 EPRule::EPRule(ConfigEntry *config)
 {
    m_dwId = 0;
-   config->getSubEntryValueUUID(_T("guid"), m_guid);
-   m_dwFlags = config->getSubEntryValueUInt(_T("flags"));
+   config->getSubEntryValueAsUUID(_T("guid"), m_guid);
+   m_dwFlags = config->getSubEntryValueAsUInt(_T("flags"));
    m_dwNumSources = 0;
    m_pdwSourceList = NULL;
    m_dwNumActions = 0;
@@ -78,9 +78,9 @@ EPRule::EPRule(ConfigEntry *config)
    }
 
    m_pszComment = _tcsdup(config->getSubEntryValue(_T("comments"), 0, _T("")));
-   m_iAlarmSeverity = config->getSubEntryValueInt(_T("alarmSeverity"));
-       m_dwAlarmTimeout = config->getSubEntryValueUInt(_T("alarmTimeout"));
-       m_dwAlarmTimeoutEvent = config->getSubEntryValueUInt(_T("alarmTimeout"), 0, EVENT_ALARM_TIMEOUT);
+   m_iAlarmSeverity = config->getSubEntryValueAsInt(_T("alarmSeverity"));
+       m_dwAlarmTimeout = config->getSubEntryValueAsUInt(_T("alarmTimeout"));
+       m_dwAlarmTimeoutEvent = config->getSubEntryValueAsUInt(_T("alarmTimeout"), 0, EVENT_ALARM_TIMEOUT);
    nx_strncpy(m_szAlarmKey, config->getSubEntryValue(_T("alarmKey"), 0, _T("")), MAX_DB_STRING);
    nx_strncpy(m_szAlarmMessage, config->getSubEntryValue(_T("alarmMessage"), 0, _T("")), MAX_DB_STRING);
 
index 3a5dbb7..f4f7549 100644 (file)
@@ -148,7 +148,7 @@ bool ValidateConfig(Config *config, UINT32 flags, TCHAR *errorText, int errorTex
                        ConfigEntry *event = events->get(i);
                        DbgPrintf(6, _T("ValidateConfig(): validating event %s"), event->getSubEntryValue(_T("name"), 0, _T("<unnamed>")));
                
-                       UINT32 code = event->getSubEntryValueUInt(_T("code"));
+                       UINT32 code = event->getSubEntryValueAsUInt(_T("code"));
                        if ((code >= FIRST_USER_EVENT_ID) || (code == 0))
                        {
                                ConfigEntry *e = event->findEntry(_T("name"));
@@ -239,7 +239,7 @@ static UINT32 ImportEvent(ConfigEntry *event)
 
        DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
 
-       UINT32 code = event->getSubEntryValueUInt(_T("code"), 0, 0);
+       UINT32 code = event->getSubEntryValueAsUInt(_T("code"), 0, 0);
        if ((code == 0) || (code >= FIRST_USER_EVENT_ID))
                code = CreateUniqueId(IDG_EVENT);
 
@@ -250,16 +250,16 @@ static UINT32 ImportEvent(ConfigEntry *event)
    if (IsDatabaseRecordExist(hdb, _T("event_cfg"), _T("event_code"), code))
    {
       _sntprintf(query, 8192, _T("UPDATE event_cfg SET event_name=%s,severity=%d,flags=%d,message=%s,description=%s WHERE event_code=%d"),
-                 (const TCHAR *)DBPrepareString(hdb, name), event->getSubEntryValueInt(_T("severity")),
-                                         event->getSubEntryValueInt(_T("flags")), (const TCHAR *)DBPrepareString(hdb, msg),
+                 (const TCHAR *)DBPrepareString(hdb, name), event->getSubEntryValueAsInt(_T("severity")),
+                                         event->getSubEntryValueAsInt(_T("flags")), (const TCHAR *)DBPrepareString(hdb, msg),
                                          (const TCHAR *)DBPrepareString(hdb, descr), code);
    }
    else
    {
       _sntprintf(query, 8192, _T("INSERT INTO event_cfg (event_code,event_name,severity,flags,")
                               _T("message,description) VALUES (%d,%s,%d,%d,%s,%s)"),
-                 code, (const TCHAR *)DBPrepareString(hdb, name), event->getSubEntryValueInt(_T("severity")),
-                                         event->getSubEntryValueInt(_T("flags")), (const TCHAR *)DBPrepareString(hdb, msg),
+                 code, (const TCHAR *)DBPrepareString(hdb, name), event->getSubEntryValueAsInt(_T("severity")),
+                                         event->getSubEntryValueAsInt(_T("flags")), (const TCHAR *)DBPrepareString(hdb, msg),
                                          (const TCHAR *)DBPrepareString(hdb, descr));
    }
        UINT32 rcc = DBQuery(hdb, query) ? RCC_SUCCESS : RCC_DB_FAILURE;
@@ -303,7 +303,7 @@ static UINT32 ImportTrap(ConfigEntry *trap)
                        {
                                ConfigEntry *parameter = parameters->get(i);
 
-                               int position = parameter->getSubEntryValueInt(_T("position"), 0, -1);
+                               int position = parameter->getSubEntryValueAsInt(_T("position"), 0, -1);
                                if (position > 0)
                                {
                                        // Positional parameter
@@ -318,7 +318,7 @@ static UINT32 ImportTrap(ConfigEntry *trap)
                                        tc.pMaps[i].pdwObjectId = (UINT32 *)nx_memdup(temp, sizeof(UINT32) * tc.pMaps[i].dwOidLen);
                                }
                                nx_strncpy(tc.pMaps[i].szDescription, parameter->getSubEntryValue(_T("description"), 0, _T("")), MAX_DB_STRING);
-                               tc.pMaps[i].dwFlags = parameter->getSubEntryValueUInt(_T("flags"), 0, 0);
+                               tc.pMaps[i].dwFlags = parameter->getSubEntryValueAsUInt(_T("flags"), 0, 0);
                        }
                }
                delete parameters;
index 358b9fb..cdc2838 100644 (file)
@@ -82,8 +82,8 @@ Template::Template(ConfigEntry *config) : NetObj()
 
        // Name and version
        nx_strncpy(m_szName, config->getSubEntryValue(_T("name"), 0, _T("Unnamed Template")), MAX_OBJECT_NAME);
-       m_dwVersion = config->getSubEntryValueUInt(_T("version"), 0, 0x00010000);
-       m_flags = config->getSubEntryValueUInt(_T("flags"), 0, 0);
+       m_dwVersion = config->getSubEntryValueAsUInt(_T("version"), 0, 0x00010000);
+       m_flags = config->getSubEntryValueAsUInt(_T("flags"), 0, 0);
 
        // Auto-apply filter
        m_applyFilter = NULL;
index 0f8a774..dc9a9c0 100644 (file)
@@ -8,4 +8,4 @@
 # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
-SUBDIRS = dummy generic nxagent portech
+SUBDIRS = dummy generic nxagent portech ${SMSDRV_DIRS}
index b727e75..93b9c26 100644 (file)
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"
                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
                        >
-                       <File
-                               RelativePath=".\main.h"
-                               >
-                       </File>
                        <File
                                RelativePath="..\..\..\..\include\netxms-version.h"
                                >
index 87c93a0..1fb7270 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <nms_common.h>
 #include <nxsrvapi.h>
-#include <nxdbapi.h>
 #include <nms_util.h>
 
 #ifdef _WIN32
 #define EXPORT
 #endif
 
+/**
+ * Init driver
+ */
 extern "C" BOOL EXPORT SMSDriverInit(const TCHAR *pszInitArgs)
 {
        DbgPrintf(1, _T("Dummy SMS Driver loaded, set debug=6 or higher to see actual messages"));
        return TRUE;
 }
 
+/**
+ * Send SMS
+ */
 extern "C" BOOL EXPORT SMSDriverSend(const TCHAR *pszPhoneNumber, const TCHAR *pszText)
 {
        DbgPrintf(6, _T("DummySMS: phone=\"%s\", text=\"%s\""), pszPhoneNumber, pszText);
    return TRUE;
 }
 
+/**
+ * Unload driver
+ */
 extern "C" void EXPORT SMSDriverUnload()
 {
 }
diff --git a/src/server/smsdrv/websms/Makefile.am b/src/server/smsdrv/websms/Makefile.am
new file mode 100644 (file)
index 0000000..d611fa0
--- /dev/null
@@ -0,0 +1,8 @@
+lib_LTLIBRARIES = libnxsms_websms.la
+libnxsms_websms_la_SOURCES = main.cpp
+libnxsms_websms_la_CPPFLAGS=-I@top_srcdir@/include -I@top_srcdir@/src/server/include
+libnxsms_websms_la_LDFLAGS = -version-info $(NETXMS_LIBRARY_VERSION)
+libnxsms_websms_la_LIBADD = ../../../libnetxms/libnetxms.la ../../libnxsrv/libnxsrv.la -lcurl
+
+EXTRA_DIST = \
+       websms.vcproj
diff --git a/src/server/smsdrv/websms/main.cpp b/src/server/smsdrv/websms/main.cpp
new file mode 100644 (file)
index 0000000..d81c3e3
--- /dev/null
@@ -0,0 +1,236 @@
+/* 
+** NetXMS - Network Management System
+** SMS driver for websms.ru service
+** Copyright (C) 2014 Raden Solutions
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: main.cpp
+**
+**/
+
+#include <nms_common.h>
+#include <nxsrvapi.h>
+#include <nms_util.h>
+#include <curl/curl.h>
+
+#ifdef _WIN32
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+// workaround for older cURL versions
+#define CURL_MAX_HTTP_HEADER CURL_MAX_WRITE_SIZE
+#endif
+
+/**
+ * Request data for cURL call
+ */
+struct RequestData
+{
+   size_t size;
+   size_t allocated;
+   char *data;
+};
+
+/**
+ * Configuration
+ */
+static char s_login[128] = "user";
+static char s_password[128] = "password";
+
+/**
+ * Init driver
+ */
+extern "C" BOOL EXPORT SMSDriverInit(const TCHAR *initArgs)
+{
+   if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
+   {
+      DbgPrintf(1, _T("WebSMS: cURL initialization failed"));
+      return FALSE;
+   }
+
+   DbgPrintf(1, _T("WebSMS: driver loaded"));
+   DbgPrintf(3, _T("cURL version: %hs"), curl_version());
+#if defined(_WIN32) || HAVE_DECL_CURL_VERSION_INFO
+   curl_version_info_data *version = curl_version_info(CURLVERSION_NOW);
+   char protocols[1024] = {0};
+   const char * const *p = version->protocols;
+   while (*p != NULL)
+   {
+      strncat(protocols, *p, strlen(protocols) - 1);
+      strncat(protocols, " ", strlen(protocols) - 1);
+      p++;
+   }
+   DbgPrintf(3, _T("cURL supported protocols: %hs"), protocols);
+#endif
+
+#ifdef UNICODE
+   WCHAR buffer[128];
+
+   ExtractNamedOptionValue(initArgs, _T("login"), buffer, 128);
+   WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, buffer, -1, s_login, 128, NULL, NULL);
+
+   ExtractNamedOptionValue(initArgs, _T("password"), buffer, 128);
+   WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, buffer, -1, s_password, 128, NULL, NULL);
+#else
+   ExtractNamedOptionValue(initArgs, _T("login"), s_login, 128);
+   ExtractNamedOptionValue(initArgs, _T("password"), s_password, 128);
+#endif
+
+       return TRUE;
+}
+
+/**
+ * Callback for processing data received from cURL
+ */
+static size_t OnCurlDataReceived(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+   RequestData *data = (RequestData *)userdata;
+   if ((data->allocated - data->size) < (size * nmemb))
+   {
+      char *newData = (char *)realloc(data->data, data->allocated + CURL_MAX_HTTP_HEADER);
+      if (newData == NULL)
+      {
+         return 0;
+      }
+      data->data = newData;
+      data->allocated += CURL_MAX_HTTP_HEADER;
+   }
+
+   memcpy(data->data + data->size, ptr, size * nmemb);
+   data->size += size * nmemb;
+
+   return size * nmemb;
+}
+
+/**
+ * Send SMS
+ */
+extern "C" BOOL EXPORT SMSDriverSend(const TCHAR *phoneNumber, const TCHAR *text)
+{
+   BOOL success = FALSE;
+
+       DbgPrintf(4, _T("WebSMS: phone=\"%s\", text=\"%s\""), phoneNumber, text);
+
+   CURL *curl = curl_easy_init();
+   if (curl != NULL)
+   {
+#if HAVE_DECL_CURLOPT_NOSIGNAL
+      curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
+#endif
+
+      curl_easy_setopt(curl, CURLOPT_HEADER, (long)0); // do not include header in data
+      curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
+      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &OnCurlDataReceived);
+      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+
+      RequestData *data = (RequestData *)malloc(sizeof(RequestData));
+      memset(data, 0, sizeof(RequestData));
+      curl_easy_setopt(curl, CURLOPT_WRITEDATA, data);
+
+#ifdef UNICODE
+      char *mbphone = MBStringFromWideString(phoneNumber);
+      char *mbmsg = MBStringFromWideString(text);
+      char *phone = curl_easy_escape(curl, mbphone, 0);
+      char *msg = curl_easy_escape(curl, mbmsg, 0);
+      free(mbphone);
+      free(mbmsg);
+#else
+      char *phone = curl_easy_escape(curl, phoneNumber, 0);
+      char *msg = curl_easy_escape(curl, text, 0);
+#endif
+
+      char url[4096];
+      snprintf(url, 4096, "https://websms.ru/http_in5.asp?http_username=%s&http_password=%s&phone_list=%s&format=xml&message=%s", s_login, s_password, phone, msg);
+      DbgPrintf(4, _T("WebSMS: URL set to \"%hs\""), url);
+
+      curl_free(phone);
+      curl_free(msg);
+
+      if (curl_easy_setopt(curl, CURLOPT_URL, url) == CURLE_OK)
+      {
+         if (curl_easy_perform(curl) == CURLE_OK)
+         {
+            DbgPrintf(4, _T("WebSMS: %d bytes received"), data->size);
+            if (data->allocated > 0)
+            {
+               data->data[data->size] = 0;
+
+               Config *response = new Config;
+               response->loadXmlConfigFromMemory(data->data, (int)strlen(data->data), _T("WEBSMS"), "XML");
+               ConfigEntry *e = response->getEntry(_T("/httpIn"));
+               if (e != NULL)
+               {
+                  int status = e->getAttributeAsInt(_T("error_num"), -1);
+                  if (status == 0)
+                  {
+                     DbgPrintf(4, _T("WebSMS: SMS successfully sent"));
+                     success = TRUE;
+                  }
+                  else
+                  {
+                     DbgPrintf(4, _T("WebSMS: send error %d"), status);
+                  }
+               }
+               else
+               {
+                  DbgPrintf(4, _T("WebSMS: malformed response\n%hs"), data->data);
+               }
+            }
+         }
+         else
+         {
+               DbgPrintf(4, _T("WebSMS: call to curl_easy_perform() failed"));
+         }
+      }
+      else
+      {
+       DbgPrintf(4, _T("WebSMS: call to curl_easy_setopt(CURLOPT_URL) failed"));
+      }
+      safe_free(data->data);
+      free(data);
+      curl_easy_cleanup(curl);
+   }
+   else
+   {
+       DbgPrintf(4, _T("WebSMS: call to curl_easy_init() failed"));
+   }
+
+   return success;
+}
+
+/**
+ * Unload driver
+ */
+extern "C" void EXPORT SMSDriverUnload()
+{
+}
+
+#ifdef _WIN32
+
+/**
+ * DLL Entry point
+ */
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+       if (dwReason == DLL_PROCESS_ATTACH)
+               DisableThreadLibraryCalls(hInstance);
+       return TRUE;
+}
+
+#endif
similarity index 92%
copy from src/server/smsdrv/dummy/dummy.vcproj
copy to src/server/smsdrv/websms/websms.vcproj
index b727e75..cbcb197 100644 (file)
@@ -2,9 +2,9 @@
 <VisualStudioProject
        ProjectType="Visual C++"
        Version="8.00"
-       Name="dummy"
-       ProjectGUID="{60BB5936-BF12-423F-9276-26F179E9C230}"
-       RootNamespace="dummy"
+       Name="websms"
+       ProjectGUID="{60BB5936-BF12-423F-9276-26F179E9C231}"
+       RootNamespace="websms"
        Keyword="Win32Proj"
        >
        <Platforms>
@@ -44,7 +44,7 @@
                                Name="VCCLCompilerTool"
                                Optimization="0"
                                AdditionalIncludeDirectories="..\..\..\..\include;..\..\include"
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DUMMY_EXPORTS"
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSMS_EXPORTS"
                                MinimalRebuild="true"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="3"
@@ -64,6 +64,7 @@
                        />
                        <Tool
                                Name="VCLinkerTool"
+                               AdditionalDependencies="libcurl.lib"
                                OutputFile="$(OutDir)\$(ProjectName).sms"
                                LinkIncremental="2"
                                GenerateDebugInformation="true"
                                Name="VCCLCompilerTool"
                                Optimization="0"
                                AdditionalIncludeDirectories="..\..\..\..\include;..\..\include"
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DUMMY_EXPORTS"
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSMS_EXPORTS"
                                MinimalRebuild="true"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="3"
                        />
                        <Tool
                                Name="VCLinkerTool"
+                               AdditionalDependencies="libcurl.lib"
                                OutputFile="$(OutDir)\$(ProjectName).sms"
                                LinkIncremental="2"
                                GenerateDebugInformation="true"
                        <Tool
                                Name="VCCLCompilerTool"
                                AdditionalIncludeDirectories="..\..\..\..\include;..\..\include"
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;DUMMY_EXPORTS"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSMS_EXPORTS"
                                RuntimeLibrary="2"
                                UsePrecompiledHeader="0"
                                WarningLevel="3"
                        />
                        <Tool
                                Name="VCLinkerTool"
+                               AdditionalDependencies="libcurl.lib"
                                OutputFile="$(OutDir)\$(ProjectName).sms"
                                LinkIncremental="1"
                                GenerateDebugInformation="true"
                        <Tool
                                Name="VCCLCompilerTool"
                                AdditionalIncludeDirectories="..\..\..\..\include;..\..\include"
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;DUMMY_EXPORTS"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSMS_EXPORTS"
                                RuntimeLibrary="2"
                                UsePrecompiledHeader="0"
                                WarningLevel="3"
                        />
                        <Tool
                                Name="VCLinkerTool"
+                               AdditionalDependencies="libcurl.lib"
                                OutputFile="$(OutDir)\$(ProjectName).sms"
                                LinkIncremental="1"
                                GenerateDebugInformation="true"
                        Filter="h;hpp;hxx;hm;inl;inc;xsd"
                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
                        >
-                       <File
-                               RelativePath=".\main.h"
-                               >
-                       </File>
                        <File
                                RelativePath="..\..\..\..\include\netxms-version.h"
                                >