Commit 9174ec20 by Csók Tamás

client: upgrades in the setup process, plus more logical layout of the code

parent 79e79460
......@@ -162,9 +162,9 @@ IF NOT "!output_on_screen!"=="False" (
goto loop
) else (
set test=%install_path:~0,-1%
call %running_directory%inPath test && (IF NOT "!output_on_screen!"=="False" (@echo %test% is already in PATH)) || (call %running_directory%addPath test & setx>nul PATH "%PATH%;%test%" & IF NOT "!output_on_screen!"=="False" ( @echo %test% set to local PATH))
call %running_directory%inPath test && (IF NOT "!output_on_screen!"=="False" (@echo %test% is already in PATH)) || (call %running_directory%addPath test & setx>nul PATH "%PATH%;%test%" /m & IF NOT "!output_on_screen!"=="False" ( @echo %test% set to PATH))
set test=%install_path%Scripts
call %running_directory%inPath test && (IF NOT "!output_on_screen!"=="False" (@echo %test% is already in PATH)) || (call %running_directory%addPath test & setx>nul PATH "%PATH%;%test%" & IF NOT "!output_on_screen!"=="False" ( @echo %test% set to local PATH))
call %running_directory%inPath test && (IF NOT "!output_on_screen!"=="False" (@echo %test% is already in PATH)) || (call %running_directory%addPath test & setx>nul PATH "%PATH%;%test%" /m & IF NOT "!output_on_screen!"=="False" ( @echo %test% set to PATH))
)
GOTO PIP_CHECK
......@@ -195,12 +195,11 @@ IF NOT "!output_on_screen!"=="False" (
) else (
call python -m pip install --upgrade pip >nul 2>&1
)
IF "%install_selenium%"=="False" (
SET "pip_program=winshell"
) else (
SET "pip_program=selenium"
SET "pip_program=requirements.txt"
IF NOT "!output_on_screen!"=="False" (
@echo Installing python modules
)
GOTO PIP_PACKAGE_CHECK
GOTO PIP_PACKAGE_INSTALL
rem Check if the PIP package is installed or not
:PIP_PACKAGE_CHECK
......@@ -213,9 +212,7 @@ IF NOT "!output_on_screen!"=="False" (
IF NOT "!output_on_screen!"=="False" (
@echo %%b !pip_program! is found
)
rem pywin32 cannot be installed or updated via pip
if "!pip_program!"=="pywin32" goto CHECK_PACKAGE_LIST
GOTO PIP_PACKAGE_UPDATE
GOTO CHECK_PACKAGE_LIST
)
)
IF NOT "!output_on_screen!"=="False" (
......@@ -223,38 +220,21 @@ IF NOT "!output_on_screen!"=="False" (
)
GOTO PIP_PACKAGE_INSTALL
rem Try to install the PIP package via PIP
rem Try to install the PIP packages via PIP
:PIP_PACKAGE_INSTALL
IF NOT "!output_on_screen!"=="False" (
@echo Installing !pip_program!
)
if "!pip_program!"=="pywin32" (
call python %running_directory%pywin_installer.py
) else (
IF NOT "!output_on_screen!"=="False" (
call python -m pip install !pip_program!
call python -m pip install -r requirements.txt
) else (
call python -m pip install !pip_program! >nul 2>&1
call python -m pip install -r requirements.txt >nul 2>&1
)
)
goto CHECK_PACKAGE_LIST
rem Try to update Selenium
:PIP_PACKAGE_UPDATE
IF NOT "!output_on_screen!"=="False" (
@echo Trying to update !pip_program!
call python -m pip install --upgrade !pip_program!
) else (
call python -m pip install --upgrade !pip_program! >nul 2>&1
)
goto CHECK_PACKAGE_LIST
:CHECK_PACKAGE_LIST
if "!pip_program!"=="selenium" (
set "pip_program=winshell"
goto PIP_PACKAGE_CHECK
)
if "!pip_program!"=="winshell" (
if "!pip_program!"=="requirements.txt" (
set "pip_program=pywin32"
goto PIP_PACKAGE_CHECK
)
......@@ -395,7 +375,7 @@ if "!browserToUse!"=="None" (
call :Split "%browser_path%" test
set myTest=!test:~0,-1!
rem Set that path in the PATH environment variable
call %running_directory%inPath myTest && (IF NOT "!output_on_screen!"=="False" ( @echo !myTest! is already in PATH)) || (call %running_directory%addPath myTest & setx>nul PATH "%PATH%;!myTest!" & IF NOT "!output_on_screen!"=="False" ( @echo !myTest! set to local PATH) )
call %running_directory%inPath myTest && (IF NOT "!output_on_screen!"=="False" ( @echo !myTest! is already in PATH)) || (call %running_directory%addPath myTest & setx>nul PATH "%PATH%;!myTest!" /m & IF NOT "!output_on_screen!"=="False" ( @echo !myTest! set to PATH) )
:install_driver
IF NOT "%install_selenium%"=="False" (
if NOT "!selenium_driver_name!"=="" (
......@@ -448,7 +428,7 @@ rem Create folder if needed and set it to PATH
IF NOT "!output_on_screen!"=="False" (
@echo Checking wheter ^'%install_location%^\^' exists already
)
call %running_directory%inPath install_location && (IF NOT "!output_on_screen!"=="False" ( @echo !install_location! is already in PATH)) || (call %running_directory%addPath install_location & setx>nul PATH "%PATH%;!install_location!" & IF NOT "!output_on_screen!"=="False" ( @echo !install_location! set to local PATH))
call %running_directory%inPath install_location && (IF NOT "!output_on_screen!"=="False" ( @echo !install_location! is already in PATH)) || (call %running_directory%addPath install_location & setx>nul PATH "%PATH%;!install_location!" /m & IF NOT "!output_on_screen!"=="False" ( @echo !install_location! set to PATH))
if not exist "%install_location%\" (
mkdir "%install_location%"
)
......@@ -462,7 +442,7 @@ IF NOT "!output_on_screen!"=="False" (
xcopy>nul "%running_directory%cloud.py" "%install_location%\" /y
xcopy>nul "%running_directory%cloud_connect_from_windows.py" "%install_location%\" /y
xcopy>nul "%running_directory%win_install.py" "%install_location%\" /y
xcopy>nul "%running_directory%nx_client_installer.py" "%install_location%\" /y
xcopy>nul "%running_directory%windowsclasses.py" "%install_location%\" /y
xcopy>nul "%running_directory%nxkey.py" "%install_location%\" /y
xcopy>nul "%running_directory%OrderedDict.py" "%install_location%\" /y
xcopy>nul "%running_directory%cloud.ico" "%install_location%\" /y
......
......@@ -2,6 +2,9 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "CIRCLE Client"
#define MyAppProgramInfo "Visit the CIRCLE"
#define MyAppProgram "Cloud GUI.url"
#define MyAppDir "{userappdata}\CIRCLE"
#define MyAppVersion "1.0"
#define MyAppPublisher "BME IK, IIT, VIK"
#define MyAppURL "http://cloud.bme.hu/"
......@@ -79,4 +82,5 @@ Filename: "{app}\uninstall.bat"; Parameters: "True"; Flags: waituntilterminated
[Icons]
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{group}\{#MyAppProgramInfo}"; Filename: "{#MyAppDir}\{#MyAppProgram}"; IconFilename: "{#MyAppDir}\cloud.ico"
......@@ -2,8 +2,8 @@
# -*- coding: utf-8 -*-
"""
A cloudban létrehozott virtuális gépekhez történő kapcsolódást segítő
program
Main program of the Client written for CIRCLE Cloud.
The Client job is to help the ease of use of the cloud system.
"""
import platform
......@@ -21,22 +21,22 @@ except ImporError:
class Struct:
"""
Paraméterek átadására használt struktúra
A struct used for parameter passing
Keyword arguments:
state -- A virtuális gép állapota, azt figyeljük, hogy fut-e
protocol -- SSH, NX és RDP lehetséges
host -- A virtuális gép címe
port -- Ezen a porton csatlakozunk a virtuális géphez
user -- Csatlakozáshoz használt név
password -- Csatlakozáshoz használt jelszó
state -- State of the Virtual Computer (running, etc..)
protocol -- SSH, NX and RDP possible
host -- Address of the Virtual Computer
port -- The port where we can access the Virtual Computer
user -- Username used for the connection
password -- Password used for the connection
"""
pass
def parse_arguments():
"""
Argument parser, argparse modulon alapszik
Argument parser, based on the argparse module
Keyword arguments:
@return args -- arguments given by console
......@@ -53,18 +53,16 @@ def parse_arguments():
"first the proper driver.", type=str,
choices=['firefox', 'chrome', 'ie', 'opera'],
default="firefox")
parser.add_argument(
"-o", "--old", help="Use old interface", action="store_true")
args = parser.parse_args()
return args
class Browser:
"""
Browser inicializálás
Browser initialisation
Keyword arguments:
@param args -- Az args.driver paraméterrel meghatározhatjuk,
melyik böngészőt akarjuk használni.
@param args -- args.driver tells us which installed browser
we want to use with selenium.
"""
def __init__(self, args):
self.args = args
......@@ -80,8 +78,7 @@ class Browser:
def login(self):
"""
Címtáras beléptetés a parancssorban megadott paraméterek
alapján
Eduid login based on the given console arguments
"""
driver = self.driver
args = self.args
......@@ -95,59 +92,21 @@ class Browser:
driver.find_element_by_css_selector(
"input[type='submit']").click()
def old_main(self):
"""
A régi webes felület használata
Keyword arguments:
@return vm -- Virtuális gép csatlakozásához szükséges
paraméterek
"""
vm = Struct()
driver = self.driver
driver.maximize_window()
driver.get("https://cloud.ik.bme.hu/info/")
driver.find_element_by_css_selector("a[href*='/login/']").click()
self.login()
vm.state, vm.protocol = "", "NONE"
try:
while vm.state.upper()[:3] not in ("FUT", "RUN"):
element = WebDriverWait(driver, 7200).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
"input.hidden-password.shown[type='text']")))
vm.password = element.get_attribute("value")
vm.state = driver.find_element_by_css_selector(
"#state > div > p").text
vm.protocol = driver.find_element_by_css_selector(
"#vm-credentials > div > table > tbody > "+
"tr:nth-child(1) > td").text
vm.host,vm.port = driver.find_element_by_css_selector(
"#vm-credentials > div > table > tbody > "+
"tr:nth-child(2) > td").text.split(':')
vm.user = driver.find_element_by_css_selector(
"#vm-credentials > div > table > tbody > "+
"tr:nth-child(4) > td").text
driver.find_element_by_css_selector("a[href*='/logout/']").click()
except:
print "Browser session timed out!"
raise
return vm
def main(self):
"""
Az új webes felület használata
Use of the https://cloud.bme.hu/
Keyword arguments:
@return vm -- Virtuális gép csatlakozásához szükséges
paraméterek
@return vm -- Necessarily parameters to connect
to the Virtual Machine
"""
vm = Struct()
driver = self.driver
driver.maximize_window()
driver.get("https://pc3.szgt.uni-miskolc.hu/")
#driver.find_element_by_css_selector("a[href*='/login/']").click()
#self.login()
driver.get("https://cloud.bme.hu/")
# driver.find_element_by_css_selector("a[href*='/login/']").click()
# self.login()
vm.state, vm.protocol = "", "NONE"
try:
while vm.state.upper()[:3] not in ("FUT", "RUN"):
......@@ -157,7 +116,7 @@ class Browser:
"#vm-details-pw-eye.fa.fa-eye-slash")))
vm.state = driver.find_element_by_css_selector(
"#vm-details-state > span").text
#cl: connection string converted to list
# cl: connection string converted to list
cl = driver.find_element_by_css_selector(
"#vm-details-connection-string").get_attribute(
"value").split()
......@@ -177,14 +136,7 @@ class Browser:
def main():
"""
Főprogram
Job:
beolvassuk a paramétereket
megnyitjuk a kiválasztott böngészőben a weboldalt
bejelentkezünk a címtárba
kiválasztjuk a futtatni kívánt klienst
kapcsolódunk a klienshez
Main program
"""
try:
args = parse_arguments()
......@@ -196,14 +148,8 @@ def main():
vm.state = "RUN"
else:
browser = Browser(args)
try:
if args.old:
vm = browser.old_main()
else:
vm = browser.main()
browser.driver.quit()
except:
raise
vm = browser.main()
browser.driver.quit()
if platform.system() == "Linux":
from cloud_connect_from_linux import connect
elif platform.system() == "Windows":
......@@ -212,7 +158,7 @@ def main():
connect(vm)
except:
print "Unknown error occurred! Please contact the developers!"
if __name__ == "__main__":
main()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##
# Távoli klienshez csatlakozás windows OS alól
##
"""
Configuration of the Windows specific tools to enhance the ease of use
of the CIRCLE cloud. Handles the auto launch and auto configuration
of these specific connectivity programs.
"""
import time
import os
......@@ -12,16 +15,19 @@ import win32crypt
import binascii
import nxkey
##
# A távoli klienshez csatlakozás valósítja majd meg windows alól
# @param vm Paraméterek a csatlakozáshoz
# vm.protocol SSH, NX és RDP lehetséges
# vm.host A virtuális gép címe
# vm.port Ezen a porton csatlakozunk a virtuális géphez
# vm.user Csatlakozáshoz használt név
# vm.password Csatlakozáshoz használt jelszó
#
def connect(vm):
"""
Handles to connection to the Virtual Machines from the local
machine
Keyword arguments:
vm.protocol -- SSH, NX and RDP possible
vm.host -- Address of the Virtual Computer
vm.port -- The port where we can access the Virtual Computer
vm.user -- Username used for the connection
vm.password -- Password used for the connection
"""
if vm.protocol == "SSH":
arguments = "-ssh -P %s -pw %s %s@%s" % (vm.port, vm.password, vm.user, vm.host)
subprocess.Popen("putty.exe "+arguments, shell = True)
......@@ -63,7 +69,8 @@ def connect(vm):
f.write(config)
f.close()
subprocess.Popen(config_file, shell = True)
NX_template = """<!DOCTYPE NXClientSettings>
<NXClientSettings application="nxclient" version="1.3" >
<group name="General" >
......
......@@ -195,12 +195,11 @@ IF NOT "!output_on_screen!"=="False" (
) else (
call python -m pip install --upgrade pip >nul 2>&1
)
IF "%install_selenium%"=="False" (
SET "pip_program=winshell"
) else (
SET "pip_program=selenium"
SET "pip_program=requirements.txt"
IF NOT "!output_on_screen!"=="False" (
@echo Installing python modules
)
GOTO PIP_PACKAGE_CHECK
GOTO PIP_PACKAGE_INSTALL
rem Check if the PIP package is installed or not
:PIP_PACKAGE_CHECK
......@@ -213,9 +212,7 @@ IF NOT "!output_on_screen!"=="False" (
IF NOT "!output_on_screen!"=="False" (
@echo %%b !pip_program! is found
)
rem pywin32 cannot be installed or updated via pip
if "!pip_program!"=="pywin32" goto CHECK_PACKAGE_LIST
GOTO PIP_PACKAGE_UPDATE
GOTO CHECK_PACKAGE_LIST
)
)
IF NOT "!output_on_screen!"=="False" (
......@@ -223,38 +220,21 @@ IF NOT "!output_on_screen!"=="False" (
)
GOTO PIP_PACKAGE_INSTALL
rem Try to install the PIP package via PIP
rem Try to install the PIP packages via PIP
:PIP_PACKAGE_INSTALL
IF NOT "!output_on_screen!"=="False" (
@echo Installing !pip_program!
)
if "!pip_program!"=="pywin32" (
call python %running_directory%pywin_installer.py
) else (
IF NOT "!output_on_screen!"=="False" (
call python -m pip install !pip_program!
call python -m pip install -r requirements.txt
) else (
call python -m pip install !pip_program! >nul 2>&1
call python -m pip install -r requirements.txt >nul 2>&1
)
)
goto CHECK_PACKAGE_LIST
rem Try to update Selenium
:PIP_PACKAGE_UPDATE
IF NOT "!output_on_screen!"=="False" (
@echo Trying to update !pip_program!
call python -m pip install --upgrade !pip_program!
) else (
call python -m pip install --upgrade !pip_program! >nul 2>&1
)
goto CHECK_PACKAGE_LIST
:CHECK_PACKAGE_LIST
if "!pip_program!"=="selenium" (
set "pip_program=winshell"
goto PIP_PACKAGE_CHECK
)
if "!pip_program!"=="winshell" (
if "!pip_program!"=="requirements.txt" (
set "pip_program=pywin32"
goto PIP_PACKAGE_CHECK
)
......@@ -462,7 +442,7 @@ IF NOT "!output_on_screen!"=="False" (
xcopy>nul "%running_directory%cloud.py" "%install_location%\" /y
xcopy>nul "%running_directory%cloud_connect_from_windows.py" "%install_location%\" /y
xcopy>nul "%running_directory%win_install.py" "%install_location%\" /y
xcopy>nul "%running_directory%nx_client_installer.py" "%install_location%\" /y
xcopy>nul "%running_directory%windowsclasses.py" "%install_location%\" /y
xcopy>nul "%running_directory%nxkey.py" "%install_location%\" /y
xcopy>nul "%running_directory%OrderedDict.py" "%install_location%\" /y
xcopy>nul "%running_directory%cloud.ico" "%install_location%\" /y
......
......@@ -2,23 +2,16 @@
# -*- coding: utf-8 -*-
"""
NX Client for Windows installer with RegistryHandler and
DecideArchitecture classes.
NX Client for Windows installer
Checks whether NX Client for Windows is installed in the system, the
classes used for this process are used for other operations too.
"""
import os
import sys
import argparse
import errno
import subprocess
import time
from _winreg import *
try:
from collections import *
except ImporError:
from OrderedDict import *
import windowsclasses
def parse_arguments():
......@@ -29,10 +22,12 @@ def parse_arguments():
@return args -- arguments given by console
"""
parser = argparse.ArgumentParser()
if DecideArchitecture.Is64Windows():
local_default = DecideArchitecture.GetProgramFiles64()+"\\CIRCLE\\"
if windowsclasses.DecideArchitecture.Is64Windows():
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles64()
+"\\CIRCLE\\")
else:
local_default = DecideArchitecture.GetProgramFiles32()+"\\CIRCLE\\"
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles32()
+"\\CIRCLE\\")
if (not os.path.exists(local_default[:-1])
and os.path.exists(os.environ['APPDATA']+"\\CIRCLE")):
local_default = os.environ['APPDATA']+"\\CIRCLE\\"
......@@ -40,316 +35,16 @@ def parse_arguments():
"-l", "--location",
help="Location of the client files in the system",
default=local_default)
parser.add_argument(
"-g", "--global",
help="Whether we want to edit registry globally or just locally",
action="store_true")
parser.add_argument(
"-d", "--different",
help="Only handle the architecture specific registry area",
action="store_true")
parser.add_argument(
"-r", "--registry",
help="Which HKEY_* const registry type the program should use",
type=str, choices=['HKLM', 'HKCR', 'HKCU', 'HKU', 'HKPD', 'HKCC'],
default="HKLM")
args = parser.parse_args()
return args
class Struct:
"""
Parameter bypassing struct
"""
pass
class RegistryHandler:
"""
Registry handling class, makes registry based queries and
manipulations easier.
This class can handle WOW64 based application differently and none
differently (default)
"""
def __init__(self, args = None):
"""Initialise RegistryHandler
Keyword arguments:
@param args -- The arguments that decide how the we should
handle the registry
args.registry -- What base registry should we use
(default: HKLM)
Raises AttributeError if not supported base registry type is
given
args.different -- Whether we handle registry redirection or not
"""
if args is None:
self.args = Struct()
self.args.different = None
self.args.registry = None
else:
if not hasattr(args, 'different'):
args.different = None
if not hasattr(args, 'registry'):
args.registry = None
self.args = args
if self.args.different is None:
self.args.different = False
if self.args.registry is None or self.args.registry == "HKLM":
self.args.registry = HKEY_LOCAL_MACHINE
elif self.args.registry == "HKCR":
self.args.registry = HKEY_CLASSES_ROOT
elif self.args.registry == "HKCU":
self.args.registry = HKEY_CURRENT_USER
elif self.args.registry == "HKU":
self.args.registry = HKEY_USERS
elif self.args.registry == "HKPD":
self.args.registry = HKEY_PERFORMANCE_DATA
elif self.args.registry == "HKCC":
self.args.registry = HKEY_CURRENT_CONFIG
else:
#print "Non supported registry type"
raise AttributeError
def connect_registry(self):
"""
Getting a registry open
Keyword arguments:
@return connected_registy -- Reference to the newly opened
registry
"""
return ConnectRegistry(None,self.args.registry)
def create_registry_from_dict_chain(
self, dict_chain, both = False, architect = KEY_WOW64_64KEY,
needed_rights = KEY_ALL_ACCESS):
""""
Create registry key and value multilevel tree by chained
dictionaries.
Can raise AttributeError if the provided dict chain isn't
correct
Keyword arguments:
@param key_value_chain -- The dict chain containing all the
information
@param both -- Whether create the registry in WOW64
node too
@param architect -- The current registry view (
only change it if we want to fill the
WOW6432 registry only [both = False],
on x64 windows)
@param needed_rights -- SAM rights to access the key
"""
if both and architect is KEY_WOW64_64KEY:
self.create_registry_from_dict_chain(
dict_chain, False, KEY_WOW64_32KEY, needed_rights)
if not DecideArchitecture.Is64Windows():
architect = 0
connected_registy = self.connect_registry()
if (isinstance(dict_chain, dict)
or isinstance(dict_chain, OrderedDict)):
for key, value in dict_chain.iteritems():
if isinstance(value, dict) or isinstance(value, OrderedDict):
temp_dict = OrderedDict()
for my_key, my_value in value.iteritems():
temp_dict[key+"\\"+my_key] = my_value
self.create_registry_from_dict_chain(
temp_dict, False, architect, needed_rights)
else:
if isinstance(value, list):
if len(value)%2 != 0:
#print "Not enough member in the list"
raise AttributeError
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
temp_dict = OrderedDict(
value[i:i+2] for i in range(
0, len(value), 2))
for my_key, my_value in temp_dict.iteritems():
if my_key == "default":
my_key = None
SetValueEx(
new_key, my_key, 0, REG_SZ, my_value)
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
SetValueEx(new_key, None, 0, REG_SZ, value)
else:
print "The provided attribute wasn't a dictionary chain"
raise AttributeError
def get_key(self, key_name, needed_rights = KEY_ALL_ACCESS):
"""
Getting a registry value by it's key's name
Can raise KeyError if key is not found in the registry
Keyword arguments:
@param key_name -- The specific key name of which value we
are interested in
@param needed_rights -- SAM rights to access the key
@return -- [key, architect]
key -- Reference to the opened
key handler
architect -- 0 for x86
KEY_WOW64_32KEY or
KEY_WOW64_64KEY
depending where we
found the key on x64
"""
connected_registy = self.connect_registry()
architect = 0
if DecideArchitecture.Is64Windows():
architect = KEY_WOW64_64KEY
try:
key = OpenKey(connected_registy, key_name, 0,
needed_rights | architect)
except WindowsError:
if DecideArchitecture.Is64Windows() and not self.args.different:
try:
architect = KEY_WOW64_32KEY
key = OpenKey(connected_registy, key_name,
0, needed_rights | architect)
except WindowsError:
raise KeyError
else:
raise KeyError
return [key, architect]
def get_key_values(
self, key_name, subkey_list, subroutine = False,
depth = "subkeys"):
"""
Getting registry subkeys value by it's key's name and subkeys
name
Can raise LookupError exception if there are missing data
Can raise AttributeError exception if depth attribute is wrong
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_list -- List containing all the subkeys names
which values we are interested in
@param subroutine -- Whether suppress exception about not
having enough results or not
(default: False)
@param depth -- How depth the search should go for
[options: key, subkeys, all]
(default: subkeys)
@return results{} -- Dictionary with the subkey_name - value
combinations as keys and values
"""
if depth == "key":
int_depth = 0;
elif depth == "subkeys":
int_depth = 1;
elif depth == "all":
int_depth = 2;
else:
raise AttributeError
try:
key_and_architect = self.get_key(key_name)
key = key_and_architect[0]
architect = key_and_architect[1]
except KeyError:
#print "%s doesn't exist in the registry" % key_name
raise LookupError
#print "%s found in the registry" % key_name
results = {}
if int_depth >= 1:
for i in xrange(0, QueryInfoKey(key)[0]-1):
skey_name = EnumKey(key, i)
skey = OpenKey(key, skey_name, 0, KEY_ALL_ACCESS | architect)
if int_depth == 2 and QueryInfoKey(skey)[0] > 0:
for key, value in self.get_key_values(
skey_name, subkey_list, True, depth).iteritems():
results[key] = value
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(
skey, subkey_name)[0]
except OSError as e:
if e.errno == errno.ENOENT:
#print ("%s doesn't exist in this" % subkey_name
# " subkey")
pass
skey.Close()
if not results or len(results) != len(subkey_list):
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(key, subkey_name)[0]
except OSError as e:
pass
key.Close()
if len(results) != len(subkey_list):
#print "We are missing important variables"
raise LookupError
return results
def get_key_value(
self, key_name, subkey_name, subroutine = None, depth = None):
"""
This is a wrapper for the get_key_values to be easier to use
for single subkeys.
Getting registry subkey value by it's key's name and subkey
name
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_name -- The specific subkey name which value we
are interested in
@param subroutine -- can be found at: get_key_values
@param depth -- can be found at: get_key_values
@return value -- Value of the specific subkey
"""
try:
if subroutine is None:
return self.get_key_values(key_name,
[subkey_name])[subkey_name]
elif depth is None:
return self.get_key_values(key_name, [subkey_name],
subroutine)[subkey_name]
else:
return self.get_key_values(key_name, [subkey_name],
subroutine, depth)[subkey_name]
except:
raise
class DecideArchitecture:
"""
Helper class to get the true ProgramFiles directory.
This class doesn't depend on Phyton or Windows architecture.
"""
@staticmethod
def Is64Windows():
return 'PROGRAMFILES(X86)' in os.environ
@staticmethod
def GetProgramFiles32():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMFILES(X86)']
else:
return os.environ['PROGRAMFILES']
@staticmethod
def GetProgramFiles64():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMW6432']
else:
return None
def main():
try:
args = parse_arguments()
nx_install_location = None
while nx_install_location is None:
print "Checking whether NX Client for Windows is installed"
handler = RegistryHandler()
handler = windowsclasses.RegistryHandler()
try:
nx_install_location = handler.get_key_value(
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"+
......@@ -369,7 +64,6 @@ def main():
"\\nxclient-3.5.0-9.exe").wait()
except:
pass
if __name__ == "__main__":
main()
\ No newline at end of file
......@@ -8,7 +8,7 @@ Pywin32 installer for CIRCLE client application
import os
import sys
import subprocess
from nx_client_installer import DecideArchitecture
import windowsclasses
def main():
......@@ -27,7 +27,7 @@ def main():
else:
pywin32_version = str(219)
if sys.hexversion < 0x02070000:
if DecideArchitecture.Is64Windows():
if windowsclasses.DecideArchitecture.Is64Windows():
subprocess.Popen(
"%s\\x64\\pywin32-%s.win-amd64-py2.6.exe" % (
os.path.dirname(os.path.realpath(__file__)),
......@@ -38,7 +38,7 @@ def main():
os.path.dirname(os.path.realpath(__file__)),
pywin32_version)).wait()
elif sys.hexversion < 0x02080000:
if DecideArchitecture.Is64Windows():
if windowsclasses.DecideArchitecture.Is64Windows():
subprocess.Popen(
"%s\\x64\\pywin32-%s.win-amd64-py2.7.exe" % (
os.path.dirname(os.path.realpath(__file__)),
......
winshell==0.6
\ No newline at end of file
......@@ -9,11 +9,12 @@ import os
import argparse
import subprocess
import pythoncom
import shutil
from win32com.shell import shell, shellcon
from nx_client_installer import DecideArchitecture, RegistryHandler, Struct
import windowsclasses
try:
from collections import *
except ImporError:
except ImportError:
from OrderedDict import *
......@@ -32,10 +33,12 @@ def parse_arguments():
"first the proper driver.", type=str, default="firefox",
required=False, choices=['firefox', 'chrome',
'iexplore', 'opera'])
if DecideArchitecture.Is64Windows():
local_default = DecideArchitecture.GetProgramFiles64()+"\\CIRCLE\\"
if windowsclasses.DecideArchitecture.Is64Windows():
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles64()
+"\\CIRCLE\\")
else:
local_default = DecideArchitecture.GetProgramFiles32()+"\\CIRCLE\\"
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles32()
+"\\CIRCLE\\")
if (not os.path.exists(local_default[:-1])
and os.path.exists(os.environ['APPDATA']+"\\CIRCLE")):
local_default = os.environ['APPDATA']+"\\CIRCLE\\"
......@@ -53,7 +56,7 @@ def parse_arguments():
parser.add_argument(
"-t", "--target",
help="If this is an URL icon, where should it point",
default="https://pc3.szgt.uni-miskolc.hu/", required=False)
default="https://cloud.bme.hu/", required=False)
args = parser.parse_args()
return args
......@@ -69,9 +72,9 @@ def custom_protocol_register(custom_protocol):
raise AttributeError
print "\t"+custom_protocol.iterkeys().next()
try:
custom_arguments = Struct()
custom_arguments = windowsclasses.Struct()
custom_arguments.registry = "HKCR"
handler = RegistryHandler(custom_arguments)
handler = windowsclasses.RegistryHandler(custom_arguments)
handler.create_registry_from_dict_chain(custom_protocol, True)
print "\t\tDone!"
except:
......@@ -79,14 +82,14 @@ def custom_protocol_register(custom_protocol):
def main():
"""
Main program
"""
Main program
Jobs:
read the parameters
create a proper icon with the proper driver (or delete)
call the nx_client_installer
"""
Jobs:
read the parameters
create a proper icon with the proper driver (or delete)
call the nx_client_installer
"""
try:
args = parse_arguments()
shortcut = pythoncom.CoCreateInstance (
......@@ -95,9 +98,10 @@ def main():
pythoncom.CLSCTX_INPROC_SERVER,
shell.IID_IShellLink
)
desktop_path = shell.SHGetFolderPath (0, shellcon.CSIDL_DESKTOP, 0, 0)
desktop_path = shell.SHGetFolderPath (
0, shellcon.CSIDL_DESKTOP, 0, 0)
if args.remove:
location =os.path.join(desktop_path, "Cloud GUI")
location = os.path.join(desktop_path, "Cloud GUI")
if os.path.isfile("%s%s" % (location, ".lnk")):
os.remove("%s%s" % (location, ".lnk"))
if os.path.isfile("%s%s" % (location, ".url")):
......@@ -126,9 +130,10 @@ def main():
0, shellcon.CSIDL_DESKTOP, 0, 0)
persist_file = shortcut.QueryInterface(
pythoncom.IID_IPersistFile)
persist_file.Save(
os.path.join(desktop_path, "Cloud GUI.lnk"), 0)
location = os.path.join(desktop_path, "Cloud GUI.lnk")
persist_file.Save(location, 0)
print "Icon successfully created on desktop"
shutil.copy(location, args.location)
print "Creating custom URL protocol handlers"
try:
custom_ssh = OrderedDict(
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Place holder for all windows specific frequently used classes.
Currently here:
RegistryHandler - Registry based operations
DecideArchitecture - Accurate way to decide operating system architecture
"""
import os
import argparse
import errno
from _winreg import *
try:
from collections import *
except ImporError:
from OrderedDict import *
def parse_arguments():
"""
Argument parser, based on argparse module
Keyword arguments:
@return args -- arguments given by console
"""
parser = argparse.ArgumentParser()
parser.add_argument(
"-g", "--global",
help="Whether we want to edit registry globally or just locally",
action="store_true")
parser.add_argument(
"-d", "--different",
help="Only handle the architecture specific registry area",
action="store_true")
parser.add_argument(
"-r", "--registry",
help="Which HKEY_* const registry type the program should use",
type=str, choices=['HKLM', 'HKCR', 'HKCU', 'HKU', 'HKPD', 'HKCC'],
default="HKLM")
args = parser.parse_args()
return args
def main():
return RegistryHandler(parse_arguments())
class Struct:
"""
Parameter bypassing struct
"""
pass
class RegistryHandler:
"""
Registry handling class, makes registry based queries and
manipulations easier.
This class can handle WOW64 based application differently and none
differently (default)
"""
def __init__(self, args = None):
"""Initialise RegistryHandler
Keyword arguments:
@param args -- The arguments that decide how the we should
handle the registry
args.registry -- What base registry should we use
(default: HKLM)
Raises AttributeError if not supported base registry type is
given
args.different -- Whether we handle registry redirection or not
"""
if args is None:
self.args = Struct()
self.args.different = None
self.args.registry = None
else:
if not hasattr(args, 'different'):
args.different = None
if not hasattr(args, 'registry'):
args.registry = None
self.args = args
if self.args.different is None:
self.args.different = False
if self.args.registry is None or self.args.registry == "HKLM":
self.args.registry = HKEY_LOCAL_MACHINE
elif self.args.registry == "HKCR":
self.args.registry = HKEY_CLASSES_ROOT
elif self.args.registry == "HKCU":
self.args.registry = HKEY_CURRENT_USER
elif self.args.registry == "HKU":
self.args.registry = HKEY_USERS
elif self.args.registry == "HKPD":
self.args.registry = HKEY_PERFORMANCE_DATA
elif self.args.registry == "HKCC":
self.args.registry = HKEY_CURRENT_CONFIG
else:
#print "Non supported registry type"
raise AttributeError
def connect_registry(self):
"""
Getting a registry open
Keyword arguments:
@return connected_registy -- Reference to the newly opened
registry
"""
return ConnectRegistry(None,self.args.registry)
def create_registry_from_dict_chain(
self, dict_chain, both = False, architect = KEY_WOW64_64KEY,
needed_rights = KEY_ALL_ACCESS):
""""
Create registry key and value multilevel tree by chained
dictionaries.
Can raise AttributeError if the provided dict chain isn't
correct
Keyword arguments:
@param key_value_chain -- The dict chain containing all the
information
@param both -- Whether create the registry in WOW64
node too
@param architect -- The current registry view (
only change it if we want to fill the
WOW6432 registry only [both = False],
on x64 windows)
@param needed_rights -- SAM rights to access the key
"""
if both and architect is KEY_WOW64_64KEY:
self.create_registry_from_dict_chain(
dict_chain, False, KEY_WOW64_32KEY, needed_rights)
if not DecideArchitecture.Is64Windows():
architect = 0
connected_registy = self.connect_registry()
if (isinstance(dict_chain, dict)
or isinstance(dict_chain, OrderedDict)):
for key, value in dict_chain.iteritems():
if isinstance(value, dict) or isinstance(value, OrderedDict):
temp_dict = OrderedDict()
for my_key, my_value in value.iteritems():
temp_dict[key+"\\"+my_key] = my_value
self.create_registry_from_dict_chain(
temp_dict, False, architect, needed_rights)
else:
if isinstance(value, list):
if len(value)%2 != 0:
#print "Not enough member in the list"
raise AttributeError
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
temp_dict = OrderedDict(
value[i:i+2] for i in range(
0, len(value), 2))
for my_key, my_value in temp_dict.iteritems():
if my_key == "default":
my_key = None
SetValueEx(
new_key, my_key, 0, REG_SZ, my_value)
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
SetValueEx(new_key, None, 0, REG_SZ, value)
else:
print "The provided attribute wasn't a dictionary chain"
raise AttributeError
def get_key(self, key_name, needed_rights = KEY_ALL_ACCESS):
"""
Getting a registry value by it's key's name
Can raise KeyError if key is not found in the registry
Keyword arguments:
@param key_name -- The specific key name of which value we
are interested in
@param needed_rights -- SAM rights to access the key
@return -- [key, architect]
key -- Reference to the opened
key handler
architect -- 0 for x86
KEY_WOW64_32KEY or
KEY_WOW64_64KEY
depending where we
found the key on x64
"""
connected_registy = self.connect_registry()
architect = 0
if DecideArchitecture.Is64Windows():
architect = KEY_WOW64_64KEY
try:
key = OpenKey(connected_registy, key_name, 0,
needed_rights | architect)
except WindowsError:
if DecideArchitecture.Is64Windows() and not self.args.different:
try:
architect = KEY_WOW64_32KEY
key = OpenKey(connected_registy, key_name,
0, needed_rights | architect)
except WindowsError:
raise KeyError
else:
raise KeyError
return [key, architect]
def get_key_values(
self, key_name, subkey_list, subroutine = False,
depth = "subkeys"):
"""
Getting registry subkeys value by it's key's name and subkeys
name
Can raise LookupError exception if there are missing data
Can raise AttributeError exception if depth attribute is wrong
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_list -- List containing all the subkeys names
which values we are interested in
@param subroutine -- Whether suppress exception about not
having enough results or not
(default: False)
@param depth -- How depth the search should go for
[options: key, subkeys, all]
(default: subkeys)
@return results{} -- Dictionary with the subkey_name - value
combinations as keys and values
"""
if depth == "key":
int_depth = 0;
elif depth == "subkeys":
int_depth = 1;
elif depth == "all":
int_depth = 2;
else:
raise AttributeError
try:
key_and_architect = self.get_key(key_name)
key = key_and_architect[0]
architect = key_and_architect[1]
except KeyError:
#print "%s doesn't exist in the registry" % key_name
raise LookupError
#print "%s found in the registry" % key_name
results = {}
if int_depth >= 1:
for i in xrange(0, QueryInfoKey(key)[0]-1):
skey_name = EnumKey(key, i)
skey = OpenKey(key, skey_name, 0, KEY_ALL_ACCESS | architect)
if int_depth == 2 and QueryInfoKey(skey)[0] > 0:
for key, value in self.get_key_values(
skey_name, subkey_list, True, depth).iteritems():
results[key] = value
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(
skey, subkey_name)[0]
except OSError as e:
if e.errno == errno.ENOENT:
#print ("%s doesn't exist in this" % subkey_name
# " subkey")
pass
skey.Close()
if not results or len(results) != len(subkey_list):
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(key, subkey_name)[0]
except OSError as e:
pass
key.Close()
if len(results) != len(subkey_list):
#print "We are missing important variables"
raise LookupError
return results
def get_key_value(
self, key_name, subkey_name, subroutine = None, depth = None):
"""
This is a wrapper for the get_key_values to be easier to use
for single subkeys.
Getting registry subkey value by it's key's name and subkey
name
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_name -- The specific subkey name which value we
are interested in
@param subroutine -- can be found at: get_key_values
@param depth -- can be found at: get_key_values
@return value -- Value of the specific subkey
"""
try:
if subroutine is None:
return self.get_key_values(key_name,
[subkey_name])[subkey_name]
elif depth is None:
return self.get_key_values(key_name, [subkey_name],
subroutine)[subkey_name]
else:
return self.get_key_values(key_name, [subkey_name],
subroutine, depth)[subkey_name]
except:
raise
class DecideArchitecture:
"""
Helper class to get the true ProgramFiles directory.
This class doesn't depend on Phyton or Windows architecture.
"""
@staticmethod
def Is64Windows():
return 'PROGRAMFILES(X86)' in os.environ
@staticmethod
def GetProgramFiles32():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMFILES(X86)']
else:
return os.environ['PROGRAMFILES']
@staticmethod
def GetProgramFiles64():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMW6432']
else:
return None
\ No newline at end of file
......@@ -2,8 +2,8 @@
# -*- coding: utf-8 -*-
"""
A cloudban létrehozott virtuális gépekhez történő kapcsolódást segítő
program
Main program of the Client written for CIRCLE Cloud.
The Client job is to help the ease of use of the cloud system.
"""
import platform
......@@ -21,22 +21,22 @@ except ImporError:
class Struct:
"""
Paraméterek átadására használt struktúra
A struct used for parameter passing
Keyword arguments:
state -- A virtuális gép állapota, azt figyeljük, hogy fut-e
protocol -- SSH, NX és RDP lehetséges
host -- A virtuális gép címe
port -- Ezen a porton csatlakozunk a virtuális géphez
user -- Csatlakozáshoz használt név
password -- Csatlakozáshoz használt jelszó
state -- State of the Virtual Computer (running, etc..)
protocol -- SSH, NX and RDP possible
host -- Address of the Virtual Computer
port -- The port where we can access the Virtual Computer
user -- Username used for the connection
password -- Password used for the connection
"""
pass
def parse_arguments():
"""
Argument parser, argparse modulon alapszik
Argument parser, based on the argparse module
Keyword arguments:
@return args -- arguments given by console
......@@ -53,18 +53,16 @@ def parse_arguments():
"first the proper driver.", type=str,
choices=['firefox', 'chrome', 'ie', 'opera'],
default="firefox")
parser.add_argument(
"-o", "--old", help="Use old interface", action="store_true")
args = parser.parse_args()
return args
class Browser:
"""
Browser inicializálás
Browser initialisation
Keyword arguments:
@param args -- Az args.driver paraméterrel meghatározhatjuk,
melyik böngészőt akarjuk használni.
@param args -- args.driver tells us which installed browser
we want to use with selenium.
"""
def __init__(self, args):
self.args = args
......@@ -80,8 +78,7 @@ class Browser:
def login(self):
"""
Címtáras beléptetés a parancssorban megadott paraméterek
alapján
Eduid login based on the given console arguments
"""
driver = self.driver
args = self.args
......@@ -95,59 +92,21 @@ class Browser:
driver.find_element_by_css_selector(
"input[type='submit']").click()
def old_main(self):
"""
A régi webes felület használata
Keyword arguments:
@return vm -- Virtuális gép csatlakozásához szükséges
paraméterek
"""
vm = Struct()
driver = self.driver
driver.maximize_window()
driver.get("https://cloud.ik.bme.hu/info/")
driver.find_element_by_css_selector("a[href*='/login/']").click()
self.login()
vm.state, vm.protocol = "", "NONE"
try:
while vm.state.upper()[:3] not in ("FUT", "RUN"):
element = WebDriverWait(driver, 7200).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
"input.hidden-password.shown[type='text']")))
vm.password = element.get_attribute("value")
vm.state = driver.find_element_by_css_selector(
"#state > div > p").text
vm.protocol = driver.find_element_by_css_selector(
"#vm-credentials > div > table > tbody > "+
"tr:nth-child(1) > td").text
vm.host,vm.port = driver.find_element_by_css_selector(
"#vm-credentials > div > table > tbody > "+
"tr:nth-child(2) > td").text.split(':')
vm.user = driver.find_element_by_css_selector(
"#vm-credentials > div > table > tbody > "+
"tr:nth-child(4) > td").text
driver.find_element_by_css_selector("a[href*='/logout/']").click()
except:
print "Browser session timed out!"
raise
return vm
def main(self):
"""
Az új webes felület használata
Use of the https://cloud.bme.hu/
Keyword arguments:
@return vm -- Virtuális gép csatlakozásához szükséges
paraméterek
@return vm -- Necessarily parameters to connect
to the Virtual Machine
"""
vm = Struct()
driver = self.driver
driver.maximize_window()
driver.get("https://pc3.szgt.uni-miskolc.hu/")
#driver.find_element_by_css_selector("a[href*='/login/']").click()
#self.login()
driver.get("https://cloud.bme.hu/")
# driver.find_element_by_css_selector("a[href*='/login/']").click()
# self.login()
vm.state, vm.protocol = "", "NONE"
try:
while vm.state.upper()[:3] not in ("FUT", "RUN"):
......@@ -157,7 +116,7 @@ class Browser:
"#vm-details-pw-eye.fa.fa-eye-slash")))
vm.state = driver.find_element_by_css_selector(
"#vm-details-state > span").text
#cl: connection string converted to list
# cl: connection string converted to list
cl = driver.find_element_by_css_selector(
"#vm-details-connection-string").get_attribute(
"value").split()
......@@ -177,14 +136,7 @@ class Browser:
def main():
"""
Főprogram
Job:
beolvassuk a paramétereket
megnyitjuk a kiválasztott böngészőben a weboldalt
bejelentkezünk a címtárba
kiválasztjuk a futtatni kívánt klienst
kapcsolódunk a klienshez
Main program
"""
try:
args = parse_arguments()
......@@ -196,14 +148,8 @@ def main():
vm.state = "RUN"
else:
browser = Browser(args)
try:
if args.old:
vm = browser.old_main()
else:
vm = browser.main()
browser.driver.quit()
except:
raise
vm = browser.main()
browser.driver.quit()
if platform.system() == "Linux":
from cloud_connect_from_linux import connect
elif platform.system() == "Windows":
......@@ -212,7 +158,7 @@ def main():
connect(vm)
except:
print "Unknown error occurred! Please contact the developers!"
if __name__ == "__main__":
main()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##
# Távoli klienshez csatlakozás windows OS alól
##
"""
Configuration of the Windows specific tools to enhance the ease of use
of the CIRCLE cloud. Handles the auto launch and auto configuration
of these specific connectivity programs.
"""
import time
import os
......@@ -12,16 +15,19 @@ import win32crypt
import binascii
import nxkey
##
# A távoli klienshez csatlakozás valósítja majd meg windows alól
# @param vm Paraméterek a csatlakozáshoz
# vm.protocol SSH, NX és RDP lehetséges
# vm.host A virtuális gép címe
# vm.port Ezen a porton csatlakozunk a virtuális géphez
# vm.user Csatlakozáshoz használt név
# vm.password Csatlakozáshoz használt jelszó
#
def connect(vm):
"""
Handles to connection to the Virtual Machines from the local
machine
Keyword arguments:
vm.protocol -- SSH, NX and RDP possible
vm.host -- Address of the Virtual Computer
vm.port -- The port where we can access the Virtual Computer
vm.user -- Username used for the connection
vm.password -- Password used for the connection
"""
if vm.protocol == "SSH":
arguments = "-ssh -P %s -pw %s %s@%s" % (vm.port, vm.password, vm.user, vm.host)
subprocess.Popen("putty.exe "+arguments, shell = True)
......@@ -63,7 +69,8 @@ def connect(vm):
f.write(config)
f.close()
subprocess.Popen(config_file, shell = True)
NX_template = """<!DOCTYPE NXClientSettings>
<NXClientSettings application="nxclient" version="1.3" >
<group name="General" >
......
......@@ -2,23 +2,16 @@
# -*- coding: utf-8 -*-
"""
NX Client for Windows installer with RegistryHandler and
DecideArchitecture classes.
NX Client for Windows installer
Checks whether NX Client for Windows is installed in the system, the
classes used for this process are used for other operations too.
"""
import os
import sys
import argparse
import errno
import subprocess
import time
from _winreg import *
try:
from collections import *
except ImporError:
from OrderedDict import *
import windowsclasses
def parse_arguments():
......@@ -29,10 +22,12 @@ def parse_arguments():
@return args -- arguments given by console
"""
parser = argparse.ArgumentParser()
if DecideArchitecture.Is64Windows():
local_default = DecideArchitecture.GetProgramFiles64()+"\\CIRCLE\\"
if windowsclasses.DecideArchitecture.Is64Windows():
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles64()
+"\\CIRCLE\\")
else:
local_default = DecideArchitecture.GetProgramFiles32()+"\\CIRCLE\\"
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles32()
+"\\CIRCLE\\")
if (not os.path.exists(local_default[:-1])
and os.path.exists(os.environ['APPDATA']+"\\CIRCLE")):
local_default = os.environ['APPDATA']+"\\CIRCLE\\"
......@@ -40,316 +35,16 @@ def parse_arguments():
"-l", "--location",
help="Location of the client files in the system",
default=local_default)
parser.add_argument(
"-g", "--global",
help="Whether we want to edit registry globally or just locally",
action="store_true")
parser.add_argument(
"-d", "--different",
help="Only handle the architecture specific registry area",
action="store_true")
parser.add_argument(
"-r", "--registry",
help="Which HKEY_* const registry type the program should use",
type=str, choices=['HKLM', 'HKCR', 'HKCU', 'HKU', 'HKPD', 'HKCC'],
default="HKLM")
args = parser.parse_args()
return args
class Struct:
"""
Parameter bypassing struct
"""
pass
class RegistryHandler:
"""
Registry handling class, makes registry based queries and
manipulations easier.
This class can handle WOW64 based application differently and none
differently (default)
"""
def __init__(self, args = None):
"""Initialise RegistryHandler
Keyword arguments:
@param args -- The arguments that decide how the we should
handle the registry
args.registry -- What base registry should we use
(default: HKLM)
Raises AttributeError if not supported base registry type is
given
args.different -- Whether we handle registry redirection or not
"""
if args is None:
self.args = Struct()
self.args.different = None
self.args.registry = None
else:
if not hasattr(args, 'different'):
args.different = None
if not hasattr(args, 'registry'):
args.registry = None
self.args = args
if self.args.different is None:
self.args.different = False
if self.args.registry is None or self.args.registry == "HKLM":
self.args.registry = HKEY_LOCAL_MACHINE
elif self.args.registry == "HKCR":
self.args.registry = HKEY_CLASSES_ROOT
elif self.args.registry == "HKCU":
self.args.registry = HKEY_CURRENT_USER
elif self.args.registry == "HKU":
self.args.registry = HKEY_USERS
elif self.args.registry == "HKPD":
self.args.registry = HKEY_PERFORMANCE_DATA
elif self.args.registry == "HKCC":
self.args.registry = HKEY_CURRENT_CONFIG
else:
#print "Non supported registry type"
raise AttributeError
def connect_registry(self):
"""
Getting a registry open
Keyword arguments:
@return connected_registy -- Reference to the newly opened
registry
"""
return ConnectRegistry(None,self.args.registry)
def create_registry_from_dict_chain(
self, dict_chain, both = False, architect = KEY_WOW64_64KEY,
needed_rights = KEY_ALL_ACCESS):
""""
Create registry key and value multilevel tree by chained
dictionaries.
Can raise AttributeError if the provided dict chain isn't
correct
Keyword arguments:
@param key_value_chain -- The dict chain containing all the
information
@param both -- Whether create the registry in WOW64
node too
@param architect -- The current registry view (
only change it if we want to fill the
WOW6432 registry only [both = False],
on x64 windows)
@param needed_rights -- SAM rights to access the key
"""
if both and architect is KEY_WOW64_64KEY:
self.create_registry_from_dict_chain(
dict_chain, False, KEY_WOW64_32KEY, needed_rights)
if not DecideArchitecture.Is64Windows():
architect = 0
connected_registy = self.connect_registry()
if (isinstance(dict_chain, dict)
or isinstance(dict_chain, OrderedDict)):
for key, value in dict_chain.iteritems():
if isinstance(value, dict) or isinstance(value, OrderedDict):
temp_dict = OrderedDict()
for my_key, my_value in value.iteritems():
temp_dict[key+"\\"+my_key] = my_value
self.create_registry_from_dict_chain(
temp_dict, False, architect, needed_rights)
else:
if isinstance(value, list):
if len(value)%2 != 0:
#print "Not enough member in the list"
raise AttributeError
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
temp_dict = OrderedDict(
value[i:i+2] for i in range(
0, len(value), 2))
for my_key, my_value in temp_dict.iteritems():
if my_key == "default":
my_key = None
SetValueEx(
new_key, my_key, 0, REG_SZ, my_value)
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
SetValueEx(new_key, None, 0, REG_SZ, value)
else:
print "The provided attribute wasn't a dictionary chain"
raise AttributeError
def get_key(self, key_name, needed_rights = KEY_ALL_ACCESS):
"""
Getting a registry value by it's key's name
Can raise KeyError if key is not found in the registry
Keyword arguments:
@param key_name -- The specific key name of which value we
are interested in
@param needed_rights -- SAM rights to access the key
@return -- [key, architect]
key -- Reference to the opened
key handler
architect -- 0 for x86
KEY_WOW64_32KEY or
KEY_WOW64_64KEY
depending where we
found the key on x64
"""
connected_registy = self.connect_registry()
architect = 0
if DecideArchitecture.Is64Windows():
architect = KEY_WOW64_64KEY
try:
key = OpenKey(connected_registy, key_name, 0,
needed_rights | architect)
except WindowsError:
if DecideArchitecture.Is64Windows() and not self.args.different:
try:
architect = KEY_WOW64_32KEY
key = OpenKey(connected_registy, key_name,
0, needed_rights | architect)
except WindowsError:
raise KeyError
else:
raise KeyError
return [key, architect]
def get_key_values(
self, key_name, subkey_list, subroutine = False,
depth = "subkeys"):
"""
Getting registry subkeys value by it's key's name and subkeys
name
Can raise LookupError exception if there are missing data
Can raise AttributeError exception if depth attribute is wrong
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_list -- List containing all the subkeys names
which values we are interested in
@param subroutine -- Whether suppress exception about not
having enough results or not
(default: False)
@param depth -- How depth the search should go for
[options: key, subkeys, all]
(default: subkeys)
@return results{} -- Dictionary with the subkey_name - value
combinations as keys and values
"""
if depth == "key":
int_depth = 0;
elif depth == "subkeys":
int_depth = 1;
elif depth == "all":
int_depth = 2;
else:
raise AttributeError
try:
key_and_architect = self.get_key(key_name)
key = key_and_architect[0]
architect = key_and_architect[1]
except KeyError:
#print "%s doesn't exist in the registry" % key_name
raise LookupError
#print "%s found in the registry" % key_name
results = {}
if int_depth >= 1:
for i in xrange(0, QueryInfoKey(key)[0]-1):
skey_name = EnumKey(key, i)
skey = OpenKey(key, skey_name, 0, KEY_ALL_ACCESS | architect)
if int_depth == 2 and QueryInfoKey(skey)[0] > 0:
for key, value in self.get_key_values(
skey_name, subkey_list, True, depth).iteritems():
results[key] = value
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(
skey, subkey_name)[0]
except OSError as e:
if e.errno == errno.ENOENT:
#print ("%s doesn't exist in this" % subkey_name
# " subkey")
pass
skey.Close()
if not results or len(results) != len(subkey_list):
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(key, subkey_name)[0]
except OSError as e:
pass
key.Close()
if len(results) != len(subkey_list):
#print "We are missing important variables"
raise LookupError
return results
def get_key_value(
self, key_name, subkey_name, subroutine = None, depth = None):
"""
This is a wrapper for the get_key_values to be easier to use
for single subkeys.
Getting registry subkey value by it's key's name and subkey
name
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_name -- The specific subkey name which value we
are interested in
@param subroutine -- can be found at: get_key_values
@param depth -- can be found at: get_key_values
@return value -- Value of the specific subkey
"""
try:
if subroutine is None:
return self.get_key_values(key_name,
[subkey_name])[subkey_name]
elif depth is None:
return self.get_key_values(key_name, [subkey_name],
subroutine)[subkey_name]
else:
return self.get_key_values(key_name, [subkey_name],
subroutine, depth)[subkey_name]
except:
raise
class DecideArchitecture:
"""
Helper class to get the true ProgramFiles directory.
This class doesn't depend on Phyton or Windows architecture.
"""
@staticmethod
def Is64Windows():
return 'PROGRAMFILES(X86)' in os.environ
@staticmethod
def GetProgramFiles32():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMFILES(X86)']
else:
return os.environ['PROGRAMFILES']
@staticmethod
def GetProgramFiles64():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMW6432']
else:
return None
def main():
try:
args = parse_arguments()
nx_install_location = None
while nx_install_location is None:
print "Checking whether NX Client for Windows is installed"
handler = RegistryHandler()
handler = windowsclasses.RegistryHandler()
try:
nx_install_location = handler.get_key_value(
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"+
......@@ -369,7 +64,6 @@ def main():
"\\nxclient-3.5.0-9.exe").wait()
except:
pass
if __name__ == "__main__":
main()
\ No newline at end of file
......@@ -8,7 +8,7 @@ Pywin32 installer for CIRCLE client application
import os
import sys
import subprocess
from nx_client_installer import DecideArchitecture
import windowsclasses
def main():
......@@ -27,7 +27,7 @@ def main():
else:
pywin32_version = str(219)
if sys.hexversion < 0x02070000:
if DecideArchitecture.Is64Windows():
if windowsclasses.DecideArchitecture.Is64Windows():
subprocess.Popen(
"%s\\x64\\pywin32-%s.win-amd64-py2.6.exe" % (
os.path.dirname(os.path.realpath(__file__)),
......@@ -38,7 +38,7 @@ def main():
os.path.dirname(os.path.realpath(__file__)),
pywin32_version)).wait()
elif sys.hexversion < 0x02080000:
if DecideArchitecture.Is64Windows():
if windowsclasses.DecideArchitecture.Is64Windows():
subprocess.Popen(
"%s\\x64\\pywin32-%s.win-amd64-py2.7.exe" % (
os.path.dirname(os.path.realpath(__file__)),
......
......@@ -9,11 +9,12 @@ import os
import argparse
import subprocess
import pythoncom
import shutil
from win32com.shell import shell, shellcon
from nx_client_installer import DecideArchitecture, RegistryHandler, Struct
import windowsclasses
try:
from collections import *
except ImporError:
except ImportError:
from OrderedDict import *
......@@ -32,10 +33,12 @@ def parse_arguments():
"first the proper driver.", type=str, default="firefox",
required=False, choices=['firefox', 'chrome',
'iexplore', 'opera'])
if DecideArchitecture.Is64Windows():
local_default = DecideArchitecture.GetProgramFiles64()+"\\CIRCLE\\"
if windowsclasses.DecideArchitecture.Is64Windows():
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles64()
+"\\CIRCLE\\")
else:
local_default = DecideArchitecture.GetProgramFiles32()+"\\CIRCLE\\"
local_default = (windowsclasses.DecideArchitecture.GetProgramFiles32()
+"\\CIRCLE\\")
if (not os.path.exists(local_default[:-1])
and os.path.exists(os.environ['APPDATA']+"\\CIRCLE")):
local_default = os.environ['APPDATA']+"\\CIRCLE\\"
......@@ -53,7 +56,7 @@ def parse_arguments():
parser.add_argument(
"-t", "--target",
help="If this is an URL icon, where should it point",
default="https://pc3.szgt.uni-miskolc.hu/", required=False)
default="https://cloud.bme.hu/", required=False)
args = parser.parse_args()
return args
......@@ -69,9 +72,9 @@ def custom_protocol_register(custom_protocol):
raise AttributeError
print "\t"+custom_protocol.iterkeys().next()
try:
custom_arguments = Struct()
custom_arguments = windowsclasses.Struct()
custom_arguments.registry = "HKCR"
handler = RegistryHandler(custom_arguments)
handler = windowsclasses.RegistryHandler(custom_arguments)
handler.create_registry_from_dict_chain(custom_protocol, True)
print "\t\tDone!"
except:
......@@ -79,14 +82,14 @@ def custom_protocol_register(custom_protocol):
def main():
"""
Main program
"""
Main program
Jobs:
read the parameters
create a proper icon with the proper driver (or delete)
call the nx_client_installer
"""
Jobs:
read the parameters
create a proper icon with the proper driver (or delete)
call the nx_client_installer
"""
try:
args = parse_arguments()
shortcut = pythoncom.CoCreateInstance (
......@@ -95,9 +98,10 @@ def main():
pythoncom.CLSCTX_INPROC_SERVER,
shell.IID_IShellLink
)
desktop_path = shell.SHGetFolderPath (0, shellcon.CSIDL_DESKTOP, 0, 0)
desktop_path = shell.SHGetFolderPath (
0, shellcon.CSIDL_DESKTOP, 0, 0)
if args.remove:
location =os.path.join(desktop_path, "Cloud GUI")
location = os.path.join(desktop_path, "Cloud GUI")
if os.path.isfile("%s%s" % (location, ".lnk")):
os.remove("%s%s" % (location, ".lnk"))
if os.path.isfile("%s%s" % (location, ".url")):
......@@ -126,9 +130,10 @@ def main():
0, shellcon.CSIDL_DESKTOP, 0, 0)
persist_file = shortcut.QueryInterface(
pythoncom.IID_IPersistFile)
persist_file.Save(
os.path.join(desktop_path, "Cloud GUI.lnk"), 0)
location = os.path.join(desktop_path, "Cloud GUI.lnk")
persist_file.Save(location, 0)
print "Icon successfully created on desktop"
shutil.copy(location, args.location)
print "Creating custom URL protocol handlers"
try:
custom_ssh = OrderedDict(
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Place holder for all windows specific frequently used classes.
Currently here:
RegistryHandler - Registry based operations
DecideArchitecture - Accurate way to decide operating system architecture
"""
import os
import argparse
import errno
from _winreg import *
try:
from collections import *
except ImporError:
from OrderedDict import *
def parse_arguments():
"""
Argument parser, based on argparse module
Keyword arguments:
@return args -- arguments given by console
"""
parser = argparse.ArgumentParser()
parser.add_argument(
"-g", "--global",
help="Whether we want to edit registry globally or just locally",
action="store_true")
parser.add_argument(
"-d", "--different",
help="Only handle the architecture specific registry area",
action="store_true")
parser.add_argument(
"-r", "--registry",
help="Which HKEY_* const registry type the program should use",
type=str, choices=['HKLM', 'HKCR', 'HKCU', 'HKU', 'HKPD', 'HKCC'],
default="HKLM")
args = parser.parse_args()
return args
def main():
return RegistryHandler(parse_arguments())
class Struct:
"""
Parameter bypassing struct
"""
pass
class RegistryHandler:
"""
Registry handling class, makes registry based queries and
manipulations easier.
This class can handle WOW64 based application differently and none
differently (default)
"""
def __init__(self, args = None):
"""Initialise RegistryHandler
Keyword arguments:
@param args -- The arguments that decide how the we should
handle the registry
args.registry -- What base registry should we use
(default: HKLM)
Raises AttributeError if not supported base registry type is
given
args.different -- Whether we handle registry redirection or not
"""
if args is None:
self.args = Struct()
self.args.different = None
self.args.registry = None
else:
if not hasattr(args, 'different'):
args.different = None
if not hasattr(args, 'registry'):
args.registry = None
self.args = args
if self.args.different is None:
self.args.different = False
if self.args.registry is None or self.args.registry == "HKLM":
self.args.registry = HKEY_LOCAL_MACHINE
elif self.args.registry == "HKCR":
self.args.registry = HKEY_CLASSES_ROOT
elif self.args.registry == "HKCU":
self.args.registry = HKEY_CURRENT_USER
elif self.args.registry == "HKU":
self.args.registry = HKEY_USERS
elif self.args.registry == "HKPD":
self.args.registry = HKEY_PERFORMANCE_DATA
elif self.args.registry == "HKCC":
self.args.registry = HKEY_CURRENT_CONFIG
else:
#print "Non supported registry type"
raise AttributeError
def connect_registry(self):
"""
Getting a registry open
Keyword arguments:
@return connected_registy -- Reference to the newly opened
registry
"""
return ConnectRegistry(None,self.args.registry)
def create_registry_from_dict_chain(
self, dict_chain, both = False, architect = KEY_WOW64_64KEY,
needed_rights = KEY_ALL_ACCESS):
""""
Create registry key and value multilevel tree by chained
dictionaries.
Can raise AttributeError if the provided dict chain isn't
correct
Keyword arguments:
@param key_value_chain -- The dict chain containing all the
information
@param both -- Whether create the registry in WOW64
node too
@param architect -- The current registry view (
only change it if we want to fill the
WOW6432 registry only [both = False],
on x64 windows)
@param needed_rights -- SAM rights to access the key
"""
if both and architect is KEY_WOW64_64KEY:
self.create_registry_from_dict_chain(
dict_chain, False, KEY_WOW64_32KEY, needed_rights)
if not DecideArchitecture.Is64Windows():
architect = 0
connected_registy = self.connect_registry()
if (isinstance(dict_chain, dict)
or isinstance(dict_chain, OrderedDict)):
for key, value in dict_chain.iteritems():
if isinstance(value, dict) or isinstance(value, OrderedDict):
temp_dict = OrderedDict()
for my_key, my_value in value.iteritems():
temp_dict[key+"\\"+my_key] = my_value
self.create_registry_from_dict_chain(
temp_dict, False, architect, needed_rights)
else:
if isinstance(value, list):
if len(value)%2 != 0:
#print "Not enough member in the list"
raise AttributeError
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
temp_dict = OrderedDict(
value[i:i+2] for i in range(
0, len(value), 2))
for my_key, my_value in temp_dict.iteritems():
if my_key == "default":
my_key = None
SetValueEx(
new_key, my_key, 0, REG_SZ, my_value)
else:
new_key = CreateKeyEx(
connected_registy, key, 0,
needed_rights | architect)
SetValueEx(new_key, None, 0, REG_SZ, value)
else:
print "The provided attribute wasn't a dictionary chain"
raise AttributeError
def get_key(self, key_name, needed_rights = KEY_ALL_ACCESS):
"""
Getting a registry value by it's key's name
Can raise KeyError if key is not found in the registry
Keyword arguments:
@param key_name -- The specific key name of which value we
are interested in
@param needed_rights -- SAM rights to access the key
@return -- [key, architect]
key -- Reference to the opened
key handler
architect -- 0 for x86
KEY_WOW64_32KEY or
KEY_WOW64_64KEY
depending where we
found the key on x64
"""
connected_registy = self.connect_registry()
architect = 0
if DecideArchitecture.Is64Windows():
architect = KEY_WOW64_64KEY
try:
key = OpenKey(connected_registy, key_name, 0,
needed_rights | architect)
except WindowsError:
if DecideArchitecture.Is64Windows() and not self.args.different:
try:
architect = KEY_WOW64_32KEY
key = OpenKey(connected_registy, key_name,
0, needed_rights | architect)
except WindowsError:
raise KeyError
else:
raise KeyError
return [key, architect]
def get_key_values(
self, key_name, subkey_list, subroutine = False,
depth = "subkeys"):
"""
Getting registry subkeys value by it's key's name and subkeys
name
Can raise LookupError exception if there are missing data
Can raise AttributeError exception if depth attribute is wrong
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_list -- List containing all the subkeys names
which values we are interested in
@param subroutine -- Whether suppress exception about not
having enough results or not
(default: False)
@param depth -- How depth the search should go for
[options: key, subkeys, all]
(default: subkeys)
@return results{} -- Dictionary with the subkey_name - value
combinations as keys and values
"""
if depth == "key":
int_depth = 0;
elif depth == "subkeys":
int_depth = 1;
elif depth == "all":
int_depth = 2;
else:
raise AttributeError
try:
key_and_architect = self.get_key(key_name)
key = key_and_architect[0]
architect = key_and_architect[1]
except KeyError:
#print "%s doesn't exist in the registry" % key_name
raise LookupError
#print "%s found in the registry" % key_name
results = {}
if int_depth >= 1:
for i in xrange(0, QueryInfoKey(key)[0]-1):
skey_name = EnumKey(key, i)
skey = OpenKey(key, skey_name, 0, KEY_ALL_ACCESS | architect)
if int_depth == 2 and QueryInfoKey(skey)[0] > 0:
for key, value in self.get_key_values(
skey_name, subkey_list, True, depth).iteritems():
results[key] = value
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(
skey, subkey_name)[0]
except OSError as e:
if e.errno == errno.ENOENT:
#print ("%s doesn't exist in this" % subkey_name
# " subkey")
pass
skey.Close()
if not results or len(results) != len(subkey_list):
for subkey_name in subkey_list:
try:
results[subkey_name] = QueryValueEx(key, subkey_name)[0]
except OSError as e:
pass
key.Close()
if len(results) != len(subkey_list):
#print "We are missing important variables"
raise LookupError
return results
def get_key_value(
self, key_name, subkey_name, subroutine = None, depth = None):
"""
This is a wrapper for the get_key_values to be easier to use
for single subkeys.
Getting registry subkey value by it's key's name and subkey
name
Keyword arguments:
@param key_name -- The specific key name of which subkey's
we are interested in
@param subkey_name -- The specific subkey name which value we
are interested in
@param subroutine -- can be found at: get_key_values
@param depth -- can be found at: get_key_values
@return value -- Value of the specific subkey
"""
try:
if subroutine is None:
return self.get_key_values(key_name,
[subkey_name])[subkey_name]
elif depth is None:
return self.get_key_values(key_name, [subkey_name],
subroutine)[subkey_name]
else:
return self.get_key_values(key_name, [subkey_name],
subroutine, depth)[subkey_name]
except:
raise
class DecideArchitecture:
"""
Helper class to get the true ProgramFiles directory.
This class doesn't depend on Phyton or Windows architecture.
"""
@staticmethod
def Is64Windows():
return 'PROGRAMFILES(X86)' in os.environ
@staticmethod
def GetProgramFiles32():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMFILES(X86)']
else:
return os.environ['PROGRAMFILES']
@staticmethod
def GetProgramFiles64():
if DecideArchitecture.Is64Windows():
return os.environ['PROGRAMW6432']
else:
return None
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment