1 | #!/usr/bin/env python |
||
2 | # -*- coding: utf-8 -*- |
||
3 | |||
4 | import logging |
||
5 | logger = logging.getLogger(__name__) |
||
6 | logger.debug("%s loaded", __name__) |
||
7 | |||
8 | from BaseHTTPServer import HTTPServer |
||
9 | from SocketServer import ThreadingMixIn |
||
10 | |||
11 | from random import randrange |
||
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
|
|||
12 | |||
13 | import doorpi |
||
14 | from doorpi.action.base import SingleAction |
||
15 | |||
16 | from doorpi.status.webserver_lib.session_handler import SessionHandler |
||
17 | from doorpi.status.webserver_lib.request_handler import DoorPiWebRequestHandler |
||
18 | |||
19 | class WebServerStartupAction(SingleAction): pass |
||
20 | class WebServerFakeRequestAction(SingleAction): pass |
||
21 | class WebServerShutdownAction(SingleAction): pass |
||
22 | class WebServerInformUrl(SingleAction): pass |
||
23 | |||
24 | DOORPIWEB_SECTION = 'DoorPiWeb' |
||
25 | CONF_AREA_PREFIX = 'AREA_' |
||
26 | |||
27 | def load_webserver(): |
||
28 | ip = doorpi.DoorPi().config.get(DOORPIWEB_SECTION, 'ip', '') |
||
29 | port = doorpi.DoorPi().config.get_int(DOORPIWEB_SECTION, 'port', 80) |
||
30 | |||
31 | doorpiweb_object = False |
||
32 | |||
33 | possible_ports = [port, 80, 8080, 0] |
||
34 | for single_port in possible_ports: |
||
35 | try: |
||
36 | server_address = (ip, single_port) |
||
37 | doorpiweb_object = DoorPiWeb(server_address, DoorPiWebRequestHandler) |
||
38 | logger.info('Initiating WebService at ip %s and port %s', ip, single_port) |
||
39 | doorpiweb_object.start() |
||
40 | if single_port is not port: |
||
41 | doorpi.DoorPi().event_handler.register_action('OnTimeSecondEvenNumber', doorpiweb_object.inform_own_url) |
||
42 | return doorpiweb_object |
||
43 | except Exception as exp: |
||
44 | logger.warning('failed to initiating WebService at ip %s and port %s (%s)', ip, single_port, exp) |
||
45 | |||
46 | return doorpiweb_object |
||
47 | |||
48 | def check_config(config): |
||
49 | errors = [] |
||
50 | warnings = [] |
||
51 | infos = [] |
||
52 | |||
53 | groups_with_write_permissions = config.get_keys('WritePermission') |
||
54 | groups_with_read_permissions = config.get_keys('ReadPermission') |
||
55 | groups = config.get_keys('Group') |
||
56 | users = config.get_keys('User') |
||
57 | |||
58 | if len(groups) == 0: |
||
59 | errors.append('no groups in configfile!') |
||
60 | |||
61 | if len(groups_with_write_permissions) == 0: |
||
62 | errors.append("no WritePermission found") |
||
63 | |||
64 | for group in groups_with_write_permissions: |
||
65 | if group not in groups: warnings.append("group %s doesn't exist but is assigned to WritePermission" % group) |
||
66 | |||
67 | if len(groups_with_read_permissions) == 0: |
||
68 | warnings.append("no ReadPermission found") |
||
69 | |||
70 | for group in groups_with_read_permissions: |
||
71 | if group not in groups: warnings.append("group %s doesn't exist but is assigned to ReadPermission" % group) |
||
72 | |||
73 | for group in groups: |
||
74 | users_in_group = config.get_list('Group', group) |
||
75 | for user_in_group in users_in_group: |
||
76 | if user_in_group not in users: |
||
77 | warnings.append("user %s is assigned to group %s but doesn't exist as user" % (user_in_group, group)) |
||
78 | |||
79 | config_section = config.get_sections() |
||
80 | |||
81 | for group in groups_with_write_permissions: |
||
82 | modules = config.get_list('WritePermission', group) |
||
83 | for module in modules: |
||
84 | if CONF_AREA_PREFIX+module not in config_section: |
||
85 | warnings.append("module %s doesn't exist but is assigned to group %s in WritePermission" % (module, group)) |
||
86 | |||
87 | for group in groups_with_read_permissions: |
||
88 | modules = config.get_list('ReadPermission', group) |
||
89 | for module in modules: |
||
90 | if CONF_AREA_PREFIX+module not in config_section: |
||
91 | warnings.append("module %s doesn't exist but is assigned to group %s in ReadPermission" % (module, group)) |
||
92 | |||
93 | for info in infos: logger.info(info) |
||
94 | for warning in warnings: logger.error(warning) |
||
95 | for error in errors: logger.error(error) |
||
96 | |||
97 | return {'infos': infos, 'warnings': warnings, 'errors': errors} |
||
98 | |||
99 | class DoorPiWeb(ThreadingMixIn, HTTPServer): |
||
100 | keep_running = True |
||
101 | |||
102 | www = None |
||
103 | indexfile = None |
||
104 | loginfile = None |
||
105 | base_url = None |
||
106 | area_public_name = None |
||
107 | online_fallback = None |
||
108 | |||
109 | @property |
||
110 | def config_status(self): return check_config(self.config) |
||
111 | |||
112 | @property |
||
113 | def own_url(self): |
||
114 | if self.server_port is 80: |
||
115 | return "http://%s/"%self.server_name |
||
116 | else: |
||
117 | return "http://%s:%s/"%(self.server_name, self.server_port) |
||
118 | |||
119 | def inform_own_url(self): logger.info('DoorPiWeb URL is %s', self.own_url) |
||
120 | |||
121 | @property |
||
122 | def sessions(self): |
||
123 | if not self._session_handler and self.keep_running: |
||
124 | logger.debug('no session handler - creating it now') |
||
125 | self._session_handler = SessionHandler() |
||
126 | return self._session_handler |
||
127 | _session_handler = None |
||
128 | |||
129 | @property |
||
130 | def config(self): return doorpi.DoorPi().config |
||
131 | |||
132 | def start(self): |
||
133 | doorpi.DoorPi().event_handler.register_event('OnWebServerStart', __name__) |
||
134 | doorpi.DoorPi().event_handler.register_event('OnWebServerStop', __name__) |
||
135 | |||
136 | self.www = doorpi.DoorPi().config.get_string_parsed(DOORPIWEB_SECTION, 'www', '!BASEPATH!/../DoorPiWeb') |
||
137 | self.indexfile = doorpi.DoorPi().config.get_string_parsed(DOORPIWEB_SECTION, 'indexfile', 'index.html') |
||
138 | self.loginfile = doorpi.DoorPi().config.get_string_parsed(DOORPIWEB_SECTION, 'loginfile', 'login.html') |
||
139 | self.area_public_name = doorpi.DoorPi().config.get_string_parsed(DOORPIWEB_SECTION, 'public', 'AREA_public') |
||
140 | # https://raw.githubusercontent.com/motom001/DoorPiWeb/master/ or http://motom001.github.io/DoorPiWeb/ |
||
141 | self.online_fallback = doorpi.DoorPi().config.get_string_parsed(DOORPIWEB_SECTION, 'online_fallback', 'http://motom001.github.io/DoorPiWeb') |
||
142 | check_config(self.config) |
||
143 | |||
144 | doorpi.DoorPi().event_handler.register_action('OnWebServerStart', WebServerStartupAction(self.handle_while_not_shutdown)) |
||
145 | doorpi.DoorPi().event_handler.register_action('OnShutdown', WebServerShutdownAction(self.init_shutdown)) |
||
146 | doorpi.DoorPi().event_handler('OnWebServerStart', __name__) |
||
147 | |||
148 | DoorPiWebRequestHandler.prepare() |
||
149 | return self |
||
150 | |||
151 | def handle_while_not_shutdown(self): |
||
152 | while self.keep_running: self.handle_request() |
||
153 | |||
154 | def fake_request(self): |
||
155 | try: |
||
156 | from urllib2 import urlopen as fake_request |
||
157 | fake_request("http://%s:%s/"%(self.server_name, self.server_port), timeout = 0) |
||
158 | except: pass |
||
159 | |||
160 | def init_shutdown(self): |
||
161 | doorpi.DoorPi().event_handler('OnWebServerStop', __name__) |
||
162 | self.keep_running = False |
||
163 | if self.sessions: self.sessions.destroy() |
||
164 | DoorPiWebRequestHandler.destroy() |
||
165 | self.fake_request() |
||
166 | doorpi.DoorPi().event_handler.unregister_source(__name__, True) |
||
167 |