This commit is contained in:
Adolfo Gómez 2021-01-20 12:42:38 +01:00
commit f0b6726e19
151 changed files with 997 additions and 8800 deletions

View File

@ -57,6 +57,7 @@ class ForwardServer(socketserver.ThreadingTCPServer):
remote: typing.Tuple[str, int]
ticket: str
stop_flag: threading.Event
can_stop: bool
timeout: int
timer: typing.Optional[threading.Timer]
check_certificate: bool
@ -79,20 +80,22 @@ class ForwardServer(socketserver.ThreadingTCPServer):
)
self.remote = remote
self.ticket = ticket
self.timeout = int(time.time()) + timeout if timeout else 0
# Negative values for timeout, means "accept always connections"
# "but if no connection is stablished on timeout (positive)"
# "stop the listener"
self.timeout = int(time.time()) + timeout if timeout > 0 else 0
self.check_certificate = check_certificate
self.stop_flag = threading.Event() # False initial
self.current_connections = 0
self.status = TUNNEL_LISTENING
self.can_stop = False
if timeout:
timeout = abs(timeout) or 60
self.timer = threading.Timer(
timeout, ForwardServer.__checkStarted, args=(self,)
abs(timeout), ForwardServer.__checkStarted, args=(self,)
)
self.timer.start()
else:
self.timer = None
def stop(self) -> None:
if not self.stop_flag.is_set():
@ -120,6 +123,9 @@ class ForwardServer(socketserver.ThreadingTCPServer):
return context.wrap_socket(rsocket, server_hostname=self.remote[0])
def check(self) -> bool:
if self.status == TUNNEL_ERROR:
return False
try:
with self.connect() as ssl_socket:
ssl_socket.sendall(HANDSHAKE_V1 + b'TEST')
@ -135,11 +141,14 @@ class ForwardServer(socketserver.ThreadingTCPServer):
@property
def stoppable(self) -> bool:
return self.timeout != 0 and int(time.time()) > self.timeout
logger.debug('Is stoppable: %s', self.can_stop)
return self.can_stop or (self.timeout != 0 and int(time.time()) > self.timeout)
@staticmethod
def __checkStarted(fs: 'ForwardServer') -> None:
logger.debug('New connection limit reached')
fs.timer = None
fs.can_stop = True
if fs.current_connections <= 0:
fs.stop()
@ -150,15 +159,17 @@ class Handler(socketserver.BaseRequestHandler):
# server: ForwardServer
def handle(self) -> None:
self.server.current_connections += 1
self.server.status = TUNNEL_OPENING
# If server processing is over time
if self.server.stoppable:
logger.info('Rejected timedout connection try')
self.server.status = TUNNEL_ERROR
logger.info('Rejected timedout connection')
self.request.close() # End connection without processing it
return
self.server.current_connections += 1
# Open remote connection
try:
logger.debug('Ticket %s', self.server.ticket)
@ -169,7 +180,9 @@ class Handler(socketserver.BaseRequestHandler):
data = ssl_socket.recv(2)
if data != b'OK':
data += ssl_socket.recv(128)
raise Exception(f'Error received: {data.decode(errors="ignore")}') # Notify error
raise Exception(
f'Error received: {data.decode(errors="ignore")}'
) # Notify error
# All is fine, now we can tunnel data
self.process(remote=ssl_socket)

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014-2019 Virtual Cable S.L.
# Copyright (c) 2014-2021 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -423,6 +422,13 @@ class Login(LoginLogout):
"""
name = 'login'
@staticmethod
def process_login(userService: UserService, username: str) -> typing.Optional[osmanagers.OSManager]:
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
if not userService.in_use: # If already logged in, do not add a second login (windows does this i.e.)
osmanagers.OSManager.loggedIn(userService, username)
return osManager
def action(self) -> typing.MutableMapping[str, typing.Any]:
isManaged = self._params.get('type') != UNMANAGED
ip = hostname = ''
@ -432,9 +438,7 @@ class Login(LoginLogout):
try:
userService: UserService = self.getUserService()
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
if not userService.in_use: # If already logged in, do not add a second login (windows does this i.e.)
osmanagers.OSManager.loggedIn(userService, self._params.get('username') or '')
osManager = Login.process_login(userService, self._params.get('username') or '')
maxIdle = osManager.maxIdle() if osManager else None
@ -462,21 +466,29 @@ class Logout(LoginLogout):
"""
name = 'logout'
def action(self) -> typing.MutableMapping[str, typing.Any]:
isManaged = self._params.get('type') != UNMANAGED
logger.debug('Args: %s, Params: %s', self._args, self._params)
try:
userService: UserService = self.getUserService()
@staticmethod
def process_logout(userService: UserService, username: str) -> None:
"""
This method is static so can be invoked from elsewhere
"""
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
if userService.in_use: # If already logged out, do not add a second logout (windows does this i.e.)
osmanagers.OSManager.loggedOut(userService, self._params.get('username') or '')
osmanagers.OSManager.loggedOut(userService, username)
if osManager:
if osManager.isRemovableOnLogout(userService):
logger.debug('Removable on logout: %s', osManager)
userService.remove()
else:
userService.remove()
def action(self) -> typing.MutableMapping[str, typing.Any]:
isManaged = self._params.get('type') != UNMANAGED
logger.debug('Args: %s, Params: %s', self._args, self._params)
try:
userService: UserService = self.getUserService()
Logout.process_logout(userService, self._params.get('username') or '')
except Exception: # If unamanaged host, lest do a bit more work looking for a service with the provided parameters...
if isManaged:
raise

View File

@ -177,7 +177,7 @@ class OSManager(Module):
Helper method that informs if the os manager transforms the username and/or the password.
This is used from ServicePool
"""
return cls.processUserPassword != OSManager.processUserPassword
return hash(cls.processUserPassword) != hash(OSManager.processUserPassword)
def processUserPassword(self, userService: 'UserService', username: str, password: str) -> typing.Tuple[str, str]:
"""
@ -299,5 +299,5 @@ class OSManager(Module):
"""
return False
def __str__(self):
def __str__(self) -> str:
return "Base OS Manager"

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''

View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^uds/ognotify/(?P<msg>[a-z]+)/(?P<token>[a-zA-Z0-9-_]+)/(?P<uuid>[a-zA-Z0-9-_]+)$', views.opengnsys, name='dispatcher.opengnsys'),
]

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
import typing
import logging
from django.http import HttpResponse, HttpRequest
from uds.REST.methods import actor_v3
from uds.core.auths import auth
from uds.models import UserService
from uds.core.util.model import processUuid
from uds.core.util import states
logger = logging.getLogger(__name__)
OK = 'OK'
CONTENT_TYPE = 'text/plain'
@auth.trustedSourceRequired
def opengnsys(request: HttpRequest, msg: str, token: str, uuid: str) -> HttpResponse:
logger.debug('Received opengnsys message %s, token %s, uuid %s', msg, token, uuid)
def getUserService() -> typing.Optional[UserService]:
try:
userService = UserService.objects.get(uuid=processUuid(uuid), state=states.userService.USABLE)
if userService.getProperty('token') == token:
return userService
logger.warning(
'OpenGnsys: invalid token %s for userService %s. (Ignored)',
token,
uuid,
)
# Sleep a while in case of error?
except Exception as e:
# Any exception will stop process
logger.warning('OpenGnsys: invalid userService %s:%s. (Ignored)', token, uuid)
return None
def release() -> None:
userService = getUserService()
if userService:
logger.info('Released from OpenGnsys %s', userService.friendly_name)
userService.setProperty('from_release', '1')
userService.release()
def login() -> None:
userService = getUserService()
if userService:
# Ignore login to cached machines...
if userService.cache_level != 0:
logger.info('Ignored OpenGnsys login to %s to cached machine', userService.friendly_name)
return
logger.debug('Processing login from OpenGnsys %s', userService.friendly_name)
actor_v3.Login.process_login(userService, 'OpenGnsys')
def logout() -> None:
userService = getUserService()
if userService:
# Ignore logout to cached machines...
if userService.cache_level != 0:
logger.info('Ignored OpenGnsys logout to %s to cached machine', userService.friendly_name)
return
logger.debug('Processing logout from OpenGnsys %s', userService.friendly_name)
actor_v3.Logout.process_logout(userService, 'OpenGnsys')
fnc: typing.Optional[typing.Callable[[], None]] = {
'login': login,
'logout': logout,
'release': release,
}.get(msg)
if fnc:
fnc()
# Silently fail errors, do not notify anything (not needed anyway)
return HttpResponse(OK, content_type=CONTENT_TYPE)

View File

@ -197,12 +197,12 @@ class LinuxOsManager(osmanagers.OSManager):
elif message == "log":
self.doLog(userService, data, log.ACTOR)
elif message == "login":
osmanagers.OSManager.loggedIn(userService, data)
osmanagers.OSManager.loggedIn(userService, typing.cast(str, data))
ip, hostname = userService.getConnectionSource()
deadLine = userService.deployed_service.getDeadline()
ret = "{}\t{}\t{}".format(ip, hostname, 0 if deadLine is None else deadLine)
elif message == "logout":
osmanagers.OSManager.loggedOut(userService, data)
osmanagers.OSManager.loggedOut(userService, typing.cast(str, data))
doRemove = self.isRemovableOnLogout(userService)
elif message == "ip":
# This ocurss on main loop inside machine, so userService is usable

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017-2019 Virtual Cable S.L.
# Copyright (c) 2017-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 Virtual Cable S.L.
# Copyright (c) 2015-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -34,6 +34,7 @@ import logging
import typing
from uds.core.services import UserDeployment
from uds.core.managers import cryptoManager
from uds.core.util.state import State
from uds.core.util import log
from uds.models.util import getSqlDatetimeAsUnix
@ -47,7 +48,7 @@ if typing.TYPE_CHECKING:
logger = logging.getLogger(__name__)
opCreate, opError, opFinish, opRemove, opRetry = range(5)
opCreate, opError, opFinish, opRemove, opRetry, opStart = range(6)
class OGDeployment(UserDeployment):
@ -71,7 +72,9 @@ class OGDeployment(UserDeployment):
_stamp: int = 0
_reason: str = ''
_queue: typing.List[int] # Do not initialize mutable, just declare and it is initialized on "initialize"
_queue: typing.List[
int
] # Do not initialize mutable, just declare and it is initialized on "initialize"
_uuid: str
def initialize(self) -> None:
@ -93,7 +96,8 @@ class OGDeployment(UserDeployment):
"""
Does nothing right here, we will use environment storage in this sample
"""
return b'\1'.join([
return b'\1'.join(
[
b'v1',
self._name.encode('utf8'),
self._ip.encode('utf8'),
@ -101,8 +105,9 @@ class OGDeployment(UserDeployment):
self._machineId.encode('utf8'),
self._reason.encode('utf8'),
str(self._stamp).encode('utf8'),
pickle.dumps(self._queue, protocol=0)
])
pickle.dumps(self._queue, protocol=0),
]
)
def unmarshal(self, data: bytes) -> None:
"""
@ -135,11 +140,34 @@ class OGDeployment(UserDeployment):
OpenGnsys will try it best by sending an WOL
"""
dbs = self.dbservice()
deadline = dbs.deployed_service.getDeadline() if dbs else 0
self.service().notifyDeadline(self._machineId, deadline)
if not dbs:
return State.FINISHED
try:
# First, check Machine is alive..
status = self.__checkMachineReady()
if status == State.FINISHED:
self.service().notifyDeadline(
self._machineId, dbs.deployed_service.getDeadline()
)
return State.FINISHED
if status == State.ERROR:
return State.ERROR
# Machine powered off, check what to do...
if self.service().isRemovableIfUnavailable():
return self.__error(
'Machine is unavailable and service has "Remove if unavailable" flag active.'
)
# Try to start it, and let's see
self._queue = [opStart, opFinish]
return self.__executeQueue()
except Exception as e:
return self.__error('Error setting ready state: {}'.format(e))
def deployForUser(self, user: 'models.User') -> str:
"""
Deploys an service instance for an user.
@ -159,7 +187,11 @@ class OGDeployment(UserDeployment):
self._queue = [opCreate, opFinish]
def __checkMachineReady(self) -> str:
logger.debug('Checking that state of machine %s (%s) is ready', self._machineId, self._name)
logger.debug(
'Checking that state of machine %s (%s) is ready',
self._machineId,
self._name,
)
try:
status = self.service().status(self._machineId)
@ -202,7 +234,11 @@ class OGDeployment(UserDeployment):
logger.debug('Setting error state, reason: %s', reason)
self.doLog(log.ERROR, reason)
# TODO: Unreserve machine?? Maybe it just better to keep it assigned so UDS don't get it again in a while...
if self._machineId:
try:
self.service().unreserve(self._machineId)
except Exception:
pass
self._queue = [opError]
self._reason = str(reason)
@ -222,13 +258,16 @@ class OGDeployment(UserDeployment):
opCreate: self.__create,
opRetry: self.__retry,
opRemove: self.__remove,
opStart: self.__start,
}
try:
execFnc: typing.Optional[typing.Callable[[], str]] = fncs.get(op, None)
execFnc: typing.Optional[typing.Callable[[], str]] = fncs.get(op)
if execFnc is None:
return self.__error('Unknown operation found at execution queue ({0})'.format(op))
return self.__error(
'Unknown operation found at execution queue ({0})'.format(op)
)
execFnc()
@ -252,10 +291,11 @@ class OGDeployment(UserDeployment):
"""
Deploys a machine from template for user/cache
"""
try:
r: typing.Any = None
token = cryptoManager().randomString(32)
try:
r = self.service().reserve()
self.service().notifyEvents(r['id'], self._uuid)
self.service().notifyEvents(r['id'], token, self._uuid)
except Exception as e:
# logger.exception('Creating machine')
if r: # Reservation was done, unreserve it!!!
@ -274,18 +314,35 @@ class OGDeployment(UserDeployment):
self._ip = r['ip']
self._stamp = getSqlDatetimeAsUnix()
self.doLog(
log.INFO,
f'Reserved machine {self._name}: id: {self._machineId}, mac: {self._mac}, ip: {self._ip}',
)
# Store actor version & Known ip
dbs = self.dbservice()
if dbs:
dbs.setProperty('actor_version', '1.0-OpenGnsys')
dbs.setProperty('actor_version', '1.1-OpenGnsys')
dbs.setProperty('token', token)
dbs.logIP(self._ip)
return State.RUNNING
def __start(self) -> str:
if self._machineId:
self.service().powerOn(self._machineId)
return State.RUNNING
def __remove(self) -> str:
"""
Removes a machine from system
Avoids "double unreserve" in case the reservation was made from release
"""
dbs = self.dbservice()
if dbs:
# On release callback, we will set a property on DB called "from_release"
# so we can avoid double unreserve
if dbs.getProperty('from_release') is None:
self.service().unreserve(self._machineId)
return State.RUNNING
@ -296,6 +353,9 @@ class OGDeployment(UserDeployment):
"""
return self.__checkMachineReady()
# Alias for poweron check
__checkStart = __checkCreate
def __checkRemoved(self) -> str:
"""
Checks if a machine has been removed
@ -319,13 +379,18 @@ class OGDeployment(UserDeployment):
opCreate: self.__checkCreate,
opRetry: self.__retry,
opRemove: self.__checkRemoved,
opStart: self.__checkStart,
}
try:
chkFnc: typing.Optional[typing.Optional[typing.Callable[[], str]]] = fncs.get(op, None)
chkFnc: typing.Optional[
typing.Optional[typing.Callable[[], str]]
] = fncs.get(op)
if chkFnc is None:
return self.__error('Unknown operation found at check queue ({0})'.format(op))
return self.__error(
'Unknown operation found at check queue ({0})'.format(op)
)
state = chkFnc()
if state == State.FINISHED:
@ -379,4 +444,12 @@ class OGDeployment(UserDeployment):
}.get(op, '????')
def __debug(self, txt) -> None:
logger.debug('State at %s: name: %s, ip: %s, mac: %s, machine:%s, queue: %s', txt, self._name, self._ip, self._mac, self._machineId, [OGDeployment.__op2str(op) for op in self._queue])
logger.debug(
'State at %s: name: %s, ip: %s, mac: %s, machine:%s, queue: %s',
txt,
self._name,
self._ip,
self._mac,
self._machineId,
[OGDeployment.__op2str(op) for op in self._queue],
)

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 Virtual Cable S.L.
# Copyright (c) 2015-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -53,8 +53,12 @@ def getResources(parameters: typing.Any) -> typing.List[typing.Dict[str, typing.
api = provider.api
labs = [gui.choiceItem('0', _('All Labs'))] + [gui.choiceItem(l['id'], l['name']) for l in api.getLabs(ou=parameters['ou'])]
images = [gui.choiceItem(z['id'], z['name']) for z in api.getImages(ou=parameters['ou'])]
labs = [gui.choiceItem('0', _('All Labs'))] + [
gui.choiceItem(l['id'], l['name']) for l in api.getLabs(ou=parameters['ou'])
]
images = [
gui.choiceItem(z['id'], z['name']) for z in api.getImages(ou=parameters['ou'])
]
data = [
{'name': 'lab', 'values': labs},

View File

@ -56,17 +56,22 @@ def ensureConnected(fnc: typing.Callable[..., RT]) -> typing.Callable[..., RT]:
def inner(*args, **kwargs) -> RT:
args[0].connect()
return fnc(*args, **kwargs)
return inner
# Result checker
def ensureResponseIsValid(response: requests.Response, errMsg: typing.Optional[str] = None) -> typing.Any:
def ensureResponseIsValid(
response: requests.Response, errMsg: typing.Optional[str] = None
) -> typing.Any:
if not response.ok:
if not errMsg:
errMsg = 'Invalid response'
try:
err = response.json()['message'] # Extract any key, in case of error is expected to have only one top key so this will work
err = response.json()[
'message'
] # Extract any key, in case of error is expected to have only one top key so this will work
except Exception:
err = response.content
errMsg = '{}: {}, ({})'.format(errMsg, err, response.status_code)
@ -76,7 +81,11 @@ def ensureResponseIsValid(response: requests.Response, errMsg: typing.Optional[s
try:
return json.loads(response.content)
except Exception:
raise Exception('Error communicating with OpenGnsys: {}'.format(response.content[:128].decode()))
raise Exception(
'Error communicating with OpenGnsys: {}'.format(
response.content[:128].decode()
)
)
class OpenGnsysClient:
@ -88,7 +97,14 @@ class OpenGnsysClient:
verifyCert: bool
cachedVersion: typing.Optional[str]
def __init__(self, username: str, password: str, endpoint: str, cache: 'Cache', verifyCert: bool = False):
def __init__(
self,
username: str,
password: str,
endpoint: str,
cache: 'Cache',
verifyCert: bool = False,
):
self.username = username
self.password = password
self.endpoint = endpoint
@ -108,11 +124,18 @@ class OpenGnsysClient:
def _ogUrl(self, path: str) -> str:
return self.endpoint + '/' + path
def _post(self, path: str, data: typing.Any, errMsg: typing.Optional[str] = None) -> typing.Any:
def _post(
self, path: str, data: typing.Any, errMsg: typing.Optional[str] = None
) -> typing.Any:
if not FAKE:
return ensureResponseIsValid(
requests.post(self._ogUrl(path), data=json.dumps(data), headers=self.headers, verify=self.verifyCert),
errMsg=errMsg
requests.post(
self._ogUrl(path),
data=json.dumps(data),
headers=self.headers,
verify=self.verifyCert,
),
errMsg=errMsg,
)
# FAKE Connection :)
return fake.post(path, data, errMsg)
@ -120,8 +143,10 @@ class OpenGnsysClient:
def _get(self, path: str, errMsg: typing.Optional[str] = None) -> typing.Any:
if not FAKE:
return ensureResponseIsValid(
requests.get(self._ogUrl(path), headers=self.headers, verify=self.verifyCert),
errMsg=errMsg
requests.get(
self._ogUrl(path), headers=self.headers, verify=self.verifyCert
),
errMsg=errMsg,
)
# FAKE Connection :)
return fake.get(path, errMsg)
@ -129,8 +154,10 @@ class OpenGnsysClient:
def _delete(self, path: str, errMsg: typing.Optional[str] = None) -> typing.Any:
if not FAKE:
return ensureResponseIsValid(
requests.delete(self._ogUrl(path), headers=self.headers, verify=self.verifyCert),
errMsg=errMsg
requests.delete(
self._ogUrl(path), headers=self.headers, verify=self.verifyCert
),
errMsg=errMsg,
)
return fake.delete(path, errMsg)
@ -145,11 +172,8 @@ class OpenGnsysClient:
auth = self._post(
urls.LOGIN,
data={
'username': self.username,
'password': self.password
},
errMsg='Loggin in'
data={'username': self.username, 'password': self.password},
errMsg='Loggin in',
)
self.auth = auth['apikey']
@ -179,7 +203,11 @@ class OpenGnsysClient:
# /ous/{ouid}/labs
# Take into accout that we must exclude the ones with "inremotepc" set to false.
errMsg = 'Getting list of labs from ou {}'.format(ou)
return [{'id': l['id'], 'name': l['name']} for l in self._get(urls.LABS.format(ou=ou), errMsg=errMsg) if l.get('inremotepc', False) is True]
return [
{'id': l['id'], 'name': l['name']}
for l in self._get(urls.LABS.format(ou=ou), errMsg=errMsg)
if l.get('inremotepc', False) is True
]
@ensureConnected
def getImages(self, ou: str) -> typing.List[typing.MutableMapping[str, str]]:
@ -187,20 +215,23 @@ class OpenGnsysClient:
# /ous/{ouid}/images
# Take into accout that we must exclude the ones with "inremotepc" set to false.
errMsg = 'Getting list of images from ou {}'.format(ou)
return [{'id': l['id'], 'name': l['name']} for l in self._get(urls.IMAGES.format(ou=ou), errMsg=errMsg) if l.get('inremotepc', False) is True]
return [
{'id': l['id'], 'name': l['name']}
for l in self._get(urls.IMAGES.format(ou=ou), errMsg=errMsg)
if l.get('inremotepc', False) is True
]
@ensureConnected
def reserve(self, ou: str, image: str, lab: int = 0, maxtime: int = 24) -> typing.MutableMapping[str, typing.Union[str, int]]:
def reserve(
self, ou: str, image: str, lab: int = 0, maxtime: int = 24
) -> typing.MutableMapping[str, typing.Union[str, int]]:
# This method is inteded to "get" a machine from OpenGnsys
# The method used is POST
# invokes /ous/{ouid}}/images/{imageid}/reserve
# also remember to store "labid"
# Labid can be "0" that means "all laboratories"
errMsg = 'Reserving image {} in ou {}'.format(image, ou)
data = {
'labid': lab,
'maxtime': maxtime
}
data = {'labid': lab, 'maxtime': maxtime}
res = self._post(urls.RESERVE.format(ou=ou, image=image), data, errMsg=errMsg)
return {
'ou': ou,
@ -210,7 +241,7 @@ class OpenGnsysClient:
'id': '.'.join((str(ou), str(res['lab']['id']), str(res['id']))),
'name': res['name'],
'ip': res['ip'],
'mac': ':'.join(re.findall('..', res['mac']))
'mac': ':'.join(re.findall('..', res['mac'])),
}
@ensureConnected
@ -219,29 +250,48 @@ class OpenGnsysClient:
# Invoked every time we need to release a reservation (i mean, if a reservation is done, this will be called with the obtained id from that reservation)
ou, lab, client = machineId.split('.')
errMsg = 'Unreserving client {} in lab {} in ou {}'.format(client, lab, ou)
return self._delete(urls.UNRESERVE.format(ou=ou, lab=lab, client=client), errMsg=errMsg)
return self._delete(
urls.UNRESERVE.format(ou=ou, lab=lab, client=client), errMsg=errMsg
)
def powerOn(self, machineId, image):
# This method ask to poweron a machine to openGnsys
ou, lab, client = machineId.split('.')
errMsg = 'Powering on client {} in lab {} in ou {}'.format(client, lab, ou)
try:
data = {
'image': image,
}
return self._post(
urls.START.format(ou=ou, lab=lab, client=client), data, errMsg=errMsg
)
except Exception: # For now, if this fails, ignore it to keep backwards compat
return 'OK'
@ensureConnected
def notifyURLs(self, machineId: str, loginURL: str, logoutURL: str) -> typing.Any:
def notifyURLs(
self, machineId: str, loginURL: str, logoutURL: str, releaseURL: str
) -> typing.Any:
ou, lab, client = machineId.split('.')
errMsg = 'Notifying login/logout urls'
data = {
'urlLogin': loginURL,
'urlLogout': logoutURL
}
data = {'urlLogin': loginURL, 'urlLogout': logoutURL, 'urlRelease': releaseURL}
return self._post(urls.EVENTS.format(ou=ou, lab=lab, client=client), data, errMsg=errMsg)
return self._post(
urls.EVENTS.format(ou=ou, lab=lab, client=client), data, errMsg=errMsg
)
@ensureConnected
def notifyDeadline(self, machineId: str, deadLine: typing.Optional[int]) -> typing.Any:
def notifyDeadline(
self, machineId: str, deadLine: typing.Optional[int]
) -> typing.Any:
ou, lab, client = machineId.split('.')
deadLine = deadLine or 0
errMsg = 'Notifying deadline'
data = {
'deadLine': deadLine
}
data = {'deadLine': deadLine}
return self._post(urls.SESSIONS.format(ou=ou, lab=lab, client=client), data, errMsg=errMsg)
return self._post(
urls.SESSIONS.format(ou=ou, lab=lab, client=client), data, errMsg=errMsg
)
@ensureConnected
def status(self, id_: str) -> typing.Any:

View File

@ -40,20 +40,13 @@ from . import urls
logger = logging.getLogger(__name__)
AUTH = {
"userid": 1001,
"apikey": "fakeAPIKeyJustForDeveloping"
}
AUTH = {"userid": 1001, "apikey": "fakeAPIKeyJustForDeveloping"}
INFO = {
"project": "OpenGnsys",
"version": "1.1.0pre",
"release": "r5299",
"services": [
"server",
"repository",
"tracker"
],
"services": ["server", "repository", "tracker"],
"oglive": [
{
"distribution": "xenial",
@ -61,7 +54,7 @@ INFO = {
"architecture": "amd64",
"revision": "r5225",
"directory": "ogLive-xenial-4.8.0-amd64-r5225",
"iso": "ogLive-xenial-4.8.0-39-generic-amd64-r5225.iso"
"iso": "ogLive-xenial-4.8.0-39-generic-amd64-r5225.iso",
},
{
"iso": "ogLive-precise-3.2.0-23-generic-r4820.iso",
@ -69,19 +62,14 @@ INFO = {
"revision": "r4820",
"architecture": "i386",
"kernel": "3.2.0-23-generic",
"distribution": "precise"
}]
"distribution": "precise",
},
],
}
OUS = [
{
"id": "1",
"name": "Unidad Organizativa (Default)"
},
{
"id": "2",
"name": "Unidad Organizatva VACIA"
},
{"id": "1", "name": "Unidad Organizativa (Default)"},
{"id": "2", "name": "Unidad Organizatva VACIA"},
]
LABS = [
@ -89,58 +77,32 @@ LABS = [
"id": "1",
"name": "Sala de control",
"inremotepc": True,
"group": {
"id": "0"
},
"ou": {
"id": "1"
}
"group": {"id": "0"},
"ou": {"id": "1"},
},
{
"id": "2",
"name": "Sala de computación cuántica",
"inremotepc": True,
"group": {
"id": "0"
"group": {"id": "0"},
"ou": {"id": "1"},
},
"ou": {
"id": "1"
}
}
]
IMAGES = [
{
"id": "1",
"name": "Basica1604",
"inremotepc": True,
"ou": {
"id": "1"
}
},
{
"id": "2",
"name": "Ubuntu16",
"inremotepc": True,
"ou": {
"id": "1"
}
},
{"id": "1", "name": "Basica1604", "inremotepc": True, "ou": {"id": "1"}},
{"id": "2", "name": "Ubuntu16", "inremotepc": True, "ou": {"id": "1"}},
{
"id": "3",
"name": "Ubuntu64 Not in Remote",
"inremotepc": False,
"ou": {
"id": "1"
}
"ou": {"id": "1"},
},
{
"id": "4",
"name": "Ubuntu96 Not In Remote",
"inremotepc": False,
"ou": {
"id": "1"
}
"ou": {"id": "1"},
},
]
@ -149,58 +111,50 @@ RESERVE: typing.Dict[str, typing.Any] = {
"name": "pcpruebas",
"mac": "4061860521FE",
"ip": "10.1.14.31",
"lab": {
"id": 1
},
"ou": {
"id": 1
}
"lab": {"id": 1},
"ou": {"id": 1},
}
UNRESERVE = ''
STATUS_OFF = {
"id": 4,
"ip": "10.1.14.31",
"status": "off",
"loggedin": False
}
STATUS_OFF = {"id": 4, "ip": "10.1.14.31", "status": "off", "loggedin": False}
# A couple of status for testing
STATUS_READY_LINUX = {
"id": 4,
"ip": "10.1.14.31",
"status": "linux",
"loggedin": False
}
STATUS_READY_LINUX = {"id": 4, "ip": "10.1.14.31", "status": "linux", "loggedin": False}
STATUS_READY_WINDOWS = {
"id": 4,
"ip": "10.1.14.31",
"status": "windows",
"loggedin": False
"loggedin": False,
}
# FAKE post
def post(path: str, data: typing.Any, errMsg: typing.Optional[str] = None) -> typing.Any:
def post(
path: str, data: typing.Any, errMsg: typing.Optional[str] = None
) -> typing.Any:
logger.info('FAKE POST request to %s with %s data. (%s)', path, data, errMsg)
if path == urls.LOGIN:
return AUTH
if path == urls.RESERVE.format(ou=1, image=1) or path == urls.RESERVE.format(ou=1, image=2):
if path == urls.RESERVE.format(ou=1, image=1) or path == urls.RESERVE.format(
ou=1, image=2
):
res = copy.deepcopy(RESERVE)
res['name'] += str(random.randint(5000, 100000))
res['mac'] = ''.join(random.choice('0123456789ABCDEF') for _ in range(12))
res['ip'] = '1.2.3.4'
return res
# raise Exception('Unknown FAKE URL on POST: {}'.format(path))
return ''
# Ignore rest of responses
return {'status': 'ok'}
# FAKE get
def get(path, errMsg: typing.Optional[str]) -> typing.Any: # pylint: disable=too-many-return-statements
def get(
path, errMsg: typing.Optional[str]
) -> typing.Any: # pylint: disable=too-many-return-statements
logger.info('FAKE GET request to %s. (%s)', path, errMsg)
if path == urls.INFO:
return INFO

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017-2019 Virtual Cable S.L.
# Copyright (c) 2017-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -43,3 +42,5 @@ UNRESERVE = '/ous/{ou}/labs/{lab}/clients/{client}/unreserve'
STATUS = '/ous/{ou}/labs/{lab}/clients/{client}/status'
EVENTS = '/ous/{ou}/labs/{lab}/clients/{client}/events'
SESSIONS = '/ous/{ou}/labs/{lab}/clients/{client}/session'
# TODO: fix this
START = '/ous/{ou}/labs/{lab}/clients/{client}/init'

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2019 Virtual Cable S.L.
# Copyright (c) 2012-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -51,6 +50,7 @@ if typing.TYPE_CHECKING:
logger = logging.getLogger(__name__)
class OGProvider(ServiceProvider):
"""
This class represents the sample services provider
@ -68,6 +68,7 @@ class OGProvider(ServiceProvider):
we MUST register it at package __init__.
"""
# : What kind of services we offer, this are classes inherited from Service
offers = [OGService]
# : Name to show the administrator. This string will be translated BEFORE
@ -92,17 +93,81 @@ class OGProvider(ServiceProvider):
# but used for sample purposes
# If we don't indicate an order, the output order of fields will be
# "random"
host = gui.TextField(length=64, label=_('Host'), order=1, tooltip=_('OpenGnsys Host'), required=True)
port = gui.NumericField(length=5, label=_('Port'), defvalue='443', order=2, tooltip=_('OpenGnsys Port (default is 443, and only ssl connection is allowed)'), required=True)
checkCert = gui.CheckBoxField(label=_('Check Cert.'), order=3, tooltip=_('If checked, ssl certificate of OpenGnsys server must be valid (not self signed)'))
username = gui.TextField(length=32, label=_('Username'), order=4, tooltip=_('User with valid privileges on OpenGnsys'), required=True)
password = gui.PasswordField(lenth=32, label=_('Password'), order=5, tooltip=_('Password of the user of OpenGnsys'), required=True)
udsServerAccessUrl = gui.TextField(length=32, label=_('UDS Server URL'), order=6, tooltip=_('URL used by OpenGnsys to access UDS. If empty, UDS will guess it.'), required=False, tab=gui.PARAMETERS_TAB)
host = gui.TextField(
length=64, label=_('Host'), order=1, tooltip=_('OpenGnsys Host'), required=True
)
port = gui.NumericField(
length=5,
label=_('Port'),
defvalue='443',
order=2,
tooltip=_(
'OpenGnsys Port (default is 443, and only ssl connection is allowed)'
),
required=True,
)
checkCert = gui.CheckBoxField(
label=_('Check Cert.'),
order=3,
tooltip=_(
'If checked, ssl certificate of OpenGnsys server must be valid (not self signed)'
),
)
username = gui.TextField(
length=32,
label=_('Username'),
order=4,
tooltip=_('User with valid privileges on OpenGnsys'),
required=True,
)
password = gui.PasswordField(
lenth=32,
label=_('Password'),
order=5,
tooltip=_('Password of the user of OpenGnsys'),
required=True,
)
udsServerAccessUrl = gui.TextField(
length=32,
label=_('UDS Server URL'),
order=6,
tooltip=_('URL used by OpenGnsys to access UDS. If empty, UDS will guess it.'),
required=False,
tab=gui.PARAMETERS_TAB,
)
maxPreparingServices = gui.NumericField(length=3, label=_('Creation concurrency'), defvalue='10', minValue=1, maxValue=65536, order=50, tooltip=_('Maximum number of concurrently creating VMs'), required=True, tab=gui.ADVANCED_TAB)
maxRemovingServices = gui.NumericField(length=3, label=_('Removal concurrency'), defvalue='8', minValue=1, maxValue=65536, order=51, tooltip=_('Maximum number of concurrently removing VMs'), required=True, tab=gui.ADVANCED_TAB)
maxPreparingServices = gui.NumericField(
length=3,
label=_('Creation concurrency'),
defvalue='10',
minValue=1,
maxValue=65536,
order=50,
tooltip=_('Maximum number of concurrently creating VMs'),
required=True,
tab=gui.ADVANCED_TAB,
)
maxRemovingServices = gui.NumericField(
length=3,
label=_('Removal concurrency'),
defvalue='8',
minValue=1,
maxValue=65536,
order=51,
tooltip=_('Maximum number of concurrently removing VMs'),
required=True,
tab=gui.ADVANCED_TAB,
)
timeout = gui.NumericField(length=3, label=_('Timeout'), defvalue='10', order=90, tooltip=_('Timeout in seconds of connection to OpenGnsys'), required=True, tab=gui.ADVANCED_TAB)
timeout = gui.NumericField(
length=3,
label=_('Timeout'),
defvalue='10',
order=90,
tooltip=_('Timeout in seconds of connection to OpenGnsys'),
required=True,
tab=gui.ADVANCED_TAB,
)
# Own variables
_api: typing.Optional[og.OpenGnsysClient] = None
@ -137,7 +202,13 @@ class OGProvider(ServiceProvider):
@property
def api(self) -> og.OpenGnsysClient:
if not self._api:
self._api = og.OpenGnsysClient(self.username.value, self.password.value, self.endpoint, self.cache, self.checkCert.isTrue())
self._api = og.OpenGnsysClient(
self.username.value,
self.password.value,
self.endpoint,
self.cache,
self.checkCert.isTrue(),
)
logger.debug('Api: %s', self._api)
return self._api
@ -155,7 +226,12 @@ class OGProvider(ServiceProvider):
"""
try:
if self.api.version[0:5] < '1.1.0':
return [False, 'OpenGnsys version is not supported (required version 1.1.0 or newer and found {})'.format(self.api.version)]
return [
False,
'OpenGnsys version is not supported (required version 1.1.0 or newer and found {})'.format(
self.api.version
),
]
except Exception as e:
logger.exception('Error')
return [False, '{}'.format(e)]
@ -184,16 +260,25 @@ class OGProvider(ServiceProvider):
def getUDSServerAccessUrl(self) -> str:
return self.udsServerAccessUrl.value
def reserve(self, ou: str, image: str, lab: int = 0, maxtime: int = 0) -> typing.Any:
def reserve(
self, ou: str, image: str, lab: int = 0, maxtime: int = 0
) -> typing.Any:
return self.api.reserve(ou, image, lab, maxtime)
def unreserve(self, machineId: str) -> typing.Any:
return self.api.unreserve(machineId)
def notifyEvents(self, machineId: str, loginURL: str, logoutURL: str) -> typing.Any:
return self.api.notifyURLs(machineId, loginURL, logoutURL)
def powerOn(self, machineId: str, image: str) -> typing.Any:
return self.api.powerOn(machineId, image)
def notifyDeadline(self, machineId: str, deadLine: typing.Optional[int]) -> typing.Any:
def notifyEvents(
self, machineId: str, loginURL: str, logoutURL: str, releaseURL: str
) -> typing.Any:
return self.api.notifyURLs(machineId, loginURL, logoutURL, releaseURL)
def notifyDeadline(
self, machineId: str, deadLine: typing.Optional[int]
) -> typing.Any:
return self.api.notifyDeadline(machineId, deadLine)
def status(self, machineId: str) -> typing.Any:

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017-2019 Virtual Cable S.L.
# Copyright (c) 2017-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -48,9 +47,12 @@ class OGPublication(Publication):
"""
This class provides the publication of a oVirtLinkedService
"""
_name: str = ''
suggestedTime = 5 # : Suggested recheck time if publication is unfinished in seconds
suggestedTime = (
5 # : Suggested recheck time if publication is unfinished in seconds
)
def service(self) -> 'OGService':
return typing.cast('OGService', super().service())

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017-2019 Virtual Cable S.L.
# Copyright (c) 2017-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -55,6 +54,7 @@ class OGService(Service):
"""
OpenGnsys Service
"""
# : Name to show the administrator. This string will be translated BEFORE
# : sending it to administration interface, so don't forget to
# : mark it as _ (using ugettext_noop)
@ -102,20 +102,17 @@ class OGService(Service):
label=_("OU"),
order=100,
fills={
'callbackName' : 'osFillData',
'function' : helpers.getResources,
'parameters' : ['ov', 'ev', 'ou']
'callbackName': 'osFillData',
'function': helpers.getResources,
'parameters': ['ov', 'ev', 'ou'],
},
tooltip=_('Organizational Unit'),
required=True
required=True,
)
# Lab is not required, but maybe used as filter
lab = gui.ChoiceField(
label=_("lab"),
order=101,
tooltip=_('Laboratory'),
required=False
label=_("lab"), order=101, tooltip=_('Laboratory'), required=False
)
# Required, this is the base image
@ -123,22 +120,33 @@ class OGService(Service):
label=_("OS Image"),
order=102,
tooltip=_('OpenGnsys Operating System Image'),
required=True
required=True,
)
maxReservationTime = gui.NumericField(
length=3,
label=_("Max. reservation time"),
order=110,
tooltip=_('Security parameter for OpenGnsys to keep reservations at most this hours. Handle with care!'),
tooltip=_(
'Security parameter for OpenGnsys to keep reservations at most this hours. Handle with care!'
),
defvalue='2400', # 1 hundred days
minValue='24',
tab=_('Advanced'),
required=False
required=False,
)
startIfUnavailable = gui.CheckBoxField(
label=_('Start if unavailable'),
defvalue=gui.TRUE,
order=111,
tooltip=_('If active, machines that are not available on user connect (on some OS) will try to power on through OpenGnsys.'),
)
ov = gui.HiddenField(value=None)
ev = gui.HiddenField(value=None) # We need to keep the env so we can instantiate the Provider
ev = gui.HiddenField(
value=None
) # We need to keep the env so we can instantiate the Provider
def initGui(self) -> None:
"""
@ -157,27 +165,49 @@ class OGService(Service):
return self.parent().status(machineId)
def reserve(self) -> typing.Any:
return self.parent().reserve(self.ou.value, self.image.value, self.lab.value, self.maxReservationTime.num())
return self.parent().reserve(
self.ou.value,
self.image.value,
self.lab.value,
self.maxReservationTime.num(),
)
def unreserve(self, machineId: str) -> typing.Any:
return self.parent().unreserve(machineId)
def notifyEvents(self, machineId: str, serviceUUID: str) -> typing.Any:
return self.parent().notifyEvents(machineId, self.getLoginNotifyURL(serviceUUID), self.getLogoutNotifyURL(serviceUUID))
def notifyEvents(self, machineId: str, token: str, uuid: str) -> typing.Any:
return self.parent().notifyEvents(
machineId,
self.getLoginNotifyURL(uuid, token),
self.getLogoutNotifyURL(uuid, token),
self.getReleaseURL(uuid, token)
)
def notifyDeadline(self, machineId: str, deadLine: typing.Optional[int]) -> typing.Any:
def notifyDeadline(
self, machineId: str, deadLine: typing.Optional[int]
) -> typing.Any:
return self.parent().notifyDeadline(machineId, deadLine)
def _notifyURL(self, uuid: str, message: str) -> str:
def powerOn(self, machineId: str) -> typing.Any:
return self.parent().powerOn(machineId, self.image.value)
def _notifyURL(self, uuid: str, token:str, message: str) -> str:
# The URL is "GET messages URL".
return '{accessURL}rest/actor/PostThoughGet/{uuid}/{message}'.format(
return '{accessURL}uds/ognotify/{message}/{token}/{uuid}'.format(
accessURL=self.parent().getUDSServerAccessUrl(),
uuid=uuid,
token=token,
message=message
)
def getLoginNotifyURL(self, serviceUUID: str) -> str:
return self._notifyURL(serviceUUID, 'login')
def getLoginNotifyURL(self, uuid: str, token: str) -> str:
return self._notifyURL(uuid, token, 'login')
def getLogoutNotifyURL(self, serviceUUID: str) -> str:
return self._notifyURL(serviceUUID, 'logout')
def getLogoutNotifyURL(self, uuid: str, token: str) -> str:
return self._notifyURL(uuid, token, 'logout')
def getReleaseURL(self, uuid: str, token: str) -> str:
return self._notifyURL(uuid, token, 'release')
def isRemovableIfUnavailable(self):
return self.startIfUnavailable.isTrue()

View File

@ -30,7 +30,7 @@ MIT
MIT
The MIT License
Copyright (c) 2020 Google LLC.
Copyright (c) 2021 Google LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -64,7 +64,7 @@ MIT
MIT
The MIT License
Copyright (c) 2020 Google LLC.
Copyright (c) 2021 Google LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -30,7 +30,7 @@ MIT
MIT
The MIT License
Copyright (c) 2020 Google LLC.
Copyright (c) 2021 Google LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -64,7 +64,7 @@ MIT
MIT
The MIT License
Copyright (c) 2020 Google LLC.
Copyright (c) 2021 Google LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -25,7 +25,7 @@ gettext("Error launching service");
gettext("Please wait until the service is launched.");
gettext("Your connection is being prepared. It will open on a new window when ready.");
gettext("The service is now being prepared. (It is at #).'.replace('#', '' + data.running + '%");
gettext("Please, tray again in a few moments.");
gettext("Please, try again in a few moments.");
gettext("Error launching service");
// HTML
gettext("You can access UDS Open Source code at");

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2019 Virtual Cable S.L.
# Copyright (c) 2012-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,

View File

@ -84,34 +84,23 @@ class TSNXTransport(BaseNXTransport):
label=_('Tunnel wait time'),
defvalue='30',
minValue=5,
maxValue=65536,
maxValue=3600 * 24,
order=2,
tooltip=_('Maximum time to wait before closing the tunnel listener'),
required=True,
tab=gui.TUNNEL_TAB,
)
ticketValidity = gui.NumericField(
length=3,
label=_('Tunnel ticket validity time (seconds)'),
defvalue='7200',
minValue=60, # One minute as min
maxValue=7*60*60*24, # one week as max
order=3,
tooltip=_('Maximum validity time for user ticket to allow reconnection'),
required=True,
tab=gui.TUNNEL_TAB,
)
verifyCertificate = gui.CheckBoxField(
label=_('Force SSL certificate verification'),
order=23,
tooltip=_('If enabled, the certificate of tunnel server will be verified (recommended).'),
tooltip=_(
'If enabled, the certificate of tunnel server will be verified (recommended).'
),
defvalue=gui.TRUE,
tab=gui.TUNNEL_TAB
tab=gui.TUNNEL_TAB,
)
useEmptyCreds = gui.CheckBoxField(
label=_('Empty creds'),
order=3,
@ -217,7 +206,6 @@ class TSNXTransport(BaseNXTransport):
_cacheMem: str = ''
_screenSize: str = ''
_tunnelWait: int = 30
_ticketValidity: int = 60
_verifyCertificate: bool = False
def initialize(self, values: 'Module.ValuesType'):
@ -228,7 +216,6 @@ class TSNXTransport(BaseNXTransport):
)
self._tunnelServer = values['tunnelServer']
self._tunnelWait = int(values['tunnelWait'])
self._ticketValidity = int(values['ticketValidity'])
self._verifyCertificate = gui.strToBool(values['verifyCertificate'])
self._tunnelCheckServer = ''
self._useEmptyCreds = gui.strToBool(values['useEmptyCreds'])
@ -241,7 +228,6 @@ class TSNXTransport(BaseNXTransport):
self._cacheMem = values['cacheMem']
self._screenSize = values['screenSize']
def marshal(self) -> bytes:
"""
Serializes the transport data so we can store it in database
@ -262,7 +248,6 @@ class TSNXTransport(BaseNXTransport):
self._tunnelCheckServer,
self._screenSize,
str(self._tunnelWait),
str(self._ticketValidity),
gui.boolToStr(self._verifyCertificate),
],
)
@ -288,10 +273,9 @@ class TSNXTransport(BaseNXTransport):
values[11] if values[0] == 'v2' else CommonPrefs.SZ_FULLSCREEN
)
if values[0] == 'v3':
self._tunnelWait, self._ticketValidity, self._verifyCertificate = (
self._tunnelWait, self._verifyCertificate = (
int(values[12]),
int(values[13]),
gui.strToBool(values[14])
gui.strToBool(values[13]),
)
def valuesDict(self) -> gui.ValuesDictType:
@ -306,7 +290,6 @@ class TSNXTransport(BaseNXTransport):
'cacheMem': self._cacheMem,
'tunnelServer': self._tunnelServer,
'tunnelWait': str(self._tunnelWait),
'ticketValidity': str(self._ticketValidity),
'verifyCertificate': gui.boolToStr(self._verifyCertificate),
}
@ -334,8 +317,8 @@ class TSNXTransport(BaseNXTransport):
ticket = TicketStore.create_for_tunnel(
userService=userService,
port=3389,
validity=self.ticketValidity.num()
port=int(self._listenPort),
validity=self._tunnelWait + 60, # Ticket overtime
)
tunHost, tunPort = self.tunnelServer.value.split(':')
@ -367,10 +350,9 @@ class TSNXTransport(BaseNXTransport):
'ip': ip,
'tunHost': tunHost,
'tunPort': tunPort,
'tunWait': self.tunnelWait.num(),
'tunChk': self.verifyCertificate.isTrue(),
'tunWait': self._tunnelWait,
'tunChk': self._verifyCertificate,
'ticket': ticket,
'port': self._listenPort,
'as_file_for_format': r.as_file_for_format,
}

View File

@ -18,13 +18,13 @@ except Exception:
''')
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
theFile = sp['as_file_for_format'].format(
theFile = sp['as_file_for_format'].format( # type: ignore
address='127.0.0.1',
port=fs.server_address[1]
)

View File

@ -1 +1 @@
Jb61ZM6xlsxMLnk4a2X2INN3IyGp+ztSgjXV+AsbH2hKDtKANM9nqHXgI/4LfxAogM3Y17k2tHOnbf049mWNaDRNCqOY9tG/xL3am2HkOTb3L9YOpK60gk/0hF9y1qLN9Y/CM+TP6B3DvVW+fsSnVfmDoK/NyqR5nb+6iRs37nmr+ILcum8IYgT4BeoKUqcMjHBQFF1MGfD5arKJW1t9pFQZw9+BZUzyw1c++2mnajIe294gjUEqgRxKPX6ejYX9J/AfAvM8K+NruT23VcxbBkp6diRUHFzM0buqHxUVzCqyfnU+umS7FKLOLw8M1B0goYfK8B0p8lu8ICRA24yOPpnnbBBWBUjZm3OZUGt7fqanaPbsVvehibxOsPB2z/vktp6mVBx8tkjU8Uyli1RxMSdT8xjsCT3mkK521AasqfE5Vn/Plwe9ciBo5AfqVxkl9OFVgUCCDTug9oNx50u+eSj/XUCxlTu39OBWUV6HAUhWDIgRWoYpLCC5Xtb+ILkgYPtTU8CiQSS2EFk8uUqxCSCbJKwfQRHhcYItSZk6fP0TH1nfirR8DB/AW5ltbO8QPe4PIllAyQl827fy6vQTytSw1wWBkEf7OCBEfv1w3AwFOC35fKQoRk+ygbD5fLhFbQsDpaMVtabNL/zjlw51CtrQfQ1ru69bvKeHLbp265M=
EFxcQ0pD5IdbGBhlBdULIIPckwR0BlC2XQpWmxUngQlK/qe2s9CleQBjTcGyp6SSzy7uc6osweHA1b9N4o4opodLI0mD5X3H5+cP/92HsKcBT1QPRh1S8i+hGyGa5WO/fxdpeIM0rco9OcFDx9iloRbxCN0op3GJe3X0DwtS89r0MwaMs3rz7A913geshVGmJ/5oZM+EXf/kD6oGTRVkRagqeNkpB+Aup0LxhVET5EO6tY5TBDd2TvgCSBOqOkcA5vtavcxxb5As20lgl5/UsYDpCXuz7gGyq4EKn0nDSYHYiFeqsyJgaXWqdWW9rVQpGl8qjbm/Ndc2bC3s/3Q8bDgEjev0EQjKQ6oMUtdOJNJ89fP9TEd8Y0UKocBZRsGMxvQdcFN4Q5jMzplPcP9F3VuaCvA9W+uLZ/b1EvFPFdLrDBLhUsgUiWNoEQCqpG7FG+qz3dy0oVkmAZs9ewI6/oOxE+KaTs7uJv1mIbWpJEWhvLwzMg6j6jPSsV4bu9kbtjr3dBFwTNI5EsaW9vP9NeEg2hqD6vBOrlw4PB9SWIPBdFX0tPsT4tAgJxaUx13OepO7DWTItzA6EjT/be3BIUSJPoJuCJA7nxGj/ZOFqN4grmAlMKa8JXq8L/6++Jtqf+iSNgZjD+5cxC5j9M4yRlsBTFQaQhf+OnawjxAd1a4=

View File

@ -6,7 +6,7 @@ from __future__ import unicode_literals
import subprocess
import os
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
cmd = '/Applications/OpenNX/OpenNX.app/Contents/MacOS/OpenNXapp'
@ -16,6 +16,6 @@ if os.path.isfile(cmd) is False:
''')
filename = tools.saveTempFile(sp['as_file']) # @UndefinedVariable
tools.addTaskToWait(subprocess.Popen([cmd, '--session={{}}'.format(filename), '--autologin', '--killerrors']))
filename = tools.saveTempFile(sp['as_file']) # type: ignore
tools.addTaskToWait(subprocess.Popen([cmd, '--session={{}}'.format(filename), '--autologin', '--killerrors'])) # type: ignore
tools.addFileToUnlink(filename)

View File

@ -1 +1 @@
A4XL73+4BMMTm+pLNL5Ae4xqoZVasAxPc10CveDJFoSLNyierVIQRlNfbEP4ZuUSnpR/q01Y1KoRuYao5wQaNdW/4LKlnN4OFM01K04782Ug05JiSO1BZ8KBM5w8XmWyVqbmGveQiGVGWwyXwg0YqBmlSbMeFLDYZsO5ILq5F+FsY223C26P9XUiwzTSh58qb1OX6L6Yj5fhFVP3yLldy236SxBZAA7HmvoMvIGk8bKw4r+HRWtgfpUU5rxmFszNUikfcSSR45ci7qZYU/S6WuQ0RZD/5XV+jwTIQdZpn8qcFtXf5GSqSjdVV1vqUaRg04/cRpaFVZ8s+31Os00sZ7AWmBLFZAmRD8BRqks4Nz7RbjM2teH1+S67pvOPDzzYIiLpWeq0qQRKmJ6/DLprqBPfZ4uthqus2f6i6w2t+/CzI25K4Vrjaz0z3wp9k9O5bP7GFpFmfmwt0WW6jLJO43b4XVJ6N+yj02rvAGS2t1i/1S4IfK58/B6XMSchqUgPx1UiW/WHT7dujqiDDTMhLAncW7mwHs2ABwBlPfRxWkyHY8KZUpD9PWDypUf5JvOsNJgyNP/mXIDvCd2htscyfVkpZj5mAdeg9m3sMWNJivCHX0qa5KVcxyI2bn+MfBU9/khRTnOyhgikB8pHVnWqPIiSHL6BLdHiBFlJ7e8OYHw=
hgPD0KnclF5OpaW4tIs+6pWX5tLeactCv1MGI1bk942nHoS4c/Nm87qd5dkHek51UMm1s8o2eB7xdrkJ6CVi/eOf2jnEs63luF+etmdwccHQU9BcQZjev1aId4q0q7HiQCXjXaS2vorIevH9uvf1NWl6AyPABynYhC7zvWb9nz/GTNBXO7TAqfVarGJLRXwY2KHpBXqUKEPB0H46+h3S9AWD2pHxfZnVBKdjoGgrD5/pt905aI2lrl1yCE14LFENkpssH/dBxYnaEMMYiWTuAe3lAP8MQEFlWmHBT63G7xMhDR3wc2sqC2eh8RQieEj1EoqCPLJFwMoxA1SZfS+JLhppskdJi06o+pqiJ4bzO0Is47plGn+KBodBAT+5/dOgOK/lKv+7Q8j3MS59TQUFty4TkybS6Ujk40SjlOlCwofVb6awKMSUSny853K20yKClt0gGhUjykstex3/eaXmU7hWLBBbDsFmY5W7Xhvxi1vPmrJ3uJ2M+R9WIeCM4xygLQPcMkZbY2k1bonv3NhK+AlapmY36y3IBbziL1Xv4agjRAykls3y+qrxMjE4Lx4ZUAI0OdX7COqdz7Ix7baYpMHrLgROjtkp/EJqVIfhvRSvJqMWLsZxbqCjoswNSI4zlyWFR980y4ITHhBsbP95X0yJnoRsgcN+wARNolxVL7o=

View File

@ -17,13 +17,13 @@ if os.path.isfile(cmd) is False:
''')
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
theFile = sp['as_file_for_format'].format(
theFile = sp['as_file_for_format'].format( # type: ignore
address='127.0.0.1',
port=fs.server_address[1]
)

View File

@ -1 +1 @@
sNIIRiS5PiCdCSHQ0Uv5iS4gdYBcFEfI8KPfvD1V8ZTry/Hw8NqB0qzHW0D3YgKGPZMBBnHM+mYiZNXwPuSObRn12Iw/dSh1kmSgh/1S/UvummsdD1vq8T8WdupvI8z1AyQemNPzjA0vUPhDhGakMy5/dAuy7hlND+K9swSTBI3kz5Dcx+PfsnNLxcCtCtmBT/3RDEESJlEVQAbH0sjt9sAQpHap8lDDV2vO/8kahKM4Gpre+uloFbjiYR53qEiQkECJipq3WWQbMq/5IIyBqcruXrHen0jybpuHoWjI++deS6d1NI6A+u9+oUp0AacQOnRzMdKUiykyA14Zjb+Hws0s/fVjPpWDqQMD52Ii1O6goCtsRszJVIdU7UGCTHYctBd+iQ3Qxk5cLXs/vBZ22WIwF6/YN62Gt9aIxonTojUevL2cvCQ6YrMR+X6fAIuvD1Jso86X4Fr2jGPPbzSnfLSn4dLtf8T6XPOn4mPaivosn9eUtMptJiUl3++vYGcdnOhF8Amk7hGUI58ck+gg+vo/MfUFCHTW3XxJtsD4Hr8uelgQNPvFs6whZuUSGVCjyvo107ikqafkiCu4QgWqMfmWzs8DVYAZ3KgPKaqp62R5gIIDdjwH0XZ4DET2+h8gFs+K+T1xcbbHvo8q8i2PRCSbdX9JsupOLuqE78NXAfA=
lsChjBOL2LNJeEjnFSXjK3y9F8uPfz/j6ZlHg511XyQxakyrxPKhEnrAJ9DT7X7Py99D1SQqrMmn+A9B/lH658LmXyCLaQMKFVNLZxc1WH/0Ytl4int6ZJA3uTrt/bHYMNh91OxMsS6WPWjN8g2aCkGhgZIKHehP4oKlQmxOnI4EXSoWtHwl/aN2JaWV6pltiVDKMiyVxMHCnRm0L1KSVaOsC5OxW76DvsUWcYELXiue+bMlBx96lQN0/g4xd9UJKJFqRmA+tPnUhKYdm/gt1804xsdGQ2v2IdPiJjhBvN4riFUffkls0T67HFOEedNdoV7ox/lz8RmamlAGbs36Qz84U/hYdeEwpOZfzHvVKuq8M1EZQciboqdlaRDPDbF+o7mZHQsOCSzRTp6qBqb46pzcELuXBH4/jod/tAX9iyvz7BBxrQsTmhivHIwu3VOdjClN3bw2GrNSyhKxSYsb7wq/YiABfHWHJkHzMZnwxGOpYuYSHNNew2liH3zE3gZPX6rGnyFn7rv80rIGvbLmQV9hJmAluyzU6hQivHYqZnpnfQN1cKT5SKbDiZVCnAC9c8uPGD7VsHJZpaGR3Hi4bB/J2qyVG+zbfVVsLyRh/wDfGfucCBxt9ecY/xcZ6aebzabrEnyluhEmrehu6Ovp1lsWJQPb3mUzSHC0muN4M3s=

View File

@ -3,21 +3,24 @@
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module
import _winreg
try:
import winreg as wreg
except ImportError: # Python 2.7 fallback
import _winreg as wreg # type: ignore
import subprocess
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
try:
k = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\Classes\\NXClient.session\\shell\\open\\command') # @UndefinedVariable
cmd = _winreg.QueryValue(k, '') # @UndefinedVariable
k = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Classes\\NXClient.session\\shell\\open\\command') # @UndefinedVariable
cmd = wreg.QueryValue(k, '') # type: ignore
wreg.CloseKey(k)
except Exception:
raise Exception('''<p>You need to have installed NX Client version 3.5 in order to connect to this UDS service.</p>
<p>Please, install appropriate package for your system.</p>
''')
filename = tools.saveTempFile(sp['as_file']) # @UndefinedVariable
filename = tools.saveTempFile(sp['as_file']) # type: ignore
cmd = cmd.replace('%1', filename)
tools.addTaskToWait(subprocess.Popen(cmd))
tools.addFileToUnlink(filename)

View File

@ -1 +1 @@
jyAVq4zJ1QR0otsMsh2vIarVH2Jy2UPGHi3JfLZPlwR1NFlM67f6uDgZO4wJNeQzOkPOGgpoklkB5ROxHjdUQUdm23XANXDpIZA1ywhrjLQ6lh4HSkbZ0i3QZizDAH5x5XxwHSOIrFeiT75qxXY67lFEXE4DhfxBMJMLm3xQyyjBxTyB1K/3UG3Ryhf0ApFqpaERoLEPJGjLeVj6bIeRre7TlxJMgO+VosjKkbUKRDTZD85X/iwvyRzGHy3OpS8zTOWt/Wstcph9+DrlPkbx8Z6yMpuwNW/mMEWblMcYWdyApBpnLEt8nLKlSQb3rGu2j7QaxzWwtPwuxWcd1IQzxCt0R/pbMlyl75QfrumKKoZ+MnPL4kK5kI4RHoBqzNKpirXHm36URfW5+9oKTuIgbwK6YvOPXtLAsYTtaWEmO21Tb6g+4XCzC1eoOlXWaA6NQe3rr0JXQpwAWjzg+EkaW0G45amef7ta4wGQC8zCZ1cSsA8uFGe6Q11fS94Q+Rv6rl5KubCf6KxvmsYDqkQkdzdvN8tDVkVX9mPNMaquLWaDWmKVp3Hp6WxdUELtAt50KfmGbaD7eMyLgHtBrhCUr1aRG3DxxysDOPhZYiO7Z73BR7OAeVM/bH3rpZLRsZOwi6s6zifqmmV5K2I5aozwybAQgVoR7+ZjZn5irPPULBc=
isXacHwak7jQEx9QFKLUaVUTG75t5ogtWFiV7m7eMDttzBTkkS1/0hVLX1avLdaMOBCY60JTfTrPcHcd8XESfSzR3w92i1BzfccHmpV3g67lbeESZqpjsJTWC3F9kCpZHsj6DHXQICQjPPeW++tchJj8bAoETc6MyH5IHSJ/KOmbgLOBM+2x9crnX1ZWHrwF2xQyMaLn5rgntklvSX2KmOS6z0WC0C5DLFpVzZvSsDwMyfhhxd4fGNWCxUW4v5f5S1GUCM1AfzXWZEPYAWbRFgOzG2MKB2dhHasxVt25VtjeKgrD+Q5A28ihQBUkh5vZRmOtAWjtneF6K6bOM59ZL0vzjGIL1/y/6oysjyeOAG4YvagekMRAZT0folf7d4prUb1tN+8jvabZszGCxjvb0kYjfiT6zN53lxDSExLuvjBEwHkWM3CPCTkPLJ7UWiRT6Fyd8c3vJw860WhnohPYg+4q2udjf/ZgdDiyVPEyOB5AKpDnHB3HfsQr7upw+WqWUH56ylF2myWyP0uSmOrLJnUyFX1FFVx2R+/Rc0AjPmM+VE9UwPUkSSpFaRdKPP2nJxDYrReZwk/kfFmRvIqLAUz+rwSIH2JJqEB6NT//tMdxRu4lAKrpX29nqDSWCiMvew3D21OQYafzGGJ9GTn2n+Mwki3cbKpxLXxLxlCh0S8=

View File

@ -13,23 +13,23 @@ from uds.tunnel import forward # type: ignore
from uds import tools # type: ignore
try:
k = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Classes\\NXClient.session\\shell\\open\\command') # @UndefinedVariable
k = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Classes\\NXClient.session\\shell\\open\\command')
cmd = wreg.QueryValue(k, '')
wreg.CloseKey(k)
except Exception:
raise Exception('''<p>You need to have installed NX Client version 3.5 in order to connect to this UDS service.</p>
<p>Please, install appropriate package for your system.</p>
''')
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
theFile = sp['as_file_for_format'].format(
theFile = sp['as_file_for_format'].format( # type: ignore
address='127.0.0.1',
port=fs.server_address[1]
)

View File

@ -1 +1 @@
jR6BkXPX1vmZqU6AMnLXJNwHhdw+v6pt4DdqpF0bWorB7tFbxAJ7U47A2NjDPSHMVpe2qtUIpL2eBAgpQCcfEbQNyzqpJmtS2w2y2lCHfT0sb/TMjsMJLfLpwJiH4dkRfF/bP7rAw55DHj4Q0Mc/lzwxGZuTOd+sjp89WxBximdD9y2/BQF9IRlsVGQOU2pjB1Ko1Wg719gXfqBM/ezg1gC2M8vAqxRZq6jyaPIRs+Hl1GALR2gi0MiwYckopJMWGQHmgGIUt8S9bAR8M5wkmNK3Fbc7qoa+tGuthfkoVYYqhSC2Wdd9tmhcVyGSwDv77OnN4QK9MAFSJxQV2GejaOn1Dp96prtmkNn1350d8y5kjTNFV0h4Y5sGW0XtDROrg/fdbuxHf7cZhn+hThotZjNfWp7PXbc5mlwwc+gYTGIwNd7qV20WzdBodvc6X79pJP4Oy2fZbMGYPdHYjiC8yPV+SliqrhUBCYLZI0z667rGupnyu4qh0ciRrz33AKHuQZZGJfux4WFOfhB9mMUyL621ospkORGKaWwr/v7dePotGUSkUbDHBrliN/qOlgHXls9C6NDGvXr1z2nlo2VCgjQMAxkqh8Lc/DDOOBSbcZ4S8RczxBwevYdKVA+ZZ1FP+PuhA/x50JtctbjiltaBFeK8buuv25PMsFVsNuNp05k=
o+152nwWH5xKg7nrK4ffYSeGjzitZS5LxvkC9Z0aa86J2D9gEIsUqDAQjh2ljuO+g4ik2s72T7Yb5HiZizhHfRfjwe22yjIj+NtK1Xoeh/VW3773bq5VCXAjfMbVU6GuGnNMndQOn4qrS/l12YLDhxXFKUkpwNU1TjRGo33ns1DFPNTf0dT7W/WpQkf/75Jlt6bMnGxFWDWYhc1wLySmwlVPj7GOKQTD9pS9MaB7eqpq/GO9gADNGWcTbz3GGs8iO8N5dxBHTnyHxO7P29aQL9bOvtrY0rxAopfy+TTcuE03qNDI6pCBjhYxCqL+GqiRrzmLJq9ZtvhNxvQ5+kvDDrw3ErFZbXoBOF4f7SeP6Tr9A6aOkLG579czsqNGSpHqkUPgvb38xXfSPv983pDvzhi3lo2GzNhAu4ZYM+/Z/Q32ssYBfst4joHAC9mcHmP37ZTKRiMfRz3hafkJlSmm2RQf5/OPYCz5ha8AAcs2CvqYMlOiJhP9Zx8AwtB9oxVlFPS+ZUJ9h/0waRVFBKQm1m70Z7odjJqT0ThTTJQEjuedfnNuxW1V5GtCi62NcwskulWOL2fXjmf9eh0u5PPn1tdqLIUmZXa9eqGU+LjZqA52w7V3sHHWoMYvfEC4SG9HXfZxd6YZdfPx12z6WYh4PnJLNUqd7bgfl4YswALJyaA=

View File

@ -74,7 +74,6 @@ class TRDPTransport(BaseRDPTransport):
),
tab=gui.TUNNEL_TAB,
)
# tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order=2, tooltip=_('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'), tab=gui.TUNNEL_TAB)
tunnelWait = gui.NumericField(
length=3,
@ -88,27 +87,16 @@ class TRDPTransport(BaseRDPTransport):
tab=gui.TUNNEL_TAB,
)
ticketValidity = gui.NumericField(
length=3,
label=_('Tunnel ticket validity time (seconds)'),
defvalue='7200',
minValue=60, # One minute as min
maxValue=7*60*60*24, # one week as max
order=3,
tooltip=_('Maximum validity time for user ticket to allow reconnection'),
required=True,
tab=gui.TUNNEL_TAB,
)
verifyCertificate = gui.CheckBoxField(
label=_('Force SSL certificate verification'),
order=23,
tooltip=_('If enabled, the certificate of tunnel server will be verified (recommended).'),
tooltip=_(
'If enabled, the certificate of tunnel server will be verified (recommended).'
),
defvalue=gui.TRUE,
tab=gui.TUNNEL_TAB
tab=gui.TUNNEL_TAB,
)
useEmptyCreds = BaseRDPTransport.useEmptyCreds
fixedName = BaseRDPTransport.fixedName
fixedPassword = BaseRDPTransport.fixedPassword
@ -175,12 +163,11 @@ class TRDPTransport(BaseRDPTransport):
ticket = TicketStore.create_for_tunnel(
userService=userService,
port=3389,
validity=self.ticketValidity.num()
validity=self.tunnelWait.num() + 60, # Ticket overtime
)
tunHost, tunPort = self.tunnelServer.value.split(':')
r = RDPFile(
width == '-1' or height == '-1', width, height, depth, target=os['OS']
)

View File

@ -2,24 +2,22 @@
# Saved as .py for easier editing
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
import subprocess
import re
from uds import tools
from uds import tools # type: ignore
# Inject local passed sp into globals for inner functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def execUdsRdp(udsrdp):
import subprocess # @Reimport
params = [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])] # @UndefinedVariable
params = [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
def execNewXFreeRdp(xfreerdp):
import subprocess # @Reimport
params = [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])] # @UndefinedVariable
params = [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)

View File

@ -1 +1 @@
m7XY+kUSxXSqD276bNG7ChwBU06IOR75uTw9eXdSdBYqbvG4FhrUmL1OXRjfNRUh5kzUqkIggcJ5mj3b5Ws76QMWUjqcKS+SM2V5CGOzzPW+lFDeMLEnLCtsrmxZcCPacLce/utMlNf/AqLnraWAUCj8s+5CR68FeHE9fH3CRUryjHhvUPf51GDpMMXq+jnLotWn34xgZ2DI62Kp39qTdFYhmnZ3cGI3cHSks5Jo+uqeD1n0J+pF7vPM22aRknxW8XcLj+tXeUSw1QZVD0tXOI8RaUeD1jAH3bn0tBwP2spUfBwLFsxbWDULkuN89klfe1C/rardNJgIog7pUyyUD4HmeYQqd31Z5kfno3KD9NeAkEe8EaW99PAj3maLPrl8wZB6myYJfiq5k0LV0tzt5JNy20p61JOXFl4F04Ndb0m+IlcvYcknfecsF5RA6ID9U/0vX84y0OHtrEut1G5OBck95X2l0ksKHYcCqxhSKAAds227aeHI3FcWNsIpGpvtnQDrCrxM/lHO5mXk9+t4OVCG8dxawNrSoRmx1gUN/QvRiZvRFJ3WFZgo4OLc6ls62YBxm8FhWn+19NyVzXKI5U+Q5wJFAUkZ7+XnnHrvz75zvt/Ym5SvgMHSBMe7L+4njcEFq5UMfiTCEATorJXk03YDUrQI7uKiE0UTVwIJlGc=
eY7ynpCTiB3Y0zGryBe7SAuc426LEi4+UbyAbMmZXi4I8uFA4KnO7lsQfdmfDjIzZqktTWaAQBGy0cRUEypa8fjbPc+TrkQmAJerLE5+DtH1RH2eHm9eH5uQHN7e4tn8vf3NrD5FCYdenOlVXtzCZhauATjy7VyjMha5RfPbuRDfHvNPcAwlE4Ty6Im8oKBa3kLmCczdI1eSKZgrXHrzDOyJYpIAlBE6RknVusGEcPnUbtoPxgBB3/YNIcy3AswToyElrmWeY0egpYm3skcTKtrrvKD5zc74ueTb5WZER0EzCfEZNHPwo6QnCbyo06U5u6dEkBg1kVFIXxEx/OoIXwpWWUWJn08cqVA/g7RNNdkXZ4iB9v4gRducZEpWGJbH8aq0tOSBOgTg7dxN1SGoayXQT0We3pCZL8Utl/gU5FqvCCGBeHE3dq/ELoAlFuq66AHV+stY08cUuURPObvgwrwA18HpmnppXgYY3RXmX8udfxwCCvOzya4iTuzC4mlQTj/QbYvKCtOgnP/upv7bEhu0+bGfTYSyLBKNFPItgIThc0ockn0BxSHuM0Ln2mK5COruhyYh3sNaQALFGST6pcBm2SvfP1HqWKzvB2V6a+xls5yqYtAR9RyHvZ1bc5QouwKNgqjzV9xSclf7QBwPjXTlOXvln6s4dj6LhLyt9kg=

View File

@ -2,9 +2,7 @@
# Saved as .py for easier editing
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
import subprocess
import re
from uds.tunnel import forward # type: ignore
from uds import tools # type: ignore
@ -14,13 +12,13 @@ globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def execUdsRdp(udsrdp, port):
import subprocess # @Reimport
params = [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:127.0.0.1:{}'.format(port)] # @UndefinedVariable
params = [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:127.0.0.1:{}'.format(port)] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
def execNewXFreeRdp(xfreerdp, port):
import subprocess # @Reimport
params = [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:127.0.0.1:{}'.format(port)] # @UndefinedVariable
params = [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:127.0.0.1:{}'.format(port)] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
@ -41,7 +39,7 @@ if app is None or fnc is None:
''')
else:
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:

View File

@ -1 +1 @@
F12wItI+7Bo+mnANcC0IX3hdcr7d/V+XbnX7sH6zKpw7q/gEJBZW3xHaKpYDWBYYsR5pkCiJ+zawt7lHcc7+GmPJYIpFeXZeGlJWjrNN5FqqI02C+sRnuImX9DNggHGNW0hn3mGdE6U/wB1T6clXtoMK6um8cpLVQtfcVUKn1/gki4dMg+0NSJhQHfBpeQ1yffO/VLaTBWB2qnnQUjYNkqGo0x+nxJ4G67jqJU/sh0vM0OyT3JQwgIH+AidCqL694amngAprWzlOiABL3NoF/yJjn9bBfLHhHtsVp4v1YsYjTWXMegVRK8HWGvAaiGzRbOAdfjZl8GejaROSpLQTo5djBwuHN7ULtnNpk0ZCYJP00AKvQU6yW3omm5c2vZwVc1yUj5fzxnY4QY6VcpoSK15p8wR0FEWaY6kdE4bf2PWwaBGcNVGIe7itmwKv0n7AhZsJG68zmZOR45PNx1ljgFCco/Sg+rGnAxk09c0DtZNIs3BR7lhcUUHo16EFTHeUI8RwxyMKRBW75bTqrNMDUtwk7yxA58ec/mAkZmdlJ5MLYOAc1iL3U+qd8ZKxMOiwo9ZWZNsgLALXfKcg8/DGponnsrPXkmEY4CigW25t9fdooJ8WwrDTssYQJdmmOgXAkj5YyjcEryF73gXaGYL2j9tu6VKEfs9cY5WtGvfJUmA=
qohDf0W4PxfiAn8RDcQrZcl3v/V6+B6Zj2Ba2FukDlm+XXEbrNE0dHONXJPd6zTZ+lWRvYrTHKWWyJVgRoN3gxhEghY+iw+4B4yX6uwxynb/DtHNVg8wG1tFzFfGnHCua9E7+iY+5Y6oDJo76tOmLGYZNGmOA0vwn5IDNqIKTqnAPzJnNbpHrePV5LO/xF59aZ2RthxhcBquSpkZA8Hm9z7Hw4oagOysqSknXTxdyeLBxQLc+KpGXhdo8jbD2In+21r/9V3pqFUM5AyL85tl5eunhDDyKt5KvN8vznMFCITxpJWQ8BSWtqOqNiJvhfqSXm3CVlATeLEDOeuVinF/P4AYzw9qybagKyxL0GQTSATXEmarevAKsZ5nvY5wPUx1BL6OloUWXHjlAvSDCBIRyde3ravDWtT+cajQGyinD8Mhb4emOutr/syirKZXDK8orP3L0gEMCqERKHrv0IpbIldyiyZ2Pt85lvtAQ0nYkPBUnA/kodBrESgJ0DVFqZLEx1YhzEEHEVGZuklt/hUpOzOhtTGhT2MHG2la8ANYJo8pQ+QZTaMtZHGH4uI3r6AxrI7DIBa1K5JZn66jC5pFik5Y7KcJR9d+D8QZU8QVFK4pz5oO6RI7xzka48MxhV3CFvRQ+wDeukfOWS1xThpabxPQbsrc0O/KLFkRrzsHHco=

View File

@ -7,7 +7,7 @@ import subprocess
import shutil
import os
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
# Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
@ -20,18 +20,18 @@ def fixResolution():
import re
import subprocess
results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0])
res = re.search(': \d* x \d*', results).group(0).split(' ')
res = re.search(r': \d* x \d*', results).group(0).split(' ')
width, height = str(int(res[1])-4), str(int(int(res[3])-128)) # Width and Height
return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params']))
return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params'])) # type: ignore
# Check first xfreerdp, allow password redir
if os.path.isfile(xfreerdp):
executable = xfreerdp
elif os.path.isfile(msrdc) and sp['as_file']:
elif os.path.isfile(msrdc) and sp['as_file']: # type: ignore
executable = msrdc
if executable is None:
if sp['as_file']:
if sp['as_file']: # type: ignore
raise Exception('''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul>
@ -63,7 +63,7 @@ if executable is None:
</ul>
''')
elif executable == msrdc:
theFile = sp['as_file']
theFile = sp['as_file'] # type: ignore
filename = tools.saveTempFile(theFile)
# Rename as .rdp, so open recognizes it
shutil.move(filename, filename + '.rdp')
@ -75,8 +75,8 @@ elif executable == xfreerdp:
try:
xfparms = fixResolution()
except Exception as e:
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params']))
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params'])) # type: ignore
params = [executable] + xfparms + ['/v:{}'.format(sp['address'])] # @UndefinedVariable
params = [executable] + xfparms + ['/v:{}'.format(sp['address'])] # type: ignore
subprocess.Popen(params)

View File

@ -1 +1 @@
noBupbQ4cXphbjY5YyaiPhqdv7z47GKvj++IvZHyyyit+9wWgZGxaPx+bLmqvr6Rz+ZJrxXYcW4qk5+CN+AKDe2aoGzbusAziBdd0Oluik09Vl5EHq1+OPUp/VkdNHu3M6EB8SiwwHM0KGWz5PEvegp5V3xyaJutnr7JcEMrMxGL97iCbYtKT3G7BaZOY/gCO7BPTexJlyjZ66xb8+hmUTix12Cnwhxpn2xEuZ3N6raGtbmgOHAp6SHz4Y78GBnFhHrhu/EnkHZVgSIoQbyW9koB2tBYdQi3915sUvTLIdHuN3kjz9UKSH/tPJVL+CGrBE/+TXJe90xOTBbzRAgZcUtUjCNyDULhRCT87N1sRH5RFJNsvQv3cqYTgnVUBF5Oew8guTj0UdAAB6tGtUdZqFXz4NspA+f+PkzLmUzmd8y6hqwX4Ojbh0SL0N3Tb5SJw+uOcKTN/FNSEavWK62alPyA36VDf0IIJLV604DhxvOeUTWYz0H7TnrME4e5d9F82iYPCre71yNofzHihZ5SelKJUQ0AniZxQIY+7vYcZNRpcEkGnt0oTWHDvXeTqDwtAkvzwt3QvTsl7/i3yDQ2XYJInICLWaM81op/sVOSM+DSgEd0n+O3r1SE/dD72u0VhSMZYYKZw0ZApcFXMHBk7c9DcjVYMXoMFMKqsqnoe9A=
Ro5JrmfPQnCaJAd5mc1x+wKPoB3ipy3ueRnbD00lUtKhTpLxNm2HGovfEk8CbL3VOzpDyvvavWGo+wiU1qpU1baF5/gGzGYuFQiFB4da+kwjSmd8Jr6p9p9KS3eTkRD5GiWV5zBCHNnlO9200+gw9tvMGllZ65chkEbCHaN1MGiP6Af3wi9hK9yi2QR8sqpxqJ06UgolK+HM2OFuZTf28BVNZACcL8rZmCpjVN27nv9WE7nYnICr5OXL9VV7uclZuLH9VjZkkxpJWH3o8E8ftO6MqbOBeLwlyZgQU+PlGHu4rXtSjH39h9tSLjbAkF4YrT2n6yO9BxrEwqasW+mwnMqm0uI4Cpj60nKrm9eTEIPMhsgZRGyCcA0l/ozzBKwtOfP2OLu1bPdUNdU7XlW6ctgjcfczukCU3/aEbVACkv+6nsg7EFoFkPW4RN+xbB5URaTlA7ddfbjKkCQjY5h/ZeEEm0Nj8e+uIYzOmA9/ftsQOWyhTkwRqK4o+bylQFWSQJhGWPB7hF4jY01yPo7sLY9H/YMci2ds1emys0K4tyyBDQOjcqRz6H0owvjPmWAPflJ6w+g39yklzPdegj4zHzbCtj0NFkWY0xGxhEclG/meTh1txl1SflU1k2E7LtLlV8x3Lgm1FF/QNFH/u0bBlXHg8AMik6Qi9fcf5NEveKY=

View File

@ -18,9 +18,9 @@ def fixResolution():
import re
import subprocess
results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0])
res = re.search(': \d* x \d*', results).group(0).split(' ')
res = re.search(r': \d* x \d*', results).group(0).split(' ')
width, height = str(int(res[1])-4), str(int(int(res[3])-128)) # Width and Height
return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params']))
return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params'])) # type: ignore
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
@ -30,11 +30,11 @@ executable = None
# Check first xfreerdp, allow password redir
if os.path.isfile(xfreerdp):
executable = xfreerdp
elif os.path.isfile(msrdc) and sp['as_file']:
elif os.path.isfile(msrdc) and sp['as_file']: # type: ignore
executable = msrdc
if executable is None:
if sp['as_rdp_url']:
if sp['as_rdp_url']: # type: ignore
raise Exception('''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul>
@ -67,15 +67,16 @@ if executable is None:
''')
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
address = '127.0.0.1:{}'.format(fs.server_address[1])
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
if executable == msrdc:
theFile = theFile = sp['as_file'].format(
address='127.0.0.1:{}'.format(fs.server_address[1])
theFile = theFile = sp['as_file'].format( # type: ignore
address=address
)
filename = tools.saveTempFile(theFile)
@ -89,7 +90,7 @@ elif executable == xfreerdp:
try:
xfparms = fixResolution()
except Exception as e:
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params']))
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params'])) # type: ignore
params = [executable] + xfparms + ['/v:{}'.format(address)]
subprocess.Popen(params)

View File

@ -1 +1 @@
akjWk2TMZx4h/STESjRKWvyxDs4IKdIdX2e2bX2Os6wDhFm40THwJENyXzOjjvDwIv77WgdQJLbBAbKusVA+GA70slmA6W+cdG5pMFFtjgna3OxNo8ClSHHRKer6cwz4FJ70k2nihpTfsQOIlUBr60Gt4/3Il5c7AAUED4/IpekS3MwJfWvsxEpUujP+nsQSEeIvhpFD9oqfA3WnCGD+OOZlXfMe05fNaWKA2/UmtxQlo0rvRsPV4puGjWWHZxmdYVYIvSIcNkqGc6nIxmMmO5NwHXRY7JgoCBEAeLExVcn4ZUW+qPWQji+6tvsiycIfydT2A5ZOUcpbvIY8l1zLR4HaBs6+RiAa+fVEwIlnMl4qvZl2eP7ljo2RKZeaD/t4H+9wLa1kYVEE7/suVEny/Pap6I1BkDHXh6qEUn90pE8QPCFbutzWmbVXpiE+5UhPAp7L4DMc65Oh/qW8QZVzjpB4Np6LRnxMe5Qwb4+uFYNJH2H04Bmbgor+StvEnO/4rOAb1rCOjKDD1V8tzYvUAfizXBLP1ImiHHxJ6tg5s7ztUb+vyH1rD1U5OktpkzfIaBB7/sHG87DnF+e+PDb/mKY3IKyRGL4ndf7yE2TEbOgXqH6dJUuFh1V9JALWFcaB3fPN5FC0R/EB+3iBp/RsEv5ABrqGnOImMWLgNU1OXEo=
eD97r30FTBTbnkNU3qWsqJoiB8jyrpXhN3LcjYILryptrOLhxY5uTw9wfXGkFeB8UIEJl/QMjH85t6E8pKPQdzs35qqH5DMgQWCg/QCmhTa8T8gqSqXT3ZWSTkzvyVXu5aVM8TYdLbsQqZ6o7Y4DO6vt5h2rm+jVLHg7GlhALDaV1WbQKqjMLekt6QLb3M3hN2YYA0j7XbeunplgpzyS9BeMvRtt4dRaPs6yrWP4AmopP+2oYk4qTDzKxiZBje0548n+wA3oYVQdOeYtAVawApg2Ve7Jst3pkG5qAMvzt08Iiu4wIKWJrvUTsapWm3iD1N8dVgheh054L6Nv3MpKvifwhJfY1XeATIFJkvCFw8VAuJBMko1cEcsjmPAEhLCnwBPnOvPDsrvt7CEX8sBiYbZX8M2PR/UHHmKvJ7RE8LEsmhK+5LqhbwnmUypFwuEYciQo0Yg26xIKTRpldQG491a8dGiqjcLI5Qw5F/xG7xzgIsq6puyNXW3Lmi3Iu/cYXmOdleQHWtjfUs4Je+X7f1MHkGduuy7S+b/TKRooa5diVPpmZzAk1jBZAFAaFu+AqaieotbM2Pu3QtPxtiG/2rQSQtgsWGGV+MGKDpBAcTUeKwt9ZYPpHkumyDsSrKy5pt4y2aU/9AcdYiu5Ry7HOev0PygMusSGA6EGzBkTWHA=

View File

@ -17,23 +17,24 @@ from uds import tools # type: ignore
import six
thePass = six.binary_type(sp['password'].encode('UTF-16LE')) # type: ignore
try:
thePass = six.binary_type(sp['password'].encode('UTF-16LE')) # type: ignore
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01), 'hex').decode()
except Exception:
# logger.info('Cannot encrypt for user, trying for machine')
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x05), 'hex').decode()
try:
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Terminal Server Client\\LocalDevices', 0, wreg.KEY_SET_VALUE) # @UndefinedVariable
wreg.SetValueEx(key, sp['ip'], 0, wreg.REG_DWORD, 255) # @UndefinedVariable
wreg.CloseKey(key) # @UndefinedVariable
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Terminal Server Client\\LocalDevices', 0, wreg.KEY_SET_VALUE)
wreg.SetValueEx(key, sp['ip'], 0, wreg.REG_DWORD, 255) # type: ignore
wreg.CloseKey(key)
except Exception as e:
# logger.warn('Exception fixing redirection dialog: %s', e)
pass # Key does not exists, ok...
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
theFile = sp['as_file'].format(# @UndefinedVariable
theFile = sp['as_file'].format( # type: ignore
password=password
)
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
V8FP9WC6BBzo9NnAZNKznkQE5Xdrz1D4KDif+rw7x+0X8MMNbzhB2g/Ukjyvdc1KPBH1T0M89LLFw7XNHwHWLrNmnAppyBCnBgJuIReWPBKvtSqyYRapDydykx0Xv9s+vbaI+LO9vPnO4KSZbxgbfocGhNzV7kYE0pwlXV5N8Qe4dpr2GvnnXwMHv/UGBBRf+KnGIa+/h77+qrejW8dvlvo4od0enH12oh1zQJMZrd7LUx+1vds4/IDPs5seu1KVVNDHawcDg8Fg8RKh+K5kAK8O/kHalulbBcGu3woFxFqERTf65bCG5Cj/476b6JoCk1enyE1HN+0DzrNqvJakim/mAWYIkfkqmsLZ0bu3oFJHfFDixbdj+flMwZ7mv9qNjXFBEp2G6OTGn8I5vEgs0ZFKAQi4sNYyso92k5um3fady1jr+Xf9CMTJsmbEuAIafs44k/9BRpBKHfTaJudVGB3Y2l+/wW2ynh7/J9sO8AkHPrmxNmKpQGHLUpdoHATRKq1AJvZf/fb+cTu/VFF2qigbFk+oApOh6KTeWhU/2qOIWPCczQ/9hbExaTSCVlQ6coQbHBU+S0sHVlqq+zxf0sWhfXfduwM3dqRHKW/pm57gItbH7HgS+yG9o9SeLVaxB52p4019j6Da+DAfmrovYVqPxrykA6kKnka3sY7cCHE=
EbLkCRb09VB7luaOpj43/F1tiPfnw8TPO3bCRqasEwWEi1S9BvK/hgpfTuCKFsKJ4q8+X1lGwPbIGquryzBaa+g+Q9o74ZMaP7hLZH2ko9G32Zd56B6XisHg7qfJC46pjwrHEI7jBec8Du6cBEfi3FCg3i1lHxUXPgZeLWrmuSv4x/HZKYGtXTSMI77ZL6zi8ZFkUk1pceyo9aNj9Zr3uok4Ddg/z/OSU+tD49tkJvIj8GTbpl0Wf4gu02ikrN+nF5+Yu5zac2nz26yPnAXJh1PecoKw/uuwDW5hpvSAwMfBIACezD1r5wfzjpMLqfbIq8VKca57USsi+1R4kwbV1dewTotwh6pHOj8bcVk78LTPqshdVud56390D3jV4C7fQtdA3+CWe6M6SScAwu7a0zDo2CNagmQJuBmlbmxjYgKFsUfjQTZehESCHBLpGiXPuIipU7A+F0iWYLUMKtrT1twfWDaxkCDSO5PGt+hNbt1Jie4qCQ97SvDx4cReaQomkVm4hAaAphS+/HOhZSTQ/+jfGmOYX8MgrM43c3o7r3Avg7heDn2r7CCMMeC5Kh8Clh3nzvM/F0QjvY9TibvlzO1qzyylt5U2OXrJ8agZ8Rpu4IJJQFL6DubVZAlPjlHAJ2d+8Vv8QNi42HEc967RDToaStoeofS6d4eft2SOUP4=

View File

@ -20,21 +20,22 @@ from uds import tools # type: ignore
import six
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk'])
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
thePass = six.binary_type(sp['password'].encode('UTF-16LE')) # type: ignore
try:
thePass = six.binary_type(sp['password'].encode('UTF-16LE')) # @UndefinedVariable
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01), 'hex').decode()
except Exception:
# Cannot encrypt for user, trying for machine
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x05), 'hex').decode()
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
theFile = sp['as_file'].format(# @UndefinedVariable
theFile = sp['as_file'].format( # type: ignore
password=password,
address='127.0.0.1:{}'.format(fs.server_address[1])
)
@ -45,9 +46,9 @@ if executable is None:
raise Exception('Unable to find mstsc.exe. Check that path points to your SYSTEM32 folder')
try:
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\Microsoft\Terminal Server Client\LocalDevices', 0, wreg.KEY_SET_VALUE) # @UndefinedVariable
wreg.SetValueEx(key, '127.0.0.1', 0, wreg.REG_DWORD, 255) # @UndefinedVariable
wreg.CloseKey(key) # @UndefinedVariable
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Terminal Server Client\\LocalDevices', 0, wreg.KEY_SET_VALUE)
wreg.SetValueEx(key, '127.0.0.1', 0, wreg.REG_DWORD, 255) # type: ignore
wreg.CloseKey(key)
except Exception as e:
# logger.warn('Exception fixing redirection dialog: %s', e)
pass # Key does not exists, but it's ok

View File

@ -1 +1 @@
Jnc7MGVnKf5HG89jPUC/bdAebjCX9g6Afl9MX9d9vgpFvopcRmAw5pQrvGi+J9W8jLjg//kNoatGtZ7OCV6Umt7/UQjJyVUQ2bqGm3qBMagtr00v82vz5uUgald/kxvhHPdNYLP8ZKzSs5jESF+WeyKfF2mIhm4CpZLjmwwfQviG7V/Yr7NgENRz+gCaaGlTuz2JIxF7shZjw/zZqRzJQ6CtYozRXjJRTgO+BNNsN+k/dFKRZnRHsVIPQHooPCQ/5duDzWnqG3wEwOx4aibrOb1OSmhOtA0PQjt0pKUUveddRnKMbhqRGFA2+KbYE2pcDAaYCWTI27JEP+gPSoqjFX+8b4LnnM9qrnam5LMQ4EdURdb5/LZdAUyAm8MLglzNBhUbSzBC45PGG9Hs5lf6Hx8RCvZ5yzw17sJfAjJL8CbQoWE2/jy06hidvNDmUJbl/5NSuwAvXzB162qdGRSEpz0q1K6uYl+kmvrSgQEyu6V4P4ITbeHJmVmaaPXK5tPvf2SQhScUhz80Qclh0dE9ZZFJ46KjLohqBgRac0//MIVpuNVjvDuom/p84K3HiY0MUV8V/3KoBcDofR3T/jAwd/0ZgEkwoRNFBsBpseRXkacDq7j9zkpe0S8a5W4gQnay8tJmLmKjKd16OWhqpKLkJKVs1e87Gy1osswwU+f87AA=
PxgUpszz7f/yliXrWhEzYUPd8D4bTMhI2Wq94xh8ZszcHVWwkwudtv7M9on3QJ9vDQ/E7YF9bFsuM+Vql4Fjcnk8sJMHiToXXJADIvNPUOWB24inPUxSkJGiZVITpfMhyNFzcykxcQ7U8U/UepK7ZRdIVQWJpR23XGTARmBDzxgYITS3LrIhpgtJ3jiQZov1K3Ub0oY3GUUK6UxidtRov70e/S1btHi7U6OvjT0Q/PhJBpxMBm0+xf7IF1t//dcGg591SOn1s97wjWhvSTVVFm/P1+7Xso6ZJuWVd5P+yTSH5v9xVTLcARkKRou+0I2syrSb6+zn2FyJgthp3PWYoepFJ+t946qDj//ew6fEBP4p4PcFeQ4Uuc/1F7/bKbNdHj6UzE06qmzbMpYl8QD2DXlL0zrUTlKFEUIKGSdmVmeWFgMrp/yJyUJaFceX0WMSC88Wj3MUW8qO0eTG/KtwgFRYldNt+l9xXl46pp/CsyIRnZQmWf2Lv3+YBU4okn6EPdS9V23Oy+jC4WkgOdHGwaP9weL8BLEIbvpPwgtAGJm9v6MuLT/VXf9sx5PidA+e1XUuvkR7yq7LtfbjdjTKvWtKtaPUiBnCQMc0uYGB0YnpaEj6WU/7yiahbEBZzbShbWMFXbV4RuV+lQsfHYwBNbAxbckhgEK2+ASpNb/7au8=

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module
import subprocess
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
executable = tools.findApp('remote-viewer')
@ -16,7 +16,7 @@ if executable is None:
</p>
''')
theFile = sp['as_file']
theFile = sp['as_file'] # type: ignore
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
KVdckBRbRq0iPwi9PwkkNDA7lLaopVALN+nNHanqrbNT6BT382WIx2aZQl542OOR6lr1y9A8nRDqpuqrWzwQvHESoetb/apvWKtM0H8qH3kygtN3jUwyr9854LQ3woaiykPOwBQC0w0JnSra1aeNM+rCbL035r40d7yYqHyul9fCkCuSMrnMamSBTqykKSGUOZ+dY4Wr9jYD2CEsyD3jgULlLTyTH0rVgE/1I2jiebzjgUMPHxdW1T43TXt4UQdPXb2AlUFRCgCxwxZ/0bE3bAOuxvaYG1oejT0lJPBswqlrQcYLDoAbd9hqotWqfTEB5qFEd2Xsr3TzO7ijfMlAE/UpU3Foybc8+FB90d0uGGjunsYyy+y4C5B6a/XkYfV25X2llSk21mOMGlzXDvY9FaH2CHIfiN7nUOuO1hl8p5aLr16sNMPibcRvx3bLvamexAAPMLB6r8hyQViZIHhMIT+DLXOWN3LyW4U+dR3QdG7KCF06r90OZ39Wf4p6ZXTJ0xK4NJHMRn3UznOhjmHSWGGrDdM5e3N8wrvCPOAHlP5JzWb4aVAFjTUGxxjVGTZk5qWm00o1JGTwVwViTsYfqyCvxXJ1oUq4xiOwjuiheTjD00rc1OUwkGYWwTs1qVVE/q5/V6MZSgiOlteh9bx5VADzGoIyhfR8GjIpi6wFNzk=
Ke13liZe+UPqfKgJBONj0zbw3IaTUVMr5YA3fDbf7tnOf47E7CwFE5l8cBZhpHwg29o/KFZyCDaQ5fwIyT2fQHa4q1HN1I5ra+MG+EFM2wPxOD8y2ZE5QzlVNOt2NvZ4mPJI2RKHaTSd0+wtEUISuY84DAgu8mKG06N1+M2E3yjN6KA2tgZBWiURkaJMuzwDYFRE0kdWi23KdXp2m1EYRf8EBa5klkYAT/cwHgX5iM66Mc92/JirFs/9qZ4bww57fee59gnq1RErmfWbK+V0YX1ROZ4WWs+dYE1cK1zmY/oTtJlmeu6HOkPYEXZldeu+od5/bFdeQzPsVwTTraZsDjeIoyX23YLPUz2hf8vRUhI/JDw+QVsG1xUyKQBmkWYc2W6Gqd25kl2pIOacVy+fzMSrufcd3ekkFrxJbBe1Yc1I9WDwxuG7MaA3atycKZcjLS5hSYXoIwjw7nWlAOYdaxW6DjsmH96LP80IgwumOhrB11+LrYzN+tzBpU+jCpm+3T2Dhpm/FciidCrr0OE1kBC+y1H6eq6H7EFm0nvDG7gOoRw4RZVqdQrTjSs9D+clz8c2K3T16/8cekJhIA6unHHdh89ESmf5liK5cYUNPBZ0Jk07BGAUEHSs/sXXQLM2daUQxyKcuPlrkEawqUhK5aQSV96XCZ/J+PkPahShju8=

View File

@ -5,8 +5,8 @@ from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, undefined-variable
import subprocess
from uds import tools # @UnresolvedImport
from uds.forward import forward # @UnresolvedImport
from uds import tools # type: ignore
from uds.tunnel import forward # type: ignore
executable = tools.findApp('remote-viewer')
@ -21,31 +21,28 @@ if executable is None:
''')
theFile = sp['as_file_ns']
if sp['port'] != '-1':
forwardThread1, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['port'])
theFile = sp['as_file_ns'] # type: ignore
fs = None
if sp['ticket']: # type: ignore
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
if forwardThread1.status == 2:
raise Exception('Unable to open tunnel')
else:
port = -1
fss = None
if sp['ticket_secure']: # type: ignore
# Open tunnel
fss = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket_secure'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
if sp['secure_port'] != '-1':
theFile = sp['as_file']
if port != -1:
forwardThread2, secure_port = forwardThread1.clone(sp['ip'], sp['secure_port'])
else:
forwardThread2, secure_port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['secure_port'])
if forwardThread2.status == 2:
raise Exception('Unable to open tunnel')
else:
secure_port = -1
# Check that tunnel works..
if fss.check() is False:
raise Exception('<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>')
theFile = theFile.format(
secure_port=secure_port,
port=port
secure_port='-1' if not fss else fss.server_address[1],
port='-1' if not fs else fs.server_address[1]
)
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
MwVxZsoxUK+gcMchgM9c3iYky6K7KZ+3z34uZCgpJzvad8dH7lwihqrJ+7tlk55mZU/ea+J4dqk4EgMX1LGzzm9SyE6/9Yz86lfNlj/bH4AtnwkWUHEtKUizTOCpZlhFjRs5Cif6LICeVzGLnPx27vpKzHhbre95kpsmCzJ33vmMnB0IsCrFBSmJw4BdxUcf/+n1CyA5WiUqzIXC1cIkJ212plpl6n+WP0tc40A7WVVcnMV7Kpel7xyihI+hSvpSwOubgXTbdS01IzCD6ecG35VPbuBoOK/rl7yfTVexo+grfiDtTN9kRkXzBkJIkYaPlIhEJNODcGv/23ni1Dx0+45TmFFdfthspZobEsA0b9YKpMZ5FhH1cx5sDQtZTEW9/YrA+cP8KC4UJ+uRuebbF96rKJL6l1OYX88aWoFtRNFf92QvSREwJFmA9MGnpHphdqo4bmwS06CEDn6KE3AxR76ICcJvoioBvO+F+X7CRll7KNJumIB60k74XNxKdBdlR8fV+PDY1kP0RvwQYii2z/40zRFB8l7BnvSs8OgSwACHoKDcsESAUvAwVSi6q9mmTZkKvrpDu0fZIstn4iLFgOS+PnwJYZv5dmW3SrE7DCnwn6ktZMqGCQoRZ2R+Ydi1mnH8+CTf1F03Vxn4UUwZ+G5gPMYk4iW0FhX543TdqBA=
LGPWahJB3T+s8VzwosVugREQVNuBWpzHibiVGK/rHsiOfZFDWkWvErLCZsLQMdDF5VptZ8EeQL2iIUXN3170xaxzT9Nvi6dYah47vTfKPscZEj9MafzER5rchXEPZunBXnuAYBEamN6h2Y6RguEd6E12Mr3YQ0etxi82ZqaOM8iMGSLQJnFZM6rxmIbSNArXYszCnQgIfYfJV1yTKLKeTWCCw6b7hOgQSXalRaRVpx22aCawxInHMfGkH1O0B2ZBEClLeLP9XoD/K0LeKROe72ouyeeAjzeX3x+LHdsSemc/ql8DDQMJUNhTsrNJWfDPlhImD2CcvSyMOJhimPfUeztFjDNhSA7mpoSudMMjpROtz5E5l+VVTUHeFIoRL2F8pAqtN+9Sk544AXcsc+uXbGm6/Hwwc4Df9+jXUNoDgRwhZ1EAUDLeAcoV+lu5u2Kyb60p9K6GhbK8i1IIDcxxg3akR3/FIF/Dqv04TOrKaCO3lZKMI4UmT0btjmCrlxDTn9RsAO+n/lJ2AdcbsKuo6sCwyEvLge2i8F2yxlibA1pQh+v3ZD/agapWf7MUlQgM8RCtq1BD/Bm7FmnNFhbkKVzu8vAHdbKGooSqg64ZzIc5Ak6u9nRaupnn5DHGnKNcR4DRxmCYjLdHhzjzfE61ErQ8PnVI7Yc4j23hYEMd+TM=

View File

@ -6,7 +6,7 @@ from __future__ import unicode_literals
import os
import subprocess
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
@ -25,7 +25,7 @@ if not os.path.isfile(remoteViewer):
''')
theFile = sp['as_file']
theFile = sp['as_file'] # type: ignore
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
omMUcXLu3wGpKRISFlcEG9j0GWbhkud++umoXOoAREnLPlqwxxlIiWEaB5fkTR2ZjPFIXB/lQzGN28PEDbCkxagXb8KA+zXWmYvwkj3uB0QpCkfk0I+5/0cy5p1njxaAyENGZQFVZorqWvtWzuaFsDZrDZvV0qygWK/a7TTwQOxr2xFElnG+u/HzSNx09VzAIeVNkIu/3xP3LA6fo5/uzswDDFmRSch02aFp7AL6PBroq2mdN4aopu/xsdSAEdRzSumPWRLNLVd/yttfW+OOvMX6liUQr0CkFP0BQrHeAJnZVHXVnUNYDqRvnb3m9DjVfjUbFRs5vljxgr9zlcmFRdUXOJMYgDZelMqY0MidOPStoxnx/VHNijurMyBF4rlra0jIAkojqwNMxe788A9WJwKmPxkgeBiqVrVNYgSUpGWixSp3UpNGOtyD6jbY0ghnABoED/3NQl2NZj93SUHliUV14shf6pkrcxk7I4AB0BSIvvLRX6B3sN5hk6wm5rgzLpPl1DlgRGLvCLuLyp8cqiXQalntWPThck9OZLL9MATRK5BkPqNx5M2eEl3gqNNYKwnm+cEFvwbUhSQKsnyqpKCdzQJzp6LkgO4XuSdP4GrNCjUObL4X6Ogq2kb/tc3//ouvES81M11aeS84jBV7+PRcibLXc0t7gcyAUuRxlnc=
dqg89d/khZKFk2SUIrROrthcq22mzSffp2JwLDEMqt6RVwvpT9hHY3eajSauVFJXdAl/DfLnUB1W0mQHWp1FyFQsFzprQhvOxROmnsa+vju2TnwjJHpGFMGIT7AWs3pGlxs1399gGcTXoU09m2/qtHxGgzxTyLprdlqMD1WivN2T+8o1QjLvfPIkXX/A252zJ2GEgZPRW9eni4TjAPY7jUVyoFs3wXkAO5uqBZcB2tGnCkxQ9UuGIa2ladff6o00m9TgAuSvCikVDnknVWFIOguJ+WZ8TDfYVCmHLAH43JI+EWwPcn4OvIgdDc6E9GAn71Mnv33yI48/VTtzV/KFu9aQiAuPoUV1JPCP++jcfsZ7vs1Qe8PdI6gBeHM/3j48oREoQRGpn//q0xpwfbKvBm8qHQ+GI9tv9gDi4sva7tJPNELK4xzMBhCZcG3bHt0tq984oid6o3e8q6sgkVdUE7Jvh3gjlk6H8x596rX2f8hPvqzPEEB8JERl3iJTEGBYWl0l+d9LJiMQcSaMyKSoySoYT9btcdK6p3Dr1uurZxOjgjF/jHi/5yP3H8i5XspiEY/u4Dcehf8Y2rd7K3sFRh1GVSROCdUhBFXbvE4nDRxwUKehwmE769jLOWsq21L0TYtq3ErFahr5QxVjGP3yAmFWGjY2ToTKTqBveCb8DmU=

View File

@ -6,8 +6,8 @@ from __future__ import unicode_literals
import os
import subprocess
from uds import tools # @UnresolvedImport
from uds.forward import forward # @UnresolvedImport
from uds import tools # type: ignore
from uds.tunnel import forward # type: ignore
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
@ -25,31 +25,28 @@ if not os.path.isfile(remoteViewer):
</p>
''')
theFile = sp['as_file_ns']
if sp['port'] != '-1':
forwardThread1, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['port'])
theFile = sp['as_file_ns'] # type: ignore
fs = None
if sp['ticket']: # type: ignore
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
if forwardThread1.status == 2:
raise Exception('Unable to open tunnel')
else:
port = -1
fss = None
if sp['ticket_secure']: # type: ignore
# Open tunnel
fss = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket_secure'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
if sp['secure_port'] != '-1':
theFile = sp['as_file']
if port != -1:
forwardThread2, secure_port = forwardThread1.clone(sp['ip'], sp['secure_port'])
else:
forwardThread2, secure_port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['secure_port'])
if forwardThread2.status == 2:
raise Exception('Unable to open tunnel')
else:
secure_port = -1
# Check that tunnel works..
if fss.check() is False:
raise Exception('<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>')
theFile = theFile.format(
secure_port=secure_port,
port=port
secure_port='-1' if not fss else fss.server_address[1],
port='-1' if not fs else fs.server_address[1]
)
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
dR+uIC5WKTM3Iicua7Jv7YEksMy8gIf3U5MfYzh6pCNYkkdEywpuszoIxHqgn/ltIjuvY4s2kATXqQtuZ7BYCNhB7vGw/nA/PDGqpOPNDCAamRL+N15Ctjb1+olmhQgqR+D/lv7GaScO+5n579OSmrHPaZkDbRo3U9wRiMzg+FLaL6Rknz8Hirpeas4kAculg+s3BeCRmf0fghz6UI9/xf+At0sd6M76p1E/3oFiIBjBNw9yKkLiPgDzq5DrrxA0SLWBwl15IPYqNpBCGo/VMV2pBQsSWmFGS62C3R6KdjMHN9jmO+seWcfhcNF2eCk3ODcoFeZUTfvXT+GoN7u7z3Dt4CyWx9k01RqSMxXcnf+vv2MqgBZde5Lu75ZqIpYP4qBkO4h6CH5isg1KVZJW/tGWGgU3fyVAkY9oxt6B8R2xo3mQeTkY+AGH+7KQHsB9l/OU0R1jHllbEIo9wopb4/SzZLMrECDMgOscA69BFodoFt6suT+QimzPHcgCQLE8xGY9KUZ7rrEn82rr3O7bAKXlJIti+UaT+zbgOizekA5+9CJRNVsWTmFsZ+6ghqY6L/QdyWJhere3Rrzh/0mg36Jk4XEaI8GI/VI/TmtmTwgut6B5gH/6fg+yaVAqYexIcINVMSSdIZyBVeX1QXbzcgYc5QJo9+EOJrzP5U0K+pI=
NCdcJPSAu3yby5d/PiANn+iTTGsOt/GF8Kp9XxhdE1hZKFsR2USQob6tGTdM0HIIuL6i0KDOOvSa5JiD4Tq4OPE4sYSmaK4eDNo+RO7Fa4qP91ksOc3EcUCBGCru9+BNBVrWmAmlaJIfywvowodv8cP70yQxWqz93VomWvVUfJXhF6ylomzYN+gtLqjueKATWznf2d8pQ63g6p9j7p5yVJUGGZQCbuepS1Y3WUhSkf1EHrA233O+ZRK3YP6XDS75WnGkBEr/d/LrkzyYxlHX1UNFYaOay1I5cRXPJ9n2AVkmmZX8wyKxoCvAjwVZWaHoQWSZxNaDQ4YaEh14JK1JBnkpDQUDmgwVq1M0iY+aNlLg4VIMlFz6pVk3jcLk/CZfxMpH7ZkzYkL41vFlzG4lpFnQYoCCb3dPTZdAzg0EdtMy/Sk0X3Bn3dJzz+S2S4RjcLRHgy9hI5YeSVhFksruirWsbryb1WXIWjkjUIlMc/WVN17457onNpNQI2u7bebtoRopIox3gx06Afb3u5f0r7fUus+/1jWwoI8H73ES/RqpL2zXwXh9Ks1+5gFD1TDNkQn98Ia717DKwWoqZtjiJ+thY5Q3rgfLhgzJxRXm+XWDDSIVFdviyFB6m8U7/51xKME7ll5Tx4lVrwhMjFkfJj1TbOlnuvEiVrn4/9XDqo8=

View File

@ -7,14 +7,14 @@ import os
import glob
import subprocess
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
# Lets find remote viewer
# There is a bug that when installed, the remote viewer (at least 64 bits version) does not store correctly its path, so lets find it "a las bravas"
extraPaths = ()
for env in ('PROGRAMFILES', 'PROGRAMW6432'):
if env in os.environ:
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*'))
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*')) # type: ignore
executable = tools.findApp('remote-viewer.exe', extraPaths)
@ -28,7 +28,7 @@ if executable is None:
</p>
''')
theFile = sp['as_file']
theFile = sp['as_file'] # type: ignore
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
CVmFltgXbShVc/gO64FfdFJU7BzxnSs+I6MjMpDk/dm3U+mdPNC/4uVe0ZX/+uc13dUSYzqTMKfuU3dnee8eh03WLIvOHlzs0k1ApQiIj6zaWYpQcjmyTzMbiADykN+JTzy37aQDu0kANuYWePqqNWGruWFwNul4kHCVjvRzvXnSxmLYAleIg4yMUABTRou3AIMAeAaW6oUBqKEvLdQz9z+Iu83DzX8l6MW/okR9DgaMiiqbamJKs4lyE/qXcIC5hegcV2/KcWWKt4FEoHbpnat23u6gg6Bmfri4kC66CiIrD5U2HmWK/6EkdmbrJxVglBF8RmHX7f6wpW20xD3rlw9SL+k01p1QN77Xu7kiHj+uoFi6jl7MYnA02/PVw6Ke/lBx0fFLAdd1KCj5VqEIhccU+k37VEcGPKW3GbTAinZ2yvkzo4rL8uFRnNTQ/ClWfaPV32BRfAoXCPO1yiZxy498uVa1QuKcCQnCrC7X2ZgwEacsePUY+0zHuaBCNqdlHRFsXCwNiwGjETuuCNJmVtzGfOrhaSlHWUdxWOCNpY10XwmIw2s3BL/5T5N0Adh08N5ozI9lbzHUHngj78B9kfTrZDIXR2lJBBQ7CQGN++3iLAd6IlVD8eNwRk39FUQyp/OxMyzrBS1R8O/nIgTK0j68fpU2y3vLxh9pELo2gCw=
eziVaJ6nCWndvYbDpD483QpNFA375Y9FB4lSasUZxJocIW9zjbF4082o+XMPbz/SSO9/6KlSJnZfABVJNFoPWETkf55ryHvzPj6AwNUtWkR/UZQLT4k/RZ8DPz1/r1Boha4A3nxRpuwMbsSy7z4rmg7HKQpwsyD/0qu8Rc0+YmhT14N0Jqkhh4aIISIKiwdUD6+6y6yq9iRPDoL0UJXeEBLJNOJGJk0jBV5YNwcYVoabiTthh4vPnaSzWE45GqJrFe9fX92pnM/3wVDL0Wld67Br5SAwxlKEeucveZedbLwYbAnL/cv0WHkqWC6+o4ahPlXobVXIGtd3mHeiwrNn9SVBnk/fQpeMHN/wwqIs/9VArvOKRcuaMrGR2U3slRwIpWODGTN2DHIHwZ1s3ghIfgm/REC7Q33pz7/pAQ0LthjJ77H41rePMig6aaO8yWhTuEk4K0XHJVq5fHaDAWCTvUdUiuRQuEjjJOhC8wSE0uMjCJ9hARVk+66xbrgllgbQwnDlmLVeA61+DQo6ygOCpqrHDlRFyPjVUvBThSehYM/eyUXY+Rsf9YLNx8FfCZQxmyUvb4r97EtCKadyDecumS/KHgeyA8gbosJLu2nNeHDYgOAFX5fewOt0leUHsqNTMpVznSMOFjO8wIv/XAJsfjkCkct0HVYVW3erQ2FVWyE=

View File

@ -7,15 +7,15 @@ import os
import glob
import subprocess
from uds import tools # @UnresolvedImport
from uds.forward import forward # @UnresolvedImport
from uds import tools # type: ignore
from uds.tunnel import forward # type: ignore
# Lets find remote viewer
# There is a bug that when installed, the remote viewer (at least 64 bits version) does not store correctly its path, so lets find it "a las bravas"
extraPaths = ()
for env in ('PROGRAMFILES', 'PROGRAMW6432'):
if env in os.environ:
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*'))
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*')) # type: ignore
executable = tools.findApp('remote-viewer.exe', extraPaths)
@ -28,31 +28,28 @@ if executable is None:
<a href="http://virt-manager.org/download/">Open download page</a>
</p>
''')
theFile = sp['as_file_ns']
if sp['port'] != '-1':
forwardThread1, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['port'])
theFile = sp['as_file_ns'] # type: ignore
fs = None
if sp['ticket']: # type: ignore
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
if forwardThread1.status == 2:
raise Exception('Unable to open tunnel')
else:
port = -1
fss = None
if sp['ticket_secure']: # type: ignore
# Open tunnel
fss = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket_secure'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
if sp['secure_port'] != '-1':
theFile = sp['as_file']
if port != -1:
forwardThread2, secure_port = forwardThread1.clone(sp['ip'], sp['secure_port'])
else:
forwardThread2, secure_port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['secure_port'])
if forwardThread2.status == 2:
raise Exception('Unable to open tunnel')
else:
secure_port = -1
# Check that tunnel works..
if fss.check() is False:
raise Exception('<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>')
theFile = theFile.format(
secure_port=secure_port,
port=port
secure_port='-1' if not fss else fss.server_address[1],
port='-1' if not fs else fs.server_address[1]
)
filename = tools.saveTempFile(theFile)

View File

@ -1 +1 @@
WxhSxSYZISZNlj+Slprz8cdzstKFghx3zuQXdMmakzg5mLDyetwR9cSdWRkYd9vcP8j6aeufbK1io4rwvsdxu+7jRLSL9GVwB+MbIQYrBZ7RbiA2hqWhzQ/LCncSL73Jq9jZtt3i2pgWyA691z8UUbpts6wimsn6cDXQtEHda7MOFIi4Nzlzjf8AMpPTCkPldIDiXhyH+nuCXdzpOY32Gvrq8w6eTQrUWF8dswa1er0SQJENc2StEh9Tt1378QwTBtPQNgyop++sv/FhLdDB8hBQliX5LX7t9NxzZcvyFBYHqFnfXEsYc2bWWkt264CWfULREPLRQK11UWZ51ldvY1+xFOEg1eGAna8nWhapZ9R5DagSfehokpAov30Y0PwjTx5MGxiubd0gMeP4Vr2YZ77qBb5JnPKplEH2VsHS7TRgJyKNf2xI9Yw80iGSrO8LUC6L+9+cLDACyrmFINUA/2sFbRLjqdogY7CREIMzP07DUOluEcNgMnPLBKrTZ5U9nxnwgdgptLZgDNJHagitAiW5zMS10lEnJKRLZ0zVgWdiFna29SB7o75jO5M0LA+adIOzRH4G0C5vFYiiMVwsfLhqT3nUvaacTMLslFxWbr5T4QxWJkuLNjIMypw0cOzSaPsXW1tuZXwL0CjgnXDat7iNFQZCzEDQuoDaGDWvYpE=
LNhHPgRKio48GqUpYgPIokcVEV6XHf/I17eSLSNabQ34QWiZybvlq2O7Gfztdag+1Zvig5urzFVbjuOfR3kIWAlt6hDRBo32cOveMngzUNnZfrpfehmMiFoCD91+/R/lXNm6x/fSpisbnThDejzk5vnG/xUZEls9qazSJLvpgRYR95IJxoArkhUMrAhkK7n0/0RDGQmhNJV50TYYYlnRcXCzeRaOJcReK1JkuovVHGFwTDDiLYa/irr5gWZqIhCgIzW7yGHeQGMAUoJkgPXexV9mWjMPIRbx3rBnPhtOJnywyILN+HQZ6SU2lsvGZMQQ2d/4WAZ+uP0k7CNS/81Cm6PZAL3LpnZ0zfszcWaAAF4rLbkimm1aKUXHoUwWkXfxjxodlQRXD3oE/jnTuMucl8WLUNnP7AwH5VQNxVTn33EoE8C3jRR5LcjL1ut7qSPno7Lf/UW2Yx1GGOCR0GLtuB5OPq0cIRjdqckibkL4jXRMX7QsXnh5uEYG+wih7gohzdcprFnhzQjFy4esQsKXqWTSaMgBVtUMOSGHylsQAps1j7Co6EGCMu/g7jrevk0f9T8moETA2fRPEmdV2Md/DFezsP2a042g8Git8llLGtibq329K/XAwC2mAwN768BHVu+WlZQmYcyz7iEU/tR9Dxq7y05ljiOCgAS4oK8ucQE=

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2019 Virtual Cable S.L.
# Copyright (c) 2012-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -57,15 +56,44 @@ logger = logging.getLogger(__name__)
class TSPICETransport(BaseSpiceTransport):
"""
Provides access via SPICE to service.
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
"""
typeName = _('SPICE')
typeType = 'TSSPICETransport'
typeDescription = _('SPICE Protocol. Tunneled connection.')
protocol = transports.protocols.SPICE
group: typing.ClassVar[str] = transports.TUNNELED_GROUP
tunnelServer = gui.TextField(label=_('Tunnel server'), order=1, tooltip=_('IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'), tab=gui.TUNNEL_TAB)
tunnelServer = gui.TextField(
label=_('Tunnel server'),
order=1,
tooltip=_(
'IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'
),
tab=gui.TUNNEL_TAB,
)
tunnelWait = gui.NumericField(
length=3,
label=_('Tunnel wait time'),
defvalue='30',
minValue=5,
maxValue=65536,
order=2,
tooltip=_('Maximum time to wait before closing the tunnel listener'),
required=True,
tab=gui.TUNNEL_TAB,
)
verifyCertificate = gui.CheckBoxField(
label=_('Force SSL certificate verification'),
order=23,
tooltip=_(
'If enabled, the certificate of tunnel server will be verified (recommended).'
),
defvalue=gui.TRUE,
tab=gui.TUNNEL_TAB,
)
serverCertificate = BaseSpiceTransport.serverCertificate
fullScreen = BaseSpiceTransport.fullScreen
@ -76,7 +104,9 @@ class TSPICETransport(BaseSpiceTransport):
def initialize(self, values: 'Module.ValuesType'):
if values:
if values['tunnelServer'].count(':') != 1:
raise transports.Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
raise transports.Transport.ValidationException(
_('Must use HOST:PORT in Tunnel Server Field')
)
def getUDSTransportScript( # pylint: disable=too-many-locals
self,
@ -86,24 +116,40 @@ class TSPICETransport(BaseSpiceTransport):
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest'
request: 'HttpRequest',
) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
userServiceInstance: typing.Any = userService.getInstance()
# Spice connection
con = userServiceInstance.getConsoleConnection()
port: str = con['port'] or '-1'
secure_port: str = con['secure_port'] or '-1'
# Ticket
tunpass = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _i in range(12))
tunuser = TicketStore.create(tunpass)
# We MAY need two tickets, one for 'insecure' port an one for secure
ticket = ''
if con['port']:
ticket = TicketStore.create_for_tunnel(
userService=userService,
port=int(con['port']),
validity=self.tunnelWait.num() + 60, # Ticket overtime
)
sshHost, sshPort = self.tunnelServer.value.split(':')
ticket_secure = ''
if con['secure_port']:
ticket_secure = TicketStore.create_for_tunnel(
userService=userService,
port=int(con['secure_port']),
validity=self.tunnelWait.num() + 60, # Ticket overtime
)
tunHost, tunPort = self.tunnelServer.value.split(':')
r = RemoteViewerFile(
'127.0.0.1', '{port}', '{secure_port}', con['ticket']['value'],
self.serverCertificate.value.strip(), con['cert_subject'], fullscreen=self.fullScreen.isTrue()
'127.0.0.1',
'{port}',
'{secure_port}',
con['ticket']['value'], # This is secure ticket from kvm, not UDS ticket
self.serverCertificate.value.strip(),
con['cert_subject'],
fullscreen=self.fullScreen.isTrue(),
)
r.usb_auto_share = self.usbShare.isTrue()
r.new_usb_auto_share = self.autoNewUsbShare.isTrue()
@ -112,11 +158,13 @@ class TSPICETransport(BaseSpiceTransport):
osName = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
OsDetector.Macintosh: 'macosx',
}.get(os['OS'])
if osName is None:
return super().getUDSTransportScript(userService, transport, ip, os, user, password, request)
return super().getUDSTransportScript(
userService, transport, ip, os, user, password, request
)
# if sso: # If SSO requested, and when supported by platform
# userServiceInstance.desktopLogin(user, password, '')
@ -124,13 +172,12 @@ class TSPICETransport(BaseSpiceTransport):
sp = {
'as_file': r.as_file,
'as_file_ns': r.as_file_ns,
'tunUser': tunuser,
'tunPass': tunpass,
'tunHost': sshHost,
'tunPort': sshPort,
'ip': con['address'],
'port': port,
'secure_port': secure_port
'tunHost': tunHost,
'tunPort': tunPort,
'tunWait': self.tunnelWait.num(),
'tunChk': self.verifyCertificate.isTrue(),
'ticket': ticket,
'ticket_secure': ticket_secure,
}
return self.getScript('scripts/{}/tunnel.py', osName, sp)

View File

@ -6,11 +6,11 @@ from __future__ import unicode_literals
import subprocess
from os.path import expanduser
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
home = expanduser('~') + ':1;/media:1;'
keyFile = tools.saveTempFile(sp['key'])
theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip=sp['ip'], port=sp['port'])
keyFile = tools.saveTempFile(sp['key']) # type: ignore
theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip=sp['ip'], port=sp['port']) # type: ignore
filename = tools.saveTempFile(theFile)
# HOME=[temporal folder, where we create a .x2goclient folder and a sessions inside] pyhoca-cli -P UDS/test-session

View File

@ -1 +1 @@
Td27A1n4tterDd2/pY/jMBlvZyucmhte0u8aj9KQ2zSGNFXWdKnqmyfes2QY38weBVHEiI71jMopKsrZ3NGefFkvHODTFmiyA6gtzNZkO3ux1QEioPfP8BrvY0IjMrrmvlAOb3OSF3hCqGcWbbM2F3U6wdGmWirRmThN2FUSgTaOW0ITffKcPE2Fc8CHXDMGgvjloyP01KXy3M72DMR5Ir/Yj5RmumfvHLhi8/nsXz/jHjCLYxoSi3rOHTterH41/axT3cFIE4nVZIFSegx85mJ0JZRFcTL6dUx1b9FC/7iw8H5fuutkcCi/3gEL1j1tsD0juWT+36QPpH7SrT/TM2H2T+dlaZ9DxlRn+EaWwcW8olfygtNjpqOOspGLMSnI3c1cZeS4QGegCaeYK6xeOpmsF0qh+1J4ctu/GA/0hMJ3Cv+mSQA5w4B9uGWj7p8K4Z2rMpIB+uZouijDNe8J+wj4AMttFUypkZBX+oa+33uQDasM2AZSG2247AqRqLcAfNj3m3I9LGqW85V45ytbcmqfQGTfE8mO3FAl0o2aivHi1KUgZQrze06pYJi/C1K9quqV9Pq2XntJPJsM8LzUuIWZrfesCge6h7w1i+CCos3L3MxHu8S9jU/uFeeXWHS1wwYkTghw3DFcZu0bGQilZa2XM6ITwxiVtyFaucHFPwU=
FDUIODILNyuC5PSK/2BNLgcenZ3xdaMw1UPAvwWc1hG93v7MtKNptbSOkSsMEh9/0dlME0+icUvj46aUbuflemQ+36gUVELdd+7e8aP+J0jLhHpBKHl4QGYcRGJv8u9VnmfSIQGJfFRatyVMEFNCCl+81lmRwKYq+2qP0nS5ufbcjQLd4cfQEgXpiTJsW69jENIc5/TgifLhCsaoL3y2vln4pq5VXTWlBTNYAyNOV/BiBgdPvLlPmIdD+wLrZ1gJ+Bzk+QjENdeBfhZE8N6DthjCTn1FzLcG00q7rlL0qo37J1TKojXe+CkuWoOPXXuBfGfzWTnrF7CdVl9kPb4jb56FHUa69nFp5+3ISH3tKlVQjsXekv/XezQWRihRze9wXJAb1lP2qxRJrkMPmI1iRa3ie1YSuxzbnpuysFkuTg8rl23cYLFyWRy/zdokJAdX9FC5b1KsFZ3slGI4iy1Q9WEIrNuFTvgZCE44V4HgP7IwadfMceF/RKOUs3L8Y1JAktqhe6bWjt/7e+ZLz0hIgoRj+OqCEkfp7xqp9eYNGTscUfQRcrqjN73786l34NNqYeWBkTnJNBcgZrp5NnKF3avzNDnMHTRnCZSSuGzKcXDP+UXdI2EUlk2oWQ0cZpuXe4JKH6fvWqtZ9E+TpywVMp3JEtlFZOmao+KKIst8Wdw=

View File

@ -5,20 +5,21 @@ from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable
import subprocess
from uds.forward import forward # @UnresolvedImport
from uds.tunnel import forward # type: ignore
from os.path import expanduser
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
forwardThread, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['port'])
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
if forwardThread.status == 2:
raise Exception('Unable to open tunnel')
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
tools.addTaskToWait(forwardThread)
home = expanduser('~') + ':1;/media:1;'
keyFile = tools.saveTempFile(sp['key'])
theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip='127.0.0.1', port=port)
keyFile = tools.saveTempFile(sp['key']) # type: ignore
theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip='127.0.0.1', port=fs.server_address[1]) # type: ignore
filename = tools.saveTempFile(theFile)
# HOME=[temporal folder, where we create a .x2goclient folder and a sessions inside] pyhoca-cli -P UDS/test-session

View File

@ -1 +1 @@
CnCqJRFLyii+jk4neecfXQ1tK3pKsdJ0b4z6XmLKPSLtzP+mMyrr5EK7RStN02KwvRhLwuXoH3lSp6ydGSwGtnRn44E6V2wIHkb/2dm09guR/KlTw21uBVabyYvH62yRjs54il0gL6YmTku3qWA7LeEEg7YuSxtXuNUgyEx28B1sTNBnW9E/FjIUSYF7vPgxiUaSbntmPvQehuqgaYKREtfVyB8cbTctqaJhz7sUtcetu461N9me4Lz7dxqAA3aAI2N1JV5QR/ATJAx29VuH0pG7iqhaXGe+K9oNbQyaS4sNIGHX+u/WR5a/ngr/m0llIcewHu/WxrAnSJLv6e+4+xpB5NQko0HR42cG6hy+IsaGMpid9Ubwilje1w+R0jWVZr3Xt14NnJKktysNhqLTEWw/hoCaJThJhzvEtM8B4H9Um65lPXGwTgvi2S71Hlql+IVJqxoj4DGdC7emU+MtwdHc3H4/YyCJC7X27PA1Hnmvr+BIjciQZC6BjuCyyppP3DozplmptAs0+FVZZs8BvJSsqm0pnFI5NM5Tf1WF/56JxBaAz0u4ugEwx4w/JnxorrydezOmP/xADIjFY3Xh7fkAGg1a48+WFGB+gpmXohbHnR8u4tnY30gnkCUqoJe/ZVJuK2Wyzs+8508+1A7ztTUGamZjhQPoXIrn0EDA5bs=
OQ3g4Z39LoR6k8LseDP2Kktk3QCj14WeJ7RlqLcyXN5QXJTdu86lKQhLHapS4GUX9apcgcF1I+o5NyPeXoE8iXBQr0456Cz6k+O35jzlwrO1BXPby9bWEuUwlXvyQuHPY9wThQA++jWiKDV9UD5UC+BHP3BWWZVj1aVEunHJa2uqnMLQMVb63vIndclQXJcLXNuQk1v2jD6f2INxG0iojzfxJ95XrCN5OjgfhStimuFC3dCjm1shq1vSgpPVgampzMYO8ViJCzIk9dg6UKO+aWUmd617wRf0ZHJvez2Oerc8PDu/uYKSjPOChUapvkWRX84S8Ydn/4wUhUK9TKQt9iIBW4HOCVxB8gzX1fZwu5LqEii5f/LJWybFgrh33eJIBBJDyUU0Y+fp9IS8ayvOnEj1xONNTKpo0ZO407H1yTjcwoWAhT9Uob2BaMxCk90qy/OTN6mjtYbUvgKayUkV3OhbbSS8B/+t/wpyk2N6w74Qx2SqB5EqNIZT82raz4QM/Rggjq2im2F3gWwKUMkldt4u0Zf0qt6x8ov8qr/xeVuP+lUfnHJyYXvIOyUI6QZmdTem+lIATs/0a/Dp02yb+khW0TyDc3kc6F3Igf32PzleCiwXVkKfC/QZzKTLPPjaRZL+vEWu0tfh9qOZAutSRzs5nCuhIbvmnH19sbvBr4w=

View File

@ -7,12 +7,12 @@ import os
import subprocess
from os.path import expanduser
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
home = expanduser('~').replace('\\', '\\\\') + '#1;'
keyFile = tools.saveTempFile(sp['key'])
keyFile = tools.saveTempFile(sp['key']) # type: ignore
# On windows, the separator beween active and not is "#"
theFile = sp['xf'].format(export='c:\\\\#1;', keyFile=keyFile.replace('\\', '/'), ip=sp['ip'], port=sp['port'])
theFile = sp['xf'].format(export='c:\\\\#1;', keyFile=keyFile.replace('\\', '/'), ip=sp['ip'], port=sp['port']) # type: ignore
filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'

View File

@ -1 +1 @@
LuB4norDe9e4uHcdO158ENqlTNC9Wyp3xE7p/usaTGkJiQ8xgEbojPpXlJcbL9ovhRdcbkM499iJ8+tpd2XNNPkq3kEa3yy8ZbfKQWvcoDArJsi3MaWsTBfL48BpsPAwpgFgXwTNYLldWJ2uOp1RJijfNce1zD3NdC6JEWsewwoR0H+BjfHGHHvFtXSx5No35onSGS3g3Y1igmkg9/6GEqmANHCNyfegyFHIfaDJZwynm19Fk4A7ZQIY3PTq/kxWq5PXaVcHB6nC0UJBXHsEXePBFek9zaKViWiA5ZFlGYiaqKp1dj87QDEuwJ7GWrktDBRrbt8ZARAV/odhozx14V0Uxh6IiSvNUECb1pJ76H/Nqm1oQW3eRnWXZHjgN2rfsL9+988AZymJluC9acNcPHZw6TjaWksGrCu2qSIYAc62dxHSOJlov6/4/AqDPdmj2VSO8yRrmLkjhmlAZ1mcH29s8E1tw0HpBjPPiFRN+Hw4PCXdI3Qm5TkTbpWWYX14rm5u+KoNviUi1G0r9S0ZVM0e/xtUa9WKuOwUs81D3vHrAzgjHRGL7MaUWgXNHb1dB7SpogGsPmV05r4FMrZ9ip4qdVgM6391oETGzc+kWrWn6U8/Hm/N7aiUF19ipDN3U5ICiOMfeQqwb3oHJyvyoZUR2+x0q95FFND7O/gx0mg=
HW48ZI/UF5SKfE5vTqyfKKOm2CZDoRVPyrJrmL2z6B9kuBQMB+o4T6RYsOPYMNQaII7ynG2YTSwfrFC3vQ5qNcWQtYbED0oRxGVW8Vl+sxFW3AvIcxhC3LMcO6+sRr5MUA5E8gGAq01AWbIE/lXBF8n/jovqT6sv1mApBQ3qlBwPq+YgqsvKdOXsNKWcZCc7Ig9xPGvVAQwSyiQCUUfyw2zk4l1LlAEklKpOcjy4c19dmO6wiU4ZWB3UZdMbu1vFRVMHTcKe5r/I0yUgB/2OcylniCvqM4+10OJAZKIEsK+mHz7+hF1rbBdey4qlXgUGtnCd5YLfctp6+lpsqr/awgl0h3BPRz+uPUMEQWqPxnqKMsP6sLrz4WJYnqP4yFnlUJKNqt1XZShMrzCz7VkT91RWHrIi7Mzz+QVlpC+PZS+0c2APiU1yfTPeXaaLKOQYjcKwHtFc4wZOJquwRbYFQbf/g/33zkRcmRQEueli6AHqKwxhpOPyuunNgY6itoS+PNIvyHK/xURrsao3kO7RhDavBOIiWiaIpvsaDCYPdpGTtgD/yVjlAMQnvQMqPUhg8Gxjxc5h3KaNNMJrLjFjXicY9Xh5P3sx0SgJKUxvg3UdYgyJHlNNLa5dJBQSEUfiP6zzX88w2h73rMP+BE6u1Yv0YsSY3967ctLMRO2/fWA=

View File

@ -6,22 +6,22 @@
import os
import subprocess
from uds.forward import forward # @UnresolvedImport
from uds.tunnel import forward # type: ignore
from os.path import expanduser
from uds import tools # @UnresolvedImport
from uds import tools # type: ignore
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
forwardThread, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], sp['port'])
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
if forwardThread.status == 2:
raise Exception('Unable to open tunnel')
tools.addTaskToWait(forwardThread)
# Care, expanduser is encoding using "mcbs", so treat it as bytes always
# Care, expanduser is encoding using "mcbs", so treat it as bytes on python 2.7
home = expanduser('~').replace('\\', '\\\\') + '#1;'
keyFile = tools.saveTempFile(sp['key'])
theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip='127.0.0.1', port=port)
keyFile = tools.saveTempFile(sp['key']) # type: ignore
theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip='127.0.0.1', port=fs.server_address[1]) # type: ignore
filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'

View File

@ -1 +1 @@
pKLTspUmlmfjY7Ei6aiNFtCh+8mQ8TkZztS7D/kjGRj25FxmfG5Y0HMOdlu8kouiLTAwkzpyj+J+GjebWwcPCJv7hFJ8kWFJ7XaX8b3uX8BREq+G1p4UYSiZDM7qSaPviM9VFoTLNwRa+yBknbyosLBRCpesKSbaUlis9tsAHByU98peQ0QSOrrUvfFBIl5EUzx+frgKTS67tCNGJ+L4POOnOakKNoqDYiJ0z4/S4vMC2w/JQ1OxZPgXsyPRAwM7KqCOA5zhzB1Pjucoj9lfZvJz8T7DDpX05eN8dUU0dsgUZHKbm92Tn6MnMDpNbUH/CIIeQMfbBThTNlr2vvYYzdAjbpNlg4R4s10RCfIWb0Tqfvu9jRs/8dUOMkfOZSbv3DVukXIadQt1ednzbagBXoMPE3jiLe5OKQqAg4LFcU9vm1HJB/EIenpeCo/Oxmytb6VLatl5RF4COwC0WfFAZoku9qXW6BFzTWhGMGkzuXYS0C8rnDb1m53DBXNp3aPkVJ8ktoDCQ4fWbb9YDFZ2GNDVt5QppyizkblvbQoy4gVxPXlo+aPc9b92/hKmMha9RA1FByhDB7Lzx4a0iYZicv3LjX3N/VPvrTGpmfeiSDovqMWfBR9au3qneNmndxM4LnXL6wbyVyfeJey6XRIshRAE+gWlz9Ew1vzD0llnfN8=
mYksg6meXqkKrrIES6xDkYeWsb78ejjJqA7EV7H3OgExs3gpxYr35fJR5IpVKrxUu1uT3mZK8PqmQ2ZA4beZkB+1IqdOZk5OWBpm4a1IGzU+KsPsCw+F1auvizJioZtM2JaG5FSSuskzu/Gflm1/akq3F4Ttkv0+Jt6daiEOnXioO0I+Jiv/fgaaI2DVDl2kc6bcPP+A/oS/cLO7RVrjLf+rcIeK1sUrhLhwhtD/8NyN/5nP5Xfq4jjNxEl2SFQZC3SUyXDfWY2LhbSt24O6rkYG9WkX/eNUwGK0ojdX4jdPlRq3gsu2rlkhIW91IBOztGoWZRWOi0vkqWODQdd7uTHA0Wrbi+5YZb07gv4K4r1TFPTEVWjEiY/xox3fZIJYhSIbGxFZXd9LlVOhpZ8Q2tEME/18rjDxuEsr5AdBihv9JEvsYIwfjHoOY9a5LK7FExnTWwEHlzscQ7f3sq9CihT3QnAwKBhqp2hQbZxT/28SAQF+0JAehWCSAi6hCk3ZYs3US5SmPcm32jwsHxh93Ae64Vfm1R/HA/QH9J1EEVA0pVS0H9H3mCAaPz2qq/oLLnXh5qbsbrXKFl/2pi3haYhGR0FSxbG625d7ZoAVTFrF8BMFErWerQjx9X9UDftbf5moBJZiTyk2cwnCnG4Q3DDddukudKiLwPzEnHaN1Zo=

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016-2019 Virtual Cable S.L.
# Copyright (c) 2016-2021 Virtual Cable S.L.U.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -60,12 +59,43 @@ class TX2GOTransport(BaseX2GOTransport):
Provides access via X2GO to service.
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
"""
typeName = _('X2Go')
typeType = 'TX2GOTransport'
typeDescription = _('X2Go access (Experimental). Tunneled connection.')
group = transports.TUNNELED_GROUP
tunnelServer = gui.TextField(label=_('Tunnel server'), order=1, tooltip=_('IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'), tab=gui.TUNNEL_TAB)
tunnelServer = gui.TextField(
label=_('Tunnel server'),
order=1,
tooltip=_(
'IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'
),
tab=gui.TUNNEL_TAB,
)
tunnelWait = gui.NumericField(
length=3,
label=_('Tunnel wait time'),
defvalue='30',
minValue=5,
maxValue=65536,
order=2,
tooltip=_('Maximum time to wait before closing the tunnel listener'),
required=True,
tab=gui.TUNNEL_TAB,
)
verifyCertificate = gui.CheckBoxField(
label=_('Force SSL certificate verification'),
order=23,
tooltip=_(
'If enabled, the certificate of tunnel server will be verified (recommended).'
),
defvalue=gui.TRUE,
tab=gui.TUNNEL_TAB,
)
fixedName = BaseX2GOTransport.fixedName
screenSize = BaseX2GOTransport.screenSize
@ -83,7 +113,9 @@ class TX2GOTransport(BaseX2GOTransport):
def initialize(self, values: 'Module.ValuesType'):
if values:
if values['tunnelServer'].count(':') != 1:
raise BaseX2GOTransport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
raise BaseX2GOTransport.ValidationException(
_('Must use HOST:PORT in Tunnel Server Field')
)
def getUDSTransportScript( # pylint: disable=too-many-locals
self,
@ -93,7 +125,7 @@ class TX2GOTransport(BaseX2GOTransport):
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest'
request: 'HttpRequest',
) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
ci = self.getConnectionInfo(userService, user, password)
@ -120,13 +152,16 @@ class TX2GOTransport(BaseX2GOTransport):
rootless=rootless,
width=width,
height=height,
user=username
user=username,
)
tunpass = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _i in range(12))
tunuser = TicketStore.create(tunpass)
ticket = TicketStore.create_for_tunnel(
userService=userService,
port=22,
validity=self.tunnelWait.num() + 60, # Ticket overtime
)
sshHost, sshPort = self.tunnelServer.value.split(':')
tunHost, tunPort = self.tunnelServer.value.split(':')
# data
data = {
@ -140,7 +175,7 @@ class TX2GOTransport(BaseX2GOTransport):
'drives': self.exports.isTrue(),
'fullScreen': width == -1 or height == -1,
'this_server': request.build_absolute_uri('/'),
'xf': xf
'xf': xf,
}
m = tools.DictAsObj(data)
@ -152,17 +187,18 @@ class TX2GOTransport(BaseX2GOTransport):
}.get(os['OS'])
if osName is None:
return super().getUDSTransportScript(userService, transport, ip, os, user, password, request)
return super().getUDSTransportScript(
userService, transport, ip, os, user, password, request
)
sp = {
'tunUser': tunuser,
'tunPass': tunpass,
'tunHost': sshHost,
'tunPort': sshPort,
'ip': ip,
'port': '22',
'tunHost': tunHost,
'tunPort': tunPort,
'tunWait': self.tunnelWait.num(),
'tunChk': self.verifyCertificate.isTrue(),
'ticket': ticket,
'key': priv,
'xf': xf
'xf': xf,
}
return self.getScript('scripts/{}/tunnel.py', osName, sp)

View File

@ -1,3 +0,0 @@
{
"directory": "bower_components"
}

View File

@ -1,21 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@ -1 +0,0 @@
* text=auto

View File

@ -1,4 +0,0 @@
node_modules
.tmp
bower_components
dist

View File

@ -1,3 +0,0 @@
{
"generator-mocha": {}
}

View File

@ -1,428 +0,0 @@
// Generated on 2015-09-21 using
// generator-webapp 1.1.0
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// If you want to recursively match all subfolders, use:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Automatically load required grunt tasks
require('jit-grunt')(grunt, {
useminPrepare: 'grunt-usemin'
});
// Configurable paths
var config = {
app: 'app',
dist: 'dist'
};
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
config: config,
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
babel: {
// files: ['<%= config.app %>/js/{,*/}*.js'],
files: [],
tasks: ['babel:dist']
},
babelTest: {
// files: ['test/spec/{,*/}*.js'],
files: [],
tasks: ['babel:test', 'test:watch']
},
gruntfile: {
files: ['Gruntfile.js']
},
sass: {
files: ['<%= config.app %>/css/{,*/}*.{scss,sass}'],
tasks: ['sass', 'postcss']
},
css: {
files: ['<%= config.app %>/css/{,*/}*.css'],
tasks: ['newer:copy:css', 'postcss']
}
},
browserSync: {
options: {
notify: false,
background: true,
watchOptions: {
ignored: ''
}
},
livereload: {
options: {
files: [
'<%= config.app %>/{,*/}*.html',
'.tmp/css/{,*/}*.css',
'<%= config.app %>/img/{,*/}*',
'.tmp/js/{,*/}*.js'
],
port: 9000,
server: {
baseDir: ['.tmp', config.app],
routes: {
'/bower_components': './bower_components'
}
}
}
},
test: {
options: {
port: 9001,
open: false,
logLevel: 'silent',
host: 'localhost',
server: {
baseDir: ['.tmp', './test', config.app],
routes: {
'/bower_components': './bower_components'
}
}
}
},
dist: {
options: {
background: false,
server: '<%= config.dist %>'
}
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= config.dist %>/*',
'!<%= config.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Make sure code css are up to par and there are no obvious mistakes
eslint: {
target: [
'Gruntfile.js',
// '<%= config.app %>/js/{,*/}*.js',
'!<%= config.app %>/js/vendor/*',
'test/spec/{,*/}*.js'
]
},
// Mocha testing framework configuration options
mocha: {
all: {
options: {
run: true,
urls: ['http://<%= browserSync.test.options.host %>:<%= browserSync.test.options.port %>/index.html']
}
}
},
// Compiles ES6 with Babel
babel: {
options: {
sourceMap: true
},
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/js',
src: '{,*/}*.jss',
dest: '.tmp/js',
ext: '.jss'
}]
},
test: {
files: [{
expand: true,
cwd: 'test/spec',
src: '{,*/}*.jss',
dest: '.tmp/spec',
ext: '.jss'
}]
}
},
// Compiles Sass to CSS and generates necessary files if requested
sass: {
options: {
sourceMap: true,
sourceMapEmbed: true,
sourceMapContents: true,
includePaths: ['.']
},
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/css',
src: ['*.{scss,sass}'],
dest: '.tmp/css',
ext: '.css'
}]
}
},
postcss: {
options: {
map: true,
processors: [
// Add vendor prefixed css
require('autoprefixer')({
browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']
})
]
},
dist: {
files: [{
expand: true,
cwd: '.tmp/css/',
src: '{,*/}*.css',
dest: '.tmp/css/'
}]
}
},
// Automatically inject Bower components into the HTML file
wiredep: {
app: {
src: ['<%= config.app %>/index.html'],
exclude: ['bootstrap.js'],
ignorePath: /^(\.\.\/)*\.\./
},
sass: {
src: ['<%= config.app %>/css/{,*/}*.{scss,sass}'],
ignorePath: /^(\.\.\/)+/
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'<%= config.dist %>/js/{,*/}*.js',
'<%= config.dist %>/css/{,*/}*.css',
'<%= config.dist %>/img/{,*/}*.*',
'<%= config.dist %>/css/fonts/{,*/}*.*',
'<%= config.dist %>/*.{ico,png}'
]
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
options: {
dest: '<%= config.dist %>'
},
html: '<%= config.app %>/index.html'
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
options: {
assetsDirs: [
'<%= config.dist %>',
'<%= config.dist %>/img',
'<%= config.dist %>/css'
]
},
html: ['<%= config.dist %>/{,*/}*.html'],
css: ['<%= config.dist %>/css/{,*/}*.css']
},
// The following *-min tasks produce minified files in the dist folder
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/img',
src: '{,*/}*.{gif,jpeg,jpg,png}',
dest: '<%= config.dist %>/img'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/img',
src: '{,*/}*.svg',
dest: '<%= config.dist %>/img'
}]
}
},
htmlmin: {
dist: {
options: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
conservativeCollapse: true,
removeAttributeQuotes: true,
removeCommentsFromCDATA: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
// true would impact css with attribute selectors
removeRedundantAttributes: false,
useShortDoctype: true
},
files: [{
expand: true,
cwd: '<%= config.dist %>',
src: '{,*/}*.html',
dest: '<%= config.dist %>'
}]
}
},
// By default, your `index.html`'s <!-- Usemin block --> will take care
// of minification. These next options are pre-configured if you do not
// wish to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= config.dist %>/css/main.css': [
// '.tmp/css/{,*/}*.css',
// '<%= config.app %>/css/{,*/}*.css'
// ]
// }
// }
// },
// uglify: {
// dist: {
// files: {
// '<%= config.dist %>/js/js.js': [
// '<%= config.dist %>/js/js.js'
// ]
// }
// }
// },
// concat: {
// dist: {}
// },
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= config.app %>',
dest: '<%= config.dist %>',
src: [
'*.{ico,png,txt}',
'img/{,*/}*.webp',
'{,*/}*.html',
'css/fonts/{,*/}*.*'
]
}, {
expand: true,
dot: true,
cwd: '.',
src: 'bower_components/bootstrap-sass/assets/fonts/bootstrap/*',
dest: '<%= config.dist %>'
}]
}
},
// Run some tasks in parallel to speed up build process
concurrent: {
server: [
// 'babel:dist',
'sass'
],
test: [
//'babel'
],
dist: [
//'babel',
'sass',
//'imagemin',
//'svgmin'
]
}
});
grunt.registerTask('serve', 'start the server and preview your app', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'browserSync:dist']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'postcss',
'browserSync:livereload',
'watch'
]);
});
grunt.registerTask('server', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run([target ? ('serve:' + target) : 'serve']);
});
grunt.registerTask('test', function (target) {
if (target !== 'watch') {
grunt.task.run([
'clean:server',
'concurrent:test',
'postcss'
]);
}
grunt.task.run([
'browserSync:test',
'mocha'
]);
});
grunt.registerTask('build', [
'clean:dist',
'wiredep',
'useminPrepare',
'concurrent:dist',
'postcss',
'concat',
'cssmin',
// 'uglify',
'copy:dist'
// 'filerev',
// 'usemin'
// 'htmlmin'
]);
grunt.registerTask('default', [
'newer:eslint',
'test',
'build'
]);
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -1,76 +0,0 @@
$btn-margin: $font-size-base/2;
.btn-alert {
//@include button-variant(complement($brand-danger), darken($brand-danger, 10%), darken($brand-danger, 20%));
@include pretty-buttons(complement($brand-danger), darken($brand-danger, 10%));
margin-right: $btn-margin;
}
.btn-action {
//@include button-variant($btn-default-color, invert($btn-default-color), $btn-default-border);
@include pretty-buttons($btn-default-color, $btn-default-bg);
margin-right: $font-size-base/2;
}
.btn-export {
//@include button-variant($btn-default-color, $btn-default-bg, $btn-default-border);
@include pretty-buttons($btn-default-color, $btn-default-bg);
margin-right: $font-size-base/2;
}
// Default buttons a bit more beautiful
.btn {
&.btn-default {
@include pretty-buttons($btn-default-color, $btn-default-bg);
}
&.btn-primary {
@include pretty-buttons($btn-primary-color, $btn-primary-bg);
}
&.btn-success {
@include pretty-buttons($btn-success-color, $btn-success-bg);
}
&.btn-info {
@include pretty-buttons($btn-info-color, $btn-info-bg);
}
&.btn-warning {
@include pretty-buttons($btn-warning-color, $btn-warning-bg);
}
&.btn-danger {
@include pretty-buttons($btn-danger-color, $btn-danger-bg);
}
&.btn-inverse {
@include pretty-buttons(white, #474949);
}
}
/*.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary {
background: #337ab7 none repeat scroll 0 0;
color: #fff;
}*/
.bootstrap-switch {
.bootstrap-switch-label {
@include pretty-buttons($btn-default-color, $btn-default-bg);
}
.bootstrap-switch-handle-on {
&.bootstrap-switch-default {
@include pretty-buttons($btn-default-color, $btn-default-bg);
}
&.bootstrap-switch-primary {
@include pretty-buttons($btn-primary-color, $btn-primary-bg);
}
}
.bootstrap-switch-handle-off {
&.bootstrap-switch-default {
@include pretty-buttons($btn-warning-color, $btn-warning-bg);
}
&.bootstrap-switch-primary {
@include pretty-buttons($btn-warning-color, $btn-warning-bg);
}
}
}

View File

@ -1,42 +0,0 @@
.dataTables_wrapper {
overflow-x: hidden;
}
table.dataTable thead .sorting {
background-image: url("../img/sort_both.png");
}
table.dataTable thead .sorting_asc {
background-image: url("../img/sort_asc.png");
}
table.dataTable thead .sorting_desc {
background-image: url("../img/sort_desc.png");
}
table.dataTable thead .sorting_asc_disabled {
background-image: url("../img/sort_asc_disabled.png");
}
table.dataTable thead .sorting_desc_disabled {
background-image: url("../img/sort_desc_disabled.png");
}
table.dataTable {
border-collapse: inherit;
}
table.dataTable tbody > tr.selected, table.dataTable tbody > tr > .selected {
background-color: lighten($table-bg-active, 30%);
&:hover {
background-color: $table-bg-hover;
}
}
tr.even:not(.selected):not(:hover) {
.sorting_1 {
background-color: darken(#FFFFFF, 5%);
}
}
tr.odd:not(.selected):not(:hover) {
.sorting_1 {
background-color: darken($table-bg-accent, 5%);
}
}

View File

@ -1,89 +0,0 @@
/*
This states displays as default
*/
.row-maintenance-true {
color: lighten($brand-danger, 20%);
}
.log-WARN {
color: $brand-warning;
}
.log-DEBUG {
color: $brand-success;
}
.log-INFO, .log-OTHER {
color: $brand-info;
}
.log-ERROR, &.log-FATAL {
color: $brand-danger;
}
// To position correctly things
.btns-tables {
float: left;
margin-bottom: 16px;
}
.dataTables_info {
float: left;
}
.dataTables_paginate {
float: right;
}
.table {
color: #00496b;
border: 1px solid $brand-primary;
// $font-family-monospace
// $font-family-serif
// $font-family-sans-serif
// font-family: $font-family-monospace;
// font-size: $font-size-large;
> tbody > tr {
cursor: pointer;
}
}
/*.table tbody tr.selected {
background-color: $uds-color-blue;
color: $brand-warning;
&:hover {
background-color: $uds-color-blue-dark;
}
}*/
/*.table-striped > tbody > tr {
td.sorting_1 {
color: $uds-color-blue;
}
}*/
.uds-table {
min-height: $uds-panel-min-height - 48px;
padding-right: 2px;
}
.row-state-S {
color: gray;
}
.row-running-Yes {
color: green;
}
@media (max-width: 768px) {
.label-tbl-button {
display: none;
}
.uds-table {
min-height: 0px;
}
}

View File

@ -1,20 +0,0 @@
// fixes breadcrumb for using
.breadcrumb {
> li {
+ li:before {
content: "/ "; // Unicode space added since inline-block means non-collapsing white-space
}
}
}
.bootstrap-timepicker-widget a.btn, .bootstrap-timepicker-widget input {
background: $input-bg;
border-color: $brand-primary;
border-radius: 0;
border-style: solid;
border-width: 1px;
}
.bootstrap-timepicker-widget table td a {
color: $brand-primary;
}

View File

@ -1,58 +0,0 @@
@mixin pretty-buttons($color, $background, $text-shadow: none) {
color: $color;
@include gradient-vertical(lighten($background, 5%), darken($background, 5%), 0%, 100%);
border-color: darken($background, 10%);
border-bottom-color: darken($background, 20%);
text-shadow: $text-shadow;
//@include box-shadow(inset 0 1px 0 rgba(255, 255, 255, .1));
&:hover,
&:focus,
&:active,
&.active {
@include gradient-vertical(darken($background, 0), darken($background, 10%), 0%, 100%);
border-color: darken($background, 20%);
color: $color;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&,
&:hover,
&:focus,
&:active,
&.active {
background-color: $background;
border-color: darken($background, 5%);
}
}
}
/*
.btn {
&.btn-default {
@include pretty-buttons($btn-default-color, $btn-default-bg);
}
&.btn-primary {
@include pretty-buttons($btn-primary-color, $btn-primary-bg);
}
&.btn-success {
@include pretty-buttons($btn-success-color, $btn-success-bg);
}
&.btn-info {
@include pretty-buttons($btn-info-color, $btn-info-bg);
}
&.btn-warning {
@include pretty-buttons($btn-warning-color, $btn-warning-bg);
}
&.btn-danger {
@include pretty-buttons($btn-danger-color, $btn-danger-bg);
}
&.btn-inverse {
@include pretty-buttons(white, #474949);
}
}
*/

View File

@ -1,859 +0,0 @@
//
// Variables
// --------------------------------------------------
//== Colors
//
//## Gray and brand colors for use across Bootstrap.
$bg-color1: #252830;
$bg-color2: lighten($bg-color1, 14%);
$gray-base: #FFFFFF;
$gray-darker: darken($gray-base, 13.5%); // #222
$gray-dark: darken($gray-base, 20%); // #333
$gray: darken($gray-base, 33.5%); // #555
$gray-light: darken($gray-base, 46.7%); // #777
$gray-lighter: darken($gray-base, 93.5%); // #eee
$brand-primary: darken(#1CA8DD, 0%); // #337ab7
$brand-success: #1BC98E;
$brand-info: #9F86FF;
$brand-warning: #E4D836;
$brand-danger: #E64759;
//== Scaffolding
//
//## Settings for some of the most global styles.
//** Background color for `<body>`.
$body-bg: $bg-color1;
//** Global text color on `<body>`.
$text-color: $gray-darker;
//** Global textual link color.
$link-color: $brand-primary;
//** Link hover color set via `darken()` function.
$link-hover-color: lighten($link-color, 15%);
//** Link hover decoration.
$link-hover-decoration: underline;
//== Typography
//
//## Font, line-height, and color for body text, headings, and more.
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-family-base: $font-family-sans-serif;
$font-size-base: 14px;
$font-size-large: ceil(($font-size-base * 1.25)); // ~18px
$font-size-small: ceil(($font-size-base * 0.85)); // ~12px
$font-size-h1: floor(($font-size-base * 2.6)); // ~36px
$font-size-h2: floor(($font-size-base * 2.15)); // ~30px
$font-size-h3: ceil(($font-size-base * 1.7)); // ~24px
$font-size-h4: ceil(($font-size-base * 1.25)); // ~18px
$font-size-h5: $font-size-base;
$font-size-h6: ceil(($font-size-base * 0.85)); // ~12px
//** Unit-less `line-height` for use in components like buttons.
$line-height-base: 1.428571429; // 20/14
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
$line-height-computed: floor(($font-size-base * $line-height-base)); // ~20px
//** By default, this inherits from the `<body>`.
$headings-font-family: inherit;
$headings-font-weight: 500;
$headings-line-height: 1.1;
$headings-color: $brand-info;
//== Iconography
//
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
//** Load fonts from this directory.
$icon-font-path: "../fonts/";
//** File name for all font files.
$icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file.
$icon-font-svg-id: "glyphicons_halflingsregular";
//== Components
//
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
$padding-base-vertical: 6px;
$padding-base-horizontal: 12px;
$padding-large-vertical: 10px;
$padding-large-horizontal: 16px;
$padding-small-vertical: 5px;
$padding-small-horizontal: 10px;
$padding-xs-vertical: 1px;
$padding-xs-horizontal: 5px;
$line-height-large: 1.33;
$line-height-small: 1.5;
$border-radius-base: 0px;
$border-radius-large: 0px;
$border-radius-small: 0px;
//** Global color for active items (e.g., navs or dropdowns).
$component-active-color: #fff;
//** Global background color for active items (e.g., navs or dropdowns).
$component-active-bg: $brand-primary;
//** Width of the `border` for generating carets that indicator dropdowns.
$caret-width-base: 4px;
//** Carets increase slightly in size for larger components.
$caret-width-large: 5px;
//== Tables
//
//## Customizes the `.table` component with basic values, each used across all table variations.
//** Padding for `<th>`s and `<td>`s.
$table-cell-padding: 8px;
//** Padding for cells in `.table-condensed`.
$table-condensed-cell-padding: 5px;
//** Default background color used for all tables.
$table-bg: transparent;
//** Background color used for `.table-striped`.
$table-bg-accent: lighten($body-bg, 10%);
//** Background color used for `.table-hover`.
$table-bg-hover: $brand-primary;
$table-bg-active: darken($brand-primary, 20%);
//** Border color for table and cell borders.
$table-border-color: darken($body-bg, 10%);
//== Buttons
//
//## For each of Bootstrap's buttons, define text, background and border color.
$btn-font-weight: normal;
$btn-default-color: $gray-base;
$btn-default-bg: lighten($body-bg, 20%);
$btn-default-border: lighten($body-bg, 10%);
$btn-primary-color: $gray-base;
$btn-primary-bg: $brand-primary;
$btn-primary-border: darken($btn-primary-bg, 5%);
$btn-success-color: $gray-base;
$btn-success-bg: $brand-success;
$btn-success-border: darken($btn-success-bg, 5%);
$btn-info-color: $gray-base;
$btn-info-bg: $brand-info;
$btn-info-border: darken($btn-info-bg, 5%);
$btn-warning-color: $gray-base;
$btn-warning-bg: $brand-warning;
$btn-warning-border: darken($btn-warning-bg, 5%);
$btn-danger-color: $gray-base;
$btn-danger-bg: $brand-danger;
$btn-danger-border: darken($btn-danger-bg, 5%);
$btn-link-disabled-color: $gray-light;
//== Forms
//
//##
//** `<input>` background color
$input-bg: $body-bg;
//** `<input disabled>` background color
$input-bg-disabled: lighten($body-bg, 15%);
//** Text color for `<input>`s
$input-color: $gray-base;
//** `<input>` border color
$input-border: $brand-primary;
// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
//** Default `.form-control` border radius
$input-border-radius: $border-radius-base;
//** Large `.form-control` border radius
$input-border-radius-large: $border-radius-large;
//** Small `.form-control` border radius
$input-border-radius-small: $border-radius-small;
//** Border color for inputs on focus
$input-border-focus: $brand-info;
//** Placeholder text color
$input-color-placeholder: darken($brand-primary, 15%);
//** Default `.form-control` height
$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2);
//** Large `.form-control` height
$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2);
//** Small `.form-control` height
$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2);
$legend-color: $gray-dark;
$legend-border-color: lighten($body-bg, 15%);
//** Background color for textual input addons
$input-group-addon-bg: $input-bg;
//** Border color for textual input addons
$input-group-addon-border-color: $input-border;
//** Disabled cursor for form controls and buttons.
$cursor-disabled: not-allowed;
//== Dropdowns
//
//## Dropdown menu container and contents.
//** Background for the dropdown menu.
$dropdown-bg: lighten($body-bg, 15%);
//** Dropdown menu `border-color`.
$dropdown-border: lighten($body-bg, 40%);
//** Dropdown menu `border-color` **for IE8**.
$dropdown-fallback-border: lighten($body-bg, 40%);
//** Divider color for between dropdown items.
$dropdown-divider-bg: lighten($body-bg, 40%);
//** Dropdown link text color.
$dropdown-link-color: $gray-dark;
//** Hover color for dropdown links.
$dropdown-link-hover-color: darken($gray-dark, 5%);
//** Hover background for dropdown links.
$dropdown-link-hover-bg: $gray-lighter;
//** Active dropdown menu item text color.
$dropdown-link-active-color: $component-active-color;
//** Active dropdown menu item background color.
$dropdown-link-active-bg: $component-active-bg;
//** Disabled dropdown menu item background color.
$dropdown-link-disabled-color: $gray-light;
//** Text color for headers within dropdown menus.
$dropdown-header-color: $gray-light;
//** Deprecated `$dropdown-caret-color` as of v3.1.0
$dropdown-caret-color: $gray-light;
//-- Z-index master list
//
// Warning: Avoid customizing these values. They're used for a bird's eye view
// of components dependent on the z-axis and are designed to all work together.
//
// Note: These variables are not generated into the Customizer.
$zindex-navbar: 1000;
$zindex-dropdown: 1000;
$zindex-popover: 1060;
$zindex-tooltip: 1070;
$zindex-navbar-fixed: 1030;
$zindex-modal: 1050;
$zindex-modal-background: 1040;
//== Media queries breakpoints
//
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
// Extra small screen / phone
//** Deprecated `$screen-xs` as of v3.0.1
$screen-xs: 480px;
//** Deprecated `$screen-xs-min` as of v3.2.0
$screen-xs-min: $screen-xs;
//** Deprecated `$screen-phone` as of v3.0.1
$screen-phone: $screen-xs-min;
// Small screen / tablet
//** Deprecated `$screen-sm` as of v3.0.1
$screen-sm: 768px;
$screen-sm-min: $screen-sm;
//** Deprecated `$screen-tablet` as of v3.0.1
$screen-tablet: $screen-sm-min;
// Medium screen / desktop
//** Deprecated `$screen-md` as of v3.0.1
$screen-md: 992px;
$screen-md-min: $screen-md;
//** Deprecated `$screen-desktop` as of v3.0.1
$screen-desktop: $screen-md-min;
// Large screen / wide desktop
//** Deprecated `$screen-lg` as of v3.0.1
$screen-lg: 1200px;
$screen-lg-min: $screen-lg;
//** Deprecated `$screen-lg-desktop` as of v3.0.1
$screen-lg-desktop: $screen-lg-min;
// So media queries don't overlap when required, provide a maximum
$screen-xs-max: ($screen-sm-min - 1);
$screen-sm-max: ($screen-md-min - 1);
$screen-md-max: ($screen-lg-min - 1);
//== Grid system
//
//## Define your custom responsive grid.
//** Number of columns in the grid.
$grid-columns: 12;
//** Padding between columns. Gets divided in half for the left and right.
$grid-gutter-width: 30px;
// Navbar collapse
//** Point at which the navbar becomes uncollapsed.
$grid-float-breakpoint: $screen-sm-min;
//** Point at which the navbar begins collapsing.
$grid-float-breakpoint-max: ($grid-float-breakpoint - 1);
//== Container sizes
//
//## Define the maximum width of `.container` for different screen sizes.
// Small screen / tablet
$container-tablet: (720px + $grid-gutter-width);
//** For `$screen-sm-min` and up.
$container-sm: $container-tablet;
// Medium screen / desktop
$container-desktop: (940px + $grid-gutter-width);
//** For `$screen-md-min` and up.
$container-md: $container-desktop;
// Large screen / wide desktop
$container-large-desktop: (1140px + $grid-gutter-width);
//** For `$screen-lg-min` and up.
$container-lg: $container-large-desktop;
//== Navbar
//
//##
// Basics of a navbar
$navbar-height: 50px;
$navbar-margin-bottom: $line-height-computed;
$navbar-border-radius: $border-radius-base;
$navbar-padding-horizontal: floor(($grid-gutter-width / 2));
$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2);
$navbar-collapse-max-height: 340px;
$navbar-default-color: #777;
$navbar-default-bg: #f8f8f8;
$navbar-default-border: darken($navbar-default-bg, 6.5%);
// Navbar links
$navbar-default-link-color: #777;
$navbar-default-link-hover-color: #333;
$navbar-default-link-hover-bg: transparent;
$navbar-default-link-active-color: #555;
$navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%);
$navbar-default-link-disabled-color: #ccc;
$navbar-default-link-disabled-bg: transparent;
// Navbar brand label
$navbar-default-brand-color: $navbar-default-link-color;
$navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%);
$navbar-default-brand-hover-bg: transparent;
// Navbar toggle
$navbar-default-toggle-hover-bg: #ddd;
$navbar-default-toggle-icon-bar-bg: #888;
$navbar-default-toggle-border-color: #ddd;
// Inverted navbar
// Reset inverted navbar basics
$navbar-inverse-color: lighten($gray-light, 15%);
$navbar-inverse-bg: darken($body-bg, 5%);
$navbar-inverse-border: darken($navbar-inverse-bg, 10%);
// Inverted navbar links
$navbar-inverse-link-color: lighten($gray-light, 15%);
$navbar-inverse-link-hover-color: $gray-light;
$navbar-inverse-link-hover-bg: darken($brand-primary, 30%);
$navbar-inverse-link-active-color: $gray-lighter;
$navbar-inverse-link-active-bg: $brand-primary;
$navbar-inverse-link-disabled-color: #444;
$navbar-inverse-link-disabled-bg: transparent;
// Inverted navbar brand label
$navbar-inverse-brand-color: $navbar-inverse-link-color;
$navbar-inverse-brand-hover-color: $brand-primary;
$navbar-inverse-brand-hover-bg: transparent;
// Inverted navbar toggle
$navbar-inverse-toggle-hover-bg: #333;
$navbar-inverse-toggle-icon-bar-bg: #fff;
$navbar-inverse-toggle-border-color: #333;
//== Navs
//
//##
//=== Shared nav styles
$nav-link-padding: 10px 15px;
$nav-link-hover-bg: $gray-lighter;
$nav-disabled-link-color: $gray-light;
$nav-disabled-link-hover-color: $gray-light;
//== Tabs
$nav-tabs-border-color: #ddd;
$nav-tabs-link-hover-border-color: $gray-lighter;
$nav-tabs-active-link-hover-bg: $body-bg;
$nav-tabs-active-link-hover-color: $gray;
$nav-tabs-active-link-hover-border-color: #ddd;
$nav-tabs-justified-link-border-color: #ddd;
$nav-tabs-justified-active-link-border-color: $body-bg;
//== Pills
$nav-pills-border-radius: $border-radius-base;
$nav-pills-active-link-hover-bg: $component-active-bg;
$nav-pills-active-link-hover-color: $component-active-color;
//== Pagination
//
//##
$pagination-color: $link-color;
$pagination-bg: $body-bg;
$pagination-border: $brand-primary;
$pagination-hover-color: $gray-base;
$pagination-hover-bg: $brand-primary;
$pagination-hover-border: $pagination-border;
$pagination-active-color: $gray-lighter;
$pagination-active-bg: $brand-primary;
$pagination-active-border: $brand-primary;
$pagination-disabled-color: darken($pagination-color, 30%);
$pagination-disabled-bg: darken($pagination-bg, 30%);
$pagination-disabled-border: darken($pagination-border, 0%);
//== Pager
//
//##
$pager-bg: $pagination-bg;
$pager-border: $pagination-border;
$pager-border-radius: 0px;
$pager-hover-bg: $pagination-hover-bg;
$pager-active-bg: $pagination-active-bg;
$pager-active-color: $pagination-active-color;
$pager-disabled-color: $pagination-disabled-color;
//== Jumbotron
//
//##
$jumbotron-padding: 30px;
$jumbotron-color: inherit;
$jumbotron-bg: lighten($body-bg,30%);
$jumbotron-heading-color: inherit;
$jumbotron-font-size: ceil(($font-size-base * 1.5));
//== Form states and alerts
//
//## Define colors for form feedback states and, by default, alerts.
$state-success-text: $brand-success;
$state-success-bg: darken($state-success-text, 50%);;
$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%);
$state-info-text: $brand-info;
$state-info-bg: darken($state-info-text, 50%);;
$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%);
$state-warning-text: $brand-warning;
$state-warning-bg: darken($state-warning-text, 50%);
$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%);
$state-danger-text: $brand-danger;
$state-danger-bg: darken($state-danger-text, 50%);
$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%);
//== Tooltips
//
//##
//** Tooltip max width
$tooltip-max-width: 200px;
//** Tooltip text color
$tooltip-color: $gray-base;
//** Tooltip background color
$tooltip-bg: lighten($body-bg, 25%);
$tooltip-opacity: .9;
//** Tooltip arrow width
$tooltip-arrow-width: 5px;
//** Tooltip arrow color
$tooltip-arrow-color: $tooltip-bg;
//== Popovers
//
//##
//** Popover body background color
$popover-bg: #fff;
//** Popover maximum width
$popover-max-width: 276px;
//** Popover border color
$popover-border-color: rgba(0,0,0,.2);
//** Popover fallback border color
$popover-fallback-border-color: #ccc;
//** Popover title background color
$popover-title-bg: darken($popover-bg, 3%);
//** Popover arrow width
$popover-arrow-width: 10px;
//** Popover arrow color
$popover-arrow-color: $popover-bg;
//** Popover outer arrow width
$popover-arrow-outer-width: ($popover-arrow-width + 1);
//** Popover outer arrow color
$popover-arrow-outer-color: fadein($popover-border-color, 5%);
//** Popover outer arrow fallback color
$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%);
//== Labels
//
//##
//** Default label background color
$label-default-bg: lighten($body-bg, 15%);
//** Primary label background color
$label-primary-bg: $brand-primary;
//** Success label background color
$label-success-bg: $brand-success;
//** Info label background color
$label-info-bg: $brand-info;
//** Warning label background color
$label-warning-bg: $brand-warning;
//** Danger label background color
$label-danger-bg: $brand-danger;
//** Default label text color
$label-color: $gray-lighter;
//** Default text color of a linked label
$label-link-hover-color: #fff;
//== Modals
//
//##
//** Padding applied to the modal body
$modal-inner-padding: 15px;
//** Padding applied to the modal title
$modal-title-padding: 15px;
//** Modal title line-height
$modal-title-line-height: $line-height-base;
//** Background color of modal content area
$modal-content-bg: lighten($body-bg, 15%);
//** Modal content border color
$modal-content-border-color: $brand-primary;
//** Modal content border color **for IE8**
$modal-content-fallback-border-color: $brand-info;
//** Modal backdrop background color
$modal-backdrop-bg: #000;
//** Modal backdrop opacity
$modal-backdrop-opacity: .4;
//** Modal header border color
$modal-header-border-color: $brand-primary;
//** Modal footer border color
$modal-footer-border-color: $modal-header-border-color;
$modal-lg: 900px;
$modal-md: 600px;
$modal-sm: 300px;
//== Alerts
//
//## Define alert colors, border radius, and padding.
$alert-padding: 15px;
$alert-border-radius: $border-radius-base;
$alert-link-font-weight: bold;
$alert-success-bg: $state-success-bg;
$alert-success-text: $state-success-text;
$alert-success-border: $state-success-border;
$alert-info-bg: $state-info-bg;
$alert-info-text: $state-info-text;
$alert-info-border: $state-info-border;
$alert-warning-bg: $state-warning-bg;
$alert-warning-text: $state-warning-text;
$alert-warning-border: $state-warning-border;
$alert-danger-bg: $state-danger-bg;
$alert-danger-text: $state-danger-text;
$alert-danger-border: $state-danger-border;
//== Progress bars
//
//##
//** Background color of the whole progress component
$progress-bg: lighten($body-bg, 15%);
//** Progress bar text color
$progress-bar-color: #fff;
//** Variable for setting rounded corners on progress bar.
$progress-border-radius: $border-radius-base;
//** Default progress bar color
$progress-bar-bg: $brand-primary;
//** Success progress bar color
$progress-bar-success-bg: $brand-success;
//** Warning progress bar color
$progress-bar-warning-bg: $brand-warning;
//** Danger progress bar color
$progress-bar-danger-bg: $brand-danger;
//** Info progress bar color
$progress-bar-info-bg: $brand-info;
//== List group
//
//##
//** Background color on `.list-group-item`
$list-group-bg: lighten($body-bg, 15%);
//** `.list-group-item` border color
$list-group-border: lighten($body-bg, 30%);
//** List group border radius
$list-group-border-radius: $border-radius-base;
//** Background color of single list items on hover
$list-group-hover-bg: $gray-dark;
//** Text color of active list items
$list-group-active-color: $gray-base;
//** Background color of active list items
$list-group-active-bg: $gray-darker;
//** Border color of active list elements
$list-group-active-border: $list-group-active-bg;
//** Text color for content within active list items
$list-group-active-text-color: lighten($list-group-active-bg, 40%);
//** Text color of disabled list items
$list-group-disabled-color: $gray-darker;
//** Background color of disabled list items
$list-group-disabled-bg: $gray-lighter;
//** Text color for content within disabled list items
$list-group-disabled-text-color: $list-group-disabled-color;
$list-group-link-color: $brand-primary;
$list-group-link-hover-color: $list-group-link-color;
$list-group-link-heading-color: $gray-base;
//== Panels
//
//##
$panel-bg: lighten($body-bg, 15%);
$panel-body-padding: 15px;
$panel-heading-padding: 10px 15px;
$panel-footer-padding: $panel-heading-padding;
$panel-border-radius: $border-radius-base;
//** Border color for elements within panels
$panel-inner-border: $brand-primary;
$panel-footer-bg: lighten($body-bg,5%);
$panel-default-text: $gray-lighter;
$panel-default-border: $brand-primary;
$panel-default-heading-bg: lighten($body-bg, 45%);
$panel-primary-text: $gray-lighter;
$panel-primary-border: $brand-primary;
$panel-primary-heading-bg: $brand-primary;
$panel-success-text: $state-success-text;
$panel-success-border: $state-success-border;
$panel-success-heading-bg: $state-success-bg;
$panel-info-text: $state-info-text;
$panel-info-border: $state-info-border;
$panel-info-heading-bg: $state-info-bg;
$panel-warning-text: $state-warning-text;
$panel-warning-border: $state-warning-border;
$panel-warning-heading-bg: $state-warning-bg;
$panel-danger-text: $state-danger-text;
$panel-danger-border: $state-danger-border;
$panel-danger-heading-bg: $state-danger-bg;
//== Thumbnails
//
//##
//** Padding around the thumbnail image
$thumbnail-padding: 4px;
//** Thumbnail background color
$thumbnail-bg: $body-bg;
//** Thumbnail border color
$thumbnail-border: #ddd;
//** Thumbnail border radius
$thumbnail-border-radius: $border-radius-base;
//** Custom text color for thumbnail captions
$thumbnail-caption-color: $text-color;
//** Padding around the thumbnail caption
$thumbnail-caption-padding: 9px;
//== Wells
//
//##
$well-bg: lighten($body-bg, 15%);
$well-border: darken($well-bg, 7%);
//== Badges
//
//##
$badge-color: #fff;
//** Linked badge text color on hover
$badge-link-hover-color: #fff;
$badge-bg: $gray-light;
//** Badge text color in active nav link
$badge-active-color: $link-color;
//** Badge background color in active nav link
$badge-active-bg: #fff;
$badge-font-weight: bold;
$badge-line-height: 1;
$badge-border-radius: 10px;
//== Breadcrumbs
//
//##
$breadcrumb-padding-vertical: 8px;
$breadcrumb-padding-horizontal: 15px;
//** Breadcrumb background color
$breadcrumb-bg: $body-bg;
//** Breadcrumb text color
$breadcrumb-color: #ccc;
//** Text color of current page in the breadcrumb
$breadcrumb-active-color: $gray-light;
//** Textual separator for between breadcrumb elements
$breadcrumb-separator: "/ ";
//== Carousel
//
//##
$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
$carousel-control-color: #fff;
$carousel-control-width: 15%;
$carousel-control-opacity: .5;
$carousel-control-font-size: 20px;
$carousel-indicator-active-bg: #fff;
$carousel-indicator-border-color: #fff;
$carousel-caption-color: #fff;
//== Close
//
//##
$close-font-weight: bold;
$close-color: #000;
$close-text-shadow: 0 1px 0 #fff;
//== Code
//
//##
$code-color: #c7254e;
$code-bg: #f9f2f4;
$kbd-color: #fff;
$kbd-bg: #333;
$pre-bg: #f5f5f5;
$pre-color: $gray-dark;
$pre-border-color: #ccc;
$pre-scrollable-max-height: 340px;
//== Type
//
//##
//** Horizontal offset for forms and lists.
$component-offset-horizontal: 180px;
//** Text muted color
$text-muted: $gray-light;
//** Abbreviations and acronyms border color
$abbr-border-color: $gray-light;
//** Headings small color
$headings-small-color: $gray-light;
//** Blockquote small color
$blockquote-small-color: $gray-light;
//** Blockquote font size
$blockquote-font-size: ($font-size-base * 1.25);
//** Blockquote border color
$blockquote-border-color: $gray-lighter;
//** Page header border color
$page-header-border-color: $gray-lighter;
//** Width of horizontal description list titles
$dl-horizontal-offset: $component-offset-horizontal;
//** Horizontal line color.
$hr-border: $gray-lighter;

View File

@ -1,857 +0,0 @@
//
// Variables
// --------------------------------------------------
//== Colors
//
//## Gray and brand colors for use across Bootstrap.
$gray-base: #000;
$gray-darker: lighten($gray-base, 13.5%); // #222
$gray-dark: lighten($gray-base, 20%); // #333
$gray: lighten($gray-base, 33.5%); // #555
$gray-light: lighten($gray-base, 46.7%); // #777
$gray-lighter: lighten($gray-base, 93.5%); // #eee
$brand-primary: darken(#428bca, 6.5%); // #337ab7
$brand-success: #5cb85c;
$brand-info: #5bc0de;
$brand-warning: #f0ad4e;
$brand-danger: #d9534f;
//== Scaffolding
//
//## Settings for some of the most global styles.
//** Background color for `<body>`.
$body-bg: #fff;
//** Global text color on `<body>`.
$text-color: $gray-dark;
//** Global textual link color.
$link-color: $brand-primary;
//** Link hover color set via `darken()` function.
$link-hover-color: darken($link-color, 15%);
//** Link hover decoration.
$link-hover-decoration: underline;
//== Typography
//
//## Font, line-height, and color for body text, headings, and more.
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-family-base: $font-family-sans-serif;
$font-size-base: 14px;
$font-size-large: ceil(($font-size-base * 1.25)); // ~18px
$font-size-small: ceil(($font-size-base * 0.85)); // ~12px
$font-size-h1: floor(($font-size-base * 2.6)); // ~36px
$font-size-h2: floor(($font-size-base * 2.15)); // ~30px
$font-size-h3: ceil(($font-size-base * 1.7)); // ~24px
$font-size-h4: ceil(($font-size-base * 1.25)); // ~18px
$font-size-h5: $font-size-base;
$font-size-h6: ceil(($font-size-base * 0.85)); // ~12px
//** Unit-less `line-height` for use in components like buttons.
$line-height-base: 1.428571429; // 20/14
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
$line-height-computed: floor(($font-size-base * $line-height-base)); // ~20px
//** By default, this inherits from the `<body>`.
$headings-font-family: inherit;
$headings-font-weight: 500;
$headings-line-height: 1.1;
$headings-color: inherit;
//== Iconography
//
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
//** Load fonts from this directory.
$icon-font-path: "../fonts/";
//** File name for all font files.
$icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file.
$icon-font-svg-id: "glyphicons_halflingsregular";
//== Components
//
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
$padding-base-vertical: 6px;
$padding-base-horizontal: 12px;
$padding-large-vertical: 10px;
$padding-large-horizontal: 16px;
$padding-small-vertical: 5px;
$padding-small-horizontal: 10px;
$padding-xs-vertical: 1px;
$padding-xs-horizontal: 5px;
$line-height-large: 1.33;
$line-height-small: 1.5;
$border-radius-base: 0px;
$border-radius-large: 0px;
$border-radius-small: 0px;
//** Global color for active items (e.g., navs or dropdowns).
$component-active-color: #fff;
//** Global background color for active items (e.g., navs or dropdowns).
$component-active-bg: $brand-primary;
//** Width of the `border` for generating carets that indicator dropdowns.
$caret-width-base: 4px;
//** Carets increase slightly in size for larger components.
$caret-width-large: 5px;
//== Tables
//
//## Customizes the `.table` component with basic values, each used across all table variations.
//** Padding for `<th>`s and `<td>`s.
$table-cell-padding: 8px;
//** Padding for cells in `.table-condensed`.
$table-condensed-cell-padding: 5px;
//** Default background color used for all tables.
$table-bg: transparent;
//** Background color used for `.table-striped`.
$table-bg-accent: #e1eef4;
//** Background color used for `.table-hover`.
$table-bg-hover: lighten($brand-primary, 10%);
$table-bg-active: $table-bg-hover;
//** Border color for table and cell borders.
$table-border-color: #ddd;
//== Buttons
//
//## For each of Bootstrap's buttons, define text, background and border color.
$btn-font-weight: normal;
$btn-default-color: #333;
$btn-default-bg: #fff;
$btn-default-border: #ccc;
$btn-primary-color: #fff;
$btn-primary-bg: $brand-primary;
$btn-primary-border: darken($btn-primary-bg, 5%);
$btn-success-color: #fff;
$btn-success-bg: $brand-success;
$btn-success-border: darken($btn-success-bg, 5%);
$btn-info-color: #fff;
$btn-info-bg: $brand-info;
$btn-info-border: darken($btn-info-bg, 5%);
$btn-warning-color: #fff;
$btn-warning-bg: $brand-warning;
$btn-warning-border: darken($btn-warning-bg, 5%);
$btn-danger-color: #fff;
$btn-danger-bg: $brand-danger;
$btn-danger-border: darken($btn-danger-bg, 5%);
$btn-link-disabled-color: $gray-light;
//== Forms
//
//##
//** `<input>` background color
$input-bg: #fff;
//** `<input disabled>` background color
$input-bg-disabled: $gray-lighter;
//** Text color for `<input>`s
$input-color: $gray;
//** `<input>` border color
$input-border: #ccc;
// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
//** Default `.form-control` border radius
$input-border-radius: $border-radius-base;
//** Large `.form-control` border radius
$input-border-radius-large: $border-radius-large;
//** Small `.form-control` border radius
$input-border-radius-small: $border-radius-small;
//** Border color for inputs on focus
$input-border-focus: #66afe9;
//** Placeholder text color
$input-color-placeholder: #999;
//** Default `.form-control` height
$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2);
//** Large `.form-control` height
$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2);
//** Small `.form-control` height
$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2);
$legend-color: $gray-dark;
$legend-border-color: #e5e5e5;
//** Background color for textual input addons
$input-group-addon-bg: $gray-lighter;
//** Border color for textual input addons
$input-group-addon-border-color: $input-border;
//** Disabled cursor for form controls and buttons.
$cursor-disabled: not-allowed;
//== Dropdowns
//
//## Dropdown menu container and contents.
//** Background for the dropdown menu.
$dropdown-bg: #fff;
//** Dropdown menu `border-color`.
$dropdown-border: rgba(0,0,0,.15);
//** Dropdown menu `border-color` **for IE8**.
$dropdown-fallback-border: #ccc;
//** Divider color for between dropdown items.
$dropdown-divider-bg: #e5e5e5;
//** Dropdown link text color.
$dropdown-link-color: $gray-dark;
//** Hover color for dropdown links.
$dropdown-link-hover-color: darken($gray-dark, 5%);
//** Hover background for dropdown links.
$dropdown-link-hover-bg: #f5f5f5;
//** Active dropdown menu item text color.
$dropdown-link-active-color: $component-active-color;
//** Active dropdown menu item background color.
$dropdown-link-active-bg: $component-active-bg;
//** Disabled dropdown menu item background color.
$dropdown-link-disabled-color: $gray-light;
//** Text color for headers within dropdown menus.
$dropdown-header-color: $gray-light;
//** Deprecated `$dropdown-caret-color` as of v3.1.0
$dropdown-caret-color: #000;
//-- Z-index master list
//
// Warning: Avoid customizing these values. They're used for a bird's eye view
// of components dependent on the z-axis and are designed to all work together.
//
// Note: These variables are not generated into the Customizer.
$zindex-navbar: 1000;
$zindex-dropdown: 1000;
$zindex-popover: 1060;
$zindex-tooltip: 1070;
$zindex-navbar-fixed: 1030;
$zindex-modal: 1050;
$zindex-modal-background: 1040;
//== Media queries breakpoints
//
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
// Extra small screen / phone
//** Deprecated `$screen-xs` as of v3.0.1
$screen-xs: 480px;
//** Deprecated `$screen-xs-min` as of v3.2.0
$screen-xs-min: $screen-xs;
//** Deprecated `$screen-phone` as of v3.0.1
$screen-phone: $screen-xs-min;
// Small screen / tablet
//** Deprecated `$screen-sm` as of v3.0.1
$screen-sm: 768px;
$screen-sm-min: $screen-sm;
//** Deprecated `$screen-tablet` as of v3.0.1
$screen-tablet: $screen-sm-min;
// Medium screen / desktop
//** Deprecated `$screen-md` as of v3.0.1
$screen-md: 992px;
$screen-md-min: $screen-md;
//** Deprecated `$screen-desktop` as of v3.0.1
$screen-desktop: $screen-md-min;
// Large screen / wide desktop
//** Deprecated `$screen-lg` as of v3.0.1
$screen-lg: 1200px;
$screen-lg-min: $screen-lg;
//** Deprecated `$screen-lg-desktop` as of v3.0.1
$screen-lg-desktop: $screen-lg-min;
// So media queries don't overlap when required, provide a maximum
$screen-xs-max: ($screen-sm-min - 1);
$screen-sm-max: ($screen-md-min - 1);
$screen-md-max: ($screen-lg-min - 1);
//== Grid system
//
//## Define your custom responsive grid.
//** Number of columns in the grid.
$grid-columns: 12;
//** Padding between columns. Gets divided in half for the left and right.
$grid-gutter-width: 30px;
// Navbar collapse
//** Point at which the navbar becomes uncollapsed.
$grid-float-breakpoint: $screen-sm-min;
//** Point at which the navbar begins collapsing.
$grid-float-breakpoint-max: ($grid-float-breakpoint - 1);
//== Container sizes
//
//## Define the maximum width of `.container` for different screen sizes.
// Small screen / tablet
$container-tablet: (720px + $grid-gutter-width);
//** For `$screen-sm-min` and up.
$container-sm: $container-tablet;
// Medium screen / desktop
$container-desktop: (940px + $grid-gutter-width);
//** For `$screen-md-min` and up.
$container-md: $container-desktop;
// Large screen / wide desktop
$container-large-desktop: (1140px + $grid-gutter-width);
//** For `$screen-lg-min` and up.
$container-lg: $container-large-desktop;
//== Navbar
//
//##
// Basics of a navbar
$navbar-height: 50px;
$navbar-margin-bottom: $line-height-computed;
$navbar-border-radius: $border-radius-base;
$navbar-padding-horizontal: floor(($grid-gutter-width / 2));
$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2);
$navbar-collapse-max-height: 340px;
$navbar-default-color: #777;
$navbar-default-bg: #f8f8f8;
$navbar-default-border: darken($navbar-default-bg, 6.5%);
// Navbar links
$navbar-default-link-color: #777;
$navbar-default-link-hover-color: #333;
$navbar-default-link-hover-bg: transparent;
$navbar-default-link-active-color: #555;
$navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%);
$navbar-default-link-disabled-color: #ccc;
$navbar-default-link-disabled-bg: transparent;
// Navbar brand label
$navbar-default-brand-color: $navbar-default-link-color;
$navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%);
$navbar-default-brand-hover-bg: transparent;
// Navbar toggle
$navbar-default-toggle-hover-bg: #ddd;
$navbar-default-toggle-icon-bar-bg: #888;
$navbar-default-toggle-border-color: #ddd;
// Inverted navbar
// Reset inverted navbar basics
$navbar-inverse-color: lighten($gray-light, 15%);
$navbar-inverse-bg: #222;
$navbar-inverse-border: darken($navbar-inverse-bg, 10%);
// Inverted navbar links
$navbar-inverse-link-color: lighten($gray-light, 15%);
$navbar-inverse-link-hover-color: #fff;
$navbar-inverse-link-hover-bg: transparent;
$navbar-inverse-link-active-color: $navbar-inverse-link-hover-color;
$navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%);
$navbar-inverse-link-disabled-color: #444;
$navbar-inverse-link-disabled-bg: transparent;
// Inverted navbar brand label
$navbar-inverse-brand-color: $navbar-inverse-link-color;
$navbar-inverse-brand-hover-color: #fff;
$navbar-inverse-brand-hover-bg: transparent;
// Inverted navbar toggle
$navbar-inverse-toggle-hover-bg: #333;
$navbar-inverse-toggle-icon-bar-bg: #fff;
$navbar-inverse-toggle-border-color: #333;
//== Navs
//
//##
//=== Shared nav styles
$nav-link-padding: 10px 15px;
$nav-link-hover-bg: $gray-lighter;
$nav-disabled-link-color: $gray-light;
$nav-disabled-link-hover-color: $gray-light;
//== Tabs
$nav-tabs-border-color: #ddd;
$nav-tabs-link-hover-border-color: $gray-lighter;
$nav-tabs-active-link-hover-bg: $body-bg;
$nav-tabs-active-link-hover-color: $gray;
$nav-tabs-active-link-hover-border-color: #ddd;
$nav-tabs-justified-link-border-color: #ddd;
$nav-tabs-justified-active-link-border-color: $body-bg;
//== Pills
$nav-pills-border-radius: $border-radius-base;
$nav-pills-active-link-hover-bg: $component-active-bg;
$nav-pills-active-link-hover-color: $component-active-color;
//== Pagination
//
//##
$pagination-color: $link-color;
$pagination-bg: #fff;
$pagination-border: #ddd;
$pagination-hover-color: $link-hover-color;
$pagination-hover-bg: $gray-lighter;
$pagination-hover-border: #ddd;
$pagination-active-color: #fff;
$pagination-active-bg: $brand-primary;
$pagination-active-border: $brand-primary;
$pagination-disabled-color: $gray-light;
$pagination-disabled-bg: #fff;
$pagination-disabled-border: #ddd;
//== Pager
//
//##
$pager-bg: $pagination-bg;
$pager-border: $pagination-border;
$pager-border-radius: 15px;
$pager-hover-bg: $pagination-hover-bg;
$pager-active-bg: $pagination-active-bg;
$pager-active-color: $pagination-active-color;
$pager-disabled-color: $pagination-disabled-color;
//== Jumbotron
//
//##
$jumbotron-padding: 30px;
$jumbotron-color: inherit;
$jumbotron-bg: $gray-lighter;
$jumbotron-heading-color: inherit;
$jumbotron-font-size: ceil(($font-size-base * 1.5));
//== Form states and alerts
//
//## Define colors for form feedback states and, by default, alerts.
$state-success-text: #3c763d;
$state-success-bg: #dff0d8;
$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%);
$state-info-text: #31708f;
$state-info-bg: #d9edf7;
$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%);
$state-warning-text: #8a6d3b;
$state-warning-bg: #fcf8e3;
$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%);
$state-danger-text: #a94442;
$state-danger-bg: #f2dede;
$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%);
//== Tooltips
//
//##
//** Tooltip max width
$tooltip-max-width: 200px;
//** Tooltip text color
$tooltip-color: #fff;
//** Tooltip background color
$tooltip-bg: #000;
$tooltip-opacity: .9;
//** Tooltip arrow width
$tooltip-arrow-width: 5px;
//** Tooltip arrow color
$tooltip-arrow-color: $tooltip-bg;
//== Popovers
//
//##
//** Popover body background color
$popover-bg: #fff;
//** Popover maximum width
$popover-max-width: 276px;
//** Popover border color
$popover-border-color: rgba(0,0,0,.2);
//** Popover fallback border color
$popover-fallback-border-color: #ccc;
//** Popover title background color
$popover-title-bg: darken($popover-bg, 3%);
//** Popover arrow width
$popover-arrow-width: 10px;
//** Popover arrow color
$popover-arrow-color: $popover-bg;
//** Popover outer arrow width
$popover-arrow-outer-width: ($popover-arrow-width + 1);
//** Popover outer arrow color
$popover-arrow-outer-color: fadein($popover-border-color, 5%);
//** Popover outer arrow fallback color
$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%);
//== Labels
//
//##
//** Default label background color
$label-default-bg: $gray-light;
//** Primary label background color
$label-primary-bg: $brand-primary;
//** Success label background color
$label-success-bg: $brand-success;
//** Info label background color
$label-info-bg: $brand-info;
//** Warning label background color
$label-warning-bg: $brand-warning;
//** Danger label background color
$label-danger-bg: $brand-danger;
//** Default label text color
$label-color: #fff;
//** Default text color of a linked label
$label-link-hover-color: #fff;
//== Modals
//
//##
//** Padding applied to the modal body
$modal-inner-padding: 15px;
//** Padding applied to the modal title
$modal-title-padding: 15px;
//** Modal title line-height
$modal-title-line-height: $line-height-base;
//** Background color of modal content area
$modal-content-bg: #fff;
//** Modal content border color
$modal-content-border-color: rgba(0,0,0,.2);
//** Modal content border color **for IE8**
$modal-content-fallback-border-color: #999;
//** Modal backdrop background color
$modal-backdrop-bg: #000;
//** Modal backdrop opacity
$modal-backdrop-opacity: .5;
//** Modal header border color
$modal-header-border-color: #e5e5e5;
//** Modal footer border color
$modal-footer-border-color: $modal-header-border-color;
$modal-lg: 900px;
$modal-md: 600px;
$modal-sm: 300px;
//== Alerts
//
//## Define alert colors, border radius, and padding.
$alert-padding: 15px;
$alert-border-radius: $border-radius-base;
$alert-link-font-weight: bold;
$alert-success-bg: $state-success-bg;
$alert-success-text: $state-success-text;
$alert-success-border: $state-success-border;
$alert-info-bg: $state-info-bg;
$alert-info-text: $state-info-text;
$alert-info-border: $state-info-border;
$alert-warning-bg: $state-warning-bg;
$alert-warning-text: $state-warning-text;
$alert-warning-border: $state-warning-border;
$alert-danger-bg: $state-danger-bg;
$alert-danger-text: $state-danger-text;
$alert-danger-border: $state-danger-border;
//== Progress bars
//
//##
//** Background color of the whole progress component
$progress-bg: #f5f5f5;
//** Progress bar text color
$progress-bar-color: #fff;
//** Variable for setting rounded corners on progress bar.
$progress-border-radius: $border-radius-base;
//** Default progress bar color
$progress-bar-bg: $brand-primary;
//** Success progress bar color
$progress-bar-success-bg: $brand-success;
//** Warning progress bar color
$progress-bar-warning-bg: $brand-warning;
//** Danger progress bar color
$progress-bar-danger-bg: $brand-danger;
//** Info progress bar color
$progress-bar-info-bg: $brand-info;
//== List group
//
//##
//** Background color on `.list-group-item`
$list-group-bg: #fff;
//** `.list-group-item` border color
$list-group-border: #ddd;
//** List group border radius
$list-group-border-radius: $border-radius-base;
//** Background color of single list items on hover
$list-group-hover-bg: #f5f5f5;
//** Text color of active list items
$list-group-active-color: $component-active-color;
//** Background color of active list items
$list-group-active-bg: $component-active-bg;
//** Border color of active list elements
$list-group-active-border: $list-group-active-bg;
//** Text color for content within active list items
$list-group-active-text-color: lighten($list-group-active-bg, 40%);
//** Text color of disabled list items
$list-group-disabled-color: $gray-light;
//** Background color of disabled list items
$list-group-disabled-bg: $gray-lighter;
//** Text color for content within disabled list items
$list-group-disabled-text-color: $list-group-disabled-color;
$list-group-link-color: #555;
$list-group-link-hover-color: $list-group-link-color;
$list-group-link-heading-color: #333;
//== Panels
//
//##
$panel-bg: #fff;
$panel-body-padding: 15px;
$panel-heading-padding: 10px 15px;
$panel-footer-padding: $panel-heading-padding;
$panel-border-radius: $border-radius-base;
//** Border color for elements within panels
$panel-inner-border: #ddd;
$panel-footer-bg: #f5f5f5;
$panel-default-text: $gray-dark;
$panel-default-border: #ddd;
$panel-default-heading-bg: #f5f5f5;
$panel-primary-text: #fff;
$panel-primary-border: $brand-primary;
$panel-primary-heading-bg: $brand-primary;
$panel-success-text: $state-success-text;
$panel-success-border: $state-success-border;
$panel-success-heading-bg: $state-success-bg;
$panel-info-text: $state-info-text;
$panel-info-border: $state-info-border;
$panel-info-heading-bg: $state-info-bg;
$panel-warning-text: $state-warning-text;
$panel-warning-border: $state-warning-border;
$panel-warning-heading-bg: $state-warning-bg;
$panel-danger-text: $state-danger-text;
$panel-danger-border: $state-danger-border;
$panel-danger-heading-bg: $state-danger-bg;
//== Thumbnails
//
//##
//** Padding around the thumbnail image
$thumbnail-padding: 4px;
//** Thumbnail background color
$thumbnail-bg: $body-bg;
//** Thumbnail border color
$thumbnail-border: #ddd;
//** Thumbnail border radius
$thumbnail-border-radius: $border-radius-base;
//** Custom text color for thumbnail captions
$thumbnail-caption-color: $text-color;
//** Padding around the thumbnail caption
$thumbnail-caption-padding: 9px;
//== Wells
//
//##
$well-bg: #f5f5f5;
$well-border: darken($well-bg, 7%);
//== Badges
//
//##
$badge-color: #fff;
//** Linked badge text color on hover
$badge-link-hover-color: #fff;
$badge-bg: $gray-light;
//** Badge text color in active nav link
$badge-active-color: $link-color;
//** Badge background color in active nav link
$badge-active-bg: #fff;
$badge-font-weight: bold;
$badge-line-height: 1;
$badge-border-radius: 10px;
//== Breadcrumbs
//
//##
$breadcrumb-padding-vertical: 8px;
$breadcrumb-padding-horizontal: 15px;
//** Breadcrumb background color
$breadcrumb-bg: #f5f5f5;
//** Breadcrumb text color
$breadcrumb-color: #ccc;
//** Text color of current page in the breadcrumb
$breadcrumb-active-color: $gray-light;
//** Textual separator for between breadcrumb elements
$breadcrumb-separator: "/";
//== Carousel
//
//##
$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
$carousel-control-color: #fff;
$carousel-control-width: 15%;
$carousel-control-opacity: .5;
$carousel-control-font-size: 20px;
$carousel-indicator-active-bg: #fff;
$carousel-indicator-border-color: #fff;
$carousel-caption-color: #fff;
//== Close
//
//##
$close-font-weight: bold;
$close-color: #000;
$close-text-shadow: 0 1px 0 #fff;
//== Code
//
//##
$code-color: #c7254e;
$code-bg: #f9f2f4;
$kbd-color: #fff;
$kbd-bg: #333;
$pre-bg: #f5f5f5;
$pre-color: $gray-dark;
$pre-border-color: #ccc;
$pre-scrollable-max-height: 340px;
//== Type
//
//##
//** Horizontal offset for forms and lists.
$component-offset-horizontal: 180px;
//** Text muted color
$text-muted: $gray-light;
//** Abbreviations and acronyms border color
$abbr-border-color: $gray-light;
//** Headings small color
$headings-small-color: $gray-light;
//** Blockquote small color
$blockquote-small-color: $gray-light;
//** Blockquote font size
$blockquote-font-size: ($font-size-base * 1.25);
//** Blockquote border color
$blockquote-border-color: $gray-lighter;
//** Page header border color
$page-header-border-color: $gray-lighter;
//** Width of horizontal description list titles
$dl-horizontal-offset: $component-offset-horizontal;
//** Horizontal line color.
$hr-border: $gray-lighter;

View File

@ -1,361 +0,0 @@
// Widgets
$widget-head-bg-start: darken($body-bg, 10%);
$widget-head-bg-end: darken($body-bg, 15%);
$widget-body-bg: transparent;
$widget-border-color: darken($body-bg, 25%);
.widget {
background: $widget-body-bg;
border: 1px solid $widget-border-color;
margin: 0 auto 20px;
position: static;
.tab-content {
padding: 0;
}
.widget-head {
background-color: $widget-head-bg-start;
background-image: linear-gradient(to bottom, $widget-head-bg-start, $widget-head-bg-end);
background-image: -moz-linear-gradient(top, $widget-head-bg-start, $widget-head-bg-end);
background-image: -o-linear-gradient(top, $widget-head-bg-start, $widget-head-bg-end);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($widget-head-bg-start), to($widget-head-bg-end));
background-image: -webkit-linear-gradient(top, $widget-head-bg-start, $widget-head-bg-end);
background-repeat: repeat-x;
border-bottom: 1px solid $widget-border-color;
color: $text-color;
height: 40px;
line-height: 40px;
padding: 0 15px 0 0;
position: relative;
// text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
&.progress {
border-radius: 0 0 0 0;
margin: 0;
moz-border-radius: 0 0 0 0;
padding: 0;
webkit-border-radius: 0 0 0 0;
}
.glyphicons {
height: 40px;
padding: 0;
width: 30px;
}
.fai:before {
color: rgba(255, 255, 255, 0.5);
font-size: 16px;
height: 40px;
line-height: 31px;
text-align: center;
width: 30px;
}
.heading {
color: $text-color;
float: left;
font-size: 14px;
height: 40px;
line-height: 40px;
margin: 0;
padding: 0 15px;
&.glyphicons {
display: block;
padding: 0 0 0 35px;
width: auto;
}
&.fai:before {
color: #45484d;
font-size: 16px;
font-weight: normal;
height: 40px;
left: 0;
line-height: 40px;
margin: 0;
padding: 0;
text-align: center;
text-shadow: none;
top: 0;
width: 35px;
}
}
a {
text-shadow: none;
}
.dropdown-menu li > a {
&:hover, &:focus {
background-color: $body-bg;
background-image: linear-gradient(to bottom, $body-bg, #d24343);
background-image: -moz-linear-gradient(top, $body-bg, #d24343);
background-image: -o-linear-gradient(top, $body-bg, #d24343);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($body-bg), to(#d24343));
background-image: -webkit-linear-gradient(top, $body-bg, #d24343);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffda4c4c', endColorstr='#ffd24343', GradientType=0);
}
}
.dropdown-submenu:hover > a {
background-color: $body-bg;
background-image: linear-gradient(to bottom, $body-bg, #d24343);
background-image: -moz-linear-gradient(top, $body-bg, #d24343);
background-image: -o-linear-gradient(top, $body-bg, #d24343);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($body-bg), to(#d24343));
background-image: -webkit-linear-gradient(top, $body-bg, #d24343);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffda4c4c', endColorstr='#ffd24343', GradientType=0);
}
}
.details {
color: $text-color;
font-size: 8pt;
}
.widget-body {
padding: 20px 15px;
background-color: $widget-body-bg;
form {
margin: 0;
}
.count {
font-size: 15pt;
font-weight: 400;
}
> p:last-child {
margin: 0;
}
&.list {
color: #575655;
padding: 0;
ul {
list-style: none;
margin: 0;
li {
border-bottom: 1px solid rgba(0, 0, 0, 0.02);
clear: both;
height: 39px;
line-height: 39px;
padding: 0 10px;
text-align: left;
&:first-child {
border-top: none;
}
&:last-child {
border-bottom: none;
}
.count {
color: $body-bg;
float: right;
}
.sparkline {
margin-left: 5px;
position: relative;
top: 5px;
}
}
}
&.products {
li {
height: 60px;
line-height: 60px;
}
.img {
background: #272729;
border-radius: 3px 3px 3px 3px;
color: #818181;
cursor: pointer;
display: inline-block;
float: left;
font-size: 10pt;
font-weight: 600;
height: 44px;
line-height: 44px;
margin: 8px 8px 0 0;
moz-border-radius: 3px 3px 3px 3px;
text-align: center;
webkit-border-radius: 3px 3px 3px 3px;
width: 48px;
}
.title {
display: inline-block;
font-family: "Raleway",sans-serif;
line-height: normal;
padding: 13px 0 0;
text-transform: uppercase;
strong {
font-family: "Open Sans",sans-serif;
text-transform: none;
}
}
}
&.fluid ul li {
height: auto;
line-height: normal;
padding: 10px;
}
&.list-2 ul li {
background: #f8f8f8;
border-bottom: 1px solid #d8d9da;
border-top: none;
&.active {
background: #fff;
border-color: #dddddd;
i:before {
background: $body-bg;
color: #fff;
font-weight: normal;
text-shadow: none;
}
a {
color: $body-bg;
}
}
&:last-child {
border-bottom: none;
}
a {
color: #222;
display: block;
padding: 0 0 0 30px;
i:before {
background: #dddddd;
border: 1px solid #ccc;
color: #555;
font-size: 14px;
height: 17px;
left: 0;
padding-top: 3px;
text-align: center;
text-shadow: 0 1px 0 #fff;
top: 9px;
vertical-align: middle;
width: 20px;
}
}
&.hasSubmenu {
height: auto;
ul {
padding: 0 0 10px;
li {
background: none;
border: none;
height: auto;
line-height: 20px;
line-height: normal;
a {
color: #333;
padding: 0 0 0 20px;
}
&.active a {
font-weight: bold;
}
}
}
}
}
}
}
.widget-footer {
background: $body-bg;
// border-bottom: 1px solid $widget-border-color;
border-top: 1px solid $widget-border-color;
height: 25px;
line-height: 25px;
.fa {
float: right;
height: 25px;
line-height: 25px;
padding: 0;
width: 25px;
i:before {
color: #c3c3c3;
font-size: 16px;
height: 25px;
line-height: 25px;
text-align: center;
text-shadow: 0 1px 0 #fff;
width: 20px;
}
&:hover i:before {
color: rgba(0, 0, 0, 0.5);
}
}
}
&.margin-bottom-none {
margin-bottom: 0;
}
&.widget-gray {
background: #f5f5f5;
.widget-head {
background: #e9e9e9;
border-color: #d1d2d3;
box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.6), inset -1px -1px 1px rgba(0, 0, 0, 0);
moz-box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.6), inset -1px -1px 1px rgba(0, 0, 0, 0);
webkit-box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.6), inset -1px -1px 1px rgba(0, 0, 0, 0);
.heading {
color: #555555;
text-shadow: 0 1px 0 #fff;
&.fai:before {
background: none;
border-color: rgba(0, 0, 0, 0.1);
color: #555;
}
}
}
}
&.widget-body-white .widget-body {
background: $body-bg;
}
}
.widget-icon {
margin-left: 0.6em !important;
cursor: pointer;
}

View File

@ -1,195 +0,0 @@
/* ========================================================================
* bootstrap-switch - v3.3.2
* http://www.bootstrap-switch.org
* ========================================================================
* Copyright 2012-2013 Mattia Larentis
*
* ========================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================================
*/
.bootstrap-switch {
display: inline-block;
direction: ltr;
cursor: pointer;
border-radius: 4px;
border: 1px solid;
border-color: #cccccc;
position: relative;
text-align: left;
overflow: hidden;
line-height: 8px;
z-index: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
vertical-align: middle;
-webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
.bootstrap-switch .bootstrap-switch-container {
display: inline-block;
top: 0;
border-radius: 4px;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.bootstrap-switch .bootstrap-switch-handle-on,
.bootstrap-switch .bootstrap-switch-handle-off,
.bootstrap-switch .bootstrap-switch-label {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
cursor: pointer;
display: inline-block !important;
height: 100%;
padding: 6px 12px;
font-size: 14px;
line-height: 20px;
}
.bootstrap-switch .bootstrap-switch-handle-on,
.bootstrap-switch .bootstrap-switch-handle-off {
text-align: center;
z-index: 1;
}
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary,
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary {
color: #fff;
background: #337ab7;
}
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info,
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info {
color: #fff;
background: #5bc0de;
}
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success,
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success {
color: #fff;
background: #5cb85c;
}
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning,
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning {
background: #f0ad4e;
color: #fff;
}
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger,
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger {
color: #fff;
background: #d9534f;
}
.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default,
.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default {
color: #000;
background: #eeeeee;
}
.bootstrap-switch .bootstrap-switch-label {
text-align: center;
margin-top: -1px;
margin-bottom: -1px;
z-index: 100;
color: #333333;
background: #ffffff;
}
.bootstrap-switch .bootstrap-switch-handle-on {
border-bottom-left-radius: 3px;
border-top-left-radius: 3px;
}
.bootstrap-switch .bootstrap-switch-handle-off {
border-bottom-right-radius: 3px;
border-top-right-radius: 3px;
}
.bootstrap-switch input[type='radio'],
.bootstrap-switch input[type='checkbox'] {
position: absolute !important;
top: 0;
left: 0;
margin: 0;
z-index: -1;
opacity: 0;
filter: alpha(opacity=0);
}
.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on,
.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off,
.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label {
padding: 1px 5px;
font-size: 12px;
line-height: 1.5;
}
.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on,
.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off,
.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label {
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
}
.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on,
.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off,
.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label {
padding: 6px 16px;
font-size: 18px;
line-height: 1.3333333;
}
.bootstrap-switch.bootstrap-switch-disabled,
.bootstrap-switch.bootstrap-switch-readonly,
.bootstrap-switch.bootstrap-switch-indeterminate {
cursor: default !important;
}
.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on,
.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on,
.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on,
.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off,
.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off,
.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off,
.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label,
.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label,
.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label {
opacity: 0.5;
filter: alpha(opacity=50);
cursor: default !important;
}
.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container {
-webkit-transition: margin-left 0.5s;
-o-transition: margin-left 0.5s;
transition: margin-left 0.5s;
}
.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
border-bottom-right-radius: 3px;
border-top-right-radius: 3px;
}
.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 3px;
border-top-left-radius: 3px;
}
.bootstrap-switch.bootstrap-switch-focused {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
}
.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label,
.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label {
border-bottom-right-radius: 3px;
border-top-right-radius: 3px;
}
.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label,
.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label {
border-bottom-left-radius: 3px;
border-top-left-radius: 3px;
}

View File

@ -1,809 +0,0 @@
/*
* This combined file was created by the DataTables downloader builder:
* https://datatables.net/download
*
* To rebuild or modify this file with the latest versions of the included
* software please visit:
* https://datatables.net/download/#dt/dt-1.10.11,cr-1.3.1,fh-3.1.1,r-2.0.2,rr-1.1.1,se-1.1.2
*
* Included libraries:
* DataTables 1.10.11, ColReorder 1.3.1, FixedHeader 3.1.1, Responsive 2.0.2, RowReorder 1.1.1, Select 1.1.2
*/
/*
* Table styles
*/
table.dataTable {
width: 100%;
margin: 0 auto;
clear: both;
border-collapse: separate;
border-spacing: 0;
/*
* Header and footer styles
*/
/*
* Body styles
*/
}
table.dataTable thead th,
table.dataTable tfoot th {
font-weight: bold;
}
table.dataTable thead th,
table.dataTable thead td {
padding: 10px 18px;
border-bottom: 1px solid #111;
}
table.dataTable thead th:active,
table.dataTable thead td:active {
outline: none;
}
table.dataTable tfoot th,
table.dataTable tfoot td {
padding: 10px 18px 6px 18px;
border-top: 1px solid #111;
}
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc {
cursor: pointer;
*cursor: hand;
}
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc,
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
background-repeat: no-repeat;
background-position: center right;
}
table.dataTable thead .sorting {
background-image: url("DataTables-1.10.11/images/sort_both.png");
}
table.dataTable thead .sorting_asc {
background-image: url("DataTables-1.10.11/images/sort_asc.png");
}
table.dataTable thead .sorting_desc {
background-image: url("DataTables-1.10.11/images/sort_desc.png");
}
table.dataTable thead .sorting_asc_disabled {
background-image: url("DataTables-1.10.11/images/sort_asc_disabled.png");
}
table.dataTable thead .sorting_desc_disabled {
background-image: url("DataTables-1.10.11/images/sort_desc_disabled.png");
}
table.dataTable tbody tr {
background-color: #ffffff;
}
table.dataTable tbody tr.selected {
background-color: #B0BED9;
}
table.dataTable tbody th,
table.dataTable tbody td {
padding: 8px 10px;
}
table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
border-top: 1px solid #ddd;
}
table.dataTable.row-border tbody tr:first-child th,
table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,
table.dataTable.display tbody tr:first-child td {
border-top: none;
}
table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {
border-top: 1px solid #ddd;
border-right: 1px solid #ddd;
}
table.dataTable.cell-border tbody tr th:first-child,
table.dataTable.cell-border tbody tr td:first-child {
border-left: 1px solid #ddd;
}
table.dataTable.cell-border tbody tr:first-child th,
table.dataTable.cell-border tbody tr:first-child td {
border-top: none;
}
table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
background-color: #f9f9f9;
}
table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
background-color: #acbad4;
}
table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover {
background-color: #f6f6f6;
}
table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected {
background-color: #aab7d1;
}
table.dataTable.order-column tbody tr > .sorting_1,
table.dataTable.order-column tbody tr > .sorting_2,
table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,
table.dataTable.display tbody tr > .sorting_2,
table.dataTable.display tbody tr > .sorting_3 {
background-color: #fafafa;
}
table.dataTable.order-column tbody tr.selected > .sorting_1,
table.dataTable.order-column tbody tr.selected > .sorting_2,
table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,
table.dataTable.display tbody tr.selected > .sorting_2,
table.dataTable.display tbody tr.selected > .sorting_3 {
background-color: #acbad5;
}
table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
background-color: #f1f1f1;
}
table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
background-color: #f3f3f3;
}
table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
background-color: whitesmoke;
}
table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
background-color: #a6b4cd;
}
table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
background-color: #a8b5cf;
}
table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
background-color: #a9b7d1;
}
table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
background-color: #fafafa;
}
table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
background-color: #fcfcfc;
}
table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
background-color: #fefefe;
}
table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
background-color: #acbad5;
}
table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
background-color: #aebcd6;
}
table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
background-color: #afbdd8;
}
table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
background-color: #eaeaea;
}
table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
background-color: #ececec;
}
table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
background-color: #efefef;
}
table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
background-color: #a2aec7;
}
table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
background-color: #a3b0c9;
}
table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
background-color: #a5b2cb;
}
table.dataTable.no-footer {
border-bottom: 1px solid #111;
}
table.dataTable.nowrap th, table.dataTable.nowrap td {
white-space: nowrap;
}
table.dataTable.compact thead th,
table.dataTable.compact thead td {
padding: 4px 17px 4px 4px;
}
table.dataTable.compact tfoot th,
table.dataTable.compact tfoot td {
padding: 4px;
}
table.dataTable.compact tbody th,
table.dataTable.compact tbody td {
padding: 4px;
}
table.dataTable th.dt-left,
table.dataTable td.dt-left {
text-align: left;
}
table.dataTable th.dt-center,
table.dataTable td.dt-center,
table.dataTable td.dataTables_empty {
text-align: center;
}
table.dataTable th.dt-right,
table.dataTable td.dt-right {
text-align: right;
}
table.dataTable th.dt-justify,
table.dataTable td.dt-justify {
text-align: justify;
}
table.dataTable th.dt-nowrap,
table.dataTable td.dt-nowrap {
white-space: nowrap;
}
table.dataTable thead th.dt-head-left,
table.dataTable thead td.dt-head-left,
table.dataTable tfoot th.dt-head-left,
table.dataTable tfoot td.dt-head-left {
text-align: left;
}
table.dataTable thead th.dt-head-center,
table.dataTable thead td.dt-head-center,
table.dataTable tfoot th.dt-head-center,
table.dataTable tfoot td.dt-head-center {
text-align: center;
}
table.dataTable thead th.dt-head-right,
table.dataTable thead td.dt-head-right,
table.dataTable tfoot th.dt-head-right,
table.dataTable tfoot td.dt-head-right {
text-align: right;
}
table.dataTable thead th.dt-head-justify,
table.dataTable thead td.dt-head-justify,
table.dataTable tfoot th.dt-head-justify,
table.dataTable tfoot td.dt-head-justify {
text-align: justify;
}
table.dataTable thead th.dt-head-nowrap,
table.dataTable thead td.dt-head-nowrap,
table.dataTable tfoot th.dt-head-nowrap,
table.dataTable tfoot td.dt-head-nowrap {
white-space: nowrap;
}
table.dataTable tbody th.dt-body-left,
table.dataTable tbody td.dt-body-left {
text-align: left;
}
table.dataTable tbody th.dt-body-center,
table.dataTable tbody td.dt-body-center {
text-align: center;
}
table.dataTable tbody th.dt-body-right,
table.dataTable tbody td.dt-body-right {
text-align: right;
}
table.dataTable tbody th.dt-body-justify,
table.dataTable tbody td.dt-body-justify {
text-align: justify;
}
table.dataTable tbody th.dt-body-nowrap,
table.dataTable tbody td.dt-body-nowrap {
white-space: nowrap;
}
table.dataTable,
table.dataTable th,
table.dataTable td {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/*
* Control feature layout
*/
.dataTables_wrapper {
position: relative;
clear: both;
*zoom: 1;
zoom: 1;
}
.dataTables_wrapper .dataTables_length {
float: left;
}
.dataTables_wrapper .dataTables_filter {
float: right;
text-align: right;
}
.dataTables_wrapper .dataTables_filter input {
margin-left: 0.5em;
}
.dataTables_wrapper .dataTables_info {
clear: both;
float: left;
padding-top: 0.755em;
}
.dataTables_wrapper .dataTables_paginate {
float: right;
text-align: right;
padding-top: 0.25em;
}
.dataTables_wrapper .dataTables_paginate .paginate_button {
box-sizing: border-box;
display: inline-block;
min-width: 1.5em;
padding: 0.5em 1em;
margin-left: 2px;
text-align: center;
text-decoration: none !important;
cursor: pointer;
*cursor: hand;
color: #333 !important;
border: 1px solid transparent;
border-radius: 2px;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
color: #333 !important;
border: 1px solid #979797;
background-color: white;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, white 0%, #dcdcdc 100%);
/* Chrome10+,Safari5.1+ */
background: -moz-linear-gradient(top, white 0%, #dcdcdc 100%);
/* FF3.6+ */
background: -ms-linear-gradient(top, white 0%, #dcdcdc 100%);
/* IE10+ */
background: -o-linear-gradient(top, white 0%, #dcdcdc 100%);
/* Opera 11.10+ */
background: linear-gradient(to bottom, white 0%, #dcdcdc 100%);
/* W3C */
}
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
cursor: default;
color: #666 !important;
border: 1px solid transparent;
background: transparent;
box-shadow: none;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
color: white !important;
border: 1px solid #111;
background-color: #585858;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
/* Chrome10+,Safari5.1+ */
background: -moz-linear-gradient(top, #585858 0%, #111 100%);
/* FF3.6+ */
background: -ms-linear-gradient(top, #585858 0%, #111 100%);
/* IE10+ */
background: -o-linear-gradient(top, #585858 0%, #111 100%);
/* Opera 11.10+ */
background: linear-gradient(to bottom, #585858 0%, #111 100%);
/* W3C */
}
.dataTables_wrapper .dataTables_paginate .paginate_button:active {
outline: none;
background-color: #2b2b2b;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
/* Chrome10+,Safari5.1+ */
background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
/* FF3.6+ */
background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
/* IE10+ */
background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
/* Opera 11.10+ */
background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
/* W3C */
box-shadow: inset 0 0 3px #111;
}
.dataTables_wrapper .dataTables_paginate .ellipsis {
padding: 0 1em;
}
.dataTables_wrapper .dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 40px;
margin-left: -50%;
margin-top: -25px;
padding-top: 20px;
text-align: center;
font-size: 1.2em;
background-color: white;
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
}
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_processing,
.dataTables_wrapper .dataTables_paginate {
color: #333;
}
.dataTables_wrapper .dataTables_scroll {
clear: both;
}
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
*margin-top: -1px;
-webkit-overflow-scrolling: touch;
}
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td {
vertical-align: middle;
}
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th > div.dataTables_sizing,
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td > div.dataTables_sizing {
height: 0;
overflow: hidden;
margin: 0 !important;
padding: 0 !important;
}
.dataTables_wrapper.no-footer .dataTables_scrollBody {
border-bottom: 1px solid #111;
}
.dataTables_wrapper.no-footer div.dataTables_scrollHead table,
.dataTables_wrapper.no-footer div.dataTables_scrollBody table {
border-bottom: none;
}
.dataTables_wrapper:after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
@media screen and (max-width: 767px) {
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
float: none;
text-align: center;
}
.dataTables_wrapper .dataTables_paginate {
margin-top: 0.5em;
}
}
@media screen and (max-width: 640px) {
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter {
float: none;
text-align: center;
}
.dataTables_wrapper .dataTables_filter {
margin-top: 0.5em;
}
}
table.DTCR_clonedTable.dataTable {
position: absolute !important;
background-color: rgba(255, 255, 255, 0.7);
z-index: 202;
}
div.DTCR_pointer {
width: 1px;
background-color: #0259C4;
z-index: 201;
}
table.fixedHeader-floating {
position: fixed !important;
background-color: white;
}
table.fixedHeader-floating.no-footer {
border-bottom-width: 0;
}
table.fixedHeader-locked {
position: absolute !important;
background-color: white;
}
@media print {
table.fixedHeader-floating {
display: none;
}
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td.child,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.child,
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty {
cursor: default !important;
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td.child:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.child:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty:before {
display: none !important;
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
position: relative;
padding-left: 30px;
cursor: pointer;
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child:before {
top: 8px;
left: 4px;
height: 16px;
width: 16px;
display: block;
position: absolute;
color: white;
border: 2px solid white;
border-radius: 16px;
box-shadow: 0 0 3px #444;
box-sizing: content-box;
text-align: left;
font-family: 'Courier New', Courier, monospace;
text-indent: 4px;
line-height: 16px;
content: '+';
background-color: #31b131;
}
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child:before,
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child:before {
content: '-';
background-color: #d33333;
}
table.dataTable.dtr-inline.collapsed > tbody > tr.child td:before {
display: none;
}
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child,
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child {
padding-left: 27px;
}
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child:before,
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child:before {
top: 5px;
left: 4px;
height: 14px;
width: 14px;
border-radius: 14px;
line-height: 14px;
text-indent: 3px;
}
table.dataTable.dtr-column > tbody > tr > td.control,
table.dataTable.dtr-column > tbody > tr > th.control {
position: relative;
cursor: pointer;
}
table.dataTable.dtr-column > tbody > tr > td.control:before,
table.dataTable.dtr-column > tbody > tr > th.control:before {
top: 50%;
left: 50%;
height: 16px;
width: 16px;
margin-top: -10px;
margin-left: -10px;
display: block;
position: absolute;
color: white;
border: 2px solid white;
border-radius: 16px;
box-shadow: 0 0 3px #444;
box-sizing: content-box;
text-align: left;
font-family: 'Courier New', Courier, monospace;
text-indent: 4px;
line-height: 16px;
content: '+';
background-color: #31b131;
}
table.dataTable.dtr-column > tbody > tr.parent td.control:before,
table.dataTable.dtr-column > tbody > tr.parent th.control:before {
content: '-';
background-color: #d33333;
}
table.dataTable > tbody > tr.child {
padding: 0.5em 1em;
}
table.dataTable > tbody > tr.child:hover {
background: transparent !important;
}
table.dataTable > tbody > tr.child ul {
display: inline-block;
list-style-type: none;
margin: 0;
padding: 0;
}
table.dataTable > tbody > tr.child ul li {
border-bottom: 1px solid #efefef;
padding: 0.5em 0;
}
table.dataTable > tbody > tr.child ul li:first-child {
padding-top: 0;
}
table.dataTable > tbody > tr.child ul li:last-child {
border-bottom: none;
}
table.dataTable > tbody > tr.child span.dtr-title {
display: inline-block;
min-width: 75px;
font-weight: bold;
}
div.dtr-modal {
position: fixed;
box-sizing: border-box;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 100;
padding: 10em 1em;
}
div.dtr-modal div.dtr-modal-display {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 50%;
height: 50%;
overflow: auto;
margin: auto;
z-index: 102;
overflow: auto;
background-color: #f5f5f7;
border: 1px solid black;
border-radius: 0.5em;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
}
div.dtr-modal div.dtr-modal-content {
position: relative;
padding: 1em;
}
div.dtr-modal div.dtr-modal-close {
position: absolute;
top: 6px;
right: 6px;
width: 22px;
height: 22px;
border: 1px solid #eaeaea;
background-color: #f9f9f9;
text-align: center;
border-radius: 3px;
cursor: pointer;
z-index: 12;
}
div.dtr-modal div.dtr-modal-close:hover {
background-color: #eaeaea;
}
div.dtr-modal div.dtr-modal-background {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 101;
background: rgba(0, 0, 0, 0.6);
}
@media screen and (max-width: 767px) {
div.dtr-modal div.dtr-modal-display {
width: 95%;
}
}
table.dt-rowReorder-float {
position: absolute !important;
opacity: 0.8;
table-layout: static;
outline: 2px solid #888;
outline-offset: -2px;
z-index: 2001;
}
tr.dt-rowReorder-moving {
outline: 2px solid #555;
outline-offset: -2px;
}
body.dt-rowReorder-noOverflow {
overflow-x: hidden;
}
table.dataTable td.reorder {
text-align: center;
cursor: move;
}
table.dataTable tbody > tr.selected,
table.dataTable tbody > tr > .selected {
background-color: #B0BED9;
}
table.dataTable.stripe tbody > tr.odd.selected,
table.dataTable.stripe tbody > tr.odd > .selected, table.dataTable.display tbody > tr.odd.selected,
table.dataTable.display tbody > tr.odd > .selected {
background-color: #acbad4;
}
table.dataTable.hover tbody > tr.selected:hover,
table.dataTable.hover tbody > tr > .selected:hover, table.dataTable.display tbody > tr.selected:hover,
table.dataTable.display tbody > tr > .selected:hover {
background-color: #aab7d1;
}
table.dataTable.order-column tbody > tr.selected > .sorting_1,
table.dataTable.order-column tbody > tr.selected > .sorting_2,
table.dataTable.order-column tbody > tr.selected > .sorting_3,
table.dataTable.order-column tbody > tr > .selected, table.dataTable.display tbody > tr.selected > .sorting_1,
table.dataTable.display tbody > tr.selected > .sorting_2,
table.dataTable.display tbody > tr.selected > .sorting_3,
table.dataTable.display tbody > tr > .selected {
background-color: #acbad5;
}
table.dataTable.display tbody > tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody > tr.odd.selected > .sorting_1 {
background-color: #a6b4cd;
}
table.dataTable.display tbody > tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody > tr.odd.selected > .sorting_2 {
background-color: #a8b5cf;
}
table.dataTable.display tbody > tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody > tr.odd.selected > .sorting_3 {
background-color: #a9b7d1;
}
table.dataTable.display tbody > tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody > tr.even.selected > .sorting_1 {
background-color: #acbad5;
}
table.dataTable.display tbody > tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody > tr.even.selected > .sorting_2 {
background-color: #aebcd6;
}
table.dataTable.display tbody > tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody > tr.even.selected > .sorting_3 {
background-color: #afbdd8;
}
table.dataTable.display tbody > tr.odd > .selected, table.dataTable.order-column.stripe tbody > tr.odd > .selected {
background-color: #a6b4cd;
}
table.dataTable.display tbody > tr.even > .selected, table.dataTable.order-column.stripe tbody > tr.even > .selected {
background-color: #acbad5;
}
table.dataTable.display tbody > tr.selected:hover > .sorting_1, table.dataTable.order-column.hover tbody > tr.selected:hover > .sorting_1 {
background-color: #a2aec7;
}
table.dataTable.display tbody > tr.selected:hover > .sorting_2, table.dataTable.order-column.hover tbody > tr.selected:hover > .sorting_2 {
background-color: #a3b0c9;
}
table.dataTable.display tbody > tr.selected:hover > .sorting_3, table.dataTable.order-column.hover tbody > tr.selected:hover > .sorting_3 {
background-color: #a5b2cb;
}
table.dataTable.display tbody > tr:hover > .selected,
table.dataTable.display tbody > tr > .selected:hover, table.dataTable.order-column.hover tbody > tr:hover > .selected,
table.dataTable.order-column.hover tbody > tr > .selected:hover {
background-color: #a2aec7;
}
table.dataTable td.select-checkbox {
position: relative;
}
table.dataTable td.select-checkbox:before, table.dataTable td.select-checkbox:after {
display: block;
position: absolute;
top: 1.2em;
left: 50%;
width: 12px;
height: 12px;
box-sizing: border-box;
}
table.dataTable td.select-checkbox:before {
content: ' ';
margin-top: -6px;
margin-left: -6px;
border: 1px solid black;
border-radius: 3px;
}
table.dataTable tr.selected td.select-checkbox:after {
content: '\2714';
margin-top: -11px;
margin-left: -4px;
text-align: center;
text-shadow: 1px 1px #B0BED9, -1px -1px #B0BED9, 1px -1px #B0BED9, -1px 1px #B0BED9;
}
div.dataTables_wrapper span.select-info,
div.dataTables_wrapper span.select-item {
margin-left: 0.5em;
}
@media screen and (max-width: 640px) {
div.dataTables_wrapper span.select-info,
div.dataTables_wrapper span.select-item {
margin-left: 0;
display: block;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,45 +0,0 @@
/*
* Bootstrap TouchSpin - v3.0.1
* A mobile and touch friendly input spinner component for Bootstrap 3.
* http://www.virtuosoft.eu/code/bootstrap-touchspin/
*
* Made by István Ujj-Mészáros
* Under Apache License v2.0 License
*/
.bootstrap-touchspin .input-group-btn-vertical {
position: relative;
white-space: nowrap;
width: 1%;
vertical-align: middle;
display: table-cell;
}
.bootstrap-touchspin .input-group-btn-vertical > .btn {
display: block;
float: none;
width: 100%;
max-width: 100%;
padding: 8px 10px;
margin-left: -1px;
position: relative;
}
.bootstrap-touchspin .input-group-btn-vertical .bootstrap-touchspin-up {
border-radius: 0;
border-top-right-radius: 0px;
}
.bootstrap-touchspin .input-group-btn-vertical .bootstrap-touchspin-down {
margin-top: -2px;
border-radius: 0;
border-bottom-right-radius: 0px;
}
.bootstrap-touchspin .input-group-btn-vertical i {
position: absolute;
top: 3px;
left: 5px;
font-size: 9px;
font-weight: normal;
}

View File

@ -1,428 +0,0 @@
// Bootstrap
$icon-font-path: "../fonts/";
@import "_tools";
@import "_udsvars";
// Own variables
$sidebar-icon-width: 24px;
$sidebar-icon-width-collapsed: 24px;
$sidebar-size: 225px; // 225 px
$sidebar-size-collapsed: $sidebar-icon-width-collapsed + 2*$font-size-base; // 40px;
$sidebar-top: 50px;
$sidebar-switcher-size: 14px;
$sizebar-switcher-font-size: $sidebar-switcher-size - 2px;
$sidebar-switcher-pos: $sidebar-size - $sidebar-switcher-size;
$sidebar-switcher-pos-collapsed: $sidebar-size-collapsed - $sidebar-switcher-size;
$uds-panel-min-height: 500px;
// bower:scss
@import "bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss";
// endbower
@font-face {
font-family: 'Droid Sans Mono';
font-style: normal;
font-weight: 400;
src: local('Droid Sans Mono'), local('DroidSansMono'), url(#{$icon-font-path}/DroidSansMono.woff2) format('woff2');
}
// Fix for firefox for fieldsets
@-moz-document url-prefix() {
fieldset {
display: table-cell;
}
}
body {
font-family: 'Droid Sans Mono', sans-serif;
background-color: $body-bg;
margin-top: 50px;
}
#wrapper {
padding-left: 0;
}
#page-wrapper {
width: 100%;
padding: 5px 15px;
}
/* collapsable && closeable pannels */
.chevron {
&:before {
content: "\f139";
}
&.collapsed:before {
content: "\f13a";
}
}
.widget-icon.fa-refresh {
&:hover {
animation: 2s linear 0s normal none infinite running fa-spin;
}
}
.panel-icon {
margin-left: 0.6em !important;
cursor: pointer;
}
.table-icon {
width: 1.2em;
padding-bottom: 3px;
}
.info-img {
width: 5em;
}
.navbar-img {
width: 2em;
margin-top: -8px;
}
.side-nav > .navbar-nav > li > a {
padding-bottom: $font-size-base/2;
padding-top: $font-size-base/2;
}
.cursor-pointer {
cursor: pointer !important;
}
#minimized {
margin-top: 0.6em;
margin-bottom: 0.3em;
}
/* modal dialogs & related*/
.modal-dialog {
/* new custom width */
width: 90%;
}
/*.modal-backdrop {
background-color: gray;
}*/
.modal {
overflow-y: auto;
}
.tab-pane {
margin-top: 24px;
}
.tooltip {
z-index: 2014;
}
/* Tables */
/* Logs */
.chart-big {
display: block;
height: 400px;
}
.chart-medium {
display: block;
height: 250px;
}
.chart-small {
display: block;
height: 100px;
}
/* End tables styling */
/* Charts */
.chart-content {
width: 100%;
height: 100%;
}
// Hides switcher on small devices, so menu displays correctly
.side-nav {
padding-top: 0px;
.switcher {
visibility: hidden;
width: 0px;
height: 0px;
}
.icon {
width: 24px;
vertical-align: center;
padding-bottom: 3px;
}
}
/* Edit Below to Customize Widths > 768px */
@media (min-width: 768px) {
/* Wrappers */
#wrapper {
padding-left: $sidebar-size;
-webkit-transition: padding 0.3s; /* For Safari 3.1 to 6.0 */
transition: padding 0.3s;
&.full {
padding-left: $sidebar-size-collapsed;
}
}
#page-wrapper {
padding: 15px 25px;
}
/* Side Nav */
.side-nav {
position: fixed;
top: 0px;
margin-top: $sidebar-top;
height: 100%;
overflow-y: auto;
border-radius: 0;
border-color: $navbar-default-border;
border-style: solid;
border-width: 0 1px 0 0;
background-color: $navbar-default-bg;
-webkit-transition: width 0.3s; /* For Safari 3.1 to 6.0 */
transition: width 0.3s;
margin-left: -$sidebar-size-collapsed;
padding-top: $sidebar-switcher-size;
left: $sidebar-size-collapsed;
width: $sidebar-size-collapsed;
.icon {
width: $sidebar-icon-width-collapsed;
-webkit-transition: all 0.3s; /* For Safari 3.1 to 6.0 */
transition: all 0.3s;
}
.menu-lnk {
display: none;
overflow-x: hidden;
}
> ul {
// border-top: 1px solid $navbar-default-border;
> li {
width: $sidebar-size;
overflow-x: hidden;
// border-bottom: 1px solid $navbar-default-border;
&:hover, &.active, &:focus {
color: $brand-primary;
background-color: darken($navbar-default-bg, 15%);
}
&.dropdown > ul.dropdown-menu {
width: $sidebar-size;
position: relative;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
background-color: transparent;
box-shadow: none;
-webkit-box-shadow: none;
> li > a {
color: inherit;
padding: $font-size-base/2 $font-size-base/2 $font-size-base/2 32px;
&:hover, &.active, &:focus {
color: #fff;
background-color: #080808;
}
}
}
}
}
&.full {
margin-left: -$sidebar-size;
left: $sidebar-size;
width: $sidebar-size;
.icon {
width: $sidebar-icon-width;
}
.menu-lnk {
display: inline;
opacity: 1.0;
width: 100%;
}
> ul > li {
// border-bottom: none;
//border-bottom: none;
}
}
/*&:hover {
width: $sidebar-size;
}
> li {
&.dropdown > ul.dropdown-menu {
position: relative;
min-width: $sidebar-size;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
background-color: transparent;
box-shadow: none;
-webkit-box-shadow: none;
> li > a {
color: #999999;
padding: 15px 15px 15px 15px;
&:hover, &.active, &:focus {
color: #fff;
background-color: #080808;
}
}
}
> a {
border-bottom: 1px solid darken($body-bg, 50%);
color: $text-color;
display: block;
font-size: 10px;
min-height: 60px;
padding-top: 12px;
text-align: center;
width: $sidebar-size-collapsed;
> img {
min-width: 32px;
}
}
//> a {
// width: $sidebar-size;
//}
}*/
}
/* Bootstrap Default Overrides - Customized Dropdowns for the Side Nav */
/*.navbar-inverse .navbar-nav > li > a {
&:hover, &:focus {
background-color: #080808;
}
}*/
.modal-dialog {
/* new custom width */
width: 60%;
}
}
// closeable
.closeable {
&:hover {
cursor: pointer;
color: red;
}
}
// Tag add
.tagadder {
&:hover {
cursor: pointer;
}
}
span.tag {
float: left;
margin-bottom: 4px;
margin-right: 4px;
padding-bottom: 4px;
}
/* submenus */
.dropdown-submenu {
position: relative;
>.dropdown-menu {
top: 0;
left: 100%;
margin-top: -6px;
margin-left: -1px;
-webkit-border-radius: 0 6px 6px 6px;
-moz-border-radius: 0 6px 6px 6px;
border-radius: 0 6px 6px 6px;
}
&:hover {
>.dropdown-menu {
display: block;
}
>a {
&:after {
border-left-color: #ffffff;
}
}
}
>a {
&:after {
display: block;
content: " ";
float: right;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 5px 0 5px 5px;
border-left-color: #cccccc;
margin-top: 5px;
margin-right: -10px;
}
}
}
.dropdown-submenu.pull-left {
float: none;
>.dropdown-menu {
left: -100%;
margin-left: 10px;
-webkit-border-radius: 6px 0 6px 6px;
-moz-border-radius: 6px 0 6px 6px;
border-radius: 6px 0 6px 6px;
}
}
li.selected {
background-color: #5094CE;
}
/* theme */
@import "_theme";
@import "_widgets";
@import "_buttons";
@import "_data-tables";
@import "_tables";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Some files were not shown because too many files have changed in this diff Show More