1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-10-04 05:44:42 +03:00

Compare commits

..

563 Commits

Author SHA1 Message Date
Adolfo Gómez García
15a76f3b9b Small 2.0 fix 2017-04-07 10:47:57 +02:00
Adolfo Gómez García
a3110d4623 fixed tunneld cord access 2017-03-18 11:48:52 +01:00
Adolfo Gómez García
92c3fbd827 Update checkuuid timeout from 2 to 5 2016-10-14 10:58:41 +02:00
Adolfo Gómez García
ea49e18f80 Now in case of connection error on checkuuid, the result will be that the check is correcot 2016-10-14 06:51:10 +02:00
Adolfo Gómez García
393819bc94 backported fix from 2.1 2016-10-11 07:53:31 +02:00
Adolfo Gómez García
7ab956fa4a minor fixes 2016-10-10 07:37:41 +02:00
Adolfo Gómez García
17044d38bd Improvement on ready setting logged in counter to 0 2016-10-03 14:23:19 +02:00
Adolfo Gómez García
0dc461c30b Fixed setPropert 2016-10-03 13:42:24 +02:00
Adolfo Gómez García
ced5e06ff0 Added a counter posibility to login-logout 2016-09-19 16:14:54 +02:00
Adolfo Gómez García
5e848cbc8c Fixed defvalue from 4 to 3 for ovirt, so migrations works fine from 1.9 to 2.x 2016-09-11 23:02:57 +02:00
Adolfo Gómez García
f924604217 Backport for ovirt 4.0 2016-09-11 22:21:12 +02:00
Adolfo Gómez García
efc59c0124 fixed unresolved imports 2016-09-11 22:15:04 +02:00
Adolfo Gómez García
2eaa447155 Includede persistent machines check idle also. 2016-09-07 16:49:40 +02:00
Adolfo Gómez García
3528424892 Fixed meta gruoups edition 2016-08-25 13:21:16 +02:00
Adolfo Gómez García
2eef7222d5 Backported guacamole for 2.0 availability 2016-08-17 20:39:37 +02:00
Adolfo Gómez García
0d28a5b5f7 Backported guacamole for 2.0 availability 2016-08-17 20:38:56 +02:00
Adolfo Gómez García
e0e7e26234 Fixed Translations 2016-07-28 13:33:28 +02:00
Adolfo Gómez García
2674563535 Fixed template config removal on publication failure 2016-07-27 18:22:37 +02:00
Adolfo Gómez García
a864fbac96 Publication now will correctly fail if the template cannot be cloned 2016-07-27 17:33:45 +02:00
Adolfo Gómez García
51c32a4350 Fixed for OpenNebula 5 (seems to work fine with 4 & 5 right now) 2016-07-26 16:29:40 +02:00
Adolfo Gómez García
ec95f27ee6 Updated translations && added server-keyboard-layout to guacamole 2016-07-26 13:44:36 +02:00
Adolfo Gómez García
15ce5aa938 Added failsafe to html5 keyboard 2016-07-26 12:58:56 +02:00
Adolfo Gómez García
39b353fb24 More Fixes 2016-07-22 17:57:45 +02:00
Adolfo Gómez García
7a0c8aa977 More Fixes for OpenNebula 4.x (for new API implementation) 2016-07-22 17:40:03 +02:00
Adolfo Gómez García
664418d4dc More fixes for OpenNebula 2016-07-22 16:54:09 +02:00
Adolfo Gómez García
381cf47abf * Fixed RDP to allow some optional parameters on linux clients
* dixed OpenNebula support
2016-07-21 13:51:31 +02:00
Adolfo Gómez García
1578c92a88 Adding support for OpenNebula 5.0 2016-07-18 20:12:38 +02:00
Adolfo Gómez García
6827380e99 Added - to title for xfreerdp 2016-07-15 15:33:44 +02:00
Adolfo Gómez García
62f637790c Fixed changelog of publications not being displayed on dashboard 2016-07-12 11:33:50 +02:00
Adolfo Gómez García
bf5311b5af Added sessions cleanup to scheduled task list 2016-07-12 01:29:00 +02:00
Adolfo Gómez García
d0e0418ede Fixed check due 2.0 just works only with opennebula 4.x due to api
changes on 5.x. 2.1 will cover both vversions
2016-07-11 22:16:46 +02:00
Adolfo Gómez García
243cbbfd4b Fixed log removal for cache & assigned services admin tables 2016-07-11 22:04:58 +02:00
Adolfo Gómez García
e7984d5a8e Fixed javascript error 2016-07-11 14:14:10 +02:00
Adolfo Gómez García
eacce7adda fixed images on chrome 2016-07-11 13:44:27 +02:00
Adolfo Gómez García
622e8629ff Fixed image removal on service pool group 2016-07-11 12:43:22 +02:00
Adolfo Gómez García
50e368ee7a * Added owner to dbfile, so we can remove later them selectively
* Fixed samples
2016-07-10 20:56:32 +02:00
Adolfo Gómez García
6766fe41fe Signed-off-by: Adolfo Gómez García <dkmaster@dkmon.com> 2016-07-09 02:59:55 +02:00
Adolfo Gómez
ba35968e8d Forgotten comma 2016-07-07 14:22:35 +02:00
Adolfo Gómez García
4adfac1c02 added comments field to index view 2016-07-07 13:10:18 +02:00
Adolfo Gómez García
437865b278 * Fixed a bug on Services Pool Groups Images
* Fixed a couple bugs on OpenNebula"
2016-07-05 15:40:26 +02:00
Adolfo Gómez García
793b6c9004 Fixed RDP to allow freerdp from linux to select audio controller 2016-06-24 11:10:53 +02:00
Adolfo Gómez García
96bd117622 Comment fix 2016-06-15 00:58:33 +02:00
Adolfo Gómez García
8b2df76582 Small fix so HTML5 Transport remove leading/trailing whitespaces 2016-06-13 11:39:07 +02:00
Adolfo Gómez García
4196883bfb Fixed Timings on uds Actor
Fixed oVirt to allow USB Configuration on service (for spice). Defaults to not allow.
2016-06-04 20:02:34 +02:00
Adolfo Gómez García
8585d10623 Again, fixing deadline... 2016-06-02 09:57:43 +02:00
Adolfo Gómez García
c715b92ed0 fixed getDeadline 2016-06-01 11:12:12 +02:00
Adolfo Gómez García
a3726399f1 Fixed Calendars access restrictions 2016-05-31 12:04:53 +02:00
Adolfo Gómez García
8ce3efc7ee Fixed to allow 2.0 to work with 1.9 windows actor 2016-05-30 09:33:53 +02:00
Adolfo Gómez García
0bd3e1ac72 * Added alert icon for calender restricted services
* Fixed spice to add fullscreen support on transport definition & a bug
to allow using it.
* Fixed OS Detector to include "unknown" as an os on "all OSs"
2016-05-27 13:39:51 +02:00
Adolfo Gómez García
c2d4e995e7 Fixes & tests on UDS Actor for honoring max session duration (got from
calendars)
2016-05-24 07:40:53 +02:00
Adolfo Gómez García
1b71fef8b4 Fixed about to include build version && also upgraded it a bit 2016-05-20 13:34:53 +02:00
Adolfo Gómez García
074a4d525d Fixed up about dialog 2016-05-20 10:28:00 +02:00
Adolfo Gómez García
36e19574e0 Added version stamp 2016-05-20 09:50:53 +02:00
Adolfo Gómez García
ef9165b3a2 space :( 2016-05-20 09:39:19 +02:00
Adolfo Gómez García
14cddbb210 Forgot removing comments & try-catch block :) 2016-05-20 09:38:46 +02:00
Adolfo Gómez García
2d14884454 * Fixed time picker not working on chrome
* Added warn on service being replaced by new publication
2016-05-20 09:37:12 +02:00
Adolfo Gómez García
ba4eeffc77 * Fixed client to better show errors
* Adding new publication warn for currently logged in users
2016-05-19 13:50:52 +02:00
Adolfo Gómez García
59179b818e Added mechanics to recover in case of scheduler task that got stuck 2016-05-18 12:22:11 +02:00
Adolfo Gómez García
dbcdc84b3b * Now cleanUDS cleans up possible locks also.
This command is designed to be executed with UDS backend stopped, so be
care!! :)
* Added deadLine calculation to ServicePool based on access calendars
2016-05-18 10:31:43 +02:00
Adolfo Gómez García
c73dae361f Fixed headers replication on UDS Reports 2016-05-17 09:35:53 +02:00
Adolfo Gómez García
ec29371b41 Merge branch 'master' of github.com:dkmstr/openuds 2016-05-06 13:30:18 +02:00
Adolfo Gómez García
9365f5937b Advancend & sync 2016-05-06 13:30:06 +02:00
Adolfo Gómez García
971015d33a Advancend & sync 2016-05-06 13:29:29 +02:00
Adolfo Gómez García
7a742c043b Merge remote-tracking branch 'origin/v1.9' 2016-05-03 08:15:20 +02:00
Adolfo Gómez García
c08a0cb0ed Fixed a bug not allowing linux machines to register when using an case sensitive database0 2016-05-03 08:15:12 +02:00
Adolfo Gómez García
b5926dec6f Fixed a bug on free edition not allowing to register correctly linux machines 2016-05-03 08:14:14 +02:00
Adolfo Gómez García
2fdcdb014f Merge remote-tracking branch 'origin/v1.9' 2016-04-29 11:16:13 +02:00
Adolfo Gómez García
bd70a6290e fixed to work correctly on free 2016-04-29 11:15:07 +02:00
Adolfo Gómez García
3afa96f1c5 Fixed spice scripts 2016-04-28 12:50:30 +02:00
Adolfo Gómez García
5da12a8091 Fixed & Tested that now we can open multiple redirections over same
tunnel.
2016-04-28 12:49:23 +02:00
Adolfo Gómez García
08eeff5604 Fixed duplicate declaration 2016-04-28 10:55:34 +02:00
Adolfo Gómez García
169a946a03 Fixed small bug on return clone 2016-04-28 09:34:43 +02:00
Adolfo Gómez García
94842ce0ef A better implementation for shared connections 2016-04-28 09:34:03 +02:00
Adolfo Gómez García
0fb7d5ed1b * Fixed service pool group setup bug
* Fix to allow some kind of connections to (as spice), to open two
different tunnels (We have to test the fix)
2016-04-28 08:34:47 +02:00
Adolfo Gómez García
2021fd69ec *Merged fixes for UDS Client 2016-04-27 09:59:09 +02:00
Adolfo Gómez García
813764a100 Fixed UDS Client to allow host names with unicode characters 2016-04-27 09:43:08 +02:00
Adolfo Gómez García
cbd9330907 * Fixed Login with only one authenticator (not working before)
* Added cache flush on start for FileStorage to avoid problems
2016-04-27 06:59:34 +02:00
Adolfo Gómez García
a250cf4aef Fixed calendar access cache 2016-04-26 16:04:29 +02:00
Adolfo Gómez García
50bc3cd3ef Fixing up things 2016-04-26 15:13:54 +02:00
Adolfo Gómez García
4fb863cfa7 * Fixed several literals
* Added config type field for "choices"
* removed old version snippets
2016-04-25 12:39:58 +02:00
Adolfo Gómez García
3a1bd1eed3 Fixed query to obtain restraineds 2016-04-25 11:16:47 +02:00
Adolfo Gómez García
bce3e429cf Fixed ammend 2016-04-22 15:16:05 +02:00
Adolfo Gómez García
b5baea184f Merged 1.9 update for behind-proxy support 2016-04-22 15:12:28 +02:00
Adolfo Gómez García
42cbad4117 Merged 1.9 update for behind-proxy support 2016-04-22 15:04:36 +02:00
Adolfo Gómez García
09f329db62 Allow UDS behind a proxy 2016-04-22 15:03:06 +02:00
Adolfo Gómez García
6b5f9d266d Allow UDS behind a proxy 2016-04-22 14:59:34 +02:00
Adolfo Gómez García
242d9b5e6e Advancing with semantic 2016-04-22 07:05:04 +02:00
Adolfo Gómez García
99b17e573c adding semantic 2016-04-22 05:20:30 +02:00
Adolfo Gómez García
701edb91f1 adding semantic 2016-04-22 05:19:52 +02:00
Adolfo Gómez García
f0627db09f Removed legacy html templates.
Added select rendering to template so we can use whatever styles we like
2016-04-22 03:06:00 +02:00
Adolfo Gómez García
56a579e11b Fixed spanish translations 2016-04-21 10:40:36 +02:00
Adolfo Gómez García
4427448eca Updated translations & added proxy support for reverse auth, etc... 2016-04-20 15:25:41 +02:00
Adolfo Gómez García
203e2fcdd0 Added fast navigation to administration interface 2016-04-20 11:37:04 +02:00
Adolfo Gómez García
f7fa92e6c1 Added info to services 2016-04-19 11:17:34 +02:00
Adolfo Gómez García
425257a464 adding information to services, so we can figure whats going on from services list 2016-04-19 10:04:44 +02:00
Adolfo Gómez García
0acc07ebb3 Fixed log table 2016-04-19 05:11:34 +02:00
Adolfo Gómez García
030078a619 Added tabs to a bunch of forms on administration (forms are getting too
big right now)
2016-04-18 11:50:54 +02:00
Adolfo Gómez García
0e6ca4c188 Fixing translations 2016-04-18 07:09:03 +02:00
Adolfo Gómez García
c7d5a1c928 Updated translations 2016-04-18 07:01:51 +02:00
Adolfo Gómez García
e636a4afcd fixhed weblogout 2016-04-15 16:57:16 +02:00
Adolfo Gómez García
8b76324ffc Squashed migration from 1 to 16 (until v1.9). Will keep old migrations until 2.1 release 2016-04-14 14:17:20 +02:00
Adolfo Gómez García
8fe1e55770 Removed RGS migration from 2.0. You will need to at least upgrade to 1.7 before going to 2.0 2016-04-14 13:50:00 +02:00
Adolfo Gómez García
caae694628 Merge branch 'master' of github.com:dkmstr/openuds 2016-04-13 21:32:51 -07:00
Adolfo Gómez García
268e9d551a syntax fixes 2016-04-13 21:32:42 -07:00
Adolfo Gómez García
07137c2416 Several improvements to UDS Client connector 2016-04-14 06:01:41 +02:00
Adolfo Gómez García
273b2a59c4 fixed an error with edit list 2016-04-14 05:14:58 +02:00
Adolfo Gómez García
63364f4e72 added wait to forwarthread for rdp tunnel 2016-04-13 08:05:46 +02:00
Adolfo Gómez García
abc9622d53 Fixed 2.0 client bugs 2016-04-13 07:24:41 +02:00
Adolfo Gómez García
9cd7e2f67b Added a few adds to client & Updated required version for 2.0.0 server to 2.0.0 client 2016-04-12 11:22:29 +02:00
Adolfo Gómez García
9277d3b5fb ignoring binaries 2016-04-11 06:38:58 +02:00
Adolfo Gómez García
6f46e16be8 upgrade to use guacamole 0.9.9 2016-04-11 06:38:32 +02:00
Adolfo Gómez García
0b390e406a New generation of pam files for tunneler based on cmake 2016-04-08 09:44:19 +02:00
Adolfo Gómez García
f301e4654a Updating pam tunneler module 2016-04-08 07:45:52 +02:00
Adolfo Gómez García
62481899a1 fixed tunnel field order on admin interface 2016-04-07 10:28:23 +02:00
Adolfo Gómez García
869dfc8c06 * More translations update
* Added custom limits to providers that allow it
2016-04-07 07:16:15 +02:00
Adolfo Gómez García
939d456b9d Added memcached setting to sample file && minor fixes 2016-04-06 06:13:22 +02:00
Adolfo Gómez García
9c70fb3caf Added caching to FileStorage 2016-04-06 06:02:51 +02:00
Adolfo Gómez García
baf4a677dd Added shared files storage 2016-04-05 04:59:56 +02:00
Adolfo Gómez García
4c4820f166 Chaged a bit the default ssl behaviour 2016-04-04 19:30:23 +02:00
Adolfo Gómez García
2749bfc40c fixed an js translation 2016-04-04 18:33:54 +02:00
Adolfo Gómez García
704e0607eb * Fixed scheduler action to make these execute under a transaction
* Removed xmlrpc url
2016-04-04 18:27:38 +02:00
Adolfo Gómez García
401fbac63e Removed last remaining xmlrcp part 2016-04-04 11:00:51 +02:00
Adolfo Gómez García
7f1252a70a Updating translation & fixing translations errors 2016-04-04 09:42:51 +02:00
Adolfo Gómez García
2df103a348 fixed taglist template for production (javascript must be "nice" and cannot have comments on this templates) 2016-04-04 08:27:59 +02:00
Adolfo Gómez García
489bb44c92 Fixing up for 2.0 release 2016-04-04 07:24:30 +02:00
Adolfo Gómez García
c606b6f00e Fixing up for 2.0 release 2016-04-04 07:12:38 +02:00
Adolfo Gómez García
0b4b38abe7 Fixed model of Calandars && finished Scheduled calendar actions 2016-04-01 07:18:42 +02:00
Adolfo Gómez García
40b71fa983 Fixed to use new datatables 2016-03-31 10:47:59 +02:00
Adolfo Gómez García
6116db5147 basic scheduled actions working (needs backedn worker to be done) 2016-03-30 11:23:23 +02:00
Adolfo Gómez García
e979c6e1e2 Now we can create (but not edit) scheduled actions 2016-03-29 15:45:34 +02:00
Adolfo Gómez García
8f9d042cdd Now we can create (but not edit) scheduled actions 2016-03-29 15:42:41 +02:00
Adolfo Gómez García
fcf030e693 Advanfing on action editing for services pools 2016-03-29 05:30:05 +02:00
Adolfo Gómez García
31e6e01cad fixed deletion of service on validation error 2016-03-28 06:22:03 +02:00
Adolfo Gómez García
1aad0c85a4 Merge remote-tracking branch 'origin/v1.9' 2016-03-28 06:02:23 +02:00
Adolfo Gómez García
e6e16334b3 fixed deleting service on edition & not being valid 2016-03-28 06:02:04 +02:00
Adolfo Gómez García
6544a61f72 fixed deleting element on edition instead of new 2016-03-28 06:00:43 +02:00
Adolfo Gómez García
8a285fddfa Merge remote-tracking branch 'origin/v1.9' 2016-03-19 02:30:34 +01:00
Adolfo Gómez García
c069f51e8d Fixed UDS Version download for clients 2016-03-19 02:29:06 +01:00
Adolfo Gómez García
c9a690fe8c Removed nonsense public folder from templates 2016-03-18 02:01:17 +01:00
Adolfo Gómez García
847821c66c fixed core version 2016-03-18 01:49:29 +01:00
Adolfo Gómez García
b5387d4922 * Fixed Actions Calendars migrations
* Started support for actions calendars edition on dashboard
2016-03-16 11:30:56 +01:00
Adolfo Gómez García
b0a6807ea4 Merge remote-tracking branch 'origin/v1.9'
# Conflicts:
#	VERSION
#	actors/linux/build-packages.sh
#	actors/linux/debian/changelog
#	actors/linux/debian/files
#	client/linux/debian/changelog
#	client/linux/debian/files
2016-03-14 12:16:52 +01:00
Adolfo Gómez García
2e96074961 Upgrades for 2.0
* Added support for /uuid REST method
* Now the http server is relocated on IP Change detection
2016-03-14 12:12:56 +01:00
Adolfo Gómez García
f275a91a43 Adding retry capability to interactWithBroker 2016-03-14 09:52:41 +01:00
Adolfo Gómez García
135392d245 Added get next event from a given date to calendar 2016-03-10 11:46:22 +01:00
Adolfo Gómez García
ff622bb9cd * Added optimization for serialization/deserialization (now it get cached with db object)
* Fixed model so now we invoke initGui before getting values on fillInstanceFields
* Upgraded Max creating & Max removing limits so now they can be tied to an specific provider instead of a global variable
* Tested & Fixed OpenStack. Now it seems to work as it should do.
* Several minor fixes/improvements
2016-03-09 11:42:44 +01:00
Adolfo Gómez García
608c1317d7 Updated OpenStack client & added caching features
Added counters to Cache (maybe somtime will store them on db to keep track on performance
2016-03-08 12:36:42 +01:00
Adolfo Gómez García
9f4ef20dc1 OpenStack working (initially) 2016-03-07 18:28:32 +01:00
Adolfo Gómez García
73bd3cc28e several fixes & adaptions for 1.9.1 2016-03-06 17:24:42 +01:00
Adolfo Gómez García
ea9eb04461 minor version upgrade to contain all patches 2016-03-04 15:06:10 +01:00
Adolfo Gómez García
c45833c252 Advancing on openstack a bit more 2016-03-04 14:51:44 +01:00
Adolfo Gómez García
e260fc9790 Advancing toward Openstack provider at a nice pace.
We have decided finally to use directly the REST api instead of any
available API, because we need a fustfill of things only, and we have
this way a better control. (And it's not difficult to implement)
2016-03-04 13:33:36 +01:00
Adolfo Gómez García
cc6ba2ff41 Updated to start with identity api v3 instead of v2, and advanced a lot 2016-03-03 21:33:17 +01:00
Adolfo Gómez García
bec74ddc99 UDS Client for openstack 2016-03-03 19:35:19 +01:00
Adolfo Gómez García
7af7d11c8a * New Clients Versions
* Refactoring
* Minor fixes
2016-02-26 14:16:13 +01:00
Adolfo Gómez García
8934d978fe Almost finished calendars access 2016-02-23 11:23:49 +01:00
Adolfo Gómez García
8376e81532 Adding Access calendars admin 2016-02-23 09:44:40 +01:00
Adolfo Gómez García
6587d9ba2c Fixed downloads to point to 2.0 clients 2016-02-19 09:58:15 +01:00
Adolfo Gómez García
2654036fd2 fixed uds client to work correctly with firefox on kunbuntu 2016-02-19 09:46:22 +01:00
Adolfo Gómez García
f9226e7deb Fixed login fail messages for django 1.9 2016-02-19 08:37:22 +01:00
Adolfo Gómez García
56ac8aece9 Upgrade to Django 1.9 and advances on advances on states fixes (cosmetic fixes to better identify what we refer to) 2016-02-19 08:16:55 +01:00
Adolfo Gómez García
12737df530 Advancing on calendar access & scheduling 2016-02-18 11:03:38 +01:00
Adolfo Gómez García
7b9c835562 Advancing on calendar access & scheduling 2016-02-18 11:03:25 +01:00
Adolfo Gómez García
cbb809db77 * Improved cache for calendars checkings
* Added calentar access & actions models
* Started calendar-pool integration
2016-02-17 10:55:51 +01:00
Adolfo Gómez García
4f9085f0a2 Almost finished grouping services 2016-02-16 07:00:14 +01:00
Adolfo Gómez García
389cf62150 Experimenting & adavancing on services grouping 2016-02-15 11:04:21 +01:00
Adolfo Gómez García
44c367bf8f Addind public template for working on int 2016-02-15 02:34:46 +01:00
Adolfo Gómez García
efb0083161 removing dist from list 2016-02-15 01:38:02 +01:00
Adolfo Gómez García
16c1aba3e7 Added tags to search filter on admin, and also added "tabindex" to input fields 2016-02-12 10:58:57 +01:00
Adolfo Gómez García
07ed8b9762 Fixed Images & pools groups (added priority and enhaced visual on admin 2016-02-12 09:53:33 +01:00
Adolfo Gómez García
fbd0a59a70 Removed whitspaces from tags on addition 2016-02-12 04:52:23 +01:00
Adolfo Gómez García
a08fe53383 * Added "Service Pool Group" full logic, so new we can add services pools to groups, so we can visualzize them grouped. (already needs the visualizarion part)
* Finished basic taglist edition (fixed a bug & added the possibility of insert serveral comma separated values at once')
2016-02-12 04:47:44 +01:00
Adolfo Gómez García
e1b8c43cca Added "tag editing" admin control 2016-02-11 05:44:38 +01:00
Adolfo Gómez García
60f20e64f3 testing link on uds.css 2016-02-10 07:38:51 +01:00
Adolfo Gómez García
6bb1109fe1 Adding tags & tag edition to mayor elemets of uds administration (for filtering, etc..) 2016-02-10 03:53:51 +01:00
Adolfo Gómez García
134f2059dd Added tagging capability to most entities 2016-02-10 01:51:05 +01:00
Adolfo Gómez García
ec93e5c9cc Merge remote-tracking branch 'origin/v1.9' 2016-02-09 12:53:10 +01:00
Adolfo Gómez García
1487c21e1e Fixed .desktop to make it work from chrome 2016-02-09 12:51:30 +01:00
Adolfo Gómez García
fd6b0c9458 Another big step forward for OpenNebula provider 2016-02-09 09:45:36 +01:00
Adolfo Gómez García
c41648748a Fixed CoRD on mac with a domain 2016-02-08 09:33:56 +01:00
Adolfo Gómez García
de4aef3a5c * Important advances on OpenNebula service provider
* several semantic changes
* Minor improvements & fixes
2016-02-08 09:33:17 +01:00
Adolfo Gómez García
d024d74529 Merged 1.9 fixes 2016-02-01 17:55:42 +01:00
Adolfo Gómez García
6eb5a7ccc8 Fixed security check 2016-02-01 17:47:34 +01:00
Adolfo Gómez García
335fd338bd several fixes 2016-01-25 11:38:39 +01:00
Adolfo Gómez García
d7ac59f257 Merge remote-tracking branch 'origin/v1.9' 2016-01-20 10:05:29 +01:00
Adolfo Gómez García
1ff09a1a04 Added Header elements to UDSGeraldoReport to be added to "base" report 2016-01-20 10:04:09 +01:00
Adolfo Gómez García
ca54c2c099 Merge remote-tracking branch 'origin/v1.9' 2016-01-20 09:34:30 +01:00
Adolfo Gómez García
76d209aa25 New report by pool 2016-01-20 09:34:00 +01:00
Adolfo Gómez García
491a33421d csv test 2016-01-19 17:22:22 +01:00
Adolfo Gómez García
f1cbcf86e1 Adding report to see user access time/duration 2016-01-19 15:24:19 +01:00
Adolfo Gómez García
e2e0f96d3e Refactoring states for easier reading 2016-01-08 09:37:00 +01:00
Adolfo Gómez García
4be5d8d6e5 Added host verification to uds client (so urls are approved at least
first time by users)
2016-01-08 09:34:20 +01:00
Adolfo Gómez García
0365376ab0 Fixed not rebooting machine on join domain on windows XP 2015-11-26 08:06:15 +01:00
Adolfo Gómez García
b9929566f6 Merge remote-tracking branch 'origin/v1.9' 2015-11-25 17:18:13 +01:00
Adolfo Gómez García
f463f586a3 Added 'in use' to true to Phisical Machines as soon as they are assigned, so they kept the assignation forever 2015-11-25 17:14:02 +01:00
Adolfo Gómez García
f6492256a8 Merge remote-tracking branch 'origin/v1.9' 2015-11-19 11:49:21 +01:00
Adolfo Gómez García
6fe734f67e Fixed issues on windows32 for client on users that has disabled 8dot3names and has non ASCII characters on its user name 2015-11-19 11:17:37 +01:00
Adolfo Gómez García
66d2c63a20 Merge remote-tracking branch 'origin/v1.9' 2015-11-18 14:59:20 +01:00
Adolfo Gómez García
06f2faff35 Merge branch 'v1.9' of github.com:dkmstr/openuds into v1.9 2015-11-18 09:28:55 +01:00
Adolfo Gómez García
57bd5e8149 Instead of leaving a removed deployed service once it is removed in the list, we now erase it as soon as it removal process has finished 2015-11-18 09:28:42 +01:00
Adolfo Gómez
11b9d07aef fixed hidding in mac os x 2015-11-17 15:15:47 +01:00
Adolfo Gómez García
b6f582d84e Merger 1.9 fixes 2015-11-16 20:25:06 +01:00
Adolfo Gómez García
b777919f52 A few improvements 2015-11-16 20:22:58 +01:00
Adolfo Gómez García
6371a24d23 Fixed an small bug when checking service is in maintenance 2015-11-16 20:17:51 +01:00
Adolfo Gómez García
d94cc70eff Merge remote-tracking branch 'origin/v1.9' 2015-11-16 12:45:12 +01:00
Adolfo Gómez García
7d02f3682d Fixed so empty credentials are tested 2015-11-16 12:36:52 +01:00
Adolfo Gómez García
51fb42db10 Fixed so empty credentials are tested 2015-11-16 12:35:12 +01:00
Adolfo Gómez García
a352059ddc Added logging capability to client, in windows, take a look at https://github.com/paramiko/paramiko/issues/613 because some issues on windows 32 bits 2015-11-12 18:21:46 +01:00
Adolfo Gómez García
0187b94768 Made removal of user services more robust 2015-11-11 14:36:22 +01:00
Adolfo Gómez García
163245401b Merging 1.9 fixes 2015-11-11 12:15:41 +01:00
Adolfo Gómez García
7a0f28a227 Fixed so first service served from cache are fully usable instead of "waiting for os" 2015-11-11 12:10:30 +01:00
Adolfo Gómez García
0add4b4321 Fixed new service operations checker. Improved & easier to understand with this new model 2015-11-10 08:04:39 +01:00
Adolfo Gómez García
19fdcadbcd Upgrading the UserServiceOpChecker to a new & clearer one 2015-11-06 12:04:44 +01:00
Adolfo Gómez García
7b85adaddf Updated version for master 2015-11-06 05:57:26 +01:00
Adolfo Gómez García
d8a0a2f80a Merged 2015-11-06 04:58:06 +01:00
Adolfo Gómez García
8ec6ce7edb An small fix to tiketauth 2015-11-06 04:15:56 +01:00
Adolfo Gómez García
0eab8d0f3f Added a couple of fixes for ticket authentication 2015-11-06 04:08:10 +01:00
Adolfo Gómez García
ae9a9534fc Merge remote-tracking branch 'origin/v1.9', cookie retrieval 2015-11-06 03:50:44 +01:00
Adolfo Gómez García
b56dbcfdfd Replace an uds direct cookie access by "getUdsCookie" 2015-11-06 03:50:22 +01:00
Adolfo Gómez García
1c1003eb41 Added merged from v1.9 that did not goes as expected... :) 2015-11-05 10:34:16 +01:00
Adolfo Gómez García
4bc6d88006 fixing 2015-11-05 10:31:46 +01:00
Adolfo Gómez García
fe6c701e44 Added better transpor selection for tickets 2015-11-05 10:28:10 +01:00
Adolfo Gómez García
f08593881f Merge remote-tracking branch 'origin/v1.9' 2015-11-05 08:16:54 +01:00
Adolfo Gómez García
9a59725504 added .gitignore to ignore .mo files 2015-11-05 08:16:42 +01:00
Adolfo Gómez García
30cf167e5b Merge remote-tracking branch 'origin/v1.9' 2015-11-05 08:15:55 +01:00
Adolfo Gómez García
88b7b365e7 Removed translations binaries 2015-11-05 08:13:46 +01:00
Adolfo Gómez García
064d881c1e Checking up javascript stuff 2015-11-05 07:30:06 +01:00
Adolfo Gómez García
c3f9d673bd Merge remote-tracking branch 'origin/v1.9' 2015-11-05 07:28:43 +01:00
Adolfo Gómez García
bbc2790ce0 Fixed an issue with singue quotes on base template for translations 2015-11-05 07:25:42 +01:00
Adolfo Gómez García
64970b57ca fixed sitecustomize 2015-11-02 01:21:53 +01:00
Adolfo Gómez García
4695dcaa0c Merge remote-tracking branch 'origin/v1.9' 2015-11-02 00:47:08 +01:00
Adolfo Gómez García
2b11d1715b Fixed unicode on network names for VMWare linked clones 2015-11-02 00:45:33 +01:00
Adolfo Gómez García
e23f22d92d Several fixes for dashboard && new command to clean up cache 2015-10-29 06:57:02 +01:00
Adolfo Gómez García
c8492a4c47 Removed url encoding for connfig. Not a good idea :) 2015-10-27 03:31:06 +01:00
Adolfo Gómez García
962f1fcc1c Merge remote-tracking branch 'origin/v1.9' 2015-10-27 01:53:44 +01:00
Adolfo Gómez García
2d6f4e4f2d Fixed config management param to do urldecode of parameters 2015-10-27 01:53:10 +01:00
Adolfo Gómez García
6bc70ff4de Several minor fixes & aditions 2015-10-24 10:32:51 +02:00
Adolfo Gómez García
aaf4b539d5 Merge remote-tracking branch 'origin/v1.9' 2015-10-20 19:49:34 +02:00
Adolfo Gómez García
83efb81966 Fixed Windows domain 2015-10-20 19:42:14 +02:00
Adolfo Gómez García
03d0fc2ba4 Merge remote-tracking branch 'origin/v1.9' 2015-10-19 06:36:57 +02:00
Adolfo Gómez García
41f128c2ad Updating guacamole 2015-10-19 06:07:45 +02:00
Adolfo Gómez García
bb09ef2a69 Updating guacamole 2015-10-19 05:59:14 +02:00
Adolfo Gómez García
407b0ebf55 Merge remote-tracking branch 'origin/v1.9' 2015-10-16 16:59:14 +02:00
Adolfo Gómez García
98d78d9a2e Another consinstence fix in case of db connection failure 2015-10-16 16:58:53 +02:00
Adolfo Gómez García
033ac0d1f6 Seems to finished updating tables. Need to check new working 2015-10-16 08:30:33 +02:00
Adolfo Gómez García
c9e9f60ed1 * Added a more aggresive cache for types, tables & guis (Less requests to server)
* Fixed ServicePools tables
* Fixed log tables
2015-10-16 07:43:03 +02:00
Adolfo Gómez García
162c84e21c Merge remote-tracking branch 'origin/v1.9' 2015-10-15 19:25:57 +02:00
Adolfo Gómez García
9f6d126484 Added images to memory cache instead of db cache 2015-10-15 19:25:48 +02:00
Adolfo Gómez García
f1e27f1364 Fixed sample settings & database recovery on backend 2015-10-15 18:54:36 +02:00
Adolfo Gómez García
06c7a46d2a Fixed connection lost to mysql 2015-10-15 11:17:12 +02:00
Adolfo Gómez García
0877cc01f4 Almost fixed all tables on dashboard 2015-10-06 11:32:47 +02:00
Adolfo Gómez García
00e85357cf Dashboard upgrade & enhacements 2015-10-06 07:14:40 +02:00
Adolfo Gómez García
cc72b3742f Addind multiselects & overviews to dashboard 2015-10-06 05:39:16 +02:00
Adolfo Gómez García
dff20bd6e1 Added several indexes to optimize some db queries\nFixed too many connections due to not being closed on threads termination\nAdvanced on new dashboard 2015-10-05 13:17:54 +02:00
Adolfo Gómez García
69b6f7d7d8 Merge remote-tracking branch 'origin/v1.9' 2015-10-05 11:48:22 +02:00
Adolfo Gómez García
02a2800a4b Added "connection.close" after job is done, so we use a lot of less
concurrent db connections
2015-10-05 11:46:45 +02:00
Adolfo Gómez García
9881df5117 Clean white squared admin with collapsable menu 2015-10-02 01:08:21 +02:00
Adolfo Gómez García
bc2f83c937 Clean white squared admin with collapsable menu 2015-10-02 00:56:46 +02:00
Adolfo Gómez García
fa78b4b295 Clean white squared admin with collapsable menu 2015-10-02 00:55:58 +02:00
Adolfo Gómez García
95230292c3 Experimenting with dashboard 2015-10-01 07:23:26 +02:00
Adolfo Gómez García
fdaf974009 Advancing on styling. Adding new functionality to dashboard 2015-09-25 17:27:46 +02:00
Adolfo Gómez García
26764c4cab Fixing datatables integration 2015-09-25 04:55:07 +02:00
Adolfo Gómez García
52d0e8977c Styling dashboard 2015-09-24 07:33:52 +02:00
Adolfo Gómez García
1d7df7814c Merge remote-tracking branch 'origin/v1.9' 2015-09-23 17:50:13 +02:00
Adolfo Gómez García
1551fa8efa Updated client to work fine on windows 32 bits 2015-09-23 17:39:24 +02:00
Adolfo Gómez García
7e9a37e768 advancing & gui-element tables 2015-09-23 10:43:45 +02:00
Adolfo Gómez García
80bf6d77f1 Added "multiple deletions" feature 2015-09-23 03:31:26 +02:00
Adolfo Gómez García
2d7a2d6049 Advancing on new dashboard 2015-09-22 19:53:56 +02:00
Adolfo Gómez García
8363b41a68 Advancing on new dashboard look&feel 2015-09-22 09:46:28 +02:00
Adolfo Gómez García
9804678a30 Updating look&feel of admin dashboard 2015-09-22 04:13:15 +02:00
Adolfo Gómez García
1187c0aa5e * Added a template folder to work on admin design faster
* Updated Admin CSS (Testing new view)
* Minor fixes (typos)
2015-09-22 02:23:27 +02:00
Adolfo Gómez García
36adbe387c Bad resolve fixed 2015-09-22 01:04:32 +02:00
Adolfo Gómez García
df2dcf7acd Merge remote-tracking branch 'origin/v1.9'
# Conflicts:
#	server/src/uds/services/OVirt/OVirtProvider.py
#	server/src/uds/services/OVirt/client/oVirtClient.py

Conflicts resolved
2015-09-21 08:18:45 +02:00
Adolfo Gómez García
b64fa374d7 Updated ovirt engine so 3.5.4 works correctly with disk cloning (Bug has been fixed on oVirt) 2015-09-21 07:29:10 +02:00
Adolfo Gómez García
3fbb492921 Added summary when adding new calendar rule & merged migrations 2015-09-18 10:02:39 +02:00
Adolfo Gómez García
1b97e2015d More fixes to calendars 2015-09-18 08:06:07 +02:00
Adolfo Gómez García
3814986e41 Fixed calendar checking.\nUpdated CalendarRule model to allow different durations units 2015-09-18 00:47:21 +02:00
Adolfo Gómez García
037a4b523b Fixed calendar rules. Almost finished :-) 2015-09-17 06:53:35 +02:00
Adolfo Gómez García
522d493557 Advancing more on calendar rules edition 2015-09-15 10:43:26 +02:00
Adolfo Gómez García
2ac06f7345 Advancing more on calendar rules edition 2015-09-15 10:43:12 +02:00
Adolfo Gómez García
0745a7aa9a Advancing on rule editing 2015-09-13 04:43:59 +02:00
Adolfo Gómez García
7e419aed8d Updating components for 2.0 2015-09-13 03:30:48 +02:00
Adolfo Gómez García
baa9565140 Merge remote-tracking branch 'origin/v1.9' 2015-09-13 03:30:17 +02:00
Adolfo Gómez García
069dfb154a Updating components 2015-09-13 03:30:12 +02:00
Adolfo Gómez García
eea9db7a0d fixed incorrect position of datepickers 2015-09-13 03:29:38 +02:00
Adolfo Gómez García
485ed4d60b Merge remote-tracking branch 'origin/v1.9' 2015-09-12 22:11:13 +02:00
Adolfo Gómez García
44056dda3a Removed unused return 2015-09-12 22:09:47 +02:00
Adolfo Gómez García
4de3e83ade * Upgraded bootstrap-select
* Upgraded bootstrap-switch
2015-09-11 10:18:21 +02:00
Adolfo Gómez García
73713eac69 * Adding calendar (models, permissions, adm access, ....)
* Upgraded fontawesome
2015-09-11 01:39:01 +02:00
Adolfo Gómez García
6ed924655d Adding calendar/rules models 2015-09-09 10:01:48 +02:00
Adolfo Gómez García
7706262702 Merge remote-tracking branch 'origin/v1.9' 2015-09-08 19:46:31 +02:00
Adolfo Gómez García
d878d522d7 Fixed os manager edition on service pool 2015-09-08 19:27:19 +02:00
Adolfo Gómez García
e0843179cd Fixing up several minor lang issues 2015-09-07 21:40:12 +02:00
Adolfo Gómez García
c6683db6e6 Translations done 2015-09-04 11:59:36 +02:00
Adolfo Gómez García
063b062913 Added /sec:rdp to xfreerdp call 2015-08-31 17:49:25 +02:00
Adolfo Gómez García
3dd2521408 Removed "banner_timeout" parameter (not supported on old paramiko
versions, and not really needed)
2015-08-31 17:42:09 +02:00
Adolfo Gómez García
f8e61d475a Removed \n from VERSION 2015-08-09 09:41:25 +02:00
Adolfo Gómez García
e7cea4ff6e Fixing some VERSION dependant buildings to use a global file 2015-08-09 09:33:39 +02:00
Adolfo Gómez
33d37ec0c2 Added VERSION file 2015-08-09 09:25:35 +02:00
Adolfo Gómez García
512feaed81 Some minor inprovements to plugin 2015-08-09 09:21:42 +02:00
Adolfo Gómez García
93c6c1c20e Messages 2015-08-05 11:30:12 +02:00
Adolfo Gómez García
d2298f77b9 Some minor fixes 2015-08-03 02:27:20 +02:00
Adolfo Gómez García
6979d9bc17 Some improvements over REST api for actor 2015-07-14 12:47:03 +02:00
Adolfo Gómez García
d4135d527a Finished pools performance report 2015-07-07 19:39:44 +02:00
Adolfo Gómez García
91c678eb72 A couple of typos 2015-07-07 12:40:05 +02:00
Adolfo Gómez García
1ef2c7303f Updated Phisical machine to allow same ip on a service more than once
Fixed comment on UserServiceCleaner
Fixed edition of services without cache
2015-07-07 11:58:34 +02:00
Adolfo Gómez García
1b232d1113 Updating pools report 2015-07-07 03:40:34 +02:00
Adolfo Gómez García
78652b550b Started pool performace report 2015-07-02 11:40:44 +02:00
Adolfo Gómez García
95d0965503 Fixed services pools buttons 2015-07-02 11:40:06 +02:00
Adolfo Gómez García
d8f8815137 started new report & fixed init_cmd for mysql 5.6 2015-07-02 11:26:10 +02:00
Adolfo Gómez García
9bcf7076aa Fixed prefs 2015-06-22 14:47:30 +02:00
Adolfo Gómez García
ae71e2b4bd Latests update translations 2015-06-22 11:30:32 +02:00
Adolfo Gómez García
f8934acbe4 Added a couple csv reports 2015-06-21 21:51:36 +02:00
Adolfo Gómez García
abf6d3751b Fixed report & created "basic" report class 2015-06-21 12:21:59 +02:00
Adolfo Gómez García
b77fa7dfd6 Added changelog for publications to dashboard 2015-06-17 08:21:47 +02:00
Adolfo Gómez García
32a04edbf9 Added changelog at publish stage (needs to show it on admin) 2015-06-15 09:47:33 +02:00
Adolfo Gómez García
3ff281ffa3 * Started to add a "reason" for publication (an small changelog that
helps to keep track of reasonf for launching new publications)
* Removed non usable "Usage" report
2015-06-12 10:21:46 +02:00
Adolfo Gómez García
e07f1ae068 Updated uds __init__ & added several fixes 2015-06-09 16:32:26 +02:00
Adolfo Gómez García
119635862b Added "workaround" to oVirt 3.5 so publications can be made, but only on
the original machine storage (3.5 has a bug that does not allows to
relocate disks for templates using REST API).
2015-06-09 09:38:36 +02:00
Adolfo Gómez García
e553b904c5 Adding new tools libraries 2015-06-08 08:04:54 +02:00
Adolfo Gómez García
92db63d01d Added Basque to sample language list and fixed a literal on services 2015-06-05 13:01:30 +02:00
Adolfo Gómez García
3584ff189b Updated translations 2015-06-05 12:53:23 +02:00
Adolfo Gómez García
e8614cbf14 Added Basque lang support, but no translations are made (there is a collaborator company that will make it) 2015-06-05 10:23:33 +02:00
Adolfo Gómez García
399fc901fc Some minor fixes & aditions to "Storage"\nFixed EditList to correctly show tooltip 2015-06-02 22:13:55 +02:00
Adolfo Gómez García
524e234e6d Updated translations 2015-06-02 22:07:34 +02:00
Adolfo Gómez García
c14186fb4e Added hint on services about what kind of services they offers (VDI, VAPP, ..) 2015-05-29 09:21:36 +02:00
Adolfo Gómez García
eeea4a3f39 Added hint on services about what kind of services they offers (VDI, VAPP, ..) 2015-05-29 09:21:26 +02:00
Adolfo Gómez García
567f91414f Allows "respawn" of new services instead of existing one on service
launch
2015-05-27 09:51:30 +02:00
Adolfo Gómez García
e5710eb74c * Fixed log of "user logged in" and "user logged out"
* Small typo on debug log for windows os manager
* Added Headers to __init__ of windows os managers
2015-05-26 10:36:15 +02:00
Adolfo Gómez García
1733f142be * Several fixes to UDS Actor (minor ones)
* Minor adaptions to allow REST actor to connect with "tickets'
* Fix to TicketStore
2015-05-26 08:26:36 +02:00
Adolfo Gómez García
ccebca9748 Merge remote-tracking branch 'origin/v1.7' 2015-05-21 13:17:29 +02:00
Adolfo Gómez García
cb5d6ed771 small typo 2015-05-21 13:14:25 +02:00
Adolfo Gómez García
b9283c6778 Fixed ramdom password... {3} must be {2}!!! 2015-05-21 13:06:11 +02:00
Adolfo Gómez García
5dc2c16cbe Merge remote-tracking branch 'origin/v1.7' 2015-05-21 07:23:39 +02:00
Adolfo Gómez García
8d4f60b0fb Fixed a couple things for Linux random password 2015-05-21 07:23:18 +02:00
Adolfo Gómez García
b9175be480 A couple minor fixes for RDP transports 2015-05-18 10:02:29 +02:00
Adolfo Gómez García
884bbe7363 Updated translations 2015-05-17 22:17:51 +02:00
Adolfo Gómez García
98b9e6b659 more makeup 2015-05-17 21:35:31 +02:00
Adolfo Gómez García
1c4339f404 Adding some "beauty" icons 2015-05-15 10:41:19 +02:00
Adolfo Gómez García
0ffc9964d0 Merge remote-tracking branch 'origin/v1.7'
Conflicts:
	server/src/uds/REST/methods/providers.py
	server/src/uds/REST/methods/services.py
	server/src/uds/REST/methods/tickets.py
	server/src/uds/REST/model.py
	server/src/uds/web/views/service.py
2015-05-14 12:39:58 +02:00
Adolfo Gómez García
18c9406900 Several fixes... :) 2015-05-14 12:25:35 +02:00
Adolfo Gómez García
df498dd5bc Fixed several "case" uuids tests, so UDS can work with case sensitive
databases
2015-05-14 11:46:45 +02:00
Adolfo Gómez García
e7a3c7ebeb Removed transcomp (not user anymore) 2015-05-13 07:13:12 +02:00
Adolfo Gómez García
724aecd21c Updating translations 2015-05-13 07:12:55 +02:00
Adolfo Gómez García
b00a023f30 *Updated a new buch of icons
Changed reload method for main page
* Added cache support for some kinds of pages
2015-05-13 06:52:13 +02:00
Adolfo Gómez García
592510f0f3 * Added new "Global ID Generator"
* Added a single point for all unique generators (uds.core.util.unique)
2015-05-13 05:58:50 +02:00
Adolfo Gómez García
c96e566ebf * Updated a bunch of icons
* Changed modal of transport, now it says connections
* Removed old rdptransport from current version
* Fixed error view (was getting idError as string instead of integer)
* Started to add protocol dependency to services, so we can limit some kined of services to a protocol
2015-05-13 05:57:47 +02:00
Adolfo Gómez García
78526b3560 The index is now "static", so we reload it every minute for the user to
get the state of different services updated.
2015-05-10 07:33:12 +02:00
Adolfo Gómez García
04ec90ad61 * Transports associadted to Providers working correctly
* Spice transport added (EXPERIMENTAL version)
2015-05-10 07:19:57 +02:00
Adolfo Gómez García
e69914a9a5 Fixed os detection on request when no user agent is privided (defaults
to Unknown)
2015-05-10 06:40:23 +02:00
Adolfo Gómez García
c1c54f38cc Working on Spice protocol support.
* Added "provider specific" transport support
* Fixed dashboard to new transport support
2015-05-06 09:31:37 +02:00
Adolfo Gómez García
dad83c5c50 Merge remote-tracking branch 'origin/v1.7' 2015-05-06 05:47:23 +02:00
Adolfo Gómez García
b592e10126 After upgrade of python to 2.7.9, several HTTPS connections needed to be
fixed. This is about that
2015-05-06 05:36:03 +02:00
Adolfo Gómez García
a235e43c07 Fixed edition of ovirt service O.o 2015-05-06 04:27:14 +02:00
Adolfo Gómez García
eb7185b9e3 Fixed possition of base64 js. When using "compressor" on production, it was not working on prev place 2015-05-06 02:16:39 +02:00
Adolfo Gómez García
776702f971 Added own version to client REST request for required version 2015-05-06 01:53:21 +02:00
Adolfo Gómez García
6fb9b11f1b Fixing versions so they are shown on web interface 2015-05-05 08:17:59 +02:00
Adolfo Gómez García
d3e2ab85b8 Fixed building process of actor packages 2015-05-05 07:13:30 +02:00
Adolfo Gómez García
35a4dd659c Fixed building process of client packages 2015-05-05 07:08:57 +02:00
Adolfo Gómez García
e0d2abbbd6 fixing versions. Too much changes, we are going to give out it as 1.9.0 2015-05-05 07:01:09 +02:00
Adolfo Gómez García
5db3429b2c Added user access report
added ipython notebook notes (could be it helpfull?)
fixed datepicker locales loader (UDS one)
Several fixes for reporting
2015-05-05 06:49:31 +02:00
Adolfo Gómez García
dd0c605ff4 Added datepicker to complete "date" type gui field
Started login report
several minor fixes to adapt to reporting
2015-05-03 13:32:31 +02:00
Adolfo Gómez García
54d41c1931 * Added stat about accessing platform (OS, browser & browser version)
* Added bar informing about cookie usage by site
2015-05-03 03:58:50 +02:00
Adolfo Gómez García
9ee66cf6ed * Added "force" parameter to ticket request for ticket authenticated
access
* Added detection of browser to OSDetector, so now request always have
the current browser type/version
* Fixed decorator/template tag to use new request.os.Browser &
request.os.Version
2015-05-03 03:33:05 +02:00
Adolfo Gómez García
a34de035cb * Added creation date to user & group, so we can include "auto clean by age" mechanichs
* Added changelogs to Publications, so we can "store" if we like a text with every publication
* Added "ServiceNotReadyError" as method of controlling if a service is ready, instead of returning None
* Merged several migrations into one
* Updated message error so we include a "code" when service is not ready
* Added user getService to userServiceManager, that is where it must be
2015-04-30 13:03:32 +02:00
Adolfo Gómez García
1dac61ea69 Merge remote-tracking branch 'origin/v1.7' 2015-04-30 08:23:57 +02:00
Adolfo Gómez García
15c785d5fe Again, counter fix to 15 seconds (1 minuto seems too long for me right
now...)
2015-04-30 08:23:07 +02:00
Adolfo Gómez García
7c7c609ea8 fixex pydev for current version 2015-04-29 17:45:02 +02:00
Adolfo Gómez García
f8b34e1d23 Merge remote-tracking branch 'origin/v1.7' 2015-04-29 17:44:26 +02:00
Adolfo Gómez García
6295e7400d added virtualenv for pydev project for 1.7 2015-04-29 17:43:53 +02:00
Adolfo Gómez García
42a3df5c82 Merge remote-tracking branch 'origin/v1.7' 2015-04-29 17:19:55 +02:00
Adolfo Gómez García
54a2a0cb35 Added exception checking on service main loop for windows 2015-04-29 17:19:30 +02:00
Adolfo Gómez García
ec48f27792 Merge remote-tracking branch 'origin/v1.7' 2015-04-29 17:17:23 +02:00
Adolfo Gómez García
15554ab08f A couple of minor fixes 2015-04-29 17:17:06 +02:00
Adolfo Gómez García
c042ab6b31 * Updated following admin components:
- jquery
  - Filesaver
  - datatables
  
* Added full support for report generation, in dashboard & REST backend
2015-04-29 07:59:21 +02:00
Adolfo Gómez García
40641659a5 Started "definitive" reporting system for dashboard 2015-04-28 05:03:01 +02:00
Adolfo Gómez García
f7fbc5a0c4 Fixed systray icon of UDS and a couple of minor fixes 2015-04-27 22:13:34 +02:00
Adolfo Gómez García
4a6e21d1ec Upgraded UDS Actor systray icon. The "black" background was due i was saving images witg "transparent pixel color included" from gimp 2015-04-27 22:01:31 +02:00
Adolfo Gómez García
d6dcd265a4 * Tests on reports (will be added as REST methods, this is just tests..
:) )
* Small fix to REST udsactor (got VERSION from new part)
2015-04-27 20:40:06 +02:00
Adolfo Gómez García
8fe589fa75 Finished Ticket launching mechanics, used with some external plugins
(such as UMA's Moodles plugin for UDS)
2015-04-27 07:07:44 +02:00
Adolfo Gómez García
656f10a1ca Merge branch 'master' of github.com:dkmstr/openuds 2015-04-27 05:22:30 +02:00
Adolfo Gómez García
f39d780a88 Removed "util" ticket and adapted several 1.8 db model stuff (UnsavedForeignKey) 2015-04-27 05:17:25 +02:00
Adolfo Gómez
134e9c0b61 updated .gitignore for mac buildings 2015-04-26 06:41:20 -07:00
Adolfo Gómez García
f411eec5f4 towards 1.7.5 2015-04-26 03:27:06 +02:00
Adolfo Gómez García
a996562a5e Cleaning up thing for 1.7.5 2015-04-26 03:18:15 +02:00
Adolfo Gómez García
1ea3261b27 Restored autorun functionality 2015-04-24 17:32:15 +02:00
Adolfo Gómez García
a1bd7274f4 Advancing on basic reports 2015-04-24 04:19:43 +02:00
Adolfo Gómez García
3206390c9c Removing Java plugins related code 2015-04-23 07:08:08 +02:00
Adolfo Gómez García
4ed20850ae Added downloadables for clients 2015-04-23 07:07:14 +02:00
Adolfo Gómez García
ef302205bc some cleanups 2015-04-23 06:32:03 +02:00
Adolfo Gómez García
e651d3348d All existing transports are now ported to new model. Need to do more
tests, but conversion seems to be finished (or almost.. :) )
2015-04-22 06:39:09 +02:00
Adolfo Gómez García
cc3cce6038 Migrating from Java to New agent for NX 2015-04-21 19:13:15 +02:00
Adolfo Gómez García
5b3e5242d1 Merge remote-tracking branch 'origin/v1.7' 2015-04-21 12:29:32 +02:00
Adolfo Gómez García
60556ad4ec fixed RDP with user credentials 2015-04-21 12:29:10 +02:00
Adolfo Gómez García
8686741410 fixed build packages 2015-04-20 09:24:15 +02:00
Adolfo Gómez García
199e0d3559 Almost finished connector 2015-04-20 07:33:01 +02:00
Adolfo Gómez García
95b8969f5b * Fixed service ip checking access on access
* Added new "connection" REST method (Virginios request to make
"automated" connections with local clients)
2015-04-16 20:55:28 +02:00
Adolfo Gómez García
fc447e3ccf updated handlers.py from mainstream 2015-04-16 18:24:43 +02:00
Adolfo Gómez García
6b19e75ce7 Advancing on transports & client fixes 2015-04-14 08:33:10 +02:00
Adolfo Gómez García
c3316a4745 Fixed forwarding scheme so it works with all platforms... 2015-04-13 13:55:18 +02:00
Adolfo Gómez García
250441056b Initial version for linux packagers 2015-04-10 17:31:35 +02:00
Adolfo Gómez García
bdef8b2e8c * Simplified Transports after tests
* Added direct linux support for xfreerdp right now
2015-04-08 15:21:09 +02:00
Adolfo Gómez García
aef71ba48c Adding icons for windows and fixing up things 2015-04-07 18:17:21 +02:00
Adolfo Gómez
86e5b9fcaa added mac osx icons file 2015-04-07 03:34:53 -07:00
Adolfo Gómez García
8d01e77a94 advancing new transport system 2015-04-07 12:28:41 +02:00
Adolfo Gómez García
d34248b868 advancing new transport system 2015-04-07 12:28:31 +02:00
Adolfo Gómez
c15151a35d adding icons for macosx 2015-04-07 03:21:03 -07:00
Adolfo Gómez García
b5609a7b0c tunning up things 2015-04-07 12:02:45 +02:00
Adolfo Gómez García
4067de702c tunning uds client 2015-04-07 11:57:57 +02:00
Adolfo Gómez García
375f574e9e more fixes 2015-04-07 11:43:33 +02:00
Adolfo Gómez
ee59f45838 fixing up tunnel stuff 2015-04-07 02:41:59 -07:00
Adolfo Gómez
ae5fafae76 fixin up things on mac os x 2015-04-07 02:04:51 -07:00
Adolfo Gómez
dc1dd977fc Removed notes & added basic macosx info 2015-04-06 23:18:41 -07:00
Adolfo Gómez García
f8b95382b0 * Extracting script to "template" files for transports
* Fixes to UDS Client
2015-04-07 07:59:47 +02:00
Adolfo Gómez García
2f655dce16 Advancing on Mac OS RDP TRansport and a couple minor fixes to UDS Plugin 2015-04-02 09:36:46 +02:00
Adolfo Gómez García
c5138dbc9c First part seems to work fine on mac os x with Microsoft Remote Desktop 2015-04-01 09:44:41 +02:00
Adolfo Gómez García
8a17d5d017 More on mac 2015-04-01 09:36:52 +02:00
Adolfo Gómez García
089f62e6f8 More for mac related 2015-04-01 09:32:13 +02:00
Adolfo Gómez García
e4192e6064 Advancing on client for mac os x 2015-04-01 09:07:11 +02:00
Adolfo Gómez
646334ece5 test.rdp 2015-03-31 23:13:53 -07:00
Adolfo Gómez
2480a79450 adding more notes for mac os x 2015-03-31 23:13:25 -07:00
Adolfo Gómez García
f173146d8f * Implemented uds connector script for RDP (just for windows right now)
* Advanced a lot with java removal process
* Implemented usefull things on client part
2015-03-31 18:10:44 +02:00
Adolfo Gómez García
62f50304fe Advancing on uds client connector 2015-03-30 12:08:44 +02:00
Adolfo Gómez García
c70d94e866 Started client part 2015-03-30 08:11:29 +02:00
Adolfo Gómez García
dc006e7cbc using new method for client (more homogeneous) 2015-03-27 14:44:45 +01:00
Adolfo Gómez García
c5444f0df2 Almost done with web part of new model. Retired java checks from code & pages 2015-03-27 07:41:42 +01:00
Adolfo Gómez García
c7d3e4022f added bypass plugin detection to preferences 2015-03-26 17:31:40 +01:00
Adolfo Gómez García
151623e407 Advancing on web part of new no-java version of UDS 2015-03-26 14:24:03 +01:00
Adolfo Gómez García
67393e88db Merge remote-tracking branch 'origin/v1.7' 2015-03-25 10:10:54 +01:00
Adolfo Gómez García
2fe783e3ae Updated Filesaver && fixed exporting to excel 2015-03-25 10:10:34 +01:00
Adolfo Gómez García
d87f4de4ff Web part of new uds plugin almost done 2015-03-24 12:05:40 +01:00
Adolfo Gómez García
b69f56ecb8 Fixed servicepool deletion on image deletion 2015-03-24 11:22:28 +01:00
Adolfo Gómez García
b08fd3d60e Merge remote-tracking branch 'origin/v1.7' 2015-03-24 10:42:08 +01:00
Adolfo Gómez García
7d26463639 updated translations 2015-03-24 10:41:52 +01:00
Adolfo Gómez García
4d9d4bdbee Merge remote-tracking branch 'origin/v1.7' 2015-03-24 09:43:23 +01:00
Adolfo Gómez García
523ca37ee8 typo 2015-03-24 09:42:54 +01:00
Adolfo Gómez García
65c7b34ee0 Started client plugin 2015-03-24 08:05:51 +01:00
Adolfo Gómez García
2303861650 Advancing a bit more towards new uds transport model 2015-03-23 20:06:03 +01:00
Adolfo Gómez García
38b7ac892e Merge remote-tracking branch 'origin/v1.7' 2015-03-23 12:24:42 +01:00
Adolfo Gómez García
cfad948660 Added multiple monitor support for windows clients & servers 2015-03-23 12:22:45 +01:00
Adolfo Gómez García
ccf35fcd49 Advancing on uds client 2015-03-23 12:08:39 +01:00
Adolfo Gómez García
d6e031e9e6 Creating new ticketing model, based on an independent table 2015-03-23 02:27:56 +01:00
Adolfo Gómez García
7b29d698dc Merge remote-tracking branch 'origin/v1.7' 2015-03-23 02:23:56 +01:00
Adolfo Gómez García
989600e639 Fixed uuid model case 2015-03-23 02:22:54 +01:00
Adolfo Gómez García
9fa4bacc74 fixed case of uuids to lower 2015-03-23 02:22:17 +01:00
Adolfo Gómez García
e02b3ad881 Merge remote-tracking branch 'origin/v1.7' 2015-03-20 15:16:15 +01:00
Adolfo Gómez García
cc4619220a * Added a "preinit" to xscreensaver, to give some more oportunities on
linux to initialize this correctly.
* Fixed typos on dashboard
* Fixed not saving correctly textarea fields of configuration
2015-03-20 15:15:35 +01:00
Adolfo Gómez García
c71d86825c Added download page for new uds plugin 2015-03-20 13:30:52 +01:00
Adolfo Gómez García
7648e9c655 Added a reset to initIdleDuration 2015-03-18 15:30:13 +01:00
Adolfo Gómez García
bb8931e7d4 Merge remote-tracking branch 'origin/v1.7' 2015-03-18 11:08:06 +01:00
Adolfo Gómez García
695a67c2cb Fixed so image deletion does not deletes it associated deployed service 2015-03-18 11:07:26 +01:00
Adolfo Gómez García
011ba37d2a Several minor fixes and protocol detection seems to work 2015-03-17 12:34:32 +01:00
Adolfo Gómez García
d73c8f49cc Several minor fixes and protocol detection seems to work 2015-03-17 12:34:19 +01:00
Adolfo Gómez García
3ddf2f91ad converted sample from utf16 to utf8 2015-03-16 14:42:43 +01:00
Adolfo Gómez García
809aea2c87 UDS Client project 2015-03-16 14:40:19 +01:00
Adolfo Gómez García
4e2fce147f linux notes 2015-03-16 14:39:13 +01:00
Adolfo Gómez García
26e01af696 linux notes 2015-03-16 14:38:48 +01:00
Adolfo Gómez García
cb9359f9af Fixed checking permissions on custom methods of publications 2015-03-16 11:28:53 +01:00
Adolfo Gómez García
bad482b7f1 Test for windows schema registering 2015-03-15 11:34:13 +01:00
Adolfo Gómez García
a94f7b335b Merge branch 'master' of github.com:dkmstr/openuds 2015-03-15 11:32:46 +01:00
Admin
41b86509e0 testing building on mac os x 2015-03-15 02:35:57 -07:00
Adolfo Gómez García
27224fa8a1 Starting to work on reporting 2015-03-10 09:25:18 +01:00
Adolfo Gómez García
9656aab27d Merge remote-tracking branch 'origin/v1.7' 2015-03-09 16:53:46 +01:00
Adolfo Gómez García
cbf68030d3 Removed debug from oVirt 2015-03-09 16:51:56 +01:00
Adolfo Gómez García
3e97481af2 fixed permissions tests 2015-03-09 16:08:16 +01:00
Adolfo Gómez García
705c3d7b76 Merge remote-tracking branch 'origin/v1.7' 2015-03-09 15:54:37 +01:00
Adolfo Gómez García
2470e88d55 added .pyo to ignore list 2015-03-09 15:51:47 +01:00
Adolfo Gómez García
f300770b29 Merge remote-tracking branch 'origin/v1.7' 2015-03-09 08:29:45 +01:00
Adolfo Gómez García
63278938c8 fixed translations 2015-03-09 08:29:18 +01:00
Adolfo Gómez García
5623c65763 Template 2015-03-06 09:52:48 +01:00
Adolfo Gómez García
5dca92ca5e * Added new "main dashboard" template for non admin (staff) users 2015-03-06 09:52:07 +01:00
Adolfo Gómez García
c1fd898d62 Some retouch on permissions delegation... seems nice right now :) 2015-03-05 19:10:46 +01:00
Adolfo Gómez García
2435f589b9 Needs more testing, but permission delegation seems to work right now. 2015-03-05 15:20:46 +01:00
Adolfo Gómez García
6387629e7e Almos finished permissions gui 2015-03-04 12:07:22 +01:00
Adolfo Gómez García
5bde71b117 Advancing on permissions 2015-03-03 16:58:49 +01:00
Adolfo Gómez García
b2eb7cc9c1 Advancing on permissions 2015-03-03 16:58:32 +01:00
Adolfo Gómez García
48df4390bd Started dashboard permissions edit 2015-03-02 17:02:02 +01:00
Adolfo Gómez García
9920af9c59 Adding permissions managing to objects 2015-03-02 11:51:20 +01:00
Adolfo Gómez García
681b1333d1 Advancing thought permissions delegation 2015-03-02 08:30:45 +01:00
Adolfo Gómez García
67b8955189 Started permission delegation 2015-03-01 22:04:52 +01:00
Adolfo Gómez García
d542503f55 * Adapting to new "near" auth groups 2015-02-28 12:00:57 +01:00
Adolfo Gómez García
be5ed5a70b Merge remote-tracking branch 'origin/v1.7' 2015-02-28 09:46:33 +01:00
Adolfo Gómez García
f751fff8ca Fixed using 169.254/16 as a valid IP for notifying to broker 2015-02-28 09:45:12 +01:00
Adolfo Gómez García
2d942fbac7 More minor fixes 2015-02-27 17:32:24 +01:00
Adolfo Gómez García
4bb4987937 minor fix related to grace time 2015-02-27 17:24:57 +01:00
Adolfo Gómez García
d371e3f7ac Fixed some posible "logging out too early" to users when using idle
checker
2015-02-27 17:23:26 +01:00
Adolfo Gómez García
033fb6eff2 * Fix to StatsManager so numeric fields can also be used
* Added remaining related cache elements on cache_hit & cache_miss
* pep fix to WidowsOsManger
* Reduced size of Dashboard sidebar
* Removed "AM/PM" from datetimes
2015-02-27 17:05:06 +01:00
Adolfo Gómez García
23819b77ee * Added cache hit/miss logging events 2015-02-27 09:28:04 +01:00
Adolfo Gómez García
fbcc2210b3 minor fix 2015-02-26 15:16:49 +01:00
Adolfo Gómez García
45b2e61631 * Added some debug logging to actor 2015-02-26 10:39:18 +01:00
Adolfo Gómez García
4fceb8609f Fixed log of pub manager\nModified default config of tunneler\nUpdated actor REST api to not allow less than 30 seconds of "max idle" configuration 2015-02-25 17:05:39 +01:00
Adolfo Gómez García
26c6b559a5 * Minor tuning 2015-02-25 11:15:08 +01:00
Adolfo Gómez García
90e34029f3 Fixing up rdp transport (tunneled) 2015-02-25 10:28:18 +01:00
Adolfo Gómez García
6895f602ab Just updated guacamole pom to use 0.9.4 2015-02-23 13:26:34 +01:00
Adolfo Gómez García
b1b8b613e6 Updated translations 2015-02-23 10:16:44 +01:00
Adolfo Gómez García
40ba837f70 Added logging of what caused the exception 2015-02-23 08:35:26 +01:00
Adolfo Gómez García
c075ae5a9c * Updated notification so, by default, is broker which "deduces" the
client IP and not the client who notifies it (this is left just for
"trusted" environments)
2015-02-22 09:31:56 +01:00
Adolfo Gómez García
8de49e5e94 * Removed "Trusted only" from manifest 2015-02-22 09:17:06 +01:00
Adolfo Gómez García
7887b7f3cc Fixed Linux applet to "show" wallpapers if required 2015-02-20 15:27:16 +01:00
Adolfo Gómez García
c81f162b90 Fixed "print" to "logger.debug" 2015-02-20 11:31:06 +01:00
Adolfo Gómez García
35a5a78220 updated requirements 2015-02-20 09:30:19 +01:00
Adolfo Gómez García
2bc0f64e34 Set a default ip for connection source on service connection request
(equals to request "deducted" ip...).
2015-02-18 14:45:08 +01:00
Adolfo Gómez García
19cb475e2d * Updated bootstrap switch to latest (and working) version
* Fixed displaying state "twice" in authenticators groups due to a
"developing" data left behind...
2015-02-17 23:46:56 +01:00
Adolfo Gómez García
ae4fc2d51a Removed log from user space actor for user login.. (Filtered out) 2015-02-17 22:18:01 +01:00
Adolfo Gómez García
06e886a366 * Fixed HTML5RDP to work correctly with new actor
* Fixed base transport to receive an "user" and not an "username"
2015-02-17 11:45:30 +01:00
Adolfo Gómez García
1497314a46 Fixing up windows service behavior 2015-02-17 09:51:51 +01:00
Adolfo Gómez García
e6998cb1f3 Added posibility to modify several OS Manager fields even if it is being used 2015-02-16 18:31:16 +01:00
Adolfo Gómez García
111782dffd removing binaries 2015-02-16 17:54:30 +01:00
Adolfo Gómez García
a86fbf83e8 removing binaries 2015-02-16 17:53:27 +01:00
Adolfo Gómez García
c9f6c17407 Fixed state notification when os manager is working 2015-02-16 15:58:38 +01:00
Adolfo Gómez García
c04037a4ea Fixed actor return error on DC not reachable 2015-02-16 14:58:27 +01:00
Adolfo Gómez García
d1adcebe4b Added "info" to mac users
Restored overview info to match item info
2015-02-11 11:22:56 +01:00
Adolfo Gómez García
3e5cbda861 Testing up manifest changes for signed applets on mac 2015-02-11 09:49:31 +01:00
Adolfo Gómez García
8a393c6717 Added "is in maintenance" method for userservice 2015-02-10 17:44:41 +01:00
Adolfo Gómez García
f235bc0796 If service is in maintenance, denies now new accesses (index page may be
outdated)
2015-02-10 17:26:27 +01:00
Adolfo Gómez García
2549510eaa * Fixed several "last hour" REST requests related to tickets
* Added OS Detector so if os is not detected before, tries it at request
moment
* Added a new error so services in maintenance mode are notified
2015-02-10 17:24:27 +01:00
Adolfo Gómez García
3fbcee60cb small fix 2015-02-10 10:29:01 +01:00
Adolfo Gómez García
20cc73dca8 * Added Manifest small fixes for applets
* Updated translations
* Added several "methods" support for sqlite3 db backend (on __init__ of
uds) such as max, min & ceil (needed for stats)
2015-02-10 09:54:45 +01:00
Adolfo Gómez García
375fe6551c Some minor cosmetic fixes to scheduler runner 2015-02-03 18:26:25 +01:00
Adolfo Gómez García
f74524d947 * Fixed HTML5 RDP
* Updated translations
* Fixed Scheduler to ensure that when started up, all "owned" tasks are
released
2015-02-03 18:19:21 +01:00
Adolfo Gómez García
e1f26d2157 * Fixed "double cancel" of a publication (cancelling over an already
cancelling publication will "force" the cancellation, meaning that no
check is done, it simply stops publication and mark it as "cancelled"
(leaving a log on service pool, ofc)
2015-02-03 06:30:27 +01:00
Adolfo Gómez García
7d44bd7b65 Some more minor fixes to literals & translations 2015-02-02 11:43:56 +01:00
Adolfo Gómez García
ab5f51a3b1 * Fixed several bad formed literal strings
* Updated translations
2015-02-02 11:31:59 +01:00
Adolfo Gómez García
d1e2e98099 Fixed rpm actors download path 2015-02-02 07:13:17 +01:00
Adolfo Gómez García
f94bbaad67 Fixed mime types por rpm actors packages 2015-02-01 06:18:37 +01:00
Adolfo Gómez García
7143682062 * Fixed cancelation of a publication on dashboard
* Now allows "forced cancel" after a cancel is requested
2015-02-01 06:17:11 +01:00
Adolfo Gómez García
17a087ed4a * Removed binaries for NX from git (we have source code..)
* Fixed downloadable list for administrators with actors
2015-02-01 05:53:54 +01:00
Adolfo Gómez García
762138ca57 Fixed so new publications are not allowed while a provider is in
maintenance mode
2015-02-01 05:41:24 +01:00
Adolfo Gómez García
1fb46003fc Several minor actor fixed to manage some workarounds in a better way 2015-02-01 04:07:46 +01:00
Adolfo Gómez García
e1bbbece43 * Added minimun values for Service Pool form numeric fields
* Added support for key "minValue" for numeric ui fields
* Fixed cache updater to take into account those services pools that has
initial or l1 cache to 0
* Fixed old (legacy) uds actor logging
* Fixed index view for pools that do not have assigned services
*
2015-01-31 11:14:24 +01:00
Adolfo Gómez García
e3e652d4e1 Fixed cache updater, so now we can select "0 elements" for cache,
initials, etc..
2015-01-31 10:18:12 +01:00
Adolfo Gómez García
b8a1fc31f3 Adding colours to failed services 2015-01-28 09:15:08 +01:00
Adolfo Gómez García
d5034c9971 * Restored "missing" services that where in maintenance mode. Now they
got displayed but with some transparency & can't be clicked
* Added "slightly" blue color & tooptip to indicate that a service is
currently with an opened session
2015-01-28 08:16:48 +01:00
Adolfo Gómez García
215c8f8f3e Split views across several source files to easier "maintenance" 2015-01-28 06:30:57 +01:00
Adolfo Gómez García
b2bf4bd0db * Added some more docstrings
* Fixed how logs of user login/logout on services are done
2015-01-27 07:03:38 +01:00
Adolfo Gómez García
1d2c4c8282 Fixed requests version detection
Fixed warnings so they are no more logged to console (for urllib3
mainly)
2015-01-27 07:02:24 +01:00
Adolfo Gómez García
70fc09b21a * Added service known IP to services list
* Optimized service retrieval for dashboard
* Added group regex expressions
* Added pool in maintenance mode for pools list
* Upgraded visibility of "warned" pools (couoling them)
* Improved base service list on new pool (added provider in front of
service)
2015-01-26 09:30:25 +01:00
Adolfo Gómez García
9a529b8f5b Added experimental support for pattern in group names (using pat:... as group name) 2015-01-23 08:54:52 +01:00
Adolfo Gómez García
4a2401b622 Added fld4 to stats events. Added validators to providers 2015-01-22 11:47:01 +01:00
Adolfo Gómez García
3feb502fec Started to use events stats system 2015-01-22 03:32:26 +01:00
Adolfo Gómez García
e75c86ad58 Stabilizing for 1.7
* Fixed several IDE "false errors"
* Added several needed comments
* Added logging to base os manager to login/logout process
* Fixed Linux & Windows managers to allow use of new base os manager
feature
* Fixed coffe script error that do not allows to create e new service
2015-01-21 13:30:37 +01:00
Adolfo Gómez García
9a95d39156 * added admin dashboard link for administrator to "old" interface 2015-01-21 10:14:38 +01:00
Adolfo Gómez García
cc48b50dcb Minor code fixes & updates 2015-01-21 08:36:35 +01:00
Adolfo Gómez García
32b1ac71a9 Log fixing 2015-01-21 08:20:53 +01:00
Adolfo Gómez García
bd98349dc4 Added missing resolutions to select in preferences screen 2015-01-15 18:14:07 +01:00
Adolfo Gómez García
cf6602033d Fixed LDAP authenticators so they scape "inputs" from unknown source
(basically the username).
2015-01-15 18:11:37 +01:00
Adolfo Gómez García
2959a878af Fixed navbar to not allow "root" user to access preferences (root user
will never own services)
2015-01-15 09:24:58 +01:00
Adolfo Gómez García
ea087fce53 fixed upload directory permissions on sample settings 2015-01-14 19:55:38 +01:00
Adolfo Gómez García
9335c73003 Added config initialization on config command 2015-01-14 19:35:59 +01:00
Adolfo Gómez García
e11867a55e Added config initialization on config command 2015-01-14 19:21:01 +01:00
Adolfo Gómez García
c72a8d3950 * Added new resolutions to RDP
* Added logging of generated password to service log
* Small "pepe" corrections
2015-01-13 14:50:49 +01:00
Adolfo Gómez García
ddd8df3b26 small fix 2015-01-13 05:48:59 +01:00
Adolfo Gómez García
c491dc78ab Added TODO.txt to not forget what is next :) & updated (again) translations 2015-01-13 05:37:53 +01:00
Adolfo Gómez García
fd4fe245c6 Added CoRD custom build & update download link for Mac 2015-01-13 05:06:22 +01:00
Adolfo Gómez García
cbd8a17cc4 Updated translations 2015-01-13 04:58:53 +01:00
Adolfo Gómez García
9356fc3559 Advanced on events stats 2014-12-21 12:56:21 +01:00
Adolfo Gómez García
243e627827 Added "Maintenance mode" to providers (by Seville University request..
thanks for the advice ;-) ), that marks a provider as "on Maintenance
Mode". In this mode, every operation depending on this provider will be
"paused", and deployed services will be "hidden" from users...
2014-12-20 16:47:19 +01:00
Adolfo Gómez García
bb408a31a2 Fixed OS Managers & New Services presentation 2014-12-17 21:45:48 +01:00
Adolfo Gómez García
3035360ce7 * Changed "tiled" list of services for a... better one??
* Added a switch to the service pool so we can disable the show of
alternative transports (so only main is available...)
2014-12-12 00:43:36 +01:00
Adolfo Gómez García
cdaf5a17fa * Upgraded Java Detection js
* Added generic icon of UDS
2014-12-11 16:21:20 +01:00
Adolfo Gómez García
f97e02e867 Changed "key" generation on actor to use a random 48 chars strings
instead of an uuid
2014-12-10 12:08:13 +01:00
Adolfo Gómez García
101aa6fc39 Fixed tipo "eror" :) 2014-12-09 17:30:18 +01:00
Adolfo Gómez García
8e7a6af3ad Removed old actors 2014-12-09 17:17:36 +01:00
1211 changed files with 92804 additions and 151244 deletions

4
.gitignore vendored
View File

@@ -1,10 +1,12 @@
*.pyc
*.pyo
*.orig
*~
*.swp
.DS_Store
*_enterprise.*
.settings/
.ipynb_checkpoints
# Debian buildings
*.debhelper*

6
TODO.txt Normal file
View File

@@ -0,0 +1,6 @@
* Add "Scheduler" to manage pools, and posibbly other operations (Expect to release an version 1.7.1??)
* Improve stats
* Add App Virtualization support
* Add "Meta Pools"
* Manage to connect several UDS in "tree", so one UDS can be provider o another UDS

1
VERSION Normal file
View File

@@ -0,0 +1 @@
2.0.0

View File

@@ -1 +1 @@
/udsactor-opensuse-1.7.0.spec
/udsactor-*[1-9].*.spec

View File

@@ -1,16 +1,20 @@
#!/bin/bash
VERSION=1.7.0
VERSION=`cat ../../VERSION`
RELEASE=1
top=`pwd`
# Debian based
dpkg-buildpackage -b
cat udsactor-template.spec |
sed -e s/"version 1.7.0"/"version ${VERSION}"/g |
sed -e s/"version 0.0.0"/"version ${VERSION}"/g |
sed -e s/"release 1"/"release ${RELEASE}"/g > udsactor-$VERSION.spec
# Now fix dependencies for opensuse
cat udsactor-template.spec |
sed -e s/"version 0.0.0"/"version ${VERSION}"/g |
sed -e s/"name udsactor"/"name udsactor-opensuse"/g |
sed -e s/"PyQt4"/"python-qt4"/g |
sed -e s/"libXScrnSaver"/"libXss1"/g > udsactor-opensuse-$VERSION.spec
@@ -27,4 +31,4 @@ for pkg in udsactor-$VERSION.spec udsactor-opensuse-$VERSION.spec; do
rpmbuild -v -bb --clean --buildroot=$top/rpm/BUILD/$pkg-root --target noarch $pkg 2>&1
done
#rm udsactor-$VERSION
#rm udsactor-$VERSION

View File

@@ -1,4 +1,28 @@
udsactor (1.7.0) UNRELEASED; urgency=medium
udsactor (2.0.0) stable; urgency=medium
* Upgrade for 2.0.0
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 01 Mar 2016 03:39:21 +0100
udsactor (1.9.1) stable; urgency=medium
* Upgrade for 1.9.1
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 01 Mar 2016 03:19:21 +0100
udsactor (1.9.0) stable; urgency=medium
* Upgrade for 1.9.0 (fixed package version)
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 05 May 2015 07:10:27 +0200
udsactor (1.7.5) stable; urgency=medium
* Upgrade for 1.7.5
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 23 Apr 2015 06:08:53 +0200
udsactor (1.7.0) stable; urgency=medium
* Initial release.

View File

@@ -1,3 +1,3 @@
udsactor_1.7.0_all.deb admin optional
udsactor-xrdp_1.7.0_all.deb x11 optional
udsactor-nx_1.7.0_all.deb x11 optional
udsactor-nx_2.0.0_all.deb x11 optional
udsactor-xrdp_2.0.0_all.deb x11 optional
udsactor_2.0.0_all.deb admin optional

View File

@@ -1,69 +0,0 @@
%define _topdir %(echo $PWD)/rpm
%define name udsactor
%define version 1.7.0
%define release 1
%define buildroot %{_topdir}/%{name}-%{version}-%{release}-root
BuildRoot: %{buildroot}
Name: %{name}
Version: %{version}
Release: %{release}
Summary: Actor for Universal Desktop Services (UDS) Broker
License: BSD3
Group: Admin
Requires: python-six python-requests PyQt4 libXScrnSaver
Vendor: Virtual Cable S.L.U.
URL: http://www.udsenterprise.com
Provides: udsactor
%define _rpmdir ../
%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
%install
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh install-udsactor
cd $curdir
%clean
rm -rf $RPM_BUILD_ROOT
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh clean
cd $curdir
%post
systemctl enable udsactor.service > /dev/null 2>&1
%preun
systemctl disable udsactor.service > /dev/null 2>&1
systemctl stop udsactor.service > /dev/null 2>&1
%postun
# $1 == 0 on uninstall, == 1 on upgrade for preun and postun (just a reminder for me... :) )
if [ $1 -eq 0 ]; then
rm -rf /etc/udsactor
rm /var/log/udsactor.log
fi
# And, posibly, the .pyc leaved behind on /usr/share/UDSActor
rm -rf /usr/share/UDSActor > /dev/null 2>&1
%description
This package provides the required components to allow this machine to work on an environment managed by UDS Broker.
%files
%defattr(-,root,root)
/etc/udsactor
/etc/xdg/autostart/UDSActorTool.desktop
/etc/init.d/udsactor
/usr/bin/UDSActorTool-startup
/usr/bin/udsactor
/usr/bin/UDSActorTool
/usr/sbin/UDSActorConfig
/usr/sbin/UDSActorConfig-pkexec
/usr/share/UDSActor/*
/usr/share/applications/UDS_Actor_Configuration.desktop
/usr/share/autostart/UDSActorTool.desktop
/usr/share/polkit-1/actions/org.openuds.pkexec.UDSActorConfig.policy

View File

@@ -1,6 +1,6 @@
%define _topdir %(echo $PWD)/rpm
%define name udsactor
%define version 1.7.0
%define version 0.0.0
%define release 1
%define buildroot %{_topdir}/%{name}-%{version}-%{release}-root

View File

@@ -1,61 +0,0 @@
%define _topdir %(echo $PWD)/rpm
%define name udsactor-xrdp
%define version 1.7.0
%define release 1
%define buildroot %{_topdir}/%{name}-%{version}-%{release}-root
BuildRoot: %{buildroot}
Name: %{name}
Version: %{version}
Release: %{release}
Summary: Glue between UDS Actor and XRDP
License: BSD3
Group: Admin
Requires: xrdp udsactor pam
Vendor: Virtual Cable S.L.U.
URL: http://www.udsenterprise.com
Provides: udsactor-xrdp
%define _rpmdir ../
%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
%install
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh install-udsactor-xrdp
cd $curdir
%clean
rm -rf $RPM_BUILD_ROOT
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh clean
cd $curdir
%post
SESMANFILE=/etc/pam.d/xrdp-sesman
TMPFILE=$(mktemp /tmp/sesman.XXXXX)
grep -v uds $SESMANFILE > $TMPFILE
echo >> $TMPFILE
echo "# Added by udsactor-xrdp" >> $TMPFILE
echo "session optional pam_exec.so /usr/bin/uds-sesman" >> $TMPFILE
cp $TMPFILE $SESMANFILE
rm $TMPFILE > /dev/null 2>&1
%preun
%postun
SESMANFILE=/etc/pam.d/xrdp-sesman
TMPFILE=$(mktemp /tmp/sesman.XXXXX)
grep -v uds $SESMANFILE > $TMPFILE
cp $TMPFILE $SESMANFILE
rm $TMPFILE > /dev/null 2>&1
%description
This package provides the required components to allow this machine to work on an environment managed by UDS Broker.
%files
%defattr(-,root,root)
/usr/bin/*

View File

@@ -33,10 +33,11 @@
from __future__ import unicode_literals
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
from PyQt4 import QtGui # @UnresolvedImport
from PyQt4 import QtCore # @UnresolvedImport
import pickle
import time
import datetime
import signal
from udsactor import ipc
from udsactor import utils
@@ -46,6 +47,7 @@ from udsactor import operations
from about_dialog_ui import Ui_UDSAboutDialog
from message_dialog_ui import Ui_UDSMessageDialog
from udsactor.scriptThread import ScriptExecutorThread
from udsactor import VERSION
trayIcon = None
@@ -61,6 +63,7 @@ class UDSAboutDialog(QtGui.QDialog):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_UDSAboutDialog()
self.ui.setupUi(self)
self.ui.VersionLabel.setText("Version " + VERSION)
def closeDialog(self):
self.hide()
@@ -163,8 +166,9 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
def __init__(self, app_, parent=None):
self.app = app_
style = app.style()
icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_DesktopIcon))
# style = app.style()
# icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_ComputerIcon))
icon = QtGui.QIcon(':/images/img/uds.png')
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
self.menu = QtGui.QMenu(parent)
@@ -172,13 +176,16 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
exitAction.triggered.connect(self.about)
self.setContextMenu(self.menu)
self.ipc = MessagesProcessor()
self.sessionStart = datetime.datetime.now()
self.maxIdleTime = None
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.checkIdle)
self.showIdleWarn = True
self.maxSessionTime = None
self.showMaxSessionWarn = True
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.checkTimers)
if self.ipc.isAlive() is False:
raise Exception('no connection to service, exiting')
raise Exception('No connection to service, exiting.')
self.stopped = False
@@ -197,36 +204,60 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
self.counter = 0
self.timer.start(5000) # Launch idle checking every 5 seconds
self.graceTimerShots = 6 # Start counting for idle after 30 seconds after login, got on windows some "instant" logout because of idle timer not being reset??
self.ipc.start()
# If this is running, it's because he have logged in
self.ipc.sendLogin(operations.getCurrentUser())
def checkTimers(self):
self.checkIdle()
self.checkMaxSession()
def checkMaxSession(self):
if self.maxSessionTime is None or self.maxSessionTime == 0:
logger.debug('Returning because maxSessionTime is cero')
return
remainingTime = self.maxSessionTime - (datetime.datetime.now() - self.sessionStart).total_seconds()
logger.debug('Remaining time: {}'.format(remainingTime))
if self.showMaxSessionWarn is True and remainingTime < 300: # With five minutes, show a warning message
self.showMaxSessionWarn = False
self.msgDlg.displayMessage('Your session will expire in less that 5 minutes. Please, save your work and disconnect.')
return
if remainingTime <= 0:
logger.debug('Remaining time is less than cero, exiting')
self.quit()
def checkIdle(self):
if self.maxIdleTime is None: # No idle checl
if self.maxIdleTime is None: # No idle check
return
if self.graceTimerShots > 0:
self.graceTimerShots -= 1
return
idleTime = operations.getIdleDuration()
remainingTime = self.maxIdleTime - idleTime
if remainingTime > 300: # Reset show Warning dialog if we have more than 5 minutes left
if remainingTime > 120: # Reset show Warning dialog if we have more than 5 minutes left
self.showIdleWarn = True
logger.debug('User has been idle for: {}'.format(idleTime))
if self.showIdleWarn is True and remainingTime < 120: # With two minutes, show a warning message
self.showIdleWarn = False
self.msgDlg.displayMessage("You have been idle for too long. The session will end if you don't resume operations")
if remainingTime <= 0:
logger.info('User has been idle for too long, notifying Broker that service can be reclaimed')
self.quit()
if self.showIdleWarn is True and remainingTime < 120: # With two minutes, show a warning message
self.showIdleWarn = False
self.msgDlg.displayMessage("You have been idle for too long. The session will end if you don't resume operations")
logger.debug('Here')
def displayMessage(self, message):
logger.debug('Displaying message')
self.msgDlg.displayMessage("You have been idle for too long. The session will end if you don't resume operations")
QtGui.QMessageBox.information(None, "UDS Actor", message)
self.msgDlg.displayMessage(message)
def executeScript(self, script):
logger.debug('Executing script')
@@ -235,13 +266,13 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
def logoff(self):
self.counter += 1
print("Loggof --", self.counter)
# print("Logofff --", self.counter)
def information(self, info):
'''
Invoked when received information from service
'''
logger.debug('Got information message: {}'.format(info))
logger.info('Got information message: {}'.format(info))
if 'idle' in info:
idle = int(info['idle'])
operations.initIdleDuration(idle)
@@ -250,23 +281,33 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
else:
self.maxIdleTime = None
if 'maxSession' in info:
maxSession = int(info['maxSession'])
# operations.initMaxSession(maxSession)
self.maxSessionTime = maxSession
logger.debug('Set maxsession to {}'.format(maxSession))
def about(self):
self.aboutDlg.exec_()
def quit(self):
logger.debug('Quit invoked')
if self.stopped is True:
return
self.stopped = True
if self.stopped is False:
self.stopped = True
try:
# If we close Client, send Logoff to Broker
self.ipc.sendLogout(operations.getCurrentUser())
self.timer.stop()
self.ipc.stop()
except Exception:
# May we have lost connection with server, simply exit in that case
pass
try:
# If we close Client, send Logoff to Broker
self.ipc.sendLogout(operations.getCurrentUser())
self.timer.stop()
self.ipc.stop()
operations.loggoff()
operations.loggoff() # Invoke log off
except Exception:
# May we have lost connection with server, simply exit in that case
pass
self.app.quit()
if __name__ == '__main__':
@@ -282,9 +323,12 @@ if __name__ == '__main__':
try:
trayIcon = UDSSystemTray(app)
except Exception:
logger.error('UDS Service is not running. Tool stopped')
logger.error('UDS Service is not running, or it can\'t contact with UDS Server. User Tools stopped')
sys.exit(1)
# Sets a default idle duration, but will not be used unless idle is notified from server
operations.initIdleDuration(3600 * 10)
trayIcon.show()
# Catch kill and logout user :)

View File

@@ -2,225 +2,177 @@
# Resource object code
#
# Created: Fri Nov 21 12:40:02 2014
# Created: Mon Apr 27 22:05:02 2015
# by: The Resource Compiler for PyQt (Qt v4.8.6)
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore
qt_resource_data = "\
\x00\x00\x0c\xe0\
qt_resource_data = b"\
\x00\x00\x09\xd1\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x30\x00\x00\x00\x30\x08\x06\x00\x00\x00\x57\x02\xf9\x87\
\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\
\x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x26\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea\x60\
\x00\x00\x3a\x98\x00\x00\x17\x70\x9c\xba\x51\x3c\x00\x00\x00\x06\
\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\
\x00\x07\x74\x49\x4d\x45\x07\xde\x0b\x11\x04\x03\x27\xf2\xbb\x98\
\x60\x00\x00\x0b\xe4\x49\x44\x41\x54\x68\xde\xe5\x9a\x7b\x6c\x1c\
\xc7\x79\xc0\x7f\x33\xbb\x7b\xef\x3b\x8a\xa4\xf8\x96\x48\x49\xa4\
\x25\x59\x91\x28\xc9\x72\xf4\x96\x6d\xc5\x6d\x9a\xca\x71\x22\x03\
\xb2\xe3\x5a\x71\xd2\x04\xa8\xdd\xb8\x06\x52\xd8\x4e\xd5\x36\x29\
\x60\xd4\x70\x5c\x38\x69\x8a\x06\x4d\xd0\xba\x45\x03\xb8\xa8\x0b\
\x34\x45\x0d\xd7\xad\x9d\x1a\x4d\xdc\xd4\x8f\xc0\x55\xf4\xb2\xf5\
\x20\x65\x53\x2f\x4a\x22\x45\x4a\x24\xef\x8e\xf7\xda\xdd\x99\xe9\
\x1f\x47\x52\x77\xe4\x1d\x7d\x92\x6c\x14\x45\x3f\xe0\x70\xb7\x3b\
\xdf\x7e\xf3\xfd\xbe\x99\x6f\xf6\x9b\xdd\x13\xc6\x18\xc3\xff\x61\
\x91\xff\xdb\x0e\xfc\xbf\x07\xb0\xaf\x45\xd9\x18\x83\x31\x3e\xda\
\xb8\x18\xe3\xa1\x8d\x87\xd6\x2e\x06\x1f\x8c\xc2\xa0\xd1\x5a\xe1\
\xfb\x06\xcf\xd3\xf8\xbe\x41\x69\x83\xd6\x60\x4c\xf1\x03\x02\x21\
\x04\x96\xb4\xb1\x2c\x1b\xc7\x0e\x60\xdb\x01\x02\x4e\x88\x60\x20\
\x8c\x6d\x3b\x1f\x1d\x80\x31\x06\xa5\x33\x14\xdc\x21\xf2\xee\x30\
\xae\x37\x4a\xde\x1b\xa6\xe0\x0d\xe1\xf9\x13\x78\x6a\x02\xcf\x9f\
\x40\xeb\x49\x94\xce\x71\x69\x24\xc3\xc5\xa1\x3c\xa3\x97\x0b\x8c\
\x8d\x17\x48\x4f\x7a\x14\x5c\x83\xef\x1a\x3c\x05\x46\x0b\x40\x60\
\x59\x01\xc2\xa1\x18\xe1\x70\x82\x44\xb4\x81\x44\xbc\x81\xfa\xba\
\x16\xda\x5b\x96\xb1\xa8\xed\x26\x3a\x5a\x7b\x68\x6f\x5e\x8a\xe3\
\x04\x3f\x14\x40\x54\x4a\x62\x5f\x65\x98\xcc\xf5\x31\x96\x7a\x93\
\x54\xf6\x28\x79\x77\x10\xd7\xbb\x82\xaf\x92\x28\x95\x45\xe3\x21\
\x00\x03\x08\xc0\x75\x0d\xef\x1e\xf5\x38\xf4\x6e\x81\x74\xd2\xc5\
\x53\x36\x9e\x49\xa0\x09\x82\xb0\x40\x48\x04\x80\x50\x48\xe3\x23\
\x85\x42\x90\x47\xea\x2c\xc2\xa8\x62\xb0\x84\xc4\xb6\xc3\xc4\x63\
\x0d\x34\x37\x2e\x62\xf5\xf2\x2d\xec\xdc\xfa\x05\xba\xbb\xd6\xcc\
\x0b\x52\x06\xe0\x7a\x57\x18\x9d\x78\x8d\xf3\x97\xff\x9e\x4c\xee\
\x7d\x94\xce\x62\x8c\x87\xa1\xa8\x32\xed\x74\xe9\x6f\x63\x0c\x07\
\x0e\xba\xfc\xfc\xcd\x3c\x79\xd5\xc8\x84\xbd\x93\x94\xbd\x8d\x9c\
\x5c\x84\x21\x80\xc1\x9a\xd2\x06\x21\xc0\x8e\x26\xb0\x63\x31\x2c\
\x9d\xc1\xf6\x47\x08\xba\xfd\x04\x0b\x27\x08\x15\x8e\x13\xf0\x06\
\x90\x3a\x8d\x30\x3e\x96\x65\x13\x8f\x35\xb2\x75\xc3\x5d\xec\xdd\
\xbd\x8f\x96\xa6\xae\xf9\x01\x5c\xef\x32\xfd\x83\x4f\x32\x3c\xf6\
\x2f\x68\x53\x98\xea\xf2\xaa\xc3\x65\x17\x95\xb4\x69\x65\xf8\xd9\
\x7f\xe6\xf8\xc5\x91\x66\xce\x86\xbf\x45\x5a\xae\x9b\xd2\xf1\xa7\
\xbe\xa7\xe0\x9d\x20\x76\xbc\x09\x19\x49\x4c\x59\x90\x18\x21\x01\
\x89\x30\x1a\xa9\xd3\x04\xdd\x3e\xa2\xd9\xb7\x88\x65\x5e\x27\x9c\
\xdf\x8f\xd4\x93\x20\x24\x9b\xd7\xef\xe2\x91\x2f\x7d\x87\xf6\x96\
\x65\x73\x7c\x99\x59\x85\x86\xc6\x5e\x62\x78\xec\x45\xb4\x29\x5c\
\xcd\x81\x1a\x92\xc8\xb2\xa0\xad\xcd\x22\x19\xf9\x1c\x69\xb9\x0e\
\x81\x87\xc4\x43\x60\x8a\xce\x1b\x83\xb0\x03\x38\xf5\xed\xc8\x70\
\x7c\xea\xbc\x46\xe0\x23\x8d\x8b\x34\x79\x04\x1e\x5a\x86\xc9\x86\
\x36\x70\xb9\xe1\x51\xce\xb7\xfd\x90\xe1\xe6\x67\xf0\xec\x0e\x30\
\x9a\xfd\x47\x5e\xe3\x85\x97\x9e\x65\x3c\x39\x52\x19\xc0\xf7\x5d\
\x06\x87\xdf\x41\xa0\x6a\x72\xde\x94\xb4\x1b\x60\xe5\x4d\x36\x9b\
\xd7\xe6\xc0\xe8\xb9\x5a\xb6\x83\x5d\xdf\x8e\x0c\x84\x11\xa2\xba\
\x45\x81\x46\xe2\x03\x1a\xdf\x6e\x66\x22\xf1\x00\xc3\xcd\xcf\xe0\
\xdb\xed\x28\xe5\xf1\xce\xa1\x57\x39\xda\xff\x36\xb3\x53\x56\x02\
\x28\xed\x31\x30\x38\x8e\xeb\x6b\xaa\xf6\x51\x55\x04\x4e\x40\xb0\
\x67\xcb\x4b\xdc\xbe\xfc\xa7\x68\x23\xaf\xc2\x4b\x0b\x27\xd1\x8c\
\x0c\x46\xe6\x09\x89\x98\x75\x24\x8a\xf9\x25\x20\x15\xdf\xc5\xd8\
\x82\x2f\x63\x84\xcd\x78\x72\x84\xfd\x47\x5e\x23\x93\x4b\xcd\x05\
\xb0\xed\x20\x9e\xdb\x40\xdf\x29\x77\x2a\x1a\x57\x4d\x8b\x79\xba\
\x9d\x6e\xd3\x46\x62\x09\x8f\x3d\xb7\xbe\xc0\x8a\x96\x7e\xb4\xb6\
\x30\x46\x20\x9c\x10\x22\x14\x9d\xc9\x83\xea\xe3\x39\x77\x7c\x8b\
\xd7\xd8\x4c\x46\x7f\x05\x2d\xe3\x80\xe1\xf4\xe0\x31\xb2\xd9\x0a\
\x00\x96\xb4\x59\xde\xb5\x95\xfe\x01\xc5\xa9\x41\xaf\xcc\xa8\x99\
\xa7\xdb\xd2\x36\x65\x2c\x5a\x12\x17\x78\x70\xf3\xdf\xb0\xa8\x7e\
\x10\x83\x40\x3a\x21\x84\xbc\xa6\x7b\xe5\x9c\x5e\x7c\xab\x0d\x25\
\xe3\x60\x0c\x63\x13\x97\x70\xbd\xfc\x5c\x00\x80\x4d\x6b\xee\x65\
\x49\xfb\x56\x8e\x9c\xc8\x71\xe9\x8a\x2a\x5b\x32\x67\x0f\xb4\x98\
\xf5\x29\x6d\x59\xd5\xf1\x2e\x5f\xdd\xfe\x97\xc4\x82\x19\x0c\xf6\
\x9c\xf6\xea\x96\x2a\xeb\x18\x61\x81\x28\x06\xc1\x57\x2e\xba\x2c\
\xcf\x4a\x00\x82\x81\x08\xbb\x77\xfe\x21\xd1\xf0\x32\x0e\x1e\xcd\
\x92\xce\x28\x64\x89\xdd\x52\x98\xd2\x04\x2e\x3f\x2f\x50\xda\xa2\
\x77\xf1\x01\xf6\x6c\xf8\x07\x1c\x91\x46\x95\xf5\x37\x7d\xc5\x7c\
\x8b\x74\xb9\x08\x53\x40\xe8\x02\x08\x08\xd8\x41\xa4\x28\x2f\xdf\
\xca\x8e\x7a\x3a\x37\x73\xe7\xc6\x87\x48\x4d\x06\x39\x74\x3c\x87\
\xd2\xa6\x6a\x1e\x54\x9f\x5a\x02\x63\xe0\xd3\x9f\xf8\x57\x3e\xb3\
\xe2\x9f\x91\xc6\xc7\x98\xeb\xad\x19\x25\xb6\x1a\x47\x9a\x2c\x20\
\x48\xc4\x1b\x71\xec\xe0\x2c\x8d\x12\x71\xec\x20\xdb\xd7\x3f\xc8\
\x96\xde\xfb\x38\x3f\xac\x39\x72\x22\x8f\xaf\xae\xba\x5a\x09\xa4\
\xf2\x54\x92\xd8\x96\xcb\x3d\x6b\x7f\xc4\xa7\x96\xfc\x23\x52\x28\
\x8c\x29\xd5\x98\x3d\x9e\x25\xc7\x57\xab\xbe\x62\x1a\xfb\xe7\x91\
\xda\xc5\x20\xe8\x68\xed\x21\x1c\x8a\x55\x07\x00\x88\x47\x1b\xb9\
\xfb\xf6\x7d\x74\xb6\xae\xa5\xff\x74\x9e\x81\x73\xee\x4c\x29\x31\
\xdb\xf1\xf9\xc4\x20\x09\xdb\x93\xec\x59\xf5\xa7\x6c\x6a\x7b\x05\
\x65\xec\x59\x10\x55\x64\x26\x1a\x02\x81\xc1\xf1\x2e\x02\x2e\x52\
\x48\xda\x5b\x96\x11\x0a\x46\xe6\x07\x00\x68\x69\xec\x66\xf7\xce\
\x6f\x62\xcb\x04\x47\x4f\xe6\x18\x9b\x28\xe6\x83\xa9\xd0\x57\xa5\
\x73\xd3\xa2\xb1\x88\x05\xc6\xb8\x7f\xd5\xd3\xac\x5e\xf8\xd6\x14\
\x44\x6d\x04\x06\x03\xc6\xc7\xf1\xcf\x83\xf1\x08\x87\x62\xb4\xb7\
\x74\xe3\x38\x81\x0f\x07\x00\x58\xdd\x73\x27\xbb\x76\x3c\x86\xe7\
\x85\x78\xeb\x40\x86\x74\x46\x97\x25\xf5\xf4\x10\x97\x7e\x4f\xff\
\x2e\x3d\xd6\x46\x52\x1f\x1a\xe6\x6b\xb7\x7c\x9d\x3b\x16\xff\x98\
\x68\xc0\x23\x12\x90\x04\x2c\x31\xc7\x5e\xb9\x35\x89\x65\x72\x04\
\xbc\xb3\x80\x21\x1e\xab\x67\x61\x7d\x1b\x62\x56\x12\x57\x5d\xa4\
\x03\x4e\x84\xed\xeb\xf7\x32\x78\x69\x3f\xff\xfd\xde\x2b\x1c\x3c\
\x96\x65\x63\x6f\x84\x50\xf0\xaa\x81\x4a\x23\x50\x29\xa2\x1a\x58\
\x10\x1c\x66\xef\xea\x27\xd9\x3e\x79\x12\x3b\xfc\x04\x59\x3f\xca\
\x68\xda\xe7\x42\xd2\x30\x32\xa9\xb9\x90\x34\x8c\xe7\x4a\x43\x22\
\x90\x3a\x8d\xed\x5f\x42\x00\x89\x68\x3d\xf5\x75\xcd\x73\xac\x57\
\x05\xc8\xbb\xa7\x30\xe2\xbf\xd8\xd8\x1b\xe6\xe4\xd9\x10\xe7\x2e\
\x66\xa9\x8b\x5b\xf4\xae\x08\x81\x10\x73\x72\x60\x76\x99\x3d\x17\
\xc2\x22\x6c\xa7\x58\xd3\xf8\x3c\x8b\x9a\xa0\xb3\xf5\x77\x51\xa6\
\x81\x64\xde\x30\x9e\x35\x5c\x48\x1a\xde\x3e\xe3\xf3\xc6\x29\xc5\
\xc9\x51\x8d\xa7\xc1\x52\x63\xd8\xfe\x15\x10\x82\xc6\xfa\x76\x16\
\x36\x74\xcc\x0f\xe0\xf9\x59\xb2\x85\x3e\x32\xf9\x37\x48\xe7\xf6\
\x63\x4c\x9a\x05\x75\x9a\xad\x1b\x7a\xf9\xb7\xd7\x8f\x70\xfc\xfd\
\x3c\xb1\xa8\xa4\xa7\x33\x58\x5c\x2c\xaa\xc6\xbc\x72\x9b\x41\xe2\
\xa9\x1c\xe7\x46\xfe\x0e\x08\xb0\xa4\xed\x51\xda\x12\xf5\xb4\x25\
\xe0\xe6\x16\xc3\x8e\x6e\x8b\x87\xb7\x18\xfe\xbd\xdf\xe7\xfb\x6f\
\xf8\xa4\x86\x2e\x61\xe9\x2b\xd8\x96\xcd\xd2\xc5\xab\x88\x45\x17\
\xcc\x0f\x30\x30\xf8\x36\xbf\x38\xfa\x07\x2c\x5f\x9a\xa0\x3e\x11\
\x26\x99\x6b\xe2\x83\xd1\xf5\x1c\x1e\xdd\x8e\x8e\xbf\x84\x97\xfe\
\x33\x0e\xbc\x97\xa5\x2e\x66\xd1\xd4\x50\x4c\xc8\xda\xa6\x51\x29\
\x84\xc0\xd7\x39\xce\x8e\xfc\x08\x03\x74\x77\xfc\x1e\x96\x0c\x22\
\x84\x20\x64\x43\x6b\x42\xf0\xe5\x4f\x06\x68\x89\xc1\x93\xcf\x5f\
\x44\xea\x34\x4e\x28\xc4\x8a\xee\x5b\x11\x15\xca\xd9\x32\x00\x5f\
\x49\xde\x3c\xd0\xc7\x89\x01\x87\xce\x9e\xaf\x32\x90\xfa\x0a\x43\
\xc9\xa5\x14\xfc\x30\x76\xa4\x91\x80\x7b\x80\x7c\xfe\x27\x1c\x39\
\x91\x63\xcb\x2d\x51\x22\x21\x59\xb1\x14\xab\x65\x54\xb4\xce\x70\
\x6e\xe4\x6f\x89\x85\x57\xd0\xd6\x78\xef\x1c\xe7\x36\x76\xc2\xad\
\x2d\x49\xfa\xce\xb8\x84\x82\x0d\x2c\xeb\xea\xad\x68\xb7\x2c\xa5\
\x1b\xea\xda\x49\x44\x5b\x18\x1a\x99\xe0\xcd\xe3\x3d\x9c\x1d\x5f\
\x85\xa7\x22\x48\x21\xd0\xd6\x62\xbc\xf8\x37\x11\xce\x4d\x0c\x8d\
\xba\x1c\x3e\x9e\xc3\xf5\x4c\xcd\xe5\x77\x25\x50\xa5\xb3\x0c\x5c\
\xfc\x2e\x23\x13\xaf\x62\x8c\x2a\x6b\x77\xc8\xb1\x50\xf4\x01\x82\
\x65\x9d\xbd\xb4\x2c\xec\xfc\x70\x80\x70\x30\x41\xeb\xc2\x9e\xe2\
\x4a\xac\x2e\x22\x84\x40\x88\xe2\x5e\x56\x20\xd1\x81\x2d\xb8\x89\
\x6f\x63\x88\x31\x70\xae\x40\xdf\xa9\x3c\x52\xce\x57\xdc\x55\x1f\
\x8d\x69\xc9\x15\xce\x32\x70\xe1\x59\x26\x26\x7f\x39\x6b\xb3\x62\
\x58\x10\x8b\xd2\xbd\x64\x2d\x3b\xb7\xdc\x8b\x25\xad\x1a\x00\x42\
\x09\x16\xb7\xf6\x22\xa4\x44\xf8\xfd\x88\x59\x95\x1f\x80\x0a\xee\
\x42\x45\xbe\x04\x48\x8e\x7f\x90\xe7\xe2\xa8\x37\xb3\xd3\x9a\x7d\
\x0f\xa8\x65\x34\x0c\x30\x99\x3b\xc1\xe9\xa1\xbf\x40\xe9\xec\xcc\
\xf9\x68\x38\xce\xde\x7b\xf6\xf1\x8d\x87\x9f\x63\xfb\xc6\xcf\x57\
\xb5\x55\x06\x10\x74\x22\x74\xb6\xf6\x12\x0a\x26\x90\xaa\x1f\x74\
\xb2\x42\xf8\x02\x78\xd1\x47\xd1\xc1\x9d\x78\xae\xe6\xc0\x7b\x39\
\x92\x69\x55\x75\xbb\x58\xcb\x88\x18\xe0\x4a\xea\x75\x2e\x8d\xbd\
\x3c\x33\x0a\x52\x5a\x34\x35\x74\xd0\xb3\x64\x2d\xb1\x48\x5d\x6d\
\x00\x42\x48\x96\x76\xdc\x42\x5b\xd3\xcd\x08\x35\x84\xf4\x0e\x55\
\x74\xc9\xd8\xcb\xf1\x12\x4f\x61\x02\x6b\x19\x1b\xf7\x38\x74\x3c\
\x47\xbe\x30\x7f\xd1\x57\xa9\xad\xac\xec\x30\x1e\x67\x86\x7f\x48\
\x36\x7f\xaa\x06\xe4\x2a\x00\x00\x2d\x0d\x3d\xac\x58\xb2\x03\x5b\
\xe4\xb0\x0a\xaf\x82\xc9\x57\xbc\x50\x3b\xb7\xe2\xc5\x9e\x00\x21\
\x39\x3f\xec\x72\xf2\x74\x61\xa6\x34\xa8\x65\x03\x39\x7b\xdb\x2a\
\x80\xbc\x7b\x9e\xcb\xa9\xd7\x31\x15\xa6\x6e\xcd\x00\xb6\x1d\x60\
\xdb\xba\x07\x88\x86\xe3\x58\x85\xff\x40\xf8\xc7\xaa\x38\x24\x50\
\xa1\xdd\xa8\xc8\x83\x28\xa5\x39\xfa\x7e\x8e\xa1\x51\x0f\x4b\x56\
\xd2\xa4\xea\x9d\xbb\x54\x94\xce\x92\xca\x1c\xc6\x57\x93\xd7\x0f\
\x00\xd0\xd9\xda\xcb\x9d\x9b\xbe\x86\xe5\x1f\xc3\xc9\x3c\x87\x30\
\xa9\xca\x57\x8b\x70\x71\x2a\x85\x77\xe3\x7b\xb0\xff\x48\x96\xe4\
\x64\x79\x3e\x18\xe6\x26\x77\x29\x50\x39\x88\xc1\xf5\x46\xf1\x55\
\x95\xfe\x6a\x05\x00\xd8\xd2\xfb\x05\xda\x9a\x56\x60\xe5\x5f\xc4\
\x72\xdf\xa9\x3a\x2d\xb4\x68\xc3\x8b\xfe\x0e\x38\xdd\x24\x27\x7d\
\x8e\x9d\x2c\xe0\xba\xf3\xdf\x1f\xe6\x6e\x45\xab\x8f\xca\x75\x03\
\x2c\x5c\xd0\xc5\x9d\x1b\x7f\x9b\x70\xc0\xc3\x49\x3f\x85\xd0\x23\
\x95\x15\x85\x40\x05\xb7\xe1\xc5\x1e\xc7\x18\x8b\xd3\xe7\x0b\x9c\
\xb9\xe0\x5e\xc7\xf3\xa5\xa2\x38\x76\x3d\xb6\x15\xab\x59\xbf\x2a\
\x80\x65\x39\x6c\x59\x7b\x3f\x9b\xd7\xdc\x8f\xa3\x0e\x12\x48\x7d\
\x0b\xf4\x95\xb9\xfe\x03\x10\xc4\x8f\xfc\x26\x2a\xfa\x10\xbe\x27\
\x78\xaf\x3f\xc7\xc4\x3c\x4b\x6b\x69\xe4\x4b\xa7\x92\x63\xd5\xd1\
\x98\xb8\x03\xdb\xaa\xa3\x56\xa9\x0a\x20\x84\x20\x16\x69\xe4\xb3\
\xb7\x7d\x83\x25\x1d\xeb\xb1\xf2\xff\x84\x93\x7d\x0e\x4c\xa6\x0a\
\x84\x8d\x17\x7b\x0c\x13\xdc\x46\x26\xa3\x38\x74\x3c\x87\xef\x9b\
\xaa\xcb\x26\x15\xce\x37\x26\x6e\xa7\xb9\xfe\x33\x15\x8b\xb6\x6b\
\x06\x98\x96\xe6\x86\x65\xdc\xb3\xf3\x8f\x58\x10\x8d\x62\x4f\x7e\
\x1f\x3b\xf7\x42\xf5\x88\x5a\x8b\xf1\xe2\x8f\x21\x9c\x2e\x2e\x5c\
\x72\x39\x75\xce\x9d\xb7\xb8\x9b\x79\x44\x0f\x44\x83\xcb\x58\xd6\
\xfe\x38\x8e\xbd\xa0\x66\xe7\x6b\x02\x00\xf8\x44\xf7\x4e\xbe\x78\
\xd7\xf7\x68\x4c\x84\x71\x52\xfb\xb0\xb3\xcf\x03\xf9\x0a\x05\x9a\
\x8d\x0a\xfe\x1a\x5e\xec\xeb\x68\x1d\xa0\xef\x54\x9e\x89\x94\xfa\
\x90\x1b\x9b\xa4\x2e\xb2\x8e\x55\x4b\xbe\x47\x2c\xbc\xfc\x9a\x9c\
\xaf\x19\xc0\xb2\x1c\xd6\xaf\xfc\x2c\x77\xdf\xb6\x8f\x86\x58\x1c\
\x27\xf5\xfb\xd8\x99\xbf\x46\x98\xf2\x52\xa3\xe8\xa8\x83\x1f\xde\
\x8b\x76\x56\x93\x4c\x7b\x7c\x70\xa6\x80\x2e\x79\x4c\x72\x55\xaf\
\x28\x0d\x89\x1d\xac\xec\xfa\x36\xf5\xf1\x4d\x73\xf6\xbb\x1f\x19\
\x00\x40\xc0\x09\xb3\x7d\xfd\x17\xb9\xf7\xd3\x4f\x13\x0b\x7a\x38\
\xe9\xa7\x71\xd2\xcf\x80\xc9\xcd\xd1\x35\xb2\x11\x15\xf9\x0a\xc6\
\x08\x4e\x9f\x2f\xcc\x3c\xd5\x98\x2d\x8d\x89\x3b\x58\xd9\xf9\x14\
\x0b\x62\x1b\xae\xcb\xf9\x6b\x02\x00\x08\x06\xa2\x6c\x5e\x73\x1f\
\xbf\xf1\xeb\xdf\xa5\xa9\x2e\x4e\x20\xfb\x03\x02\xc9\x47\x11\xaa\
\x1f\xf0\xcb\x5e\x45\xa9\xe0\x1d\x08\xab\x89\x5c\x4e\x71\x7a\xd0\
\x2d\x5b\x91\x2c\x19\xa1\xbd\xf1\x01\x6e\xee\x7a\x96\x58\x78\xc5\
\x75\x39\x3e\x2d\xd7\xfc\xe8\xd8\xb6\x03\x6c\x5b\xbf\x97\xa6\x86\
\xa5\xbc\xfc\xf3\x3f\xe1\xe8\x07\xcf\x23\xbd\xc3\x78\x91\x47\x50\
\xe1\xbb\x40\xb6\x4e\x2d\x8f\x06\x84\x85\x90\x70\x79\xdc\x47\xa9\
\xe2\xbe\x22\xe8\xb4\xd3\xd5\xfa\x30\xed\x8d\xf7\x11\x70\x1a\x6e\
\xc8\xf9\xeb\x02\x28\x46\xd0\xe6\xe6\xa5\xb7\x51\x1f\x6f\xe3\xc5\
\x9f\xfd\x31\x87\xfa\x5e\x26\x97\x7a\x02\x55\x78\x0d\x15\xfe\x3c\
\xc6\xea\xc0\xce\xfd\x18\xa1\x47\x99\x79\x65\x22\x20\x12\xea\xa1\
\xbb\xfd\x71\x5a\x1a\x3e\x87\x14\x37\xf2\xd8\xfd\xaa\x88\x1b\xfd\
\xaf\x44\x6a\x72\x84\xc3\xfd\xaf\xf0\x93\xb7\xff\x9c\x8b\xa3\xfd\
\x28\x13\x06\x11\x06\x3d\x06\xc6\x43\x69\x58\xb3\xa2\x8e\x5d\x3b\
\xee\xa6\xab\xf9\x11\x12\xd1\x75\x48\x79\x6d\x2f\xb3\x3f\x56\x80\
\x69\x49\x67\x2e\xf3\xd3\x77\xfe\x8a\x5f\x1e\x7f\x91\x2b\xc9\x41\
\x72\x85\x14\x96\x74\xe8\x6c\x5b\xcc\x9e\x5f\xfd\x2d\x56\x76\x3d\
\x84\x65\x45\x6e\xbc\xa3\x8f\x0b\x00\x40\x29\x8f\xa1\xcb\x27\x39\
\x73\xe1\x20\x23\xe3\xa7\x89\x84\x63\xac\xee\xd9\x44\xfb\xc2\x4f\
\x22\x65\xe0\xc6\x3b\xf8\xb8\x01\xa6\xc5\x18\x83\x52\x2e\x42\x58\
\x58\xd6\x47\x33\xd7\xab\xc9\xff\x00\xbd\xd9\x0a\x65\xdf\x68\x9f\
\x0e\x00\x00\x00\x25\x74\x45\x58\x74\x64\x61\x74\x65\x3a\x63\x72\
\x65\x61\x74\x65\x00\x32\x30\x31\x34\x2d\x31\x31\x2d\x31\x30\x54\
\x30\x35\x3a\x32\x30\x3a\x30\x36\x2b\x30\x31\x3a\x30\x30\x8d\xd4\
\xe4\x1f\x00\x00\x00\x25\x74\x45\x58\x74\x64\x61\x74\x65\x3a\x6d\
\x6f\x64\x69\x66\x79\x00\x32\x30\x31\x34\x2d\x31\x30\x2d\x31\x36\
\x54\x30\x35\x3a\x32\x32\x3a\x31\x38\x2b\x30\x32\x3a\x30\x30\xf2\
\x2f\xb1\x0f\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\
\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\
\xdf\x04\x1b\x12\x2a\x1c\x39\xec\x95\x7d\x00\x00\x09\x5e\x49\x44\
\x41\x54\x68\xde\xd5\x9a\x7b\x8c\x54\xd5\x1d\xc7\x3f\xbf\xfb\x9a\
\x99\x65\x5f\xc8\x63\x41\x51\x40\x40\xac\xd1\x20\xd1\xc5\x68\x40\
\x51\xac\x6b\xb5\xe0\xa3\xb1\x94\xa8\x58\x6b\x2a\xad\xa6\x91\xc6\
\xd8\x54\xa5\x16\x9b\xf1\xd1\x2a\xa9\x68\x6b\x35\xd1\x1a\x27\xb6\
\x6b\xb5\xad\xb5\x69\x8b\x4b\x5c\xaa\x28\x0a\x2c\x2f\x95\x5d\x1e\
\x8b\x40\x61\xdd\x65\x60\xd8\xf7\xee\x9d\xb9\xaf\xd3\x3f\x76\x06\
\x76\x61\x76\x65\x67\xc6\x3f\xfc\x25\x37\x33\x39\xf7\xce\xf9\x9d\
\xef\xf9\x9e\xdf\x73\xae\x28\xa5\xf8\x3a\x8b\x51\xc8\xc9\x6a\xea\
\x2a\x8a\x95\xa2\xa8\xb4\x54\xc2\xe5\x65\x9a\x15\xb6\x24\xec\x78\
\x4a\xab\x6f\x70\xb5\xc6\x3d\x2e\x4d\xcd\x01\x89\xa3\x81\x4a\x24\
\x7c\x3f\xbd\x6f\x3d\x40\x2b\xd0\x59\x5b\x6d\xe7\xb4\x93\x32\x1c\
\x06\x6a\xea\x2a\x42\xc0\x4c\xe0\x7c\xe0\x1c\xe0\x6c\xe0\x2c\x60\
\x14\x10\x12\x41\xb7\x2c\xd1\x5a\x0e\xf9\xda\x8e\x9d\xae\x1c\x68\
\xf2\xb4\x44\x22\x10\xcf\x03\xa5\x14\x41\x00\x4a\x81\x52\x64\x94\
\x06\x80\x97\xbe\x6c\xe0\x20\x50\x0f\x6c\x04\x56\xd7\x56\xdb\xf1\
\x9c\x01\xd4\xd4\x55\x14\xa7\x17\x76\x05\x70\x3d\x70\x25\x30\x66\
\xa8\xc9\xbe\x68\xf6\x59\xfd\x6e\x92\x2f\x9a\x5d\x74\x5d\x10\xcd\
\x02\x31\x40\x04\x85\x96\x7e\x4a\x21\x4a\x01\x01\x22\x0a\x51\x6e\
\x7a\xfd\x00\x72\xc2\x27\xfb\x81\x95\xc0\x9b\x40\x4b\x6d\xb5\x1d\
\x7c\x29\x80\x9a\xba\x8a\x31\xc0\xf7\x81\xf9\xc0\xec\xfe\xb3\x0d\
\xba\x0b\x02\x07\x9b\x7c\x5e\x7f\xa3\x87\xc0\x4b\x62\x5b\x33\xe8\
\xd4\x66\x91\xd4\x26\xe3\x4a\x39\x81\x84\x51\x98\x7d\x53\x29\x1f\
\x4d\x7c\xcc\xe2\x22\x4c\xd3\x47\xf7\x5b\x31\xbc\x38\xa6\xdb\x84\
\xe5\xee\x23\xe4\xec\xc2\x70\x0f\xa1\x44\x50\x62\x65\xd4\xb7\x01\
\x2f\x03\xbf\xae\xad\xb6\x13\x83\x02\xa8\xa9\xab\xb8\x00\xf8\x37\
\x70\xe6\x70\xce\xa1\xae\xc3\xaa\xd5\x49\x36\x6f\x4e\xd2\x3c\xe2\
\x61\xda\x8c\x2b\xf0\x89\x00\x1a\x30\x70\x83\xc4\xb0\x30\x47\x4f\
\x40\x8c\xd0\x80\xbd\x11\xe5\x20\x2a\x89\xa6\x6c\x42\xce\x5e\xca\
\x3b\xfe\x42\x79\x47\x0c\x94\x8f\x12\x33\xf3\xd8\x27\xc0\xdc\xda\
\x6a\xbb\x3d\x33\x90\xe1\x95\x35\x5b\xc7\x45\x80\x2d\xc3\x5d\x3c\
\xf4\x9d\xeb\x33\x4e\x17\x12\xc6\x0d\x24\x8c\xaa\xf4\xe2\x33\x47\
\x5c\x1d\xbb\xc4\x0c\x61\x8d\x9d\x88\x18\x56\x7a\x2c\x38\x76\x29\
\x31\x08\xb4\x62\x3c\x7d\x0c\x3d\x91\x4b\x69\x1a\xff\x7b\x1a\xce\
\x69\xa1\xbd\xfc\x8e\x34\x13\x0a\x60\x06\xf0\x5e\x7f\xdd\xc7\x00\
\xb4\x75\xf8\x4b\x72\xf5\x4a\x41\x00\xe7\x4e\x33\x99\x32\x7d\x2c\
\x0a\x3d\x2b\x42\x2d\x54\x84\x35\x76\x22\xe8\xa7\xa2\x22\x40\x54\
\x0a\x25\x16\x4d\xe3\x5f\xa4\x65\xdc\x4a\xe4\x38\x9b\x33\xe6\x2d\
\x8a\xac\x38\x09\x40\xed\x47\x5d\xd3\x74\x4d\x72\x76\xa1\xba\xa1\
\x71\xc7\xd5\xef\x30\xa6\xf8\xf0\xc9\x36\x62\x58\x18\xa7\x9d\x0e\
\xa2\xf5\xd1\x75\xea\xdc\x22\xca\xa6\xad\x6c\x21\x2d\xe3\x56\xa0\
\x05\xa9\xcc\x8d\x5b\xe7\x2d\x8a\x9c\x3e\x90\x81\x4e\xdf\xde\x52\
\xdf\x8b\xa6\xe5\x1e\x07\x4a\x23\xed\x3c\x32\xff\x21\x4c\xdd\x43\
\xa9\xe3\x9b\xa1\x17\x9f\x86\xe8\x66\xce\xf3\x8a\xf2\xe8\x28\x9e\
\x8f\x63\x4d\xcb\xb0\x50\x0e\x5c\x3a\x00\x80\x69\xc8\xaa\x86\xc6\
\x24\x4d\x2d\x2e\x92\x23\x11\x7e\xa0\x33\x7e\xe4\x01\x1e\xb8\x36\
\x8a\x65\xb8\x28\x04\xd1\x74\xb4\x48\x49\xde\x41\x32\xd0\xc2\xd8\
\x91\x0b\x33\x00\x42\xc0\x94\x01\x00\x62\x51\xa7\x36\x50\x34\xac\
\xdf\xd6\x8b\x9d\x0a\x72\x56\xe4\xf9\x26\x17\x4c\xd8\xcc\xc2\x59\
\xaf\xa1\x49\x00\x22\x88\x61\x92\xbf\x18\xf8\xfa\x69\xfd\x07\xca\
\x07\x00\x48\xcb\x2d\x3d\xbd\x81\xbf\xe6\xa3\xee\xbc\xd5\xdd\x34\
\xf3\x75\x2e\x99\xbc\x1e\x3f\x18\xee\xb9\x1f\xea\x28\xf9\x27\x8d\
\x9d\x08\x60\x87\xa6\xf1\x58\xa2\xd5\xe3\x83\x4d\x3d\x27\xba\xf0\
\x61\x89\xeb\x1b\x2c\xfd\xe6\xe3\xcc\x9a\xb4\x9e\xa4\x5d\x80\xc5\
\xe3\xa2\xfb\x03\x62\x58\xc7\x49\x00\x62\x51\x47\x01\x51\x5d\x97\
\x86\x03\x5f\x38\x34\xec\x49\xe6\xac\x50\x21\x80\x62\xc9\xe5\x2b\
\x38\x6f\xd4\x7a\x02\xa5\xe5\xb9\xfb\x0e\xa6\xd7\x92\x09\x7e\x2e\
\xd0\x9c\x8d\x01\x62\x51\xc7\x05\xaa\x00\x7f\x6b\x83\xcd\x91\x56\
\x2f\x67\xa3\x56\x08\x25\x91\x76\xee\x9e\xb5\x9c\xd1\x91\x96\x34\
\xa8\x5c\x01\xb8\xe8\xde\x31\x17\x6d\x03\x7b\xb2\x02\x48\x83\x68\
\x02\x16\x2a\x05\xff\x5d\xdf\x4d\x47\x97\x9f\xb3\x7b\x55\x4a\xe3\
\xcc\xb2\x06\xee\xbb\xf8\xc7\x94\x85\x5a\xf1\x03\x23\x67\x00\xa6\
\xd7\x9c\x61\x20\x05\xec\x1e\x14\x40\x5a\xfe\x21\xc2\x8b\x8e\xa3\
\x78\x7f\x43\x37\xc9\x94\xca\xc3\x1e\x42\x4c\x2e\xdf\xc6\xcf\x2f\
\xb9\x8d\xb2\x70\x6b\x0e\x4c\x08\x96\xd7\x82\x1c\x0f\x64\x89\xda\
\x6a\xfb\xe8\x90\x00\x62\x51\xc7\x07\x1e\x16\x61\x5f\x47\x57\xc0\
\xe6\xed\xbd\x04\xb9\x7b\x57\x02\xa5\x31\xa1\x74\x07\x3f\xbd\xf8\
\x6e\x46\x47\x5a\x00\x49\xa6\xcf\xf2\x97\xb3\x28\x3a\xa1\x64\x7d\
\xff\xa1\x0f\x07\xf3\x42\x27\x82\x38\x7a\xb4\xdd\xbd\x51\xd7\x84\
\x3d\xfb\x1d\x76\xed\x4b\x62\x18\x92\x17\x88\x73\x47\xad\xe3\xa1\
\x4b\x17\x71\xcb\xb9\x4f\xbd\xdb\x91\x2a\xb9\x0d\xb8\x1f\xf8\x6d\
\x3a\x0b\x3e\x38\x48\xa2\x42\x24\xf5\x29\xea\xb8\x31\xae\x39\xa5\
\x8a\xac\xe1\xc0\xb7\xaf\xd7\x34\x79\xb4\x7e\xcf\xa1\x8b\xfe\xba\
\x6a\x0b\x86\xa1\x33\xf7\x92\x62\x26\x4e\xb0\xf0\x7d\x95\x87\x4b\
\x54\x20\xaa\x47\x17\xff\xee\x79\x17\xb5\xfe\x79\xfa\x13\xfb\xa5\
\x33\x35\x2a\x0c\x8c\x00\xc6\x01\xdf\x03\x7e\x94\x2e\xa8\x08\xb4\
\x22\xa6\xed\xbb\x9c\xb0\xbd\x11\x25\x06\xc0\xa8\xda\x6a\xbb\xf5\
\x24\x00\xbf\x7b\x63\xba\x5c\x36\x73\x52\x79\x24\x6c\xcd\x57\x4a\
\x2d\x07\x26\x83\x22\x50\x8a\xb7\x6b\xf7\xb0\xf3\xf3\xfd\x58\xa6\
\xf0\xad\x2b\x4a\x28\x29\xd6\x0b\x11\x9b\x5c\xe0\xca\xaa\xca\xf8\
\xba\x6c\x37\xc7\x2f\xef\xba\x13\x58\x11\x68\xc5\x23\x2f\xd8\x59\
\x8a\x52\x2e\x20\x87\x6b\xab\xed\x8a\xac\x47\x68\xe7\xde\x43\xa5\
\x1f\x6c\xfa\x7c\x75\x7b\x67\xef\xab\x96\xa9\x4f\xb6\x0c\x9b\xce\
\xe4\x18\x3e\xde\xfb\x5d\x5a\xb4\x18\x18\x67\xe1\xb8\x01\x1f\x6f\
\xeb\xcd\x8b\x81\x7e\x62\x02\xab\x6b\xea\x2a\xae\xca\x76\xb3\x65\
\x79\xc9\x2b\x81\x16\x59\x10\x72\x0e\xf4\x88\xdf\x9d\xf1\x40\xff\
\x19\xb4\x22\xbb\xfd\x61\xb3\x5c\x44\xde\x0b\x59\xc6\x8c\xf3\xa7\
\x4f\x45\x95\x3f\xc6\xb6\x83\x73\xe8\x49\x95\x11\x20\xe8\xee\x27\
\x44\x8e\x5c\x88\xaf\x4c\xa6\x4d\xb2\x98\x53\x59\x8c\xeb\x15\x04\
\xc8\x61\xe0\xda\xaa\xca\xf8\xd6\x6c\x37\xcf\xbf\xef\xb9\xbf\x8d\
\x8b\x2f\xbd\xb9\xaf\xb0\xe1\xe6\xda\x6a\xfb\xad\xac\x0c\x88\x48\
\x0a\x38\x90\x72\x3c\x36\x6e\xef\x64\x6d\xe3\x7c\xba\x53\xe5\x7d\
\x59\x25\x10\x58\x33\x48\x95\xbf\x80\x26\x2e\xbb\xf6\xa6\x68\xd8\
\x93\xcc\x2b\xfd\xee\x27\x63\x81\x97\x6b\xea\x2a\x46\x67\xbd\x79\
\xe4\x91\x86\xf4\xe2\x03\x60\xfd\x50\xb9\x50\xf2\x58\x84\x13\x1f\
\xbd\x2f\xdd\xe8\x1f\x5a\xf1\x8a\x7e\x88\x1f\x59\x88\x61\xc0\xe6\
\xcf\x6c\x0e\x1d\xc9\x3d\x52\x9f\x20\x33\x81\x97\xb2\x07\x31\x7b\
\x6a\xfa\xeb\x26\xa0\x6b\x50\x00\xe9\x5c\x68\x7b\x5f\x9f\x23\x85\
\xf8\x4d\x59\xa6\xd3\x70\x4a\x9f\x41\x69\x63\xf0\x03\xc5\x86\x6d\
\xbd\x85\x3a\x46\x00\x37\xd4\xd4\x55\x3c\x93\x05\xc2\xbd\xc0\x54\
\xe0\xa6\x74\x33\x6c\xf0\xb6\xca\xe2\x65\xd6\x37\x80\x75\x48\x68\
\xa4\x53\xf6\x2a\x5e\xe4\xe6\x6c\x7e\x10\x3d\xb9\x86\x50\xeb\x35\
\xf8\xbe\x70\xf6\x59\x21\xe6\x54\x8e\x28\x54\xd6\x6c\xa7\xed\x61\
\xed\xa9\x3c\x9c\x2d\x99\xdb\x01\x34\xa2\x92\x68\xee\xa6\xc1\xb2\
\x34\xbc\xf0\x55\xb8\x25\x4f\xa1\x6b\x1e\x9f\xff\x2f\xc5\xa7\x3b\
\x93\xe8\x05\xf1\xac\x44\x80\xfb\xd3\x5d\xc0\xe1\x03\x48\xcb\xd3\
\x00\xba\x53\x8b\xa8\xce\x41\x92\x2b\x70\x47\xdc\x83\x1f\xb9\x05\
\xc3\x50\x34\x34\x26\x39\xd8\xec\x16\xca\x1e\x16\x00\x13\x73\x06\
\x10\x8b\x3a\x6f\x82\x34\x6b\xce\x46\x34\xf7\xb3\x21\x42\x6a\x08\
\xb7\xf4\x09\x94\x76\x06\xae\x17\xb0\xb5\xde\xc6\x4e\x16\xcc\x1e\
\xee\xcc\x87\x01\x80\x9f\x28\x11\xac\x8e\x7b\x87\x6c\x2e\x06\xc6\
\x14\x9c\xb2\x17\x11\xf1\x48\xb4\x7b\x6c\xfa\xac\x17\x5d\x2f\x08\
\x0d\xf3\xf3\x05\xb0\x1a\x8c\x0f\xc4\xfd\x04\xb3\xfb\xe9\xc1\x41\
\x28\xf0\xc3\xd7\xe2\x96\x3e\x8f\xa1\x79\xec\x6b\x72\xd8\xd6\xd0\
\x8b\x69\xe4\x0d\x62\x52\x5e\x00\x62\x51\xa7\x1b\x78\x06\x31\x1d\
\xa3\xeb\x49\x34\x77\xf7\xd0\x49\x4d\xd1\x0f\xf0\xc3\x37\xa2\x89\
\xa2\xa1\x31\x45\xcb\x11\x37\x5f\x00\xad\xf9\x32\x40\x2c\xea\xfc\
\x1d\x78\x5b\x54\x07\x66\xe7\x03\x80\x3f\xb4\x3d\x94\x3d\x85\xd2\
\x46\xe3\x7a\x8a\x2d\xdb\xed\xbc\xea\x07\x60\x55\xde\x00\x32\x6d\
\x3c\x90\x16\x3d\xf9\x4f\xac\xae\x28\x6a\x48\x7b\x98\x8a\x53\xfe\
\x1a\x9a\x72\x89\x27\x3c\xea\x1b\x93\xf9\xd8\xc3\xca\x82\x00\x48\
\x17\xf9\xf3\x10\x33\x69\x76\x2d\xc7\xec\xad\x1e\xaa\x8a\xc7\x0f\
\xcf\xc3\x2d\x7d\x14\x4d\x5c\x36\x6f\xef\x6b\x0a\xe4\xd0\x72\x7d\
\x21\x53\xf3\x16\x82\x81\x4c\x70\xbb\x57\x89\x89\xd5\x71\x17\x46\
\xf2\xed\x21\x41\x38\x25\x0f\x12\x84\xae\xc1\xd4\x03\xd6\x6d\xea\
\x26\xe5\x0e\xcb\xb5\x6e\x04\x7e\x51\x55\x19\xf7\x0a\x06\x20\x0d\
\xe2\x8f\xc0\xaf\x50\x2e\x56\xdb\xed\xe8\xce\x87\x43\xb8\x57\x13\
\xa7\xf4\x71\xd0\x4a\xe9\xec\x0e\xd8\xb5\x37\x75\xaa\x6a\xb6\x02\
\x57\x55\x55\xc6\x13\xa7\xfa\x83\x61\x25\xc3\xb1\xa8\xf3\x4b\x90\
\x95\x60\x13\x4e\xcc\x41\x4f\xbe\x33\x78\xa3\xd7\xba\x08\x2f\xbc\
\x10\x94\xcb\xee\x7d\x29\xec\xe4\x97\x5a\xf4\xfb\xc0\x65\x55\x95\
\xf1\x9e\xe1\xac\x69\xd8\xd9\x7c\x2c\xea\x2c\x05\x79\x52\x89\x49\
\xa8\x75\x01\x66\xf7\x8a\xc1\x53\x8d\xb2\xdf\x80\x68\x74\x75\xfb\
\xec\xdc\x9b\x62\x88\xff\x1f\x5e\x06\x16\x54\x55\xc6\x87\xdd\x0a\
\xcc\xa9\x1c\x89\x45\x9d\x07\x81\xfb\x00\xcc\xae\x07\x09\xb7\x7d\
\x27\xbb\x39\x68\x25\x04\xd6\xd5\x18\xba\x47\xfd\xee\x24\x9e\x9f\
\x95\x85\x7b\x80\x25\x55\x95\xf1\xce\x5c\xd6\x92\x73\x3d\x15\x8b\
\x3a\xcf\xa6\xc3\x7d\x97\x96\x7c\x8b\x48\x7c\x22\xba\xbb\x81\xe3\
\x7f\x99\x66\x40\x8c\xea\x3b\x52\x81\xe2\xf0\xd1\x01\x1d\xbe\x36\
\xe0\xb6\xaa\xca\xf8\x1f\xaa\x2a\xe3\x7e\xae\xeb\xc8\xab\x20\x8c\
\x45\x9d\x7f\x01\x73\xc1\x58\x2b\x41\x13\xa1\xc4\x5c\x42\xed\x4b\
\xd0\x53\x35\x48\x70\x18\x3d\xb5\x16\x3d\xb5\x0a\xc4\x40\xa0\x7f\
\x23\x60\x03\x70\x5d\x55\x65\xfc\x4f\xf9\xb7\xdc\x0b\x50\x85\x2c\
\x5e\x66\x15\x01\x77\x01\xcf\x42\x00\x52\x8c\x92\x11\x88\xea\x01\
\xd5\xd3\xd7\x1c\xf7\x14\xb7\xde\x30\x12\xcb\x94\x97\x94\xe2\x67\
\x55\x95\xf1\xb6\x42\x64\x7c\x52\xc8\x97\x3d\x16\x2f\xb3\xa6\x00\
\xaf\xa4\xeb\xdb\xe2\xe3\x0d\x5e\x38\x67\x72\xa8\x73\x4e\xe5\x88\
\x65\x73\x67\x1c\x7a\x8e\x02\x8a\x7c\x15\x6f\xab\x2c\x5e\x66\xcd\
\x06\xae\x03\x2e\x04\xcc\xd2\x62\x6d\xfb\x35\xb3\x4b\x9f\x5f\x30\
\xfb\x70\x63\xa1\x75\xc9\x57\xf9\xba\xcd\xe2\x65\x56\x91\x08\x32\
\xf3\xbc\xb0\xbd\x74\x51\x67\xf0\x55\xe8\xf8\x3f\x66\x47\x07\xd4\
\xf8\xcc\x73\x31\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\
"
qt_resource_name = "\
qt_resource_name = b"\
\x00\x06\
\x07\x03\x7d\xc3\
\x00\x69\
@@ -235,7 +187,7 @@ qt_resource_name = "\
\x00\x64\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
"
qt_resource_struct = "\
qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x12\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\

View File

@@ -88,7 +88,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="aboutTab">
<attribute name="title">
@@ -109,7 +109,7 @@
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Verdana'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-weight:600;&quot;&gt;(c) 2014, Virtual Cable S.L.U.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-weight:600;&quot;&gt;(c) 2012-2016, Virtual Cable S.L.U.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-style:italic;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.udsenterprise.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.udsenterprise.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.openuds.org&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.openuds.org&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
@@ -167,7 +167,7 @@ p, li { white-space: pre-wrap; }
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Verdana'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Copyright (c) 2014 Virtual Cable S.L.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Copyright (c) 2012-2016 Virtual Cable S.L.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;All rights reserved.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;

View File

@@ -1,154 +1,164 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'about-dialog.ui'
#
# Created: Tue Dec 09 10:54:30 2014
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_UDSAboutDialog(object):
def setupUi(self, UDSAboutDialog):
UDSAboutDialog.setObjectName(_fromUtf8("UDSAboutDialog"))
UDSAboutDialog.resize(466, 402)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Verdana"))
font.setPointSize(9)
UDSAboutDialog.setFont(font)
UDSAboutDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
UDSAboutDialog.setModal(True)
self.vboxlayout = QtGui.QVBoxLayout(UDSAboutDialog)
self.vboxlayout.setSpacing(9)
self.vboxlayout.setMargin(9)
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
self.LogoLabel = QtGui.QLabel(UDSAboutDialog)
self.LogoLabel.setObjectName(_fromUtf8("LogoLabel"))
self.vboxlayout.addWidget(self.LogoLabel)
spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self.vboxlayout.addItem(spacerItem)
self.TitleLabel = QtGui.QLabel(UDSAboutDialog)
self.TitleLabel.setObjectName(_fromUtf8("TitleLabel"))
self.vboxlayout.addWidget(self.TitleLabel)
self.VersionLabel = QtGui.QLabel(UDSAboutDialog)
self.VersionLabel.setObjectName(_fromUtf8("VersionLabel"))
self.vboxlayout.addWidget(self.VersionLabel)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self.vboxlayout.addItem(spacerItem1)
self.tabWidget = QtGui.QTabWidget(UDSAboutDialog)
self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
self.aboutTab = QtGui.QWidget()
self.aboutTab.setObjectName(_fromUtf8("aboutTab"))
self.vboxlayout1 = QtGui.QVBoxLayout(self.aboutTab)
self.vboxlayout1.setSpacing(6)
self.vboxlayout1.setMargin(9)
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
self.aboutBrowser = QtGui.QTextBrowser(self.aboutTab)
self.aboutBrowser.setOpenExternalLinks(True)
self.aboutBrowser.setObjectName(_fromUtf8("aboutBrowser"))
self.vboxlayout1.addWidget(self.aboutBrowser)
self.tabWidget.addTab(self.aboutTab, _fromUtf8(""))
self.authorsTab = QtGui.QWidget()
self.authorsTab.setObjectName(_fromUtf8("authorsTab"))
self.vboxlayout2 = QtGui.QVBoxLayout(self.authorsTab)
self.vboxlayout2.setSpacing(6)
self.vboxlayout2.setMargin(9)
self.vboxlayout2.setObjectName(_fromUtf8("vboxlayout2"))
self.authorsBrowser = QtGui.QTextBrowser(self.authorsTab)
self.authorsBrowser.setOpenExternalLinks(True)
self.authorsBrowser.setObjectName(_fromUtf8("authorsBrowser"))
self.vboxlayout2.addWidget(self.authorsBrowser)
self.tabWidget.addTab(self.authorsTab, _fromUtf8(""))
self.licenseTab = QtGui.QWidget()
self.licenseTab.setObjectName(_fromUtf8("licenseTab"))
self.vboxlayout3 = QtGui.QVBoxLayout(self.licenseTab)
self.vboxlayout3.setSpacing(6)
self.vboxlayout3.setMargin(9)
self.vboxlayout3.setObjectName(_fromUtf8("vboxlayout3"))
self.licenseBrowser = QtGui.QTextBrowser(self.licenseTab)
self.licenseBrowser.setObjectName(_fromUtf8("licenseBrowser"))
self.vboxlayout3.addWidget(self.licenseBrowser)
self.tabWidget.addTab(self.licenseTab, _fromUtf8(""))
self.vboxlayout.addWidget(self.tabWidget)
self.buttonBox = QtGui.QDialogButtonBox(UDSAboutDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.vboxlayout.addWidget(self.buttonBox)
self.retranslateUi(UDSAboutDialog)
self.tabWidget.setCurrentIndex(0)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("clicked(QAbstractButton*)")), UDSAboutDialog.closeDialog)
QtCore.QMetaObject.connectSlotsByName(UDSAboutDialog)
def retranslateUi(self, UDSAboutDialog):
UDSAboutDialog.setWindowTitle(_translate("UDSAboutDialog", "About UDS Actor", None))
self.LogoLabel.setText(_translate("UDSAboutDialog", "<html><head/><body><p><img src=\":/images/img/uds.png\"/> UDS Actor Tools</p></body></html>", None))
self.TitleLabel.setText(_translate("UDSAboutDialog", "<html><head/><body><p><span style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:600;\">UDS Actor</span></p></body></html>", None))
self.VersionLabel.setText(_translate("UDSAboutDialog", "Version 1.7.0", None))
self.aboutBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2014, Virtual Cable S.L.U.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\'; font-style:italic;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.udsenterprise.com\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.udsenterprise.com</span></a></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.openuds.org\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.openuds.org</span></a></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p></body></html>", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.aboutTab), _translate("UDSAboutDialog", "&About", None))
self.authorsBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\';\">Adolfo Gómez García &lt;agomez@virtualcable.es&gt;</span></p></body></html>", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.authorsTab), _translate("UDSAboutDialog", "A&uthors", None))
self.licenseBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2014 Virtual Cable S.L.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">All rights reserved.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Redistribution and use in source and binary forms, with or without modification,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">are permitted provided that the following conditions are met:</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Redistributions of source code must retain the above copyright notice,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> this list of conditions and the following disclaimer.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Redistributions in binary form must reproduce the above copyright notice,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> this list of conditions and the following disclaimer in the documentation</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> and/or other materials provided with the distribution.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Neither the name of Virtual Cable S.L. nor the names of its contributors</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> may be used to endorse or promote products derived from this software</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> without specific prior written permission.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p></body></html>", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.licenseTab), _translate("UDSAboutDialog", "&License Agreement", None))
import UDSActor_rc
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'about-dialog.ui'
#
# Created: Mon Apr 27 22:05:02 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_UDSAboutDialog(object):
def setupUi(self, UDSAboutDialog):
UDSAboutDialog.setObjectName(_fromUtf8("UDSAboutDialog"))
UDSAboutDialog.resize(466, 402)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Verdana"))
font.setPointSize(9)
UDSAboutDialog.setFont(font)
UDSAboutDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
UDSAboutDialog.setModal(True)
self.vboxlayout = QtGui.QVBoxLayout(UDSAboutDialog)
self.vboxlayout.setSpacing(9)
self.vboxlayout.setMargin(9)
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
self.LogoLabel = QtGui.QLabel(UDSAboutDialog)
self.LogoLabel.setObjectName(_fromUtf8("LogoLabel"))
self.vboxlayout.addWidget(self.LogoLabel)
spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self.vboxlayout.addItem(spacerItem)
self.TitleLabel = QtGui.QLabel(UDSAboutDialog)
self.TitleLabel.setObjectName(_fromUtf8("TitleLabel"))
self.vboxlayout.addWidget(self.TitleLabel)
self.VersionLabel = QtGui.QLabel(UDSAboutDialog)
self.VersionLabel.setObjectName(_fromUtf8("VersionLabel"))
self.vboxlayout.addWidget(self.VersionLabel)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
self.vboxlayout.addItem(spacerItem1)
self.tabWidget = QtGui.QTabWidget(UDSAboutDialog)
self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
self.aboutTab = QtGui.QWidget()
self.aboutTab.setObjectName(_fromUtf8("aboutTab"))
self.vboxlayout1 = QtGui.QVBoxLayout(self.aboutTab)
self.vboxlayout1.setSpacing(6)
self.vboxlayout1.setMargin(9)
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
self.aboutBrowser = QtGui.QTextBrowser(self.aboutTab)
self.aboutBrowser.setOpenExternalLinks(True)
self.aboutBrowser.setObjectName(_fromUtf8("aboutBrowser"))
self.vboxlayout1.addWidget(self.aboutBrowser)
self.tabWidget.addTab(self.aboutTab, _fromUtf8(""))
self.authorsTab = QtGui.QWidget()
self.authorsTab.setObjectName(_fromUtf8("authorsTab"))
self.vboxlayout2 = QtGui.QVBoxLayout(self.authorsTab)
self.vboxlayout2.setSpacing(6)
self.vboxlayout2.setMargin(9)
self.vboxlayout2.setObjectName(_fromUtf8("vboxlayout2"))
self.authorsBrowser = QtGui.QTextBrowser(self.authorsTab)
self.authorsBrowser.setOpenExternalLinks(True)
self.authorsBrowser.setObjectName(_fromUtf8("authorsBrowser"))
self.vboxlayout2.addWidget(self.authorsBrowser)
self.tabWidget.addTab(self.authorsTab, _fromUtf8(""))
self.licenseTab = QtGui.QWidget()
self.licenseTab.setObjectName(_fromUtf8("licenseTab"))
self.vboxlayout3 = QtGui.QVBoxLayout(self.licenseTab)
self.vboxlayout3.setSpacing(6)
self.vboxlayout3.setMargin(9)
self.vboxlayout3.setObjectName(_fromUtf8("vboxlayout3"))
self.licenseBrowser = QtGui.QTextBrowser(self.licenseTab)
self.licenseBrowser.setObjectName(_fromUtf8("licenseBrowser"))
self.vboxlayout3.addWidget(self.licenseBrowser)
self.tabWidget.addTab(self.licenseTab, _fromUtf8(""))
self.vboxlayout.addWidget(self.tabWidget)
self.buttonBox = QtGui.QDialogButtonBox(UDSAboutDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.vboxlayout.addWidget(self.buttonBox)
self.retranslateUi(UDSAboutDialog)
self.tabWidget.setCurrentIndex(0)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("clicked(QAbstractButton*)")), UDSAboutDialog.closeDialog)
QtCore.QMetaObject.connectSlotsByName(UDSAboutDialog)
def retranslateUi(self, UDSAboutDialog):
UDSAboutDialog.setWindowTitle(_translate("UDSAboutDialog", "About UDS Actor", None))
self.LogoLabel.setText(_translate("UDSAboutDialog", "<html><head/><body><p><img src=\":/images/img/uds.png\"/> UDS Actor Tools</p></body></html>", None))
self.TitleLabel.setText(_translate("UDSAboutDialog", "<html><head/><body><p><span style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:600;\">UDS Actor</span></p></body></html>", None))
self.VersionLabel.setText(_translate("UDSAboutDialog", "Version 1.7.0", None))
self.aboutBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2014, Virtual Cable S.L.U.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\'; font-style:italic;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.udsenterprise.com\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.udsenterprise.com</span></a></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.openuds.org\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.openuds.org</span></a></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p></body></html>", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.aboutTab), _translate("UDSAboutDialog", "&About", None))
self.authorsBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\';\">Adolfo Gómez García &lt;agomez@virtualcable.es&gt;</span></p></body></html>", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.authorsTab), _translate("UDSAboutDialog", "A&uthors", None))
self.licenseBrowser.setHtml(_translate("UDSAboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2014 Virtual Cable S.L.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">All rights reserved.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Redistribution and use in source and binary forms, with or without modification,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">are permitted provided that the following conditions are met:</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Redistributions of source code must retain the above copyright notice,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> this list of conditions and the following disclaimer.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Redistributions in binary form must reproduce the above copyright notice,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> this list of conditions and the following disclaimer in the documentation</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> and/or other materials provided with the distribution.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> * Neither the name of Virtual Cable S.L. nor the names of its contributors</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> may be used to endorse or promote products derived from this software</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"> without specific prior written permission.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p></body></html>", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.licenseTab), _translate("UDSAboutDialog", "&License Agreement", None))
import UDSActor_rc
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
UDSAboutDialog = QtGui.QDialog()
ui = Ui_UDSAboutDialog()
ui.setupUi(UDSAboutDialog)
UDSAboutDialog.show()
sys.exit(app.exec_())

BIN
actors/src/img/uds-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'message-dialog.ui'
#
# Created: Tue Dec 9 11:27:47 2014
# Created: Mon Apr 27 22:05:02 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
@@ -59,3 +59,13 @@ class Ui_UDSMessageDialog(object):
def retranslateUi(self, UDSMessageDialog):
UDSMessageDialog.setWindowTitle(_translate("UDSMessageDialog", "UDS Actor", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
UDSMessageDialog = QtGui.QDialog()
ui = Ui_UDSMessageDialog()
ui.setupUi(UDSMessageDialog)
UDSMessageDialog.show()
sys.exit(app.exec_())

View File

@@ -121,7 +121,7 @@
<x>20</x>
<y>20</y>
<width>361</width>
<height>146</height>
<height>131</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@@ -207,6 +207,9 @@
<property name="currentIndex">
<number>1</number>
</property>
<property name="frame">
<bool>true</bool>
</property>
<item>
<property name="text">
<string notr="true">DEBUG</string>
@@ -219,7 +222,7 @@
</item>
<item>
<property name="text">
<string notr="true">EROR</string>
<string notr="true">ERROR</string>
</property>
</item>
<item>

View File

@@ -1,141 +1,152 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'setup-dialog.ui'
#
# Created: Wed Nov 12 04:50:26 2014
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_UdsActorSetupDialog(object):
def setupUi(self, UdsActorSetupDialog):
UdsActorSetupDialog.setObjectName(_fromUtf8("UdsActorSetupDialog"))
UdsActorSetupDialog.setWindowModality(QtCore.Qt.WindowModal)
UdsActorSetupDialog.resize(400, 243)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(UdsActorSetupDialog.sizePolicy().hasHeightForWidth())
UdsActorSetupDialog.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Verdana"))
font.setPointSize(9)
UdsActorSetupDialog.setFont(font)
UdsActorSetupDialog.setAutoFillBackground(False)
UdsActorSetupDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
UdsActorSetupDialog.setSizeGripEnabled(False)
UdsActorSetupDialog.setModal(True)
self.testButton = QtGui.QPushButton(UdsActorSetupDialog)
self.testButton.setEnabled(False)
self.testButton.setGeometry(QtCore.QRect(20, 160, 361, 23))
self.testButton.setObjectName(_fromUtf8("testButton"))
self.saveButton = QtGui.QPushButton(UdsActorSetupDialog)
self.saveButton.setEnabled(False)
self.saveButton.setGeometry(QtCore.QRect(20, 190, 101, 23))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.saveButton.sizePolicy().hasHeightForWidth())
self.saveButton.setSizePolicy(sizePolicy)
self.saveButton.setObjectName(_fromUtf8("saveButton"))
self.cancelButton = QtGui.QPushButton(UdsActorSetupDialog)
self.cancelButton.setGeometry(QtCore.QRect(260, 190, 121, 23))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.cancelButton.sizePolicy().hasHeightForWidth())
self.cancelButton.setSizePolicy(sizePolicy)
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
self.layoutWidget = QtGui.QWidget(UdsActorSetupDialog)
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 146))
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
self.formLayout = QtGui.QFormLayout(self.layoutWidget)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
self.formLayout.setMargin(0)
self.formLayout.setVerticalSpacing(16)
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label = QtGui.QLabel(self.layoutWidget)
self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label)
self.host = QtGui.QLineEdit(self.layoutWidget)
self.host.setAcceptDrops(False)
self.host.setObjectName(_fromUtf8("host"))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.host)
self.label_3 = QtGui.QLabel(self.layoutWidget)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
self.masterKey = QtGui.QLineEdit(self.layoutWidget)
self.masterKey.setObjectName(_fromUtf8("masterKey"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.masterKey)
self.label_4 = QtGui.QLabel(self.layoutWidget)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_4)
self.useSSl = QtGui.QComboBox(self.layoutWidget)
self.useSSl.setObjectName(_fromUtf8("useSSl"))
self.useSSl.addItem(_fromUtf8(""))
self.useSSl.addItem(_fromUtf8(""))
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.useSSl)
self.logLevelLabel = QtGui.QLabel(self.layoutWidget)
self.logLevelLabel.setObjectName(_fromUtf8("logLevelLabel"))
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.logLevelLabel)
self.logLevelComboBox = QtGui.QComboBox(self.layoutWidget)
self.logLevelComboBox.setObjectName(_fromUtf8("logLevelComboBox"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(0, _fromUtf8("DEBUG"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(1, _fromUtf8("INFO"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(2, _fromUtf8("EROR"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(3, _fromUtf8("FATAL"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.logLevelComboBox)
self.retranslateUi(UdsActorSetupDialog)
self.logLevelComboBox.setCurrentIndex(1)
QtCore.QObject.connect(self.host, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.masterKey, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.cancelAndDiscard)
QtCore.QObject.connect(self.testButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.testParameters)
QtCore.QObject.connect(self.saveButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.acceptAndSave)
QtCore.QMetaObject.connectSlotsByName(UdsActorSetupDialog)
def retranslateUi(self, UdsActorSetupDialog):
UdsActorSetupDialog.setWindowTitle(_translate("UdsActorSetupDialog", "UDS Actor Configuration", None))
self.testButton.setToolTip(_translate("UdsActorSetupDialog", "Click to test the selecter parameters", None))
self.testButton.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Click on this button to test the server host and master key parameters.</p><p>A window will be displayed with results after the test is executed.</p><p><br/></p><p>This button will only be active if all parameters are filled.</p></body></html>", None))
self.testButton.setText(_translate("UdsActorSetupDialog", "Test parameters", None))
self.saveButton.setToolTip(_translate("UdsActorSetupDialog", "Accepts changes and saves them", None))
self.saveButton.setWhatsThis(_translate("UdsActorSetupDialog", "Clicking on this button will accept all changes and save them, closing the configuration window", None))
self.saveButton.setText(_translate("UdsActorSetupDialog", "Accept && Save", None))
self.cancelButton.setToolTip(_translate("UdsActorSetupDialog", "Cancel all changes and discard them", None))
self.cancelButton.setWhatsThis(_translate("UdsActorSetupDialog", "Discards all changes and closes the configuration window", None))
self.cancelButton.setText(_translate("UdsActorSetupDialog", "Cancel && Discard", None))
self.label.setText(_translate("UdsActorSetupDialog", "UDS Server Host", None))
self.host.setToolTip(_translate("UdsActorSetupDialog", "Uds Broker Server Addres. Use IP or FQDN", None))
self.host.setWhatsThis(_translate("UdsActorSetupDialog", "Enter here the UDS Broker Addres using either its IP address or its FQDN address", None))
self.label_3.setText(_translate("UdsActorSetupDialog", "UDS Master Key", None))
self.masterKey.setToolTip(_translate("UdsActorSetupDialog", "Master key to communicate with UDS Broker", None))
self.masterKey.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Enter the Master Key (found on<span style=\" font-weight:600;\"> UDS Configuration</span> section) of the UDS Broker to allow communication of the Actor with Broker</p></body></html>", None))
self.label_4.setText(_translate("UdsActorSetupDialog", "Security", None))
self.useSSl.setToolTip(_translate("UdsActorSetupDialog", "Select communication security with broker", None))
self.useSSl.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Select the security for communications with UDS Broker.</p><p>The recommended method of communication is <span style=\" font-weight:600;\">Use SSL</span>, but selection needs to be acording to your broker configuration.</p></body></html>", None))
self.useSSl.setItemText(0, _translate("UdsActorSetupDialog", "Do not use SSL", None))
self.useSSl.setItemText(1, _translate("UdsActorSetupDialog", "Use SSL", None))
self.logLevelLabel.setText(_translate("UdsActorSetupDialog", "Log Level", None))
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'setup-dialog.ui'
#
# Created: Mon Apr 27 22:05:03 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_UdsActorSetupDialog(object):
def setupUi(self, UdsActorSetupDialog):
UdsActorSetupDialog.setObjectName(_fromUtf8("UdsActorSetupDialog"))
UdsActorSetupDialog.setWindowModality(QtCore.Qt.WindowModal)
UdsActorSetupDialog.resize(400, 243)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(UdsActorSetupDialog.sizePolicy().hasHeightForWidth())
UdsActorSetupDialog.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Verdana"))
font.setPointSize(9)
UdsActorSetupDialog.setFont(font)
UdsActorSetupDialog.setAutoFillBackground(False)
UdsActorSetupDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
UdsActorSetupDialog.setSizeGripEnabled(False)
UdsActorSetupDialog.setModal(True)
self.testButton = QtGui.QPushButton(UdsActorSetupDialog)
self.testButton.setEnabled(False)
self.testButton.setGeometry(QtCore.QRect(20, 160, 361, 23))
self.testButton.setObjectName(_fromUtf8("testButton"))
self.saveButton = QtGui.QPushButton(UdsActorSetupDialog)
self.saveButton.setEnabled(False)
self.saveButton.setGeometry(QtCore.QRect(20, 190, 101, 23))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.saveButton.sizePolicy().hasHeightForWidth())
self.saveButton.setSizePolicy(sizePolicy)
self.saveButton.setObjectName(_fromUtf8("saveButton"))
self.cancelButton = QtGui.QPushButton(UdsActorSetupDialog)
self.cancelButton.setGeometry(QtCore.QRect(260, 190, 121, 23))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.cancelButton.sizePolicy().hasHeightForWidth())
self.cancelButton.setSizePolicy(sizePolicy)
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
self.layoutWidget = QtGui.QWidget(UdsActorSetupDialog)
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 131))
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
self.formLayout = QtGui.QFormLayout(self.layoutWidget)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
self.formLayout.setMargin(0)
self.formLayout.setVerticalSpacing(16)
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label = QtGui.QLabel(self.layoutWidget)
self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label)
self.host = QtGui.QLineEdit(self.layoutWidget)
self.host.setAcceptDrops(False)
self.host.setObjectName(_fromUtf8("host"))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.host)
self.label_3 = QtGui.QLabel(self.layoutWidget)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
self.masterKey = QtGui.QLineEdit(self.layoutWidget)
self.masterKey.setObjectName(_fromUtf8("masterKey"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.masterKey)
self.label_4 = QtGui.QLabel(self.layoutWidget)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_4)
self.useSSl = QtGui.QComboBox(self.layoutWidget)
self.useSSl.setObjectName(_fromUtf8("useSSl"))
self.useSSl.addItem(_fromUtf8(""))
self.useSSl.addItem(_fromUtf8(""))
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.useSSl)
self.logLevelLabel = QtGui.QLabel(self.layoutWidget)
self.logLevelLabel.setObjectName(_fromUtf8("logLevelLabel"))
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.logLevelLabel)
self.logLevelComboBox = QtGui.QComboBox(self.layoutWidget)
self.logLevelComboBox.setFrame(True)
self.logLevelComboBox.setObjectName(_fromUtf8("logLevelComboBox"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(0, _fromUtf8("DEBUG"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(1, _fromUtf8("INFO"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(2, _fromUtf8("ERROR"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(3, _fromUtf8("FATAL"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.logLevelComboBox)
self.retranslateUi(UdsActorSetupDialog)
self.logLevelComboBox.setCurrentIndex(1)
QtCore.QObject.connect(self.host, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.masterKey, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.cancelAndDiscard)
QtCore.QObject.connect(self.testButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.testParameters)
QtCore.QObject.connect(self.saveButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.acceptAndSave)
QtCore.QMetaObject.connectSlotsByName(UdsActorSetupDialog)
def retranslateUi(self, UdsActorSetupDialog):
UdsActorSetupDialog.setWindowTitle(_translate("UdsActorSetupDialog", "UDS Actor Configuration", None))
self.testButton.setToolTip(_translate("UdsActorSetupDialog", "Click to test the selecter parameters", None))
self.testButton.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Click on this button to test the server host and master key parameters.</p><p>A window will be displayed with results after the test is executed.</p><p><br/></p><p>This button will only be active if all parameters are filled.</p></body></html>", None))
self.testButton.setText(_translate("UdsActorSetupDialog", "Test parameters", None))
self.saveButton.setToolTip(_translate("UdsActorSetupDialog", "Accepts changes and saves them", None))
self.saveButton.setWhatsThis(_translate("UdsActorSetupDialog", "Clicking on this button will accept all changes and save them, closing the configuration window", None))
self.saveButton.setText(_translate("UdsActorSetupDialog", "Accept && Save", None))
self.cancelButton.setToolTip(_translate("UdsActorSetupDialog", "Cancel all changes and discard them", None))
self.cancelButton.setWhatsThis(_translate("UdsActorSetupDialog", "Discards all changes and closes the configuration window", None))
self.cancelButton.setText(_translate("UdsActorSetupDialog", "Cancel && Discard", None))
self.label.setText(_translate("UdsActorSetupDialog", "UDS Server Host", None))
self.host.setToolTip(_translate("UdsActorSetupDialog", "Uds Broker Server Addres. Use IP or FQDN", None))
self.host.setWhatsThis(_translate("UdsActorSetupDialog", "Enter here the UDS Broker Addres using either its IP address or its FQDN address", None))
self.label_3.setText(_translate("UdsActorSetupDialog", "UDS Master Key", None))
self.masterKey.setToolTip(_translate("UdsActorSetupDialog", "Master key to communicate with UDS Broker", None))
self.masterKey.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Enter the Master Key (found on<span style=\" font-weight:600;\"> UDS Configuration</span> section) of the UDS Broker to allow communication of the Actor with Broker</p></body></html>", None))
self.label_4.setText(_translate("UdsActorSetupDialog", "Security", None))
self.useSSl.setToolTip(_translate("UdsActorSetupDialog", "Select communication security with broker", None))
self.useSSl.setWhatsThis(_translate("UdsActorSetupDialog", "<html><head/><body><p>Select the security for communications with UDS Broker.</p><p>The recommended method of communication is <span style=\" font-weight:600;\">Use SSL</span>, but selection needs to be acording to your broker configuration.</p></body></html>", None))
self.useSSl.setItemText(0, _translate("UdsActorSetupDialog", "Do not use SSL", None))
self.useSSl.setItemText(1, _translate("UdsActorSetupDialog", "Use SSL", None))
self.logLevelLabel.setText(_translate("UdsActorSetupDialog", "Log Level", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
UdsActorSetupDialog = QtGui.QDialog()
ui = Ui_UdsActorSetupDialog()
ui.setupUi(UdsActorSetupDialog)
UdsActorSetupDialog.show()
sys.exit(app.exec_())

View File

@@ -39,10 +39,11 @@ import logging
import json
import uuid
import six
import warnings
from udsactor.log import logger
from udsactor import __version__ as VERSION
from udsactor import VERSION
from .utils import exceptionToMessage
VERIFY_CERT = False
@@ -81,6 +82,7 @@ except Exception:
try:
urllib3.disable_warnings() # @UndefinedVariable
warnings.simplefilter("ignore")
except Exception:
pass # In fact, isn't too important, but wil log warns to logging file
@@ -102,15 +104,25 @@ class Api(object):
def __init__(self, host, masterKey, ssl):
self.host = host
self.masterKey = masterKey
self.useSSL = ssl
self.useSSL = True if ssl else False
self.uuid = None
self.mac = None
self.url = "{}://{}/rest/actor/".format(('http', 'https')[ssl], self.host)
self.url = "{}://{}/rest/actor/".format(('http', 'https')[self.useSSL], self.host)
self.idle = None
self.maxSession = None
self.secretKey = six.text_type(uuid.uuid4())
self.newerRequestLib = requests.__version__.split('.') >= '1'
try:
self.newerRequestLib = requests.__version__.split('.')[0] >= '1'
except Exception:
self.newerRequestLib = False # I no version, guess this must be an old requests
# Disable logging requests messages except for errors, ...
logging.getLogger("requests").setLevel(logging.CRITICAL)
# Tries to disable all warnings
try:
warnings.simplefilter("ignore") # Disables all warnings
except Exception:
pass
def _getUrl(self, method, key=None, ids=None):
url = self.url + method
@@ -129,15 +141,17 @@ class Api(object):
def _request(self, url, data=None):
try:
if data is None:
# Old requests version does not support verify, but they do not checks ssl certificate
# Old requests version does not support verify, but they do not checks ssl certificate by default
if self.newerRequestLib:
r = requests.get(url, verify=VERIFY_CERT)
else:
logger.debug('Requesting with old')
r = requests.get(url) # Always ignore certs??
else:
if self.newerRequestLib:
r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=VERIFY_CERT)
else:
logger.debug('Requesting with old')
r = requests.post(url, data=data, headers={'content-type': 'application/json'})
r = json.loads(r.content) # Using instead of r.json() to make compatible with oooold rquests lib versions
@@ -165,17 +179,24 @@ class Api(object):
uuid, mac
Optionally can return an third parameter, that is max "idle" request time
'''
logger.debug('Invoking init')
url = self._getUrl('init', key=self.masterKey, ids=ids)
res = self._request(url)['result']
logger.debug('Got response parameters: {}'.format(res))
self.uuid, self.mac = res[0:2]
self.idle = int(res[2])
if self.idle < 15:
self.idle = None # No values under 30 seconds are allowed :)
# Optional idle parameter
try:
self.idle = int(res[2])
if self.idle < 30:
self.idle = None # No values under 30 seconds are allowed :)
except Exception:
self.idle = None
return self.uuid
def postMessage(self, msg, data, processData=True):
logger.debug('Invoking post message {} with data {}'.format(msg, data))
if self.uuid is None:
raise ConnectionError('REST api has not been initialized')
@@ -185,22 +206,28 @@ class Api(object):
return self._request(url, data)['result']
def notifyComm(self, url):
logger.debug('Notifying comms {}'.format(url))
return self.postMessage('notifyComms', url)
def login(self, username):
logger.debug('Notifying login {}'.format(username))
return self.postMessage('login', username)
def logout(self, username):
logger.debug('Notifying logout {}'.format(username))
return self.postMessage('logout', username)
def information(self):
logger.debug('Requesting information'.format())
return self.postMessage('information', '')
def setReady(self, ipsInfo):
logger.debug('Notifying readyness: {}'.format(ipsInfo))
data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo])
return self.postMessage('ready', data)
def notifyIpChanges(self, ipsInfo):
logger.debug('Notifying ip changes: {}'.format(ipsInfo))
data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo])
return self.postMessage('ip', data)

View File

@@ -31,17 +31,19 @@
'''
from __future__ import unicode_literals
__title__ = 'udsactor'
__version__ = '1.7.0'
__build__ = 0x010700
__author__ = 'Adolfo Gómez'
__license__ = "BSD 3-clause"
__copyright__ = "Copyright 2014 VirtualCable S.L.U."
# On centos, old six release does not includes byte2int, nor six.PY2
import six
VERSION = '2.0.0'
__title__ = 'udsactor'
__version__ = VERSION
__build__ = 0x010750
__author__ = 'Adolfo Gómez <dkmaster@dkmon.com>'
__license__ = "BSD 3-clause"
__copyright__ = "Copyright 2014-2016 VirtualCable S.L.U."
if not hasattr(six, 'byte2int'):
if six.PY3:
import operator

View File

@@ -37,7 +37,8 @@ from udsactor.certs import createSelfSignedCert
from udsactor.scriptThread import ScriptExecutorThread
import threading
import uuid
import string
import random
import json
import six
from six.moves import socketserver # @UnresolvedImport, pylint: disable=import-error
@@ -50,6 +51,10 @@ startTime = time.time()
class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
protocol_version = 'HTTP/1.0'
server_version = 'UDS Actor Server'
sys_version = ''
uuid = None
service = None
lock = threading.Lock()
@@ -61,6 +66,15 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.wfile.write(json.dumps({'error': message}))
return
def sendJsonResponse(self, data):
self.send_response(200)
data = json.dumps(data)
self.send_header('Content-type', 'application/json')
self.send_header('Content-Length', len(data))
self.end_headers()
# Send the html message
self.wfile.write(data)
def do_GET(self):
# Very simple path & params splitter
path = self.path.split('?')[0][1:].split('/')
@@ -74,11 +88,7 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
return
if len(path) != 2:
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
# Send the html message
self.wfile.write(json.dumps("UDS Actor has been running for {} seconds".format(time.time() - startTime)))
self.sendJsonResponse("UDS Actor has been running for {} seconds".format(time.time() - startTime))
return
try:
@@ -92,11 +102,7 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.sendJsonError(500, str(e))
return
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
# Send the html message
self.wfile.write(json.dumps(result))
self.sendJsonResponse(result)
def do_POST(self):
path = self.path.split('?')[0][1:].split('/')
@@ -112,7 +118,7 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
HTTPServerHandler.lock.acquire()
length = int(self.headers.getheader('content-length'))
content = self.rfile.read(length)
print(length, ">>", content, '<<')
logger.debug('length: {}, content >>{}<<'.format(length, content))
params = json.loads(content)
operation = getattr(self, 'post_' + path[1])
@@ -127,11 +133,7 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
finally:
HTTPServerHandler.lock.release()
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
# Send the html message
self.wfile.write(json.dumps(result))
self.sendJsonResponse(result)
def post_logoff(self, params):
logger.debug('Sending LOGOFF to clients')
@@ -170,7 +172,16 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def get_information(self, params):
# TODO: Return something useful? :)
return 'Information'
return 'Up and running'
def get_uuid(self, params):
return self.service.api.uuid
def log_error(self, fmt, *args):
logger.error('HTTP ' + fmt % args)
def log_message(self, fmt, *args):
logger.info('HTTP ' + fmt % args)
class HTTPServerThread(threading.Thread):
@@ -178,11 +189,15 @@ class HTTPServerThread(threading.Thread):
super(self.__class__, self).__init__()
if HTTPServerHandler.uuid is None:
HTTPServerHandler.uuid = uuid.uuid4().get_hex()
HTTPServerHandler.service = service
HTTPServerHandler.uuid = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(48))
self.certFile = createSelfSignedCert()
HTTPServerHandler.service = service
self.initiateServer(address)
def initiateServer(self, address):
self.server = socketserver.TCPServer(address, HTTPServerHandler)
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
@@ -193,5 +208,14 @@ class HTTPServerThread(threading.Thread):
logger.debug('Stopping REST Service')
self.server.shutdown()
def restart(self, address=None):
if address is None:
address = self.server.server_address
self.stop()
self.initiateServer(address)
def run(self):
self.server.serve_forever()

View File

@@ -87,9 +87,16 @@ class UDSActorSvc(Daemon, CommonService):
set_proctitle('UDSActorDaemon')
# Linux daemon will continue running unless something is requested to
if self.interactWithBroker() is False:
logger.debug('Interact with broker returned false, stopping service after a while')
return
while True:
brokerConnected = self.interactWithBroker()
if brokerConnected is False:
logger.debug('Interact with broker returned false, stopping service after a while')
return
elif brokerConnected is True:
break
# If brokerConnected returns None, repeat the cycle
self.doWait(16000) # Wait for a looong while
if self.isAlive is False:
logger.debug('The service is not alive after broker interaction, stopping it')

View File

@@ -57,7 +57,7 @@ def _getMacAddr(ifname):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = bytearray(fcntl.ioctl(s.fileno(), 0x8927, struct.pack(str('256s'), ifname[:15])))
return six.text_type(''.join(['%02x:' % char for char in info[18:24]])[:-1])
return six.text_type(''.join(['%02x:' % char for char in info[18:24]])[:-1]).upper()
except Exception:
return None
@@ -194,8 +194,10 @@ try:
# Fix result type to XScreenSaverInfo Structure
xss.XScreenSaverQueryExtension.restype = ctypes.c_int
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo) # Result in a XScreenSaverInfo structure
display = xlib.XOpenDisplay(None)
info = xss.XScreenSaverAllocInfo()
except Exception: # Libraries not accesible, not found or whatever..
xlib = xss = None
xlib = xss = display = info = None
def initIdleDuration(atLeastSeconds):
@@ -208,6 +210,8 @@ def initIdleDuration(atLeastSeconds):
threading._DummyThread._Thread__stop = lambda x: 42
subprocess.call(['/usr/bin/xset', 's', '{}'.format(atLeastSeconds + 30)])
# And now reset it
subprocess.call(['/usr/bin/xset', 's', 'reset'])
def getIdleDuration():
@@ -217,18 +221,20 @@ def getIdleDuration():
if xlib is None or xss is None:
return 0 # Libraries not available
# production code might want to not hardcode the offset 16...
display = xlib.XOpenDisplay(None)
event_base = ctypes.c_int()
error_base = ctypes.c_int()
available = xss.XScreenSaverQueryExtension(display, ctypes.byref(event_base), ctypes.byref(error_base))
if available != 1:
return 0
info = xss.XScreenSaverAllocInfo()
if available != 1:
return 0 # No screen saver is available, no way of getting idle
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), info)
# Centos seems to set state to 1?? (weird, but it's happening don't know why... will try this way)
if info.contents.state != 0 and 'centos' not in platform.linux_distribution()[0].lower().strip():
return 3600 * 100 * 1000 # If screen saver is active, return a high enough value
return info.contents.idle / 1000.0

View File

@@ -31,6 +31,7 @@
'''
from __future__ import unicode_literals
import traceback
import sys
import six
@@ -50,6 +51,10 @@ class Logger(object):
self.remoteLogger = None
def setLevel(self, level):
'''
Sets log level filter (minimum level required for a log message to be processed)
:param level: Any message with a level below this will be filtered out
'''
self.logLevel = int(level) # Ensures level is an integer or fails
def setRemoteLogger(self, remoteLogger):
@@ -75,7 +80,7 @@ class Logger(object):
self.log(WARN, message)
def info(self, message):
self.log(WARN, message)
self.log(INFO, message)
def error(self, message):
self.log(ERROR, message)
@@ -83,6 +88,14 @@ class Logger(object):
def fatal(self, message):
self.log(FATAL, message)
def exception(self):
try:
tb = traceback.format_exc()
except Exception:
tb = '(could not get traceback!)'
self.log(DEBUG, tb)
def flush(self):
pass

View File

@@ -108,7 +108,7 @@ class CommonService(object):
ids = ','.join([i.mac for i in netInfo])
if ids == '':
# Wait for any network interface to be ready
logger.debug('No network interfaces found, retrying in a while...')
logger.debug('No valid network interfaces found, retrying in a while...')
raise Exception()
logger.debug('Ids: {}'.format(ids))
self.api.init(ids)
@@ -126,7 +126,7 @@ class CommonService(object):
logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
return False # On unmanaged hosts, there is no reason right now to continue running
except Exception as e:
logger.debug('Exception caught: {}, retrying'.format(exceptionToMessage(e)))
logger.debug('Exception on network info: retrying')
# Any other error is expectable and recoverable, so let's wait a bit and retry again
# but, if too many errors, will log it (one every minute, for
# example)
@@ -151,9 +151,11 @@ class CommonService(object):
if data[0] == 'rename':
try:
if len(params) == 1: # Simple rename
logger.debug('Renaming computer to {}'.format(params[0]))
self.rename(params[0])
# Rename with change password for an user
elif len(params) == 4:
logger.debug('Renaming computer to {}'.format(params))
self.rename(params[0], params[1], params[2], params[3])
else:
logger.error('Got invalid parameter for rename operation: {}'.format(params))
@@ -161,11 +163,11 @@ class CommonService(object):
break
except Exception as e:
logger.error('Error at computer renaming stage: {}'.format(e.message))
return False
return None # Will retry complete broker connection if this point is reached
elif data[0] == 'domain':
if len(params) != 5:
logger.error('Got invalid parameters for domain message: {}'.format(params))
return False
return False # Stop running service
self.joinDomain(params[0], params[1], params[2], params[3], params[4])
break
else:
@@ -174,10 +176,10 @@ class CommonService(object):
except REST.UserServiceNotFoundError:
logger.error('The host has lost the sync state with broker! (host uuid changed?)')
return False
except Exception:
counter += 1
except Exception as err:
if counter % 60 == 0:
logger.warn('Too many retries in progress, though still trying (last error: {})'.format(exceptionToMessage(e)))
logger.warn('Too many retries in progress, though still trying (last error: {})'.format(exceptionToMessage(err)))
counter += 1
# Any other error is expectable and recoverable, so let's wait
# a bit and retry again
# Wait a bit before next check
@@ -193,7 +195,7 @@ class CommonService(object):
return True
def checkIpsChanged(self):
if self.api.uuid is None:
if self.api is None or self.api.uuid is None:
return # Not connected
netInfo = tuple(operations.getNetworkInfo())
for i in netInfo:
@@ -203,8 +205,17 @@ class CommonService(object):
try:
# Notifies all interfaces IPs
self.api.notifyIpChanges(((v.mac, v.ip) for v in netInfo))
# Regenerates Known ips
self.knownIps = dict(((i.mac, i.ip) for i in netInfo))
self.knownIps = dict(((v.mac, v.ip) for v in netInfo))
# And notify new listening address to broker
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
# And new listening address
self.httpServer.restart(address)
# sends notification
self.api.notifyComm(self.httpServer.getServerUrl())
except Exception as e:
logger.warn('Got an error notifiying IPs to broker: {} (will retry in a bit)'.format(e.message.decode('windows-1250', 'ignore')))
@@ -215,14 +226,21 @@ class CommonService(object):
return
if msg == ipc.REQ_LOGIN:
self.api.login(data)
elif msg == ipc.REQ_LOGOUT:
res = self.api.login(data).split('\t')
# third parameter, if exists, sets maxSession duration to this.
# First & second parameters are ip & hostname of connection source
if len(res) >= 3:
self.api.maxSession = int(res[2]) # Third parameter is max session duration
msg = ipc.REQ_INFORMATION # Senf information, requested or not, to client on login notification
if msg == ipc.REQ_LOGOUT:
self.api.logout(data)
self.onLogout(data)
elif msg == ipc.REQ_INFORMATION:
if msg == ipc.REQ_INFORMATION:
info = {}
if self.api.idle is not None:
info['idle'] = self.api.idle
if self.api.maxSession is not None:
info['maxSession'] = self.api.maxSession
self.ipc.sendInformationMessage(info)
def initIPC(self):
@@ -234,8 +252,8 @@ class CommonService(object):
self.ipc.start()
if self.api.mac in self.knownIps:
address = (self.knownIps[self.api.mac], random.randrange(40000, 44000))
logger.debug('Starting REST listener at {}'.format(address))
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
logger.info('Starting REST listener at {}'.format(address))
self.httpServer = httpserver.HTTPServerThread(address, self)
self.httpServer.start()
# And notify it to broker

View File

@@ -76,7 +76,7 @@ class SensLogon(win32com.server.policy.DesignatedWrapPolicy):
data = self.service.api.login(args[0])
logger.debug('Data received for login: {}'.format(data))
data = data.split('\t')
if len(data) == 2:
if len(data) >= 2:
logger.debug('Data is valid: {}'.format(data))
windir = os.environ['windir']
with open(os.path.join(windir, 'remoteip.txt'), 'w') as f:

View File

@@ -40,6 +40,7 @@ import win32event # @UnresolvedImport, pylint: disable=import-error
import win32com.client # @UnresolvedImport, @UnusedImport, pylint: disable=import-error
import pythoncom # @UnresolvedImport, pylint: disable=import-error
import servicemanager # @UnresolvedImport, pylint: disable=import-error
import os
from udsactor import operations
from udsactor.service import CommonService
@@ -137,13 +138,15 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
currName = operations.getComputerName()
if currName.lower() == name.lower():
currDomain = operations.getDomainName()
if currDomain is not None and currDomain.lower() == domain.lower():
if currDomain is not None:
# logger.debug('Name: "{}" vs "{}", Domain: "{}" vs "{}"'.format(currName.lower(), name.lower(), currDomain.lower(), domain.lower()))
logger.info(
'Machine {} is part of domain {}'.format(name, domain))
self.setReady()
else:
operations.joinDomain(
domain, ou, account, password, executeInOneStep=False)
self.reboot()
else:
operations.renameComputer(name)
logger.info(
@@ -153,7 +156,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
def joinDomain(self, name, domain, ou, account, password):
ver = operations.getWindowsVersion()
ver = ver[0] * 10 + ver[1]
logger.info('Starting joining domain {} with name {} (detected operating version: {})'.format(
logger.debug('Starting joining domain {} with name {} (detected operating version: {})'.format(
domain, name, ver))
# Accepts one step joinDomain, also remember XP is no more supported by
# microsoft, but this also must works with it because will do a "multi
@@ -164,6 +167,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
self.multiStepJoin(name, domain, ou, account, password)
def preConnect(self, user, protocol):
logger.debug('Pre connect invoked')
if protocol != 'rdp': # If connection is not using rdp, skip adding user
return 'ok'
# Well known SSID for Remote Desktop Users
@@ -216,38 +220,56 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
'''
Main service loop
'''
initCfg()
try:
initCfg()
logger.debug('running SvcDoRun')
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
logger.debug('running SvcDoRun')
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
# call the CoInitialize to allow the registration to run in an other
# thread
logger.debug('Initializing com...')
pythoncom.CoInitialize()
# call the CoInitialize to allow the registration to run in an other
# thread
logger.debug('Initializing com...')
pythoncom.CoInitialize()
# ********************************************************
# * Ask brokers what to do before proceding to main loop *
# ********************************************************
if self.interactWithBroker() is False:
logger.debug('Interact with broker returned false, stopping service after a while')
self.notifyStop()
win32event.WaitForSingleObject(self.hWaitStop, 5000)
return
# ********************************************************
# * Ask brokers what to do before proceding to main loop *
# ********************************************************
while True:
brokerConnected = self.interactWithBroker()
if brokerConnected is False:
logger.debug('Interact with broker returned false, stopping service after a while')
self.notifyStop()
win32event.WaitForSingleObject(self.hWaitStop, 5000)
return
elif brokerConnected is True:
break
if self.isAlive is False:
logger.debug('The service is not alive after broker interaction, stopping it')
self.notifyStop()
return
# If brokerConnected returns None, repeat the cycle
self.doWait(16000) # Wait for a looong while
if self.rebootRequested is True:
logger.debug('Reboot has been requested, stopping service')
self.notifyStop()
return
if self.interactWithBroker() is False:
logger.debug('Interact with broker returned false, stopping service after a while')
self.notifyStop()
win32event.WaitForSingleObject(self.hWaitStop, 5000)
return
self.initIPC()
if self.isAlive is False:
logger.debug('The service is not alive after broker interaction, stopping it')
self.notifyStop()
return
if self.rebootRequested is True:
logger.debug('Reboot has been requested, stopping service')
self.notifyStop()
return
self.initIPC()
except Exception: # Any init exception wil be caught, service must be then restarted
logger.exception()
logger.debug('Exiting service with failure status')
os._exit(-1) # pylint: disable=protected-access
# ********************************
# * Registers SENS subscriptions *
@@ -281,8 +303,12 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
# Process SENS messages, This will be a bit asyncronous (1 second
# delay)
pythoncom.PumpWaitingMessages()
if counter % 10 == 0:
self.checkIpsChanged()
if counter >= 15: # Once every 15 seconds
counter = 0
try:
self.checkIpsChanged()
except Exception as e:
logger.error('Error checking ip change: {}'.format(e))
# In milliseconds, will break
win32event.WaitForSingleObject(self.hWaitStop, 1000)

View File

@@ -48,7 +48,7 @@ class LocalLogger(object):
filename=os.path.join(tempfile.gettempdir(), 'udsactor.log'),
filemode='a',
format='%(levelname)s %(asctime)s %(message)s',
level=logging.DEBUG
level=logging.INFO
)
self.logger = logging.getLogger('udsactor')
self.serviceLogger = False

View File

@@ -45,6 +45,7 @@ from udsactor.log import logger
def getErrorMessage(res=0):
# sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
msg = win32api.FormatMessage(res)
return msg.decode('windows-1250', 'ignore')
@@ -62,8 +63,9 @@ def getNetworkInfo():
for ip in obj.IPAddress:
if ':' in ip: # Is IPV6, skip this
continue
if ip == '' or ip is None:
if ip is None or ip == '' or ip.startswith('169.254') or ip.startswith('0.'): # If single link ip, or no ip
continue
# logger.debug('Net config found: {}=({}, {})'.format(obj.Caption, obj.MACAddress, ip))
yield utils.Bunch(name=obj.Caption, mac=obj.MACAddress, ip=ip)
except Exception:
return
@@ -111,7 +113,7 @@ def loggoff():
def renameComputer(newName):
# Needs admin privileges to work
if ctypes.windll.kernel32.SetComputerNameExW(DWORD(win32con.ComputerNamePhysicalDnsHostname), LPCWSTR(newName)) == 0:
if ctypes.windll.kernel32.SetComputerNameExW(DWORD(win32con.ComputerNamePhysicalDnsHostname), LPCWSTR(newName)) == 0: # @UndefinedVariable
# win32api.FormatMessage -> returns error string
# win32api.GetLastError -> returns error code
# (just put this comment here to remember to log this when logger is available)
@@ -131,6 +133,14 @@ NETSETUP_DEFER_SPN_SET = 0x1000000
def joinDomain(domain, ou, account, password, executeInOneStep=False):
'''
Joins machine to a windows domain
:param domain: Domain to join to
:param ou: Ou that will hold machine
:param account: Account used to join domain
:param password: Password of account used to join domain
:param executeInOneStep: If true, means that this machine has been renamed and wants to add NETSETUP_JOIN_WITH_NEW_NAME to request so we can do rename/join in one step.
'''
# If account do not have domain, include it
if '@' not in account and '\\' not in account:
if '.' in domain:
@@ -138,7 +148,6 @@ def joinDomain(domain, ou, account, password, executeInOneStep=False):
else:
account = domain + '\\' + account
# Do log
flags = NETSETUP_ACCT_CREATE | NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN
@@ -162,8 +171,10 @@ def joinDomain(domain, ou, account, password, executeInOneStep=False):
if res != 0:
# Log the error
error = getErrorMessage(res)
print res, error
raise Exception('Error joining domain {}, with credentials {}/*****{}: {}, {}'.format(domain.value, account.value, ', under OU {}'.format(ou.value) if ou.value != None else '', res, error))
if res == 1355:
error = "DC Is not reachable"
logger.error('Error joining domain: {}, {}'.format(error, res))
raise Exception('Error joining domain {}, with credentials {}/*****{}: {}, {}'.format(domain, account, ', under OU {}'.format(ou) if ou is not None else '', res, error))
def changeUserPassword(user, oldPassword, newPassword):
@@ -198,7 +209,7 @@ def getIdleDuration():
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo))
millis = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime
millis = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime # @UndefinedVariable
return millis / 1000.0

View File

@@ -83,12 +83,13 @@ def readConfig():
return None
def writeConfig(data):
def writeConfig(data, fixPermissions=True):
try:
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
except Exception:
key = wreg.CreateKeyEx(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
fixRegistryPermissions(key.handle)
if fixPermissions is True:
fixRegistryPermissions(key.handle)
wreg.SetValueEx(key, "", 0, wreg.REG_BINARY, encoder(cPickle.dumps(data))) # @UndefinedVariable
wreg.CloseKey(key) # @UndefinedVariable

15
actors/src/update.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
function process {
pyuic4 about-dialog.ui -o about_dialog_ui.py -x
pyuic4 message-dialog.ui -o message_dialog_ui.py -x
pyuic4 setup-dialog.ui -o setup_dialog_ui.py -x
}
pyrcc4 -py3 UDSActor.qrc -o UDSActor_rc.py
# process current directory ui's
process

4
client/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/bin
/udsclient_*
/udsclient-*.tar.gz
/*.rpm

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>linuxActor</name>
<name>UDSclient</name>
<comment></comment>
<projects>
</projects>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/${PROJECT_DIR_NAME}/src</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>

4
client/linux/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/udsclient-opensuse-[0-9]*.spec
/udsclient-[0-9]*.spec
/debian/udsclient
/targz

51
client/linux/Makefile Normal file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Version
# VERSION := 1.7.5
# Directories
SOURCEDIR := ../src
LIBDIR := $(DESTDIR)/usr/lib/UDSClient
BINDIR := $(DESTDIR)/usr/bin
SBINDIR = $(DESTDIR)/usr/sbin
APPSDIR := $(DESTDIR)/usr/share/applications
PYC := $(shell find $(SOURCEDIR) -name '*.py[co]')
CACHES := $(shell find $(SOURCEDIR) -name '__pycache__')
clean:
rm -rf $(PYC) $(CACHES) $(DESTDIR)
install:
rm -rf $(DESTDIR)
mkdir -p $(LIBDIR)
#mkdir -p $(BINDIR)
#mkdir -p $(SBINDIR)
mkdir -p $(APPSDIR)
mkdir $(LIBDIR)/uds
# Cleans up .pyc and cache folders
rm -f $(PYC) $(CACHES)
cp $(SOURCEDIR)/uds/*.py $(LIBDIR)/uds
cp $(SOURCEDIR)/UDS*.py $(LIBDIR)
# URL Catchers elements for gnome/kde
cp desktop/UDSClient.desktop $(APPSDIR)
chmod 755 $(LIBDIR)/UDSClient.py
ifeq ($(DISTRO),targz)
cp installer.sh $(DESTDIR)/install.sh
tar czvf ../udsclient-$(VERSION).tar.gz -C $(DESTDIR) .
endif
# chmod 0755 $(BINDIR)/udsclient
uninstall:
rm -rf $(LIBDIR)
# rm -f $(BINDIR)/udsclient
# rm -rf $(CFGDIR)

36
client/linux/build-packages.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
VERSION=`cat ../../VERSION`
RELEASE=1
# Debian based
dpkg-buildpackage -b
# Now rpm based
top=`pwd`
cat udsclient-template.spec |
sed -e s/"version 0.0.0"/"version ${VERSION}"/g |
sed -e s/"release 1"/"release ${RELEASE}"/g > udsclient-$VERSION.spec
# Now fix dependencies for opensuse
cat udsclient-template.spec |
sed -e s/"version 0.0.0"/"version ${VERSION}"/g |
sed -e s/"name udsclient"/"name udsclient-opensuse"/g |
sed -e s/"PyQt4"/"python-qt4"/g |
sed -e s/"libXScrnSaver"/"libXss1"/g > udsclient-opensuse-$VERSION.spec
# Right now, udsactor-xrdp-.spec is not needed
for pkg in udsclient-$VERSION.spec udsclient-opensuse-$VERSION.spec; do
rm -rf rpm
for folder in SOURCES BUILD RPMS SPECS SRPMS; do
mkdir -p rpm/$folder
done
rpmbuild -v -bb --clean --buildroot=$top/rpm/BUILD/$pkg-root --target noarch $pkg 2>&1
done
#rm udsclient-$VERSION
make DESTDIR=targz DISTRO=targz VERSION=${VERSION} install

3
client/linux/debian/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/udsactor/
/udsactor-xrdp/
/udsactor-nx/

View File

@@ -0,0 +1,23 @@
udsclient (2.0.0) stable; urgency=medium
* Release upgrade
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 01 Mar 2016 09:33:18 +0100
udsclient (1.9.1) stable; urgency=medium
* Minor fixes & making version match UDS version
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 01 Mar 2016 03:02:37 +0100
udsclient (1.9.0) stable; urgency=medium
* Minor fixes & making version match UDS version
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 05 May 2015 07:03:47 +0200
udsclient (1.7.5) stable; urgency=medium
* Initial release.
-- Adolfo Gómez García <agomez@virtualcable.es> Fri, 10 Apr 2015 05:32:41 +0100

View File

@@ -0,0 +1 @@
9

View File

@@ -0,0 +1,15 @@
Source: udsclient
Section: admin
Priority: optional
Maintainer: Adolfo Gómez García <agomez@virtualcable.es>
Build-Depends: debhelper (>= 7), po-debconf
Standards-Version: 3.9.2
Homepage: http://www.virtualcable.es
Package: udsclient
Section: admin
Priority: optional
Architecture: all
Depends: python-paramiko (>=0.8.2), python-qt4 (>=4.9), python-six(>=1.1), python (>=2.7), rdesktop | freerdp-x11, desktop-file-utils, ${misc:Depends}
Description: Client connector for Universal Desktop Services (UDS) Broker
This package provides the required components to allow this machine to connect to services provided by UDS Broker.

View File

@@ -1,5 +1,5 @@
Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
Name: udsactor
Name: udsclient
Maintainer: Adolfo Gómez García
Source: http://www.udsenterprise.com/
@@ -23,4 +23,4 @@ with this program; if not, write to the Free Software Foundation, Inc.,
.
On Debian systems, the full text of the GNU General Public
License version 2 can be found in the file
`/usr/share/common-licenses/GPL-2'.
`/usr/share/common-licenses/GPL-2'.

View File

@@ -0,0 +1 @@
udsclient_2.0.0_all.deb admin optional

View File

@@ -21,7 +21,7 @@ install: build
dh_testroot
dh_prep
dh_installdirs
$(MAKE) DESTDIR=$(CURDIR)/debian/udsactor install
$(MAKE) DESTDIR=$(CURDIR)/debian/udsclient install
binary-arch: build install
# emptyness
binary-indep: build install

View File

@@ -0,0 +1,17 @@
dh_prep
dh_installdirs
dh_installchangelogs
dh_installdocs
dh_installdebconf
dh_installinit
dh_compress
dh_link
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
dh_builddeb
dh_builddeb
dh_builddeb

View File

@@ -0,0 +1,21 @@
#!/bin/sh
. /usr/share/debconf/confmodule
set -e
case "$1" in
configure)
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
#DEBHELPER#
exit 0

View File

@@ -0,0 +1,6 @@
#!/bin/sh -e
. /usr/share/debconf/confmodule
set -e

View File

@@ -0,0 +1 @@
#! /bin/bash -e

View File

@@ -1,19 +1,20 @@
Template: udsactor/server
Template: udsactor/host
Type: string
Default:
_Description: UDS Server address:
Description: UDS Server address:
The actor needs the address of the server in order to communicate with it.
Provide here full address (or i) of the UDS server
Template: udsactor/secure
Type: boolean
Default: true
_Description: Use secure (https) connection to communicate with UDS server?
Description: Use secure (https) connection to communicate with UDS server?
If selected, the communication will be done using https.
If not selected, the communication will be done using http
Template: udsactor/timeout
Template: udsactor/masterKey
Type: string
Default: 5
_Description: Timeout in communications with UDS server:
The timeout is expressed in seconds
Default:
Description: Master Key:
This key is available on UDS Administration interface.
Look for it under configuration, on Security tab.

View File

@@ -0,0 +1,11 @@
[Desktop Entry]
Name=UDSClient
Comment=UDS Helper
Keywords=uds;client;vdi;
Exec=/usr/lib/UDSClient/UDSClient.py %u
Icon=help-browser
StartupNotify=true
Terminal=false
Type=Application
Categories=Utility;
MimeType=x-scheme-handler/uds;x-scheme-handler/udss;

14
client/linux/installer.sh Normal file
View File

@@ -0,0 +1,14 @@
#!/bin/sh
cp -r usr/lib/UDSClient /usr/lib/UDSClient
cp -r usr/share/applications /usr/lib/applications -R
update-desktop-database
echo "Installation process done."
echo "Remembar that the following packages must be installed on system:"
echo "* Python paramiko"
echo "* Python pyqt4"
echo "Theese packages (as their names), are dependent on your platform, so you must locate and install them"
echo "You can install them directly on any platform with pip, using this simple command: "
echo "pip install PyQt4 paramiko"

3
client/linux/readme.txt Normal file
View File

@@ -0,0 +1,3 @@
UDSClient is the client connector needed to get acccess to services managed by UDS Broker.
Please, visit http://www.udsenterprise.com for more information

View File

@@ -0,0 +1,51 @@
%define _topdir %(echo $PWD)/rpm
%define name udsclient
%define version 0.0.0
%define release 1
%define buildroot %{_topdir}/%{name}-%{version}-%{release}-root
BuildRoot: %{buildroot}
Name: %{name}
Version: %{version}
Release: %{release}
Summary: Client for Universal Desktop Services (UDS) Broker
License: BSD3
Group: Applications/Productivity
Requires: python-six python-paramiko PyQt4
Vendor: Virtual Cable S.L.U.
URL: http://www.udsenterprise.com
Provides: udsclient
%define _rpmdir ../
%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
%install
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh install
cd $curdir
%post
/usr/bin/update-desktop-database
%clean
rm -rf $RPM_BUILD_ROOT
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh clean
cd $curdir
%postun
# And, posibly, the .pyc leaved behind on /usr/share/UDSActor
rm -rf /usr/share/UDClient > /dev/null 2>&1
/usr/bin/update-desktop-database
%description
This package provides the required components to allow connection to services offered by UDS Broker.
%files
%defattr(-,root,root)
/usr/lib/UDSClient/*
/usr/share/applications/UDSClient.desktop

4
client/src/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/build
/dist
UDSClient.dmg
UDSClient.pkg

310
client/src/UDSClient.py Executable file
View File

@@ -0,0 +1,310 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# 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 __future__ import unicode_literals
import sys
from PyQt4 import QtCore, QtGui
import six
from uds.rest import RestRequest
from uds.forward import forward
from uds.log import logger
from uds import tools
from uds import VERSION
import webbrowser
from UDSWindow import Ui_MainWindow
class RetryException(Exception):
pass
class UDSClient(QtGui.QMainWindow):
ticket = None
scrambler = None
withError = False
animTimer = None
anim = 0
animInverted = False
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.progressBar.setValue(0)
self.ui.cancelButton.clicked.connect(self.cancelPushed)
self.ui.info.setText('Initializing...')
screen = QtGui.QDesktopWidget().screenGeometry()
mysize = self.geometry()
hpos = (screen.width() - mysize.width()) / 2
vpos = (screen.height() - mysize.height() - mysize.height()) / 2
self.move(hpos, vpos)
self.animTimer = QtCore.QTimer()
QtCore.QObject.connect(self.animTimer, QtCore.SIGNAL('timeout()'), self.updateAnim)
self.activateWindow()
self.startAnim()
def closeWindow(self):
self.close()
def processError(self, data):
if 'error' in data:
# QtGui.QMessageBox.critical(self, 'Request error {}'.format(data.get('retryable', '0')), data['error'], QtGui.QMessageBox.Ok)
if data.get('retryable', '0') == '1':
raise RetryException(data['error'])
raise Exception(data['error'])
# QtGui.QMessageBox.critical(self, 'Request error', rest.data['error'], QtGui.QMessageBox.Ok)
# self.closeWindow()
# return
def showError(self, e):
logger.error('got error: {}'.format(e))
self.stopAnim()
self.ui.info.setText('UDS Plugin Error') # In fact, main window is hidden, so this is not visible... :)
self.closeWindow()
QtGui.QMessageBox.critical(None, 'UDS Plugin Error', '{}'.format(e), QtGui.QMessageBox.Ok)
self.withError = True
def cancelPushed(self):
self.close()
@QtCore.pyqtSlot()
def updateAnim(self):
self.anim += 2
if self.anim > 99:
self.animInverted = not self.animInverted
self.ui.progressBar.setInvertedAppearance(self.animInverted)
self.anim = 0
self.ui.progressBar.setValue(self.anim)
def startAnim(self):
self.ui.progressBar.invertedAppearance = False
self.anim = 0
self.animInverted = False
self.ui.progressBar.setInvertedAppearance(self.animInverted)
self.animTimer.start(40)
def stopAnim(self):
self.ui.progressBar.invertedAppearance = False
self.animTimer.stop()
@QtCore.pyqtSlot()
def getVersion(self):
self.req = RestRequest('', self, self.version)
self.req.get()
@QtCore.pyqtSlot(dict)
def version(self, data):
try:
self.processError(data)
self.ui.info.setText('Processing...')
if data['result']['requiredVersion'] > VERSION:
QtGui.QMessageBox.critical(self, 'Upgrade required', 'A newer connector version is required.\nA browser will be opened to download it.', QtGui.QMessageBox.Ok)
webbrowser.open(data['result']['downloadUrl'])
self.closeWindow()
return
self.getTransportData()
except RetryException as e:
self.ui.info.setText(six.text_type(e))
QtCore.QTimer.singleShot(1000, self.getVersion)
except Exception as e:
self.showError(e)
@QtCore.pyqtSlot()
def getTransportData(self):
try:
self.req = RestRequest('/{}/{}'.format(self.ticket, self.scrambler), self, self.transportDataReceived, params={'hostname': tools.getHostName(), 'version': VERSION})
self.req.get()
except Exception as e:
logger.exception('Got exception: {}'.format(e))
raise e
@QtCore.pyqtSlot(dict)
def transportDataReceived(self, data):
logger.debug('Transport data received')
try:
self.processError(data)
script = data['result'].decode('base64').decode('bz2')
self.stopAnim()
if 'darwin' in sys.platform:
self.showMinimized()
QtCore.QTimer.singleShot(3000, self.endScript)
self.hide()
six.exec_(script, globals(), {'parent': self})
except RetryException as e:
self.ui.info.setText(six.text_type(e) + ', retrying access...')
# Retry operation in ten seconds
QtCore.QTimer.singleShot(10000, self.getTransportData)
except Exception as e:
logger.exception('Got exception executing script:')
self.showError(e)
def endScript(self):
# After running script, wait for stuff
try:
tools.waitForTasks()
except Exception:
pass
try:
tools.unlinkFiles()
except Exception:
pass
try:
tools.execBeforeExit()
except Exception:
pass
self.closeWindow()
def start(self):
'''
Starts proccess by requesting version info
'''
self.ui.info.setText('Initializing...')
QtCore.QTimer.singleShot(100, self.getVersion)
def done(data):
QtGui.QMessageBox.critical(None, 'Notice', six.text_type(data.data), QtGui.QMessageBox.Ok)
sys.exit(0)
# Ask user to aprobe endpoint
def approveHost(host, parentWindow=None):
settings = QtCore.QSettings()
settings.beginGroup('endpoints')
approved = settings.value(host, False).toBool()
errorString = '<p>The server <b>{}</b> must be approved:</p>'.format(host)
errorString += '<p>Only approve UDS servers that you trust to avoid security issues.</p>'
if approved or QtGui.QMessageBox.warning(parentWindow, 'ACCESS Warning', errorString, QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) == QtGui.QMessageBox.Yes:
settings.setValue(host, True)
approved = True
settings.endGroup()
return approved
if __name__ == "__main__":
logger.debug('Initializing connector')
# Initialize app
app = QtGui.QApplication(sys.argv)
# Set several info for settings
QtCore.QCoreApplication.setOrganizationName('Virtual Cable S.L.U.')
QtCore.QCoreApplication.setApplicationName('UDS Connector')
if 'darwin' not in sys.platform:
logger.debug('Mac OS *NOT* Detected')
app.setStyle('plastique')
if six.PY3 is False:
logger.debug('Fixing threaded execution of commands')
import threading
threading._DummyThread._Thread__stop = lambda x: 42
# First parameter must be url
try:
uri = sys.argv[1]
if uri == '--test':
sys.exit(0)
logger.debug('URI: {}'.format(uri))
if uri[:6] != 'uds://' and uri[:7] != 'udss://':
raise Exception()
ssl = uri[3] == 's'
host, UDSClient.ticket, UDSClient.scrambler = uri.split('//')[1].split('/')
logger.debug('ssl: {}, host:{}, ticket:{}, scrambler:{}'.format(ssl, host, UDSClient.ticket, UDSClient.scrambler))
except Exception:
logger.debug('Detected execution without valid URI, exiting')
QtGui.QMessageBox.critical(None, 'Notice', 'UDS Client Version {}'.format(VERSION), QtGui.QMessageBox.Ok)
sys.exit(1)
# Setup REST api endpoint
RestRequest.restApiUrl = '{}://{}/rest/client'.format(['http', 'https'][ssl], host)
logger.debug('Setting requert URL to {}'.format(RestRequest.restApiUrl))
# RestRequest.restApiUrl = 'https://172.27.0.1/rest/client'
try:
logger.debug('Starting execution')
# Approbe before going on
if approveHost(host) is False:
raise Exception('Host {} was not approved'.format(host))
win = UDSClient()
win.show()
win.start()
exitVal = app.exec_()
logger.debug('Execution finished correctly')
except Exception as e:
logger.exception('Got an exception executing client:')
exitVal = 128
QtGui.QMessageBox.critical(None, 'Error', six.text_type(e), QtGui.QMessageBox.Ok)
logger.debug('Exiting')
sys.exit(exitVal)

View File

@@ -0,0 +1,6 @@
<RCC>
<qresource prefix="images">
<file alias="logo-uds-small">images/logo-uds-small.png</file>
<file alias="logo-uds-big">images/logo-uds.png</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

105
client/src/UDSWindow.py Normal file
View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'UDSWindow.ui'
#
# Created: Mon Apr 27 21:41:43 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.setWindowModality(QtCore.Qt.NonModal)
MainWindow.resize(259, 185)
MainWindow.setCursor(QtGui.QCursor(QtCore.Qt.BusyCursor))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/images/logo-uds-small")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
MainWindow.setWindowOpacity(1.0)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setAutoFillBackground(True)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout_2 = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout_2.setSpacing(4)
self.verticalLayout_2.setMargin(4)
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.frame = QtGui.QFrame(self.centralwidget)
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame.setFrameShadow(QtGui.QFrame.Raised)
self.frame.setObjectName(_fromUtf8("frame"))
self.verticalLayout_3 = QtGui.QVBoxLayout(self.frame)
self.verticalLayout_3.setSpacing(4)
self.verticalLayout_3.setMargin(4)
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.image = QtGui.QLabel(self.frame)
self.image.setMinimumSize(QtCore.QSize(0, 24))
self.image.setAutoFillBackground(True)
self.image.setText(_fromUtf8(""))
self.image.setPixmap(QtGui.QPixmap(_fromUtf8(":/images/logo-uds-small")))
self.image.setScaledContents(False)
self.image.setAlignment(QtCore.Qt.AlignCenter)
self.image.setObjectName(_fromUtf8("image"))
self.verticalLayout.addWidget(self.image)
self.info = QtGui.QLabel(self.frame)
self.info.setMaximumSize(QtCore.QSize(16777215, 16))
self.info.setObjectName(_fromUtf8("info"))
self.verticalLayout.addWidget(self.info)
self.progressBar = QtGui.QProgressBar(self.frame)
self.progressBar.setProperty("value", 24)
self.progressBar.setTextVisible(False)
self.progressBar.setObjectName(_fromUtf8("progressBar"))
self.verticalLayout.addWidget(self.progressBar)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.cancelButton = QtGui.QPushButton(self.frame)
self.cancelButton.setDefault(True)
self.cancelButton.setFlat(False)
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
self.horizontalLayout.addWidget(self.cancelButton)
spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.verticalLayout.addLayout(self.horizontalLayout)
self.verticalLayout_3.addLayout(self.verticalLayout)
self.verticalLayout_2.addWidget(self.frame)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "UDS Connection", None))
self.info.setText(_translate("MainWindow", "TextLabel", None))
self.cancelButton.setText(_translate("MainWindow", "Cancel", None))
import UDSResources_rc
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

160
client/src/UDSWindow.ui Normal file
View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>259</width>
<height>185</height>
</rect>
</property>
<property name="cursor">
<cursorShape>BusyCursor</cursorShape>
</property>
<property name="windowTitle">
<string>UDS Connection</string>
</property>
<property name="windowIcon">
<iconset resource="UDSResources.qrc">
<normaloff>:/images/logo-uds-small</normaloff>:/images/logo-uds-small</iconset>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<widget class="QWidget" name="centralwidget">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>4</number>
</property>
<property name="margin">
<number>4</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>4</number>
</property>
<property name="margin">
<number>4</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="image">
<property name="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="UDSResources.qrc">:/images/logo-uds-small</pixmap>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="info">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
<resources>
<include location="UDSResources.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
client/src/images/uds.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
client/src/macosx/uds.icns Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# 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 __future__ import unicode_literals
# On centos, old six release does not includes byte2int, nor six.PY2
import six
VERSION = '2.0.0'
__title__ = 'udclient'
__version__ = VERSION
__build__ = 0x010750
__author__ = 'Adolfo Gómez'
__license__ = "BSD 3-clause"
__copyright__ = "Copyright 2014-2015 VirtualCable S.L.U."

193
client/src/uds/forward.py Normal file
View File

@@ -0,0 +1,193 @@
# Based on forward.py from paramiko
# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
# https://github.com/paramiko/paramiko/blob/master/demos/forward.py
from __future__ import unicode_literals
import select
import SocketServer
import paramiko
import threading
import random
import time
from .log import logger
class ForwardServer(SocketServer.ThreadingTCPServer):
daemon_threads = True
allow_reuse_address = True
class Handler(SocketServer.BaseRequestHandler):
def handle(self):
self.thread.currentConnections += 1
try:
chan = self.ssh_transport.open_channel('direct-tcpip',
(self.chain_host, self.chain_port),
self.request.getpeername())
except Exception as e:
logger.exception('Incoming request to %s:%d failed: %s' % (self.chain_host,
self.chain_port,
repr(e)))
return
if chan is None:
logger.error('Incoming request to %s:%d was rejected by the SSH server.' %
(self.chain_host, self.chain_port))
return
logger.debug('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(),
chan.getpeername(), (self.chain_host, self.chain_port)))
try:
while self.event.is_set() is False:
r, _w, _x = select.select([self.request, chan], [], [], 1)
if self.request in r:
data = self.request.recv(1024)
if len(data) == 0:
break
chan.send(data)
if chan in r:
data = chan.recv(1024)
if len(data) == 0:
break
self.request.send(data)
except Exception:
pass
try:
peername = self.request.getpeername()
chan.close()
self.request.close()
logger.debug('Tunnel closed from %r' % (peername,))
except Exception:
pass
self.thread.currentConnections -= 1
if self.thread.stoppable is True and self.thread.currentConnections == 0:
self.thread.stop()
class ForwardThread(threading.Thread):
status = 0 # Connecting
def __init__(self, server, port, username, password, localPort, redirectHost, redirectPort, waitTime):
threading.Thread.__init__(self)
self.client = None
self.fs = None
self.server = server
self.port = int(port)
self.username = username
self.password = password
self.localPort = int(localPort)
self.redirectHost = redirectHost
self.redirectPort = redirectPort
self.waitTime = waitTime
self.stopEvent = threading.Event()
self.timer = None
self.currentConnections = 0
self.stoppable = False
self.client = None
def clone(self, redirectHost, redirectPort, localPort=None):
if localPort is None:
localPort = random.randrange(40000, 50000)
ft = ForwardThread(self.server, self.port, self.username, self.password, localPort, redirectHost, redirectPort, self.waitTime)
ft.client = self.client
self.client.useCount += 1 # One more using this client
ft.start()
while ft.status == 0:
time.sleep(0.1)
return (ft, localPort)
def _timerFnc(self):
self.timer = None
logger.debug('Timer fnc: {}'.format(self.currentConnections))
self.stoppable = True
if self.currentConnections <= 0:
self.stop()
def run(self):
if self.client is None:
self.client = paramiko.SSHClient()
self.client.useCount = 1 # Custom added variable, to keep track on when to close tunnel
self.client.load_system_host_keys()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
logger.debug('Connecting to ssh host %s:%d ...' % (self.server, self.port))
try:
self.client.connect(self.server, self.port, username=self.username, password=self.password, timeout=5)
except Exception as e:
logger.exception('Exception connecting: ')
self.status = 2 # Error
return
class SubHandler(Handler):
chain_host = self.redirectHost
chain_port = self.redirectPort
ssh_transport = self.client.get_transport()
event = self.stopEvent
thread = self
logger.debug('Wait Time: {}'.format(self.waitTime))
self.timer = threading.Timer(self.waitTime, self._timerFnc)
self.timer.start()
self.status = 1 # Ok, listening
self.fs = ForwardServer(('', self.localPort), SubHandler)
self.fs.serve_forever()
def stop(self):
try:
if self.timer:
self.timer.cancel()
self.stopEvent.set()
self.fs.shutdown()
if self.client is not None:
self.client.useCount -= 1
if self.client.useCount == 0:
self.client.close()
self.client = None # Clean up
except Exception:
logger.exception('Exception stopping')
pass
def forward(server, port, username, password, redirectHost, redirectPort, localPort=None, waitTime=10):
'''
Instantiates an ssh connection to server:port
Returns the Thread created and the local redirected port as a list: (thread, port)
'''
port, redirectPort = int(port), int(redirectPort)
if localPort is None:
localPort = random.randrange(40000, 50000)
logger.debug('Connecting to {}:{} using {}/{} redirecting to {}:{}, listening on 127.0.0.1:{}'.format(
server, port, username, password, redirectHost, redirectPort, localPort))
ft = ForwardThread(server, port, username, password, localPort, redirectHost, redirectPort, waitTime)
ft.start()
while ft.status == 0:
time.sleep(0.1)
return (ft, localPort)

45
client/src/uds/log.py Normal file
View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# 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 __future__ import unicode_literals
import logging
import os
import tempfile
logging.basicConfig(
filename=os.path.join(tempfile.gettempdir(), b'udsclient.log'),
filemode='a',
format='%(levelname)s %(asctime)s %(message)s',
level=logging.DEBUG
)
logger = logging.getLogger('udsclient')

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2015 Virtual Cable S.L.
# 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 __future__ import unicode_literals
import sys
LINUX = 'Linux'
WINDOWS = 'Windows'
MAC_OS_X = 'Mac os x'
def getOs():
if sys.platform.startswith('linux'):
return LINUX
elif sys.platform.startswith('win'):
return WINDOWS
elif sys.platform.startswith('darwin'):
return MAC_OS_X

116
client/src/uds/rest.py Normal file
View File

@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2015 Virtual Cable S.L.
# 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 __future__ import unicode_literals
from PyQt4.QtCore import pyqtSignal, pyqtSlot
from PyQt4.QtCore import QObject, QUrl, QSettings
from PyQt4.QtCore import Qt
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QSslCertificate
from PyQt4.QtGui import QMessageBox
from . import VERSION
import json
import osDetector
import six
import urllib
class RestRequest(QObject):
restApiUrl = '' #
done = pyqtSignal(dict, name='done')
def __init__(self, url, parentWindow, done, params=None): # parent not used
super(RestRequest, self).__init__()
# private
self._manager = QNetworkAccessManager()
if params is not None:
url += '?' + '&'.join('{}={}'.format(k, urllib.quote(six.text_type(v).encode('utf8'))) for k, v in params.iteritems())
self.url = QUrl(RestRequest.restApiUrl + url)
# connect asynchronous result, when a request finishes
self._manager.finished.connect(self._finished)
self._manager.sslErrors.connect(self._sslError)
self._parentWindow = parentWindow
self.done.connect(done, Qt.QueuedConnection)
# private slot, no need to declare as slot
@pyqtSlot(QNetworkReply)
def _finished(self, reply):
'''
Handle signal 'finished'. A network request has finished.
'''
try:
if reply.error() != QNetworkReply.NoError:
raise Exception(reply.errorString())
data = six.text_type(reply.readAll())
data = json.loads(data)
except Exception as e:
data = {
'result': None,
'error': six.text_type(e)
}
self.done.emit(data)
reply.deleteLater() # schedule for delete from main event loop
@pyqtSlot(QNetworkReply, list)
def _sslError(self, reply, errors):
settings = QSettings()
settings.beginGroup('ssl')
cert = errors[0].certificate()
digest = six.text_type(cert.digest().toHex())
approved = settings.value(digest, False).toBool()
errorString = '<p>The certificate for <b>{}</b> has the following errors:</p><ul>'.format(cert.subjectInfo(QSslCertificate.CommonName))
for err in errors:
errorString += '<li>' + err.errorString() + '</li>'
errorString += '</ul>'
if approved or QMessageBox.warning(self._parentWindow, 'SSL Warning', errorString, QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
settings.setValue(digest, True)
reply.ignoreSslErrors()
settings.endGroup()
def get(self):
request = QNetworkRequest(self.url)
request.setRawHeader('User-Agent', osDetector.getOs() + " - UDS Connector " + VERSION)
self._manager.get(request)

162
client/src/uds/tools.py Normal file
View File

@@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2015 Virtual Cable S.L.
# 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 __future__ import unicode_literals
import tempfile
import string
import random
import os
import socket
import stat
import six
import sys
import time
from log import logger
_unlinkFiles = []
_tasksToWait = []
_execBeforeExit = []
sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
def saveTempFile(content, filename=None):
if filename is None:
filename = b''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(16))
filename = filename + '.uds'
if 'win32' in sys.platform:
logger.info('Fixing for win32')
filename = filename.encode(sys_fs_enc)
filename = os.path.join(tempfile.gettempdir(), filename)
with open(filename, 'w') as f:
f.write(content)
logger.info('Returning filename')
return filename
def readTempFile(filename):
if 'win32' in sys.platform:
filename = filename.encode('utf-8')
filename = os.path.join(tempfile.gettempdir(), filename)
try:
with open(filename, 'r') as f:
return f.read()
except Exception:
return None
def testServer(host, port, timeOut=4):
try:
sock = socket.create_connection((host, int(port)), timeOut)
sock.close()
except Exception:
return False
return True
def findApp(appName, extraPath=None):
if 'win32' in sys.platform and isinstance(appName, six.text_type):
appName = appName.encode(sys_fs_enc)
searchPath = os.environ['PATH'].split(os.pathsep)
if extraPath is not None:
searchPath += list(extraPath)
for path in searchPath:
fileName = os.path.join(path, appName)
if os.path.isfile(fileName) and (os.stat(fileName).st_mode & stat.S_IXUSR) != 0:
return fileName
return None
def getHostName():
'''
Returns current host name
In fact, it's a wrapper for socket.gethostname()
'''
hostname = socket.gethostname()
if 'win32' in sys.platform:
hostname = hostname.decode(sys_fs_enc)
hostname = six.text_type(hostname)
logger.info('Hostname: {}'.format(hostname))
return hostname
# Queing operations (to be executed before exit)
def addFileToUnlink(filename):
'''
Adds a file to the wait-and-unlink list
'''
_unlinkFiles.append(filename)
def unlinkFiles():
'''
Removes all wait-and-unlink files
'''
if len(_unlinkFiles) > 0:
time.sleep(5) # Wait 5 seconds before deleting anything
for f in _unlinkFiles:
try:
os.unlink(f)
except Exception:
pass
def addTaskToWait(taks):
_tasksToWait.append(taks)
def waitForTasks():
for t in _tasksToWait:
try:
if hasattr(t, 'join'):
t.join()
elif hasattr(t, 'wait'):
t.wait()
except Exception:
pass
def addExecBeforeExit(fnc):
_execBeforeExit.append(fnc)
def execBeforeExit():
for fnc in _execBeforeExit:
fnc.__call__()

15
client/src/update.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
function process {
for a in *.ui; do
pyuic4 $a -o `basename $a .ui`.py -x
done
}
pyrcc4 -py3 UDSResources.qrc -o UDSResources_rc.py
# process current directory ui's
process

View File

@@ -1,9 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry including="**/*.java" kind="src" path="src/main/java"/>
<classpathentry kind="var" path="M2_REPO/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.6.1/slf4j-api-1.6.1.jar"/>
<classpathentry kind="lib" path="/home/dkmaster/.m2/repository/org/glyptodon/guacamole/guacamole-common/0.8.0/guacamole-common-0.8.0.jar"/>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -10,8 +10,14 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

5
guacamole-tunnel/NOTICE Normal file
View File

@@ -0,0 +1,5 @@
Apache Guacamole
Copyright 2016 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View File

@@ -7,36 +7,43 @@
<groupId>org.openuds.server</groupId>
<artifactId>transport</artifactId>
<packaging>war</packaging>
<version>1.7.0</version>
<version>2.0.0</version>
<name>Guacamole Transport</name>
<url>http://openuds.org/</url>
<url>https://github.com/dkmstr/openuds</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>transport</finalName>
<build>
<finalName>transport</finalName>
<plugins>
<!-- Compile using Java 1.6 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>1.6</source>
<target>1.6</target>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-Werror</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
<!-- Overlay guacamole-common-js (zip) -->
<!-- Overlay guacamole-common-js (zip) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<overlays>
<overlay>
<groupId>org.glyptodon.guacamole</groupId>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common-js</artifactId>
<type>zip</type>
</overlay>
@@ -46,36 +53,118 @@
</plugins>
</build>
<dependencies>
</build>
<dependencies>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
<version>2.5</version>
</dependency>
<!-- SLF4J - logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>1.6.1</version>
<scope>runtime</scope>
</dependency>
<!-- Main Guacamole library -->
<dependency>
<groupId>org.glyptodon.guacamole</groupId>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common</artifactId>
<version>0.9.3</version>
<scope>compile</scope>
<version>0.9.9-incubating</version>
</dependency>
<!-- Guacamole JavaScript library -->
<dependency>
<groupId>org.glyptodon.guacamole</groupId>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common-js</artifactId>
<version>0.9.3</version>
<version>0.9.9-incubating</version>
<type>zip</type>
<scope>runtime</scope>
</dependency>
<!-- JSR 356 WebSocket API -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<!-- Jetty 8 servlet API (websocket) -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>8.1.1.v20120215</version>
<scope>provided</scope>
</dependency>
<!-- Jetty 9.0 servlet API (websocket) -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-parent</artifactId>
<version>20</version>
<scope>provided</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-api</artifactId>
<version>9.0.7.v20131107</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-servlet</artifactId>
<version>9.0.7.v20131107</version>
<scope>provided</scope>
</dependency>
<!-- Tomcat servlet API (websocket) -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>7.0.37</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-coyote</artifactId>
<version>7.0.37</version>
<scope>provided</scope>
</dependency>
<!-- Jersey - Guice extension -->
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-guice</artifactId>
<version>1.17.1</version>
</dependency>
<!-- Guice Servlet -->
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
<version>3.0</version>
</dependency>
<!-- Guice - Dependency Injection -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel;
import com.google.inject.Module;
/**
* Generic means of loading a tunnel without adding explicit dependencies within
* the main ServletModule, as not all servlet containers may have the classes
* required by all tunnel implementations.
*
* @author Michael Jumper
*/
public interface TunnelLoader extends Module {
/**
* Checks whether this type of tunnel is supported by the servlet container.
*
* @return true if this type of tunnel is supported and can be loaded
* without errors, false otherwise.
*/
public boolean isSupported();
}

View File

@@ -0,0 +1,116 @@
/*
* This file has been modified from the original, upstream version to facilitate
* integration with OpenUDS.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel;
import org.apache.guacamole.tunnel.http.RestrictedGuacamoleHTTPTunnelServlet;
import com.google.inject.servlet.ServletModule;
import java.lang.reflect.InvocationTargetException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Module which loads tunnel implementations.
*
* @author Michael Jumper
*/
public class TunnelModule extends ServletModule {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(TunnelModule.class);
/**
* Classnames of all implementation-specific WebSocket tunnel modules.
*/
private static final String[] WEBSOCKET_MODULES = {
"org.apache.guacamole.tunnel.websocket.WebSocketTunnelModule",
"org.apache.guacamole.tunnel.websocket.jetty8.WebSocketTunnelModule",
"org.apache.guacamole.tunnel.websocket.jetty9.WebSocketTunnelModule",
"org.apache.guacamole.tunnel.websocket.tomcat.WebSocketTunnelModule"
};
private boolean loadWebSocketModule(String classname) {
try {
// Attempt to find WebSocket module
Class<?> module = Class.forName(classname);
// Create loader
TunnelLoader loader = (TunnelLoader) module.getConstructor().newInstance();
// Install module, if supported
if (loader.isSupported()) {
install(loader);
return true;
}
}
// If no such class or constructor, etc., then this particular
// WebSocket support is not present
catch (ClassNotFoundException e) {}
catch (NoClassDefFoundError e) {}
catch (NoSuchMethodException e) {}
// Log errors which indicate bugs
catch (InstantiationException e) {
logger.debug("Error instantiating WebSocket module.", e);
}
catch (IllegalAccessException e) {
logger.debug("Error instantiating WebSocket module.", e);
}
catch (InvocationTargetException e) {
logger.debug("Error instantiating WebSocket module.", e);
}
// Load attempt failed
return false;
}
@Override
protected void configureServlets() {
bind(TunnelRequestService.class);
// Set up HTTP tunnel
serve("/tunnel").with(RestrictedGuacamoleHTTPTunnelServlet.class);
// Try to load each WebSocket tunnel in sequence
for (String classname : WEBSOCKET_MODULES) {
if (loadWebSocketModule(classname)) {
logger.debug("WebSocket module loaded: {}", classname);
return;
}
}
// Warn of lack of WebSocket
logger.info("WebSocket support NOT present. Only HTTP will be used.");
}
}

View File

@@ -0,0 +1,371 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel;
import java.util.List;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleException;
/**
* A request object which provides only the functions absolutely required to
* retrieve and connect to a tunnel.
*
* @author Michael Jumper
*/
public abstract class TunnelRequest {
/**
* The name of the request parameter containing the user's authentication
* token.
*/
public static final String AUTH_TOKEN_PARAMETER = "token";
/**
* The name of the parameter containing the identifier of the
* AuthenticationProvider associated with the UserContext containing the
* object to which a tunnel is being requested.
*/
public static final String AUTH_PROVIDER_IDENTIFIER_PARAMETER = "GUAC_DATA_SOURCE";
/**
* The name of the parameter specifying the type of object to which a
* tunnel is being requested. Currently, this may be "c" for a Guacamole
* connection, or "g" for a Guacamole connection group.
*/
public static final String TYPE_PARAMETER = "GUAC_TYPE";
/**
* The name of the parameter containing the unique identifier of the object
* to which a tunnel is being requested.
*/
public static final String IDENTIFIER_PARAMETER = "GUAC_ID";
/**
* The name of the parameter containing the desired display width, in
* pixels.
*/
public static final String WIDTH_PARAMETER = "GUAC_WIDTH";
/**
* The name of the parameter containing the desired display height, in
* pixels.
*/
public static final String HEIGHT_PARAMETER = "GUAC_HEIGHT";
/**
* The name of the parameter containing the desired display resolution, in
* DPI.
*/
public static final String DPI_PARAMETER = "GUAC_DPI";
/**
* The name of the parameter specifying one supported audio mimetype. This
* will normally appear multiple times within a single tunnel request -
* once for each mimetype.
*/
public static final String AUDIO_PARAMETER = "GUAC_AUDIO";
/**
* The name of the parameter specifying one supported video mimetype. This
* will normally appear multiple times within a single tunnel request -
* once for each mimetype.
*/
public static final String VIDEO_PARAMETER = "GUAC_VIDEO";
/**
* The name of the parameter specifying one supported image mimetype. This
* will normally appear multiple times within a single tunnel request -
* once for each mimetype.
*/
public static final String IMAGE_PARAMETER = "GUAC_IMAGE";
/**
* All supported object types that can be used as the destination of a
* tunnel.
*/
public static enum Type {
/**
* A Guacamole connection.
*/
CONNECTION("c"),
/**
* A Guacamole connection group.
*/
CONNECTION_GROUP("g");
/**
* The parameter value which denotes a destination object of this type.
*/
final String PARAMETER_VALUE;
/**
* Defines a Type having the given corresponding parameter value.
*
* @param value
* The parameter value which denotes a destination object of this
* type.
*/
Type(String value) {
PARAMETER_VALUE = value;
}
};
/**
* Returns the value of the parameter having the given name.
*
* @param name
* The name of the parameter to return.
*
* @return
* The value of the parameter having the given name, or null if no such
* parameter was specified.
*/
public abstract String getParameter(String name);
/**
* Returns a list of all values specified for the given parameter.
*
* @param name
* The name of the parameter to return.
*
* @return
* All values of the parameter having the given name , or null if no
* such parameter was specified.
*/
public abstract List<String> getParameterValues(String name);
/**
* Returns the value of the parameter having the given name, throwing an
* exception if the parameter is missing.
*
* @param name
* The name of the parameter to return.
*
* @return
* The value of the parameter having the given name.
*
* @throws GuacamoleException
* If the parameter is not present in the request.
*/
public String getRequiredParameter(String name) throws GuacamoleException {
// Pull requested parameter, aborting if absent
String value = getParameter(name);
if (value == null)
throw new GuacamoleClientException("Parameter \"" + name + "\" is required.");
return value;
}
/**
* Returns the integer value of the parameter having the given name,
* throwing an exception if the parameter cannot be parsed.
*
* @param name
* The name of the parameter to return.
*
* @return
* The integer value of the parameter having the given name, or null if
* the parameter is missing.
*
* @throws GuacamoleException
* If the parameter is not a valid integer.
*/
public Integer getIntegerParameter(String name) throws GuacamoleException {
// Pull requested parameter
String value = getParameter(name);
if (value == null)
return null;
// Attempt to parse as an integer
try {
return Integer.parseInt(value);
}
// Rethrow any parsing error as a GuacamoleClientException
catch (NumberFormatException e) {
throw new GuacamoleClientException("Parameter \"" + name + "\" must be a valid integer.", e);
}
}
/**
* Returns the authentication token associated with this tunnel request.
*
* @return
* The authentication token associated with this tunnel request, or
* null if no authentication token is present.
*/
public String getAuthenticationToken() {
return getParameter(AUTH_TOKEN_PARAMETER);
}
/**
* Returns the identifier of the AuthenticationProvider associated with the
* UserContext from which the connection or connection group is to be
* retrieved when the tunnel is created. In the context of the REST API and
* the JavaScript side of the web application, this is referred to as the
* data source identifier.
*
* @return
* The identifier of the AuthenticationProvider associated with the
* UserContext from which the connection or connection group is to be
* retrieved when the tunnel is created.
*
* @throws GuacamoleException
* If the identifier was not present in the request.
*/
public String getAuthenticationProviderIdentifier()
throws GuacamoleException {
return getRequiredParameter(AUTH_PROVIDER_IDENTIFIER_PARAMETER);
}
/**
* Returns the type of object for which the tunnel is being requested.
*
* @return
* The type of object for which the tunnel is being requested.
*
* @throws GuacamoleException
* If the type was not present in the request, or if the type requested
* is in the wrong format.
*/
public Type getType() throws GuacamoleException {
String type = getRequiredParameter(TYPE_PARAMETER);
// For each possible object type
for (Type possibleType : Type.values()) {
// Match against defined parameter value
if (type.equals(possibleType.PARAMETER_VALUE))
return possibleType;
}
throw new GuacamoleClientException("Illegal identifier - unknown type.");
}
/**
* Returns the identifier of the destination of the tunnel being requested.
* As there are multiple types of destination objects available, and within
* multiple data sources, the associated object type and data source are
* also necessary to determine what this identifier refers to.
*
* @return
* The identifier of the destination of the tunnel being requested.
*
* @throws GuacamoleException
* If the identifier was not present in the request.
*/
public String getIdentifier() throws GuacamoleException {
return getRequiredParameter(IDENTIFIER_PARAMETER);
}
/**
* Returns the display width desired for the Guacamole session over the
* tunnel being requested.
*
* @return
* The display width desired for the Guacamole session over the tunnel
* being requested, or null if no width was given.
*
* @throws GuacamoleException
* If the width specified was not a valid integer.
*/
public Integer getWidth() throws GuacamoleException {
return getIntegerParameter(WIDTH_PARAMETER);
}
/**
* Returns the display height desired for the Guacamole session over the
* tunnel being requested.
*
* @return
* The display height desired for the Guacamole session over the tunnel
* being requested, or null if no width was given.
*
* @throws GuacamoleException
* If the height specified was not a valid integer.
*/
public Integer getHeight() throws GuacamoleException {
return getIntegerParameter(HEIGHT_PARAMETER);
}
/**
* Returns the display resolution desired for the Guacamole session over
* the tunnel being requested, in DPI.
*
* @return
* The display resolution desired for the Guacamole session over the
* tunnel being requested, or null if no resolution was given.
*
* @throws GuacamoleException
* If the resolution specified was not a valid integer.
*/
public Integer getDPI() throws GuacamoleException {
return getIntegerParameter(DPI_PARAMETER);
}
/**
* Returns a list of all audio mimetypes declared as supported within the
* tunnel request.
*
* @return
* A list of all audio mimetypes declared as supported within the
* tunnel request, or null if no mimetypes were specified.
*/
public List<String> getAudioMimetypes() {
return getParameterValues(AUDIO_PARAMETER);
}
/**
* Returns a list of all video mimetypes declared as supported within the
* tunnel request.
*
* @return
* A list of all video mimetypes declared as supported within the
* tunnel request, or null if no mimetypes were specified.
*/
public List<String> getVideoMimetypes() {
return getParameterValues(VIDEO_PARAMETER);
}
/**
* Returns a list of all image mimetypes declared as supported within the
* tunnel request.
*
* @return
* A list of all image mimetypes declared as supported within the
* tunnel request, or null if no mimetypes were specified.
*/
public List<String> getImageMimetypes() {
return getParameterValues(IMAGE_PARAMETER);
}
}

View File

@@ -0,0 +1,159 @@
/*
* This file has been modified from the original, upstream version to facilitate
* integration with OpenUDS.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleSocket;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.InetGuacamoleSocket;
import org.apache.guacamole.net.SimpleGuacamoleTunnel;
import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket;
import org.apache.guacamole.protocol.GuacamoleClientInformation;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.openuds.guacamole.connection.ConnectionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class that takes a standard request from the Guacamole JavaScript
* client and produces the corresponding GuacamoleTunnel. The implementation
* of this utility is specific to the form of request used by the upstream
* Guacamole web application, and is not necessarily useful to applications
* that use purely the Guacamole API.
*
* @author Michael Jumper
* @author Vasily Loginov
*/
@Singleton
public class TunnelRequestService {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(TunnelRequestService.class);
/**
* Service for retrieving remotely-maintained connection information.
*/
@Inject
private ConnectionService connectionService;
/**
* The hostname of the server hosting guacd.
*/
private static final String GUACD_HOSTNAME = "127.0.0.1";
/**
* The port that guacd will be listening on.
*/
private static final int GUACD_PORT = 4822;
/**
* Creates a new tunnel using the parameters and credentials present in
* the given request.
*
* @param request
* The HttpServletRequest describing the tunnel to create.
*
* @return
* The created tunnel, or null if the tunnel could not be created.
*
* @throws GuacamoleException
* If an error occurs while creating the tunnel.
*/
public GuacamoleTunnel createTunnel(TunnelRequest request) throws GuacamoleException {
// Pull OpenUDS-specific "data" parameter
String data = request.getParameter("data");
if (data == null || data.isEmpty()) {
logger.debug("No ID received in tunnel connect request.");
throw new GuacamoleClientException("Connection data not provided.");
}
logger.debug("Establishing tunnel and connection with data from \"{}\"...", data);
// Get connection from remote service
GuacamoleConfiguration config = connectionService.getConnectionConfiguration(data);
if (config == null)
throw new GuacamoleClientException("Connection configuration could not be retrieved.");
// Get client information
GuacamoleClientInformation info = new GuacamoleClientInformation();
// Set width if provided
String width = request.getParameter("GUAC_WIDTH");
if (width != null)
info.setOptimalScreenWidth(Integer.parseInt(width));
// Set height if provided
String height = request.getParameter("GUAC_HEIGHT");
if (height != null)
info.setOptimalScreenHeight(Integer.parseInt(height));
// Set resolution if provided
String dpi = request.getParameter("GUAC_DPI");
if (dpi != null)
info.setOptimalResolution(Integer.parseInt(dpi));
// Add audio mimetypes
List<String> audio_mimetypes = request.getParameterValues("GUAC_AUDIO");
if (audio_mimetypes != null)
info.getAudioMimetypes().addAll(audio_mimetypes);
// Add video mimetypes
List<String> video_mimetypes = request.getParameterValues("GUAC_VIDEO");
if (video_mimetypes != null)
info.getVideoMimetypes().addAll(video_mimetypes);
// Add image mimetypes
List<String> image_mimetypes = request.getParameterValues("GUAC_IMAGE");
if (image_mimetypes != null)
info.getImageMimetypes().addAll(image_mimetypes);
// Connect socket for connection
GuacamoleSocket socket;
try {
socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(GUACD_HOSTNAME, GUACD_PORT),
config, info
);
}
// Log any errors during connection
catch (GuacamoleException e) {
logger.error("Unable to connect to guacd.", e);
throw e;
}
// Return corresponding tunnel
return new SimpleGuacamoleTunnel(socket);
}
}

View File

@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.http;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.tunnel.TunnelRequest;
/**
* HTTP-specific implementation of TunnelRequest.
*
* @author Michael Jumper
*/
public class HTTPTunnelRequest extends TunnelRequest {
/**
* A copy of the parameters obtained from the HttpServletRequest used to
* construct the HTTPTunnelRequest.
*/
private final Map<String, List<String>> parameterMap =
new HashMap<String, List<String>>();
/**
* Creates a HTTPTunnelRequest which copies and exposes the parameters
* from the given HttpServletRequest.
*
* @param request
* The HttpServletRequest to copy parameter values from.
*/
@SuppressWarnings("unchecked") // getParameterMap() is defined as returning Map<String, String[]>
public HTTPTunnelRequest(HttpServletRequest request) {
// For each parameter
for (Map.Entry<String, String[]> mapEntry : ((Map<String, String[]>)
request.getParameterMap()).entrySet()) {
// Get parameter name and corresponding values
String parameterName = mapEntry.getKey();
List<String> parameterValues = Arrays.asList(mapEntry.getValue());
// Store copy of all values in our own map
parameterMap.put(
parameterName,
new ArrayList<String>(parameterValues)
);
}
}
@Override
public String getParameter(String name) {
List<String> values = getParameterValues(name);
// Return the first value from the list if available
if (values != null && !values.isEmpty())
return values.get(0);
return null;
}
@Override
public List<String> getParameterValues(String name) {
return parameterMap.get(name);
}
}

View File

@@ -0,0 +1,70 @@
/*
* This file has been modified from the original, upstream version to facilitate
* integration with OpenUDS.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.http;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet;
import org.apache.guacamole.tunnel.TunnelRequestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Connects users to a tunnel associated with the authorized connection
* having the given ID.
*
* @author Michael Jumper
*/
@Singleton
public class RestrictedGuacamoleHTTPTunnelServlet extends GuacamoleHTTPTunnelServlet {
/**
* Service for handling tunnel requests.
*/
@Inject
private TunnelRequestService tunnelRequestService;
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(RestrictedGuacamoleHTTPTunnelServlet.class);
@Override
protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
// Attempt to create HTTP tunnel
GuacamoleTunnel tunnel = tunnelRequestService.createTunnel(new HTTPTunnelRequest(request));
// If successful, warn of lack of WebSocket
logger.info("Using HTTP tunnel (not WebSocket). Performance may be sub-optimal.");
return tunnel;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* Classes which leverage Guacamole's built-in HTTP tunnel implementation.
*/
package org.apache.guacamole.tunnel.http;

View File

@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* Classes which are common to all tunnel implementations.
*/
package org.apache.guacamole.tunnel;

View File

@@ -0,0 +1,122 @@
/*
* This file has been modified from the original, upstream version to facilitate
* integration with OpenUDS.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.websocket;
import com.google.inject.Provider;
import java.util.Map;
import javax.websocket.EndpointConfig;
import javax.websocket.HandshakeResponse;
import javax.websocket.Session;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.tunnel.TunnelRequest;
import org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint;
import org.apache.guacamole.tunnel.TunnelRequestService;
/**
* Tunnel implementation which uses WebSocket as a tunnel backend, rather than
* HTTP, properly parsing connection IDs included in the connection request.
*/
public class RestrictedGuacamoleWebSocketTunnelEndpoint extends GuacamoleWebSocketTunnelEndpoint {
/**
* Unique string which shall be used to store the TunnelRequest
* associated with a WebSocket connection.
*/
private static final String TUNNEL_REQUEST_PROPERTY = "WS_GUAC_TUNNEL_REQUEST";
/**
* Unique string which shall be used to store the TunnelRequestService to
* be used for processing TunnelRequests.
*/
private static final String TUNNEL_REQUEST_SERVICE_PROPERTY = "WS_GUAC_TUNNEL_REQUEST_SERVICE";
/**
* Configurator implementation which stores the requested GuacamoleTunnel
* within the user properties. The GuacamoleTunnel will be later retrieved
* during the connection process.
*/
public static class Configurator extends ServerEndpointConfig.Configurator {
/**
* Provider which provides instances of a service for handling
* tunnel requests.
*/
private final Provider<TunnelRequestService> tunnelRequestServiceProvider;
/**
* Creates a new Configurator which uses the given tunnel request
* service provider to retrieve the necessary service to handle new
* connections requests.
*
* @param tunnelRequestServiceProvider
* The tunnel request service provider to use for all new
* connections.
*/
public Configurator(Provider<TunnelRequestService> tunnelRequestServiceProvider) {
this.tunnelRequestServiceProvider = tunnelRequestServiceProvider;
}
@Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request, HandshakeResponse response) {
super.modifyHandshake(config, request, response);
// Store tunnel request and tunnel request service for retrieval
// upon WebSocket open
Map<String, Object> userProperties = config.getUserProperties();
userProperties.clear();
userProperties.put(TUNNEL_REQUEST_PROPERTY, new WebSocketTunnelRequest(request));
userProperties.put(TUNNEL_REQUEST_SERVICE_PROPERTY, tunnelRequestServiceProvider.get());
}
}
@Override
protected GuacamoleTunnel createTunnel(Session session,
EndpointConfig config) throws GuacamoleException {
Map<String, Object> userProperties = config.getUserProperties();
// Get original tunnel request
TunnelRequest tunnelRequest = (TunnelRequest) userProperties.get(TUNNEL_REQUEST_PROPERTY);
if (tunnelRequest == null)
return null;
// Get tunnel request service
TunnelRequestService tunnelRequestService = (TunnelRequestService) userProperties.get(TUNNEL_REQUEST_SERVICE_PROPERTY);
if (tunnelRequestService == null)
return null;
// Create and return tunnel
return tunnelRequestService.createTunnel(tunnelRequest);
}
}

View File

@@ -0,0 +1,106 @@
/*
* This file has been modified from the original, upstream version to facilitate
* integration with OpenUDS.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.websocket;
import com.google.inject.Provider;
import com.google.inject.servlet.ServletModule;
import java.util.Arrays;
import javax.websocket.DeploymentException;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpointConfig;
import org.apache.guacamole.tunnel.TunnelLoader;
import org.apache.guacamole.tunnel.TunnelRequestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Loads the JSR-356 WebSocket tunnel implementation.
*
* @author Michael Jumper
*/
public class WebSocketTunnelModule extends ServletModule implements TunnelLoader {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(WebSocketTunnelModule.class);
@Override
public boolean isSupported() {
try {
// Attempt to find WebSocket servlet
Class.forName("javax.websocket.Endpoint");
// Support found
return true;
}
// If no such servlet class, this particular WebSocket support
// is not present
catch (ClassNotFoundException e) {}
catch (NoClassDefFoundError e) {}
// Support not found
return false;
}
@Override
public void configureServlets() {
logger.info("Loading JSR-356 WebSocket support...");
// Get container
ServerContainer container = (ServerContainer) getServletContext().getAttribute("javax.websocket.server.ServerContainer");
if (container == null) {
logger.warn("ServerContainer attribute required by JSR-356 is missing. Cannot load JSR-356 WebSocket support.");
return;
}
Provider<TunnelRequestService> tunnelRequestServiceProvider = getProvider(TunnelRequestService.class);
// Build configuration for WebSocket tunnel
ServerEndpointConfig config =
ServerEndpointConfig.Builder.create(RestrictedGuacamoleWebSocketTunnelEndpoint.class, "/websocket-tunnel")
.configurator(new RestrictedGuacamoleWebSocketTunnelEndpoint.Configurator(tunnelRequestServiceProvider))
.subprotocols(Arrays.asList(new String[]{"guacamole"}))
.build();
try {
// Add configuration to container
container.addEndpoint(config);
}
catch (DeploymentException e) {
logger.error("Unable to deploy WebSocket tunnel.", e);
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.websocket;
import java.util.List;
import java.util.Map;
import javax.websocket.server.HandshakeRequest;
import org.apache.guacamole.tunnel.TunnelRequest;
/**
* WebSocket-specific implementation of TunnelRequest.
*
* @author Michael Jumper
*/
public class WebSocketTunnelRequest extends TunnelRequest {
/**
* All parameters passed via HTTP to the WebSocket handshake.
*/
private final Map<String, List<String>> handshakeParameters;
/**
* Creates a TunnelRequest implementation which delegates parameter and
* session retrieval to the given HandshakeRequest.
*
* @param request The HandshakeRequest to wrap.
*/
public WebSocketTunnelRequest(HandshakeRequest request) {
this.handshakeParameters = request.getParameterMap();
}
@Override
public String getParameter(String name) {
// Pull list of values, if present
List<String> values = getParameterValues(name);
if (values == null || values.isEmpty())
return null;
// Return first parameter value arbitrarily
return values.get(0);
}
@Override
public List<String> getParameterValues(String name) {
return handshakeParameters.get(name);
}
}

View File

@@ -0,0 +1,236 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.websocket.jetty8;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.io.GuacamoleReader;
import org.apache.guacamole.io.GuacamoleWriter;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocket.Connection;
import org.eclipse.jetty.websocket.WebSocketServlet;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleConnectionClosedException;
import org.apache.guacamole.protocol.GuacamoleInstruction;
import org.apache.guacamole.tunnel.http.HTTPTunnelRequest;
import org.apache.guacamole.tunnel.TunnelRequest;
import org.apache.guacamole.protocol.GuacamoleStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A WebSocketServlet partial re-implementation of GuacamoleTunnelServlet.
*
* @author Michael Jumper
*/
public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(GuacamoleWebSocketTunnelServlet.class);
/**
* The default, minimum buffer size for instructions.
*/
private static final int BUFFER_SIZE = 8192;
/**
* Sends the given status on the given WebSocket connection and closes the
* connection.
*
* @param connection The WebSocket connection to close.
* @param guac_status The status to send.
*/
public static void closeConnection(Connection connection,
GuacamoleStatus guac_status) {
connection.close(guac_status.getWebSocketCode(),
Integer.toString(guac_status.getGuacamoleStatusCode()));
}
@Override
public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
final TunnelRequest tunnelRequest = new HTTPTunnelRequest(request);
// Return new WebSocket which communicates through tunnel
return new WebSocket.OnTextMessage() {
/**
* The GuacamoleTunnel associated with the connected WebSocket. If
* the WebSocket has not yet been connected, this will be null.
*/
private GuacamoleTunnel tunnel = null;
@Override
public void onMessage(String string) {
// Ignore inbound messages if there is no associated tunnel
if (tunnel == null)
return;
GuacamoleWriter writer = tunnel.acquireWriter();
// Write message received
try {
writer.write(string.toCharArray());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
}
catch (GuacamoleException e) {
logger.debug("WebSocket tunnel write failed.", e);
}
tunnel.releaseWriter();
}
@Override
public void onOpen(final Connection connection) {
try {
tunnel = doConnect(tunnelRequest);
}
catch (GuacamoleException e) {
logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
logger.debug("Error connecting WebSocket tunnel.", e);
closeConnection(connection, e.getStatus());
return;
}
// Do not start connection if tunnel does not exist
if (tunnel == null) {
closeConnection(connection, GuacamoleStatus.RESOURCE_NOT_FOUND);
return;
}
Thread readThread = new Thread() {
@Override
public void run() {
StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
GuacamoleReader reader = tunnel.acquireReader();
char[] readMessage;
try {
// Send tunnel UUID
connection.sendMessage(new GuacamoleInstruction(
GuacamoleTunnel.INTERNAL_DATA_OPCODE,
tunnel.getUUID().toString()
).toString());
try {
// Attempt to read
while ((readMessage = reader.read()) != null) {
// Buffer message
buffer.append(readMessage);
// Flush if we expect to wait or buffer is getting full
if (!reader.available() || buffer.length() >= BUFFER_SIZE) {
connection.sendMessage(buffer.toString());
buffer.setLength(0);
}
}
// No more data
closeConnection(connection, GuacamoleStatus.SUCCESS);
}
// Catch any thrown guacamole exception and attempt
// to pass within the WebSocket connection, logging
// each error appropriately.
catch (GuacamoleClientException e) {
logger.info("WebSocket connection terminated: {}", e.getMessage());
logger.debug("WebSocket connection terminated due to client error.", e);
closeConnection(connection, e.getStatus());
}
catch (GuacamoleConnectionClosedException e) {
logger.debug("Connection to guacd closed.", e);
closeConnection(connection, GuacamoleStatus.SUCCESS);
}
catch (GuacamoleException e) {
logger.error("Connection to guacd terminated abnormally: {}", e.getMessage());
logger.debug("Internal error during connection to guacd.", e);
closeConnection(connection, e.getStatus());
}
}
catch (IOException e) {
logger.debug("WebSocket tunnel read failed due to I/O error.", e);
}
}
};
readThread.start();
}
@Override
public void onClose(int i, String string) {
try {
if (tunnel != null)
tunnel.close();
}
catch (GuacamoleException e) {
logger.debug("Unable to close connection to guacd.", e);
}
}
};
}
/**
* Called whenever the JavaScript Guacamole client makes a connection
* request. It it up to the implementor of this function to define what
* conditions must be met for a tunnel to be configured and returned as a
* result of this connection request (whether some sort of credentials must
* be specified, for example).
*
* @param request
* The TunnelRequest associated with the connection request received.
* Any parameters specified along with the connection request can be
* read from this object.
*
* @return
* A newly constructed GuacamoleTunnel if successful, null otherwise.
*
* @throws GuacamoleException
* If an error occurs while constructing the GuacamoleTunnel, or if the
* conditions required for connection are not met.
*/
protected abstract GuacamoleTunnel doConnect(TunnelRequest request)
throws GuacamoleException;
}

View File

@@ -0,0 +1,54 @@
/*
* This file has been modified from the original, upstream version to facilitate
* integration with OpenUDS.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.guacamole.tunnel.websocket.jetty8;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.tunnel.TunnelRequest;
import org.apache.guacamole.tunnel.TunnelRequestService;
/**
* Tunnel servlet implementation which uses WebSocket as a tunnel backend,
* rather than HTTP, properly parsing connection IDs included in the connection
* request.
*/
@Singleton
public class RestrictedGuacamoleWebSocketTunnelServlet extends GuacamoleWebSocketTunnelServlet {
/**
* Service for handling tunnel requests.
*/
@Inject
private TunnelRequestService tunnelRequestService;
@Override
protected GuacamoleTunnel doConnect(TunnelRequest request)
throws GuacamoleException {
return tunnelRequestService.createTunnel(request);
}
}

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