From 60bf9a139fd8cc0948bcf11d4fbcfab5cd9e0641 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 10 Sep 2012 17:08:29 -0500 Subject: [PATCH] Reactivate openvpn plugin --- .../src/tdenetman-pluginmanager.cpp | 45 +++--- .../src/tdenetman-vpnservice.cpp | 8 +- tdenetworkmanager/vpn-plugins/CMakeLists.txt | 2 +- tdenetworkmanager/vpn-plugins/openvpn/AUTHORS | 1 + .../vpn-plugins/openvpn/CMakeLists.txt | 14 ++ .../vpn-plugins/openvpn/src/CMakeLists.txt | 43 ++++++ ...ager-openvpn.cpp => tdenetman-openvpn.cpp} | 133 +++++++++++------- ...kmanager-openvpn.h => tdenetman-openvpn.h} | 20 +-- ...nvpn.desktop => tdenetman_openvpn.desktop} | 8 +- 9 files changed, 183 insertions(+), 91 deletions(-) create mode 100644 tdenetworkmanager/vpn-plugins/openvpn/CMakeLists.txt create mode 100644 tdenetworkmanager/vpn-plugins/openvpn/src/CMakeLists.txt rename tdenetworkmanager/vpn-plugins/openvpn/src/{knetworkmanager-openvpn.cpp => tdenetman-openvpn.cpp} (78%) rename tdenetworkmanager/vpn-plugins/openvpn/src/{knetworkmanager-openvpn.h => tdenetman-openvpn.h} (79%) rename tdenetworkmanager/vpn-plugins/openvpn/{knetworkmanager_openvpn.desktop => tdenetman_openvpn.desktop} (75%) diff --git a/tdenetworkmanager/src/tdenetman-pluginmanager.cpp b/tdenetworkmanager/src/tdenetman-pluginmanager.cpp index a5dfce9..0dad6ad 100644 --- a/tdenetworkmanager/src/tdenetman-pluginmanager.cpp +++ b/tdenetworkmanager/src/tdenetman-pluginmanager.cpp @@ -33,8 +33,9 @@ PluginManager* PluginManager::_instance; PluginManager* PluginManager::getInstance() { - if (_instance) + if (_instance) { return _instance; + } return new PluginManager(TQT_TQOBJECT(TDENetworkManager::getInstance()), "pluginmanager"); } @@ -45,22 +46,21 @@ PluginManager::PluginManager(TQObject* parent, const char* name) this->_plugins = KPluginInfo::fromServices( KTrader::self()->query( TQString::fromLatin1( "TDENetworkManager/Plugin" ))); // a bit debug output - for(TQValueList::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) + for(TQValueList::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) { kdDebug() << k_funcinfo << TQString("Found Plugin '%1'").arg((*it)->pluginName()) << endl; + } } PluginManager::~PluginManager() { // delete all loaded plugins - while(!_loadedPlugins.empty()) - { + while(!_loadedPlugins.empty()) { PluginMap::Iterator it = _loadedPlugins.begin(); _loadedPlugins.remove(it); } // delete all available plugininfos - while(!_plugins.empty()) - { + while(!_plugins.empty()) { TQValueList::Iterator it = _plugins.begin(); delete *it; _plugins.remove(it); @@ -71,11 +71,12 @@ TQStringList PluginManager::getPluginList(const TQString& serviceType, const TQS { TQStringList ret; // find a suitable plugin - for(TQValueList::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) - { - if ((*it)->service()->serviceTypes().contains(serviceType) > 0) - if ((*it)->property(property).toString().contains(value)) + for(TQValueList::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) { + if ((*it)->service()->serviceTypes().contains(serviceType) > 0) { + if ((*it)->property(property).toString().contains(value)) { ret.append( (*it)->pluginName() ); + } + } } return ret; } @@ -83,12 +84,10 @@ TQStringList PluginManager::getPluginList(const TQString& serviceType, const TQS Plugin* PluginManager::getPlugin(const TQString& pluginID) { KPluginInfo* info = infoForPluginID(pluginID); - if (_loadedPlugins.contains(info)) - { + if (_loadedPlugins.contains(info)) { return _loadedPlugins[info]; } - else - { + else { return loadPlugin(pluginID); } return NULL; @@ -101,8 +100,7 @@ const KPluginInfo* PluginManager::getPluginInfo(const TQString& pluginID) const KPluginInfo* PluginManager::getPluginInfo(const Plugin* plugin) { - for(PluginMap::ConstIterator it = _loadedPlugins.begin(); it != _loadedPlugins.end(); ++it) - { + for(PluginMap::ConstIterator it = _loadedPlugins.begin(); it != _loadedPlugins.end(); ++it) { if (it.data() == plugin) return it.key(); } @@ -112,8 +110,7 @@ const KPluginInfo* PluginManager::getPluginInfo(const Plugin* plugin) void PluginManager::loadAllPlugins() { // iterate over all plugins - for(TQValueList::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) - { + for(TQValueList::ConstIterator it = _plugins.begin(); it != _plugins.end(); ++it) { // load Plugin loadPlugin((*it)->pluginName()); } @@ -129,13 +126,11 @@ Plugin* PluginManager::loadPlugin(const TQString& pluginID) TQString::fromLatin1( "[X-TDE-PluginInfo-Name]=='%1'" ).arg( pluginID ), this, 0, TQStringList(), &error ); // plugin loaded? - if (plugin) - { + if (plugin) { kdDebug() << k_funcinfo << TQString(i18n("successfully loaded plugin '%1'")).arg(info->pluginName()) << endl; _loadedPlugins.insert(info, plugin); } - else - { + else { // error switch( error ) { @@ -172,10 +167,10 @@ Plugin* PluginManager::loadPlugin(const TQString& pluginID) KPluginInfo * PluginManager::infoForPluginID( const TQString& pluginID ) const { TQValueList::ConstIterator it; - for ( it = this->_plugins.begin(); it != this->_plugins.end(); ++it ) - { - if ( ( *it )->pluginName() == pluginID ) + for ( it = this->_plugins.begin(); it != this->_plugins.end(); ++it ) { + if ( ( *it )->pluginName() == pluginID ) { return *it; + } } return 0L; diff --git a/tdenetworkmanager/src/tdenetman-vpnservice.cpp b/tdenetworkmanager/src/tdenetman-vpnservice.cpp index b2643cf..d97cf82 100644 --- a/tdenetworkmanager/src/tdenetman-vpnservice.cpp +++ b/tdenetworkmanager/src/tdenetman-vpnservice.cpp @@ -54,12 +54,10 @@ VPNService::VPNService(const TQString& serviceName, const TQString& service, TQO // query if a plugin for this vpn service is available PluginManager* plugMan = PluginManager::getInstance(); - if (plugMan) - { + if (plugMan) { TQStringList list = plugMan->getPluginList("TDENetworkManager/VPNPlugin", "X-NetworkManager-Services", serviceName); - if (list.size() > 0) - { - // get the first VPN Plugin handling our VPNService + if (list.size() > 0) { + // get the first VPN Plugin handling our VPNService VPNPlugin* vpnPlugin = dynamic_cast( plugMan->getPlugin(list.first()) ); if (vpnPlugin) { diff --git a/tdenetworkmanager/vpn-plugins/CMakeLists.txt b/tdenetworkmanager/vpn-plugins/CMakeLists.txt index 6e10d60..2643aad 100644 --- a/tdenetworkmanager/vpn-plugins/CMakeLists.txt +++ b/tdenetworkmanager/vpn-plugins/CMakeLists.txt @@ -9,7 +9,7 @@ # ################################################# -# add_subdirectory( openvpn ) +add_subdirectory( openvpn ) add_subdirectory( pptp ) # add_subdirectory( strongswan ) add_subdirectory( vpnc ) diff --git a/tdenetworkmanager/vpn-plugins/openvpn/AUTHORS b/tdenetworkmanager/vpn-plugins/openvpn/AUTHORS index f4340ea..d61cb52 100644 --- a/tdenetworkmanager/vpn-plugins/openvpn/AUTHORS +++ b/tdenetworkmanager/vpn-plugins/openvpn/AUTHORS @@ -1,2 +1,3 @@ +Timothy Pearson Helmut Schaa , Thomas Kallenberg diff --git a/tdenetworkmanager/vpn-plugins/openvpn/CMakeLists.txt b/tdenetworkmanager/vpn-plugins/openvpn/CMakeLists.txt new file mode 100644 index 0000000..2646dbb --- /dev/null +++ b/tdenetworkmanager/vpn-plugins/openvpn/CMakeLists.txt @@ -0,0 +1,14 @@ +################################################# +# +# (C) 2012 Timothy Pearson +# kb9vqf (AT) pearsoncomputing.net +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( src ) + +install( FILES tdenetman_openvpn.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) diff --git a/tdenetworkmanager/vpn-plugins/openvpn/src/CMakeLists.txt b/tdenetworkmanager/vpn-plugins/openvpn/src/CMakeLists.txt new file mode 100644 index 0000000..a565251 --- /dev/null +++ b/tdenetworkmanager/vpn-plugins/openvpn/src/CMakeLists.txt @@ -0,0 +1,43 @@ +################################################# +# +# (C) 2012 Timothy Pearson +# kb9vqf (AT) pearsoncomputing.net +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( -UQT_NO_ASCII_CAST ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/tdenetworkmanager/src/settings + ${CMAKE_SOURCE_DIR}/tdenetworkmanager/src/configwidgets + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${DBUS_TQT_INCLUDE_DIRS} + ${NM_UTIL_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + +##### tdenetman_openvpn (module) ################ + +set( target tdenetman_openvpn ) + +set( ${target}_SRCS + tdenetman-openvpn.cpp + openvpnprop.ui + openvpnauth.ui +) + +tde_add_kpart( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK tdeinit_kded-shared tdeinit_tdenetworkmanager-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/tdenetworkmanager/vpn-plugins/openvpn/src/knetworkmanager-openvpn.cpp b/tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.cpp similarity index 78% rename from tdenetworkmanager/vpn-plugins/openvpn/src/knetworkmanager-openvpn.cpp rename to tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.cpp index ad27368..7cee87a 100644 --- a/tdenetworkmanager/vpn-plugins/openvpn/src/knetworkmanager-openvpn.cpp +++ b/tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.cpp @@ -36,12 +36,11 @@ #include #include #include -#include -#include "knetworkmanager-openvpn.h" +#include "tdenetman-openvpn.h" typedef KGenericFactory OpenVPNPluginFactory; -K_EXPORT_COMPONENT_FACTORY( knetworkmanager_openvpn, OpenVPNPluginFactory("knetworkmanager_openvpn")); +K_EXPORT_COMPONENT_FACTORY( tdenetman_openvpn, OpenVPNPluginFactory("tdenetman_openvpn")); /************************************ * OpenVPNPlugin @@ -177,21 +176,23 @@ void OpenVPNConfig::getCipherModes() { // get all possible cipher modes TQString openvpn = findOpenVPNBinary(); - if (!openvpn.isNull()) - { + if (!openvpn.isNull()) { KProcess* cipherHelper = new KProcess(); cipherHelper->setUseShell(true, "/bin/sh"); *cipherHelper << TQString::fromLatin1("%1 --show-ciphers | awk '/^[A-Z][A-Z0-9]+-/ { print $1 }'").arg(openvpn); connect (cipherHelper, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(receiveCipherData(KProcess*, char*, int))); kdDebug() << "starting openvpn to get cipher modes" << endl; - if (!cipherHelper->start(KProcess::Block, KProcess::Stdout)) + if (!cipherHelper->start(KProcess::Block, KProcess::Stdout)) { kdDebug() << "error starting openvpn" << endl; + } } - } -void OpenVPNConfig::setVPNData(const TQStringList& routes, const TQMap& properties) +void OpenVPNConfig::setVPNData(TDENetworkSingleRouteConfigurationList& routes, TDENetworkSettingsMap& properties, TDENetworkSettingsMap& secrets) { + m_vpnProperties = properties; + m_vpnSecrets = secrets; + // fill up our inputfields for(TQMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) { @@ -283,63 +284,98 @@ void OpenVPNConfig::setVPNData(const TQStringList& routes, const TQMapchkIPAdresses->setChecked(true); - _openvpnWidget->routes->setText(routes.join(" ")); + TQStringList routesText; + for (TDENetworkSingleRouteConfigurationList::Iterator it = routes.begin(); it != routes.end(); ++it) { + routesText.append(TQString("%1/%2").arg((*it).ipAddress.toString()).arg((*it).networkMask.toCIDRMask())); + } + _openvpnWidget->routes->setText(routesText.join(" ")); } } -TQMapOpenVPNConfig::getVPNProperties() +TDENetworkSettingsMap OpenVPNConfig::getVPNProperties() { - // build a StingList of properties - TQMap strlist; - - strlist.insert("connection-type", TQString::number(OpenVPNConnectionType::mapConnectionType2String((OpenVPNConnectionType::CONNECTIONTYPE)_openvpnWidget->cboConnectionType->currentItem()))); - strlist.insert("remote", TQString(_openvpnWidget->gateway->text())); + // Build a list of properties + m_vpnProperties.insert("connection-type", TQString::number(OpenVPNConnectionType::mapConnectionType2String((OpenVPNConnectionType::CONNECTIONTYPE)_openvpnWidget->cboConnectionType->currentItem()))); + m_vpnProperties.insert("remote", TQString(_openvpnWidget->gateway->text())); // port is not necessary - if (!_openvpnWidget->port->text().isEmpty() && !_openvpnWidget->chkDefaultPort->isChecked()) - strlist.insert("port", _openvpnWidget->port->text()); + if (!_openvpnWidget->port->text().isEmpty() && !_openvpnWidget->chkDefaultPort->isChecked()) { + m_vpnProperties.insert("port", _openvpnWidget->port->text()); + } + else { + m_vpnProperties.remove("port"); + } - strlist.insert("ca", TQString(_openvpnWidget->editCA->url())); - strlist.insert("cert",TQString(_openvpnWidget->editCert->url() )); - strlist.insert("key", TQString(_openvpnWidget->editKey->url())); + m_vpnProperties.insert("ca", TQString(_openvpnWidget->editCA->url())); + m_vpnProperties.insert("cert",TQString(_openvpnWidget->editCert->url() )); + m_vpnProperties.insert("key", TQString(_openvpnWidget->editKey->url())); - if (_openvpnWidget->chkUseCipher->isChecked()) - strlist.insert("cipher", TQString(_openvpnWidget->cboCipher->currentText())); + if (_openvpnWidget->chkUseCipher->isChecked()) { + m_vpnProperties.insert("cipher", TQString(_openvpnWidget->cboCipher->currentText())); + } + else { + m_vpnProperties.remove("cipher"); + } - if (_openvpnWidget->chkUseLZO->isChecked()) - strlist.insert("comp-lzo", TQString("true")); - else - strlist.insert("comp-lzo", TQString("false")); + if (_openvpnWidget->chkUseLZO->isChecked()) { + m_vpnProperties.insert("comp-lzo", TQString("true")); + } + else { + m_vpnProperties.insert("comp-lzo", TQString("false")); + } - strlist.insert("static-key", TQString(_openvpnWidget->editSharedKey->url())); - strlist.insert("username", TQString(_openvpnWidget->editUsername->text())); - strlist.insert("local-ip", TQString(_openvpnWidget->editLocalIP->text())); - strlist.insert("remote-ip", TQString(_openvpnWidget->editRemoteIP->text())); + m_vpnProperties.insert("static-key", TQString(_openvpnWidget->editSharedKey->url())); + m_vpnProperties.insert("username", TQString(_openvpnWidget->editUsername->text())); + m_vpnProperties.insert("local-ip", TQString(_openvpnWidget->editLocalIP->text())); + m_vpnProperties.insert("remote-ip", TQString(_openvpnWidget->editRemoteIP->text())); if (_openvpnWidget->chkUseTAP->isChecked()) { - strlist.insert("tap-dev", "true"); - strlist.insert("proto-tcp", "true"); - } else { - strlist.insert("tap-dev", "false"); - strlist.insert("proto-tcp", "false"); + m_vpnProperties.insert("tap-dev", "true"); + m_vpnProperties.insert("proto-tcp", "true"); + } + else { + m_vpnProperties.insert("tap-dev", "false"); + m_vpnProperties.insert("proto-tcp", "false"); + } + + if (_openvpnWidget->chkUseTLS->isChecked()) { + m_vpnProperties.insert("ta", TQString(_openvpnWidget->editTLSAuth->url())); + } + else { + m_vpnProperties.remove("ta"); } - if (_openvpnWidget->chkUseTLS->isChecked()) - strlist.insert("ta", TQString(_openvpnWidget->editTLSAuth->url())); + m_vpnProperties.insert("ta-dir", TQString(_openvpnWidget->cboDirection->currentText())); + + return m_vpnProperties; +} - strlist.insert("ta-dir", TQString(_openvpnWidget->cboDirection->currentText())); +TDENetworkSettingsMap OpenVPNConfig::getVPNSecrets() { + // Build a list of secrets + // FIXME - return strlist; + return m_vpnSecrets; } -TQStringList OpenVPNConfig::getVPNRoutes() +TDENetworkSingleRouteConfigurationList OpenVPNConfig::getVPNRoutes() { + TDENetworkSingleRouteConfigurationList ret; TQStringList strlist; - if(_openvpnWidget->chkIPAdresses->isChecked()) - { + if(_openvpnWidget->chkIPAdresses->isChecked()) { strlist = TQStringList::split(" ", _openvpnWidget->routes->text()); } - return strlist; + + for (TQStringList::Iterator it = strlist.begin(); it != strlist.end(); ++it) { + TQStringList pieces = TQStringList::split("/", (*it)); + TDENetworkSingleRouteConfiguration routeconfig; + routeconfig.ipAddress.setAddress(pieces[0]); + if (pieces.count() > 1) { + routeconfig.networkMask.fromCIDRMask(pieces[1].toUInt()); + } + ret.append(routeconfig); + } + + return ret; } bool OpenVPNConfig::hasChanged() @@ -526,7 +562,7 @@ OpenVPNAuthentication::~OpenVPNAuthentication() } -void OpenVPNAuthentication::setVPNData(const TQStringList& /*routes*/, const TQMap& properties) +void OpenVPNAuthentication::setVPNData(TDENetworkSingleRouteConfigurationList& /*routes*/, TDENetworkSettingsMap& properties, TDENetworkSettingsMap& secrets) { // find the connection type property for(TQMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) @@ -539,7 +575,7 @@ void OpenVPNAuthentication::setVPNData(const TQStringList& /*routes*/, const TQM } } -TQMap OpenVPNAuthentication::getPasswords() +TDENetworkSettingsMap OpenVPNAuthentication::getPasswords() { TQMap pwds; if ((_connectionType == OpenVPNConnectionType::PASSWORD) || (_connectionType == OpenVPNConnectionType::X509USERPASS)) @@ -550,10 +586,10 @@ TQMap OpenVPNAuthentication::getPasswords() return pwds; } -void OpenVPNAuthentication::setPasswords(TQString name, TQString value) { - if (name == TQString("password")) { +void OpenVPNAuthentication::setPasswords(TDENetworkSettingsMap secrets) { + if (secrets.contains("password")) { _openvpnAuth->editUserPassword->erase(); - _openvpnAuth->editUserPassword->insert(value); + _openvpnAuth->editUserPassword->insert(secrets["password"]); } } @@ -564,3 +600,4 @@ bool OpenVPNAuthentication::needsUserInteraction() return false; } +#include "tdenetman-openvpn.moc" \ No newline at end of file diff --git a/tdenetworkmanager/vpn-plugins/openvpn/src/knetworkmanager-openvpn.h b/tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.h similarity index 79% rename from tdenetworkmanager/vpn-plugins/openvpn/src/knetworkmanager-openvpn.h rename to tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.h index 02c328f..2f8889d 100644 --- a/tdenetworkmanager/vpn-plugins/openvpn/src/knetworkmanager-openvpn.h +++ b/tdenetworkmanager/vpn-plugins/openvpn/src/tdenetman-openvpn.h @@ -31,7 +31,7 @@ #include #include -#include "knetworkmanager-vpnplugin.h" +#include "tdenetman-vpnplugin.h" #include "openvpnprop.h" #include "openvpnauth.h" @@ -68,11 +68,12 @@ class OpenVPNConfig : public VPNConfigWidget Q_OBJECT public: - void setVPNData(const TQStringList& routes, const TQMap& properties); - TQMap getVPNProperties(); - TQStringList getVPNRoutes(); + void setVPNData(TDENetworkSingleRouteConfigurationList& routes, TDENetworkSettingsMap& properties, TDENetworkSettingsMap& secrets); + TDENetworkSettingsMap getVPNProperties(); + TDENetworkSettingsMap getVPNSecrets(); + TDENetworkSingleRouteConfigurationList getVPNRoutes(); bool hasChanged(); - bool isValid(TQStringList& ); + bool isValid(TQStringList&); OpenVPNConfig(TQWidget* parent); ~OpenVPNConfig(); @@ -86,6 +87,9 @@ class OpenVPNConfig : public VPNConfigWidget void getCipherModes(); TQString findOpenVPNBinary(); + TDENetworkSettingsMap m_vpnProperties; + TDENetworkSettingsMap m_vpnSecrets; + protected slots: void languageChange(); }; @@ -97,9 +101,9 @@ class OpenVPNAuthentication : public VPNAuthenticationWidget public: OpenVPNAuthentication(TQWidget* parent = NULL, char* name = NULL); ~OpenVPNAuthentication(); - void setVPNData(const TQStringList&, const TQMap&); - TQMap getPasswords(); - void setPasswords(TQString name, TQString value); + void setVPNData(TDENetworkSingleRouteConfigurationList& routes, TDENetworkSettingsMap& properties, TDENetworkSettingsMap& secrets); + TDENetworkSettingsMap getPasswords(); + void setPasswords(TDENetworkSettingsMap secrets); bool needsUserInteraction(); private: diff --git a/tdenetworkmanager/vpn-plugins/openvpn/knetworkmanager_openvpn.desktop b/tdenetworkmanager/vpn-plugins/openvpn/tdenetman_openvpn.desktop similarity index 75% rename from tdenetworkmanager/vpn-plugins/openvpn/knetworkmanager_openvpn.desktop rename to tdenetworkmanager/vpn-plugins/openvpn/tdenetman_openvpn.desktop index 2f8d837..dad55c0 100644 --- a/tdenetworkmanager/vpn-plugins/openvpn/knetworkmanager_openvpn.desktop +++ b/tdenetworkmanager/vpn-plugins/openvpn/tdenetman_openvpn.desktop @@ -3,11 +3,11 @@ Encoding=UTF-8 Type=Service Icon= ServiceTypes=TDENetworkManager/VPNPlugin -X-TDE-Library=knetworkmanager_openvpn +X-TDE-Library=tdenetman_openvpn X-NetworkManager-Services=openvpn -X-TDE-PluginInfo-Author=Helmut Schaa -X-TDE-PluginInfo-Email=hschaa@suse.de -X-TDE-PluginInfo-Name=knetworkmanager_openvpn +X-TDE-PluginInfo-Author=Timothy Pearson +X-TDE-PluginInfo-Email=kb9vqf@pearsoncomputing.net +X-TDE-PluginInfo-Name=tdenetman_openvpn X-TDE-PluginInfo-Version=0.1 X-TDE-PluginInfo-Website= X-TDE-PluginInfo-Category=VPNService