# # # patch "Makefile" # from [5bacfbec95253efd5cb7fc5dfda52cf15a6efde6] # to [3147afbcc39c6b212cd75483bdd3abb67436c3d3] # # patch "README" # from [ae9a3c17baebaaa0b13ba1cf3e6f6581fc78fbf9] # to [2a7eac09189238d777b069ee9c3a13e6c280414f] # # patch "hostconfig.dist" # from [02f756cead9359b3d5c3730c840c4deff4ebf344] # to [637eec02af474adccd53780f74cdd6dd364765f3] # # patch "usher.cc" # from [302a743841e9c811a94d383359b9a53e55900042] # to [267d6aeb1e056e70d60446c997edb39dd32bce8d] # ============================================================ --- Makefile 5bacfbec95253efd5cb7fc5dfda52cf15a6efde6 +++ Makefile 3147afbcc39c6b212cd75483bdd3abb67436c3d3 @@ -1,9 +1,13 @@ .PHONY: all install all: usher.webhost: usher.cc +ifeq ($(DB),odbc) + g++ usher.cc -DUSE_ODBC -o usher.webhost -g -Wall `odbc_config --cflags --libs` +else g++ usher.cc -o usher.webhost -g -Wall `pkg-config libpqxx --cflags --libs` +endif install: ./install ============================================================ --- README ae9a3c17baebaaa0b13ba1cf3e6f6581fc78fbf9 +++ README 2a7eac09189238d777b069ee9c3a13e6c280414f @@ -1,9 +1,14 @@ Install ------- -Make sure you have postgresql, libpqxx, php-pgsql, mod_python, and mod_php. +Make sure you have mod_python and mod_php. +The postgres backend needs postgresql, libpqxx and php-pgsql. -make usher.webhost +do either + make usher.webhost +to build usher with direct postgresql support, or + make usher.webhost DB=odbc +to build usher with odbc support make install ============================================================ --- hostconfig.dist 02f756cead9359b3d5c3730c840c4deff4ebf344 +++ hostconfig.dist 637eec02af474adccd53780f74cdd6dd364765f3 @@ -1,6 +1,7 @@ userpass "username" "password" adodb_path "/usr/share/adodb/adodb.inc.php" dbstring "postgres://DBUSER:address@hidden/DBNAME" +odbc_dsn "ODBCDSN" admin "127.0.0.5:12345" hostkey "address@hidden" ============================================================ --- usher.cc 302a743841e9c811a94d383359b9a53e55900042 +++ usher.cc 267d6aeb1e056e70d60446c997edb39dd32bce8d @@ -84,7 +84,12 @@ #include #include +#if defined(USE_ODBC) +#include +#include +#else #include +#endif #include @@ -105,6 +110,7 @@ string hostname; string project_dir; string dbstring; +string odbcdsn; // defaults, overridden by command line int listenport = 4691; @@ -141,6 +147,135 @@ errstr(std::string const & s, int e): name(s), err(e) {} }; +#if defined(USE_ODBC) + +class UsherODBC +{ +public: + + UsherODBC(): + henv(0), + hdbc(0), + connected(false) + { + } + + ~UsherODBC() + { + if (connected) + { + SQLDisconnect(hdbc); + SQLFreeConnect(hdbc); + SQLFreeEnv(henv); + } + } + + set get_project_names(string const & user, + string const & pass, + string const & host, + string const & db, + string const & dsn) + { + set names; + if (!connect(user,pass,host,db,dsn)) + return names; + + SQLHSTMT hstmt; + if (error(SQLAllocStmt(hdbc, &hstmt))) + { + cerr << "SQLAllocStmt failed \n"; + return names; + } + + SQLRETURN res = SQLExecDirect(hstmt, (SQLCHAR *)"SELECT name FROM projects", SQL_NTS); + if (error(res) && SQL_NO_DATA!=res) + { + cerr << "SQLExecDirect failed \n"; + SQLFreeStmt(hstmt, SQL_DROP); + return names; + } + + char pname[1024]; + SQLLEN nullind; + if (error(SQLBindCol(hstmt, 1, SQL_C_CHAR, pname, sizeof(pname), &nullind))) + { + cerr << "SQLBindCol failed \n"; + SQLFreeStmt(hstmt, SQL_DROP); + return names; + } + + while ( !error(SQLFetch(hstmt))) + names.insert(pname); + + SQLFreeStmt(hstmt, SQL_DROP); + return names; + } + + +private: + + static inline bool error(SQLRETURN retcode) + { + // for us, SQL_NO_DATA is also considered an error + return retcode != SQL_SUCCESS && + retcode != SQL_SUCCESS_WITH_INFO; + } + + bool connect(string const & user, + string const & pass, + string const & host, + string const & db, + string const & dsn) + { + if (connected) + return true; + + if (error(SQLAllocEnv(&henv))) + { + cerr << "SQLAllocEnv failed \n"; + return false; + } + + if (error(SQLAllocConnect(henv,&hdbc))) + { + cerr << "SQLAllocConnect failed \n"; + SQLFreeEnv(henv); + return false; + } + + string fulldsn("DRIVER="); + fulldsn += dsn + ";"; + fulldsn += "UID="+user+ ";"; + fulldsn += "PWD="+pass+ ";"; + fulldsn += "SERVER="+host+ ";"; + fulldsn += "DATABASE="+db+ ";"; + + SQLCHAR buf[1024]; + SQLSMALLINT olen; + if (error(SQLDriverConnect(hdbc, NULL, + (SQLCHAR *)fulldsn.c_str(), SQL_NTS, + buf, sizeof(buf), + &olen, + SQL_DRIVER_NOPROMPT))) + { + cerr << "SQLDriverConnect failed \n"; + SQLFreeConnect(hdbc); + SQLFreeEnv(henv); + return false; + } + + connected = true; + return true; + } + +private: + SQLHENV henv; + SQLHDBC hdbc; + bool connected; +}; + +#else + set get_project_names_postgres(string const & user, string const & pass, string const & host, @@ -177,6 +312,7 @@ w.commit(); return names; } +#endif // dbstring looks like: // $driver://$username:address@hidden/$database?options[=value] @@ -219,11 +355,16 @@ } } +#if defined(USE_ODBC) + UsherODBC uodb; + return uodb.get_project_names(user, pass, host, db, odbcdsn); +#else if (driver == "postgres") return get_project_names_postgres(user, pass, host, db, opts); - + std::cerr<<"Confusing db string.\n"; return set(); +#endif } int tosserr(int ret, std::string const & name) @@ -1422,6 +1563,9 @@ done = true; } + + + administrator admin; sock h(-1); void reload_conffile(string const & file) @@ -1446,6 +1590,8 @@ project_dir = readtok(cf).s; } else if(tok.s == "dbstring") { dbstring = readtok(cf).s; + } else if(tok.s == "odbc_driver") { + odbcdsn = readtok(cf).s; } else if(tok.s == "admin") { admin.initialize(readtok(cf).s); } else if(tok.s == "listen") {