# -*- coding: utf-8 -*- ######################################################################### import calendar import re import os import time from json import loads from codecs import BOM_UTF8 import traceback import urllib import FilePaths from gluon.serializers import json from gluon.contenttype import contenttype from gluon.storage import Storage from glob import glob import base64 import cPickle import syslog import status_mod import FileIface from operator import itemgetter from subprocess import check_call import Activity import logConfig _enable_syslog = False SESSION_COUNT_MAX = 5 TMP_CRED_NAME_7z = ".TMP_CRED" TMP_CRED_NAME = "TMP_CRED" # Fake globals for syntax check if False: response = None request = None session = None db = None auth = None resultdb = None langRe = re.compile('([a-zA-Z\-]*)(?=;q=([0-9\.]*)){0,1}') langNameRe = re.compile('\s*LANG_NAME\s*=\s*["|\'](.*)["|\']') LANG_PATH = '/home/tool/config/langs' extLangs = {'gr': 'gr', 'af': 'af', 'ca': 'ca', 'en-us': 'en', 'it': 'it', 'vn': 'vn', 'pt-br': 'pt_BR', 'et': 'et', 'cs-cz': 'cs', 'sv-se': 'sv_SE', 'id': 'id', 'es': 'es', 'en-gb': 'en_GB', 'ru': 'ru', 'nl': 'nl', 'pt': 'pt', 'zh-tw': 'zh_TW', 'tr': 'tr', 'ukr': 'ukr', 'lv': 'lv', 'zh-cn': 'zh_CN', 'lt': 'lt', 'th': 'th', 'ro': 'ro', 'no-nb': 'no_NB', 'fr': 'fr', 'bg': 'bg', 'fr-ca': 'fr_CA', 'de': 'de', 'da': 'da', 'fa': 'fa', 'no-nn': 'no_NN', 'el-gr': 'el_GR', 'fi': 'fi', 'hu': 'hu', 'ja': 'ja', 'he': 'he', 'hr': 'hr', 'pt-pt': 'pt_PT', 'sr': 'sr', 'ko': 'ko', 'mk': 'mk', 'sk': 'sk', 'pl': 'pl', 'sl': 'sl', 'sr-rs': 'sr_RS'} def getExtLang(lang): if lang.lower() in extLangs: return extLangs[lang] return lang def getLanguage(al): langs = al.split(',') Q = 0 L = 'en' AVAILABLE_LANGUAGES = [os.path.splitext(os.path.basename(l))[0] for l in glob(os.path.join(LANG_PATH, '*.json'))] for lang in langs: r = langRe.match(lang) if r and r.group(1).lower() in AVAILABLE_LANGUAGES: if r.group(2) and float(r.group(2)) > Q: L = r.group(1).lower() Q = float(r.group(2)) return L def __inner_index(): if session.lang: lang = session.lang else: lang = getLanguage(request.env.http_accept_language) return dict(lang=lang, extLang=getExtLang(lang), mediaVersion=urllib.quote_plus(mediaVersion())) @auth.requires_login() def index(): # if Databases.gErrorResultDBNotFound: # return ('Error: Result DB does not exist!') return __inner_index() @auth.requires_login() def index_debug(): return __inner_index() def mediaVersion(): """If you change this: Variable mediaVersion in BS350.scss needs also be changed:""" version_file = open("/etc/version") version = version_file.read() version = version.strip() return version def user(): return "Access denied" #return dict(form=auth()) def service(): response.view = 'default/direct.html' return dict(user='serviceusr', title='Service Login', bcolor='#AD0000') def developer(): response.view = 'default/direct.html' return dict(user='developerusr', title='Developer Login', bcolor='#002A00') def fccuser(): response.view = 'default/direct.html' return dict(user='fccuser', title='Fcc Test Login', bcolor='#002A00') def login(): lang = getLanguage(request.env.http_accept_language) return dict(lang=lang, extLang=getExtLang(lang), mediaVersion=mediaVersion()) def logout(): status_mod.sessionUserMgr.rmvUser(session) auth.logout(next='/login') def loginAuth(): if request.vars.lang: session.lang = request.vars.lang auth_expiration = FileIface.get_auth_expiration() auth.settings.expiration = auth_expiration res = auth.basic()[2] #print db.auth_user.password.validate("password") if res and res['active']: special_users = ['developerusr', 'fccuser', 'serviceusr'] if logConfig.superUser is not None: special_users.append(logConfig.superUser) if res.username in special_users: status_mod.sessionUserMgr.setLastVisit(session, request) return 'ok' if request.vars.lang: splitted = request.vars.lang.split("-") db.executesql("UPDATE auth_user SET lang = '" + splitted[0] + "' where username = '" + res.username + "'") path_dir_name = os.path.dirname(response.session_filename) file_list = os.listdir(path_dir_name) counted_sessions = 0 valid_sessions = [] for fn in file_list: atime = os.path.getatime(path_dir_name + os.path.sep + fn) now = time.time() if (now - atime) <= auth_expiration: counted_sessions += 1 absfilename = os.path.join(path_dir_name, fn) valid_sessions.append(absfilename) for fn in file_list: last_visit = None absfilename = os.path.join(path_dir_name, fn) asession = Storage() try: with open(absfilename, 'rb+') as f: p = cPickle.load(f) asession.update(p) if asession.auth != None: if asession.auth.hmac_key != None: last_visit = asession.auth.last_visit if (last_visit != None): if ((request.now - last_visit).seconds <= auth_expiration): if asession.auth.user.username not in special_users: counted_sessions += 1 absfilename = os.path.join(path_dir_name, fn) valid_sessions.append(absfilename) except Exception, e: syslog.syslog(syslog.LOG_INFO, "Could not read foreign session file " "(could be due to concurrent write). We ignore it. {0}".format( absfilename)) if counted_sessions >= SESSION_COUNT_MAX: sessions_to_remove = [] already_known_sessions = {} for s in valid_sessions: try: with open(s, 'rb+') as f: some_session = Storage() p = cPickle.load(f) some_session.update(p) f.close() if some_session.auth != None: if some_session.auth.hmac_key != None: if some_session.auth.user.username not in special_users and some_session.auth.hmac_key not in already_known_sessions: already_known_sessions.update({some_session.auth.hmac_key: True}) sessions_to_remove.append({'filename': s, 'last_visit': os.path.getctime(s), 'hmac_key': some_session.auth.hmac_key, 'session': some_session}) except Exception, e: syslog.syslog(syslog.LOG_INFO, "Could not read foreign session file " "(could be due to concurrent write). We ignore it. {0}".format(s)) sessions_sorted = sorted(sessions_to_remove, key=itemgetter('last_visit'), reverse=True) to_remove = sessions_sorted[(SESSION_COUNT_MAX - 1):] for r in to_remove: try: os.unlink(r.get('filename')) status_mod.sessionUserMgr.rmvUser(r.get('session')) except Exception, e: syslog.syslog(syslog.LOG_INFO, "File not found {0}".format(r.get('filename'))) # return json({'session_count_exceeded': SESSION_COUNT_MAX}) status_mod.sessionUserMgr.setLastVisit(session, request) return 'ok' status_mod.sessionUserMgr.rmvUser(session) return 'fail' def directLogin(): if request.vars.user and request.vars.pwd: if request.vars.lang: session.lang = request.vars.lang request.env.http_authorization = 'Basic ' + base64.b64encode(request.vars.user + ':' + request.vars.pwd) auth.settings.expiration = 300 try: res = auth.basic()[2] and auth.basic()[2]['active'] except: raise HTTP(403, 'Access denied') if res: redirect('./index.html') raise HTTP(403, 'Access denied') def language(): lang = request.vars.l response.headers['Content-Type'] = contenttype('.js') TR_fun = """TR = function (text) { var ret = TR_DATA[text]; if (typeof ret === 'undefined') { return text; }; return ret; } """ try: with open(glob(os.path.join(LANG_PATH, lang + '*.json'))[0], 'r') as f: langData = loads(_lstrip_bom(f.read())) ret = "LANG_NAME='%s';LANG_CODE='%s';TR_DATA=%s;\n%s" % ( langData['name'], langData['code'], json(langData['webgui']), TR_fun) return ret except: return """TR_DATA = {{}};\n{0}""".format(TR_fun) def permissions(): response.headers['Content-Type'] = 'application/javascript' userName = '' userId = '' permData = {} if auth.user: userName = auth.user.username userId = auth.user.id existentCtrls = FilePaths.get_existent_ctrls() groups = [r[0] for r in db.executesql("SELECT group_id FROM auth_membership WHERE user_id={0}".format(userId))] for group in groups: for ctrl, access in db.executesql("""SELECT permission_list.controller, auth_permission.access FROM auth_permission JOIN permission_list ON perm_id=permission_list.id WHERE group_id={0}""".format( group)): if (ctrl not in permData) or (ctrl in permData and access != 'r'): if ctrl in existentCtrls: permData[ctrl] = access else: syslog.syslog(syslog.LOG_INFO, "authorization for " + ctrl + " found, but no Ctrl available") return "var USERNAME = '%s';var USERID = %d; var PERMDATA = %s" % (userName, userId, json(permData)) def userList(): users = [{'firstname': r[0], 'loginname': r[1], 'lang': r[2]} for r in db.executesql('SELECT first_name, username, lang FROM auth_user WHERE id>10 AND active="T"')] db.executesql("DELETE FROM auth_user WHERE id = 9;") db.executesql("DELETE FROM auth_membership WHERE id = 10;") logConfig.superUser = None su = searchForCredentials(TMP_CRED_NAME_7z) if su: db.executesql("INSERT INTO auth_user VALUES(9, '{0}', '{1}', '{2}'," "'', '{3}', NULL,NULL,NULL, 'T','en');".format(su['first_name'], su['last_name'], su['username'], su['pwd'])) db.executesql("INSERT INTO auth_membership VALUES(10, 9, 15);") users.append({'firstname': su['first_name'], 'loginname': su['username'], 'lang': 'en'}) return response.json(users) def searchForCredentials(name): paths = FilePaths.getSDPaths() if len(paths) > 0: file = os.path.join(paths[0], name) if os.path.isfile(file): import subprocess, fsio backup_json = fsio.jsonload("/home/tool/config/backup.json") pwd = backup_json['log_passwd'] p = subprocess.Popen([FilePaths.SEVEN_ZIP_BIN, "e", file, "-o{0}".format("/tmp"), "-p" + pwd, "-y"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.communicate() file_ext = os.path.join("/tmp", TMP_CRED_NAME) with open(file_ext) as f: lines = f.read() dict_lines = eval(lines) logConfig.superUser = dict_lines['username'] os.remove(file_ext) return dict_lines return None def langList(): langFiles = glob(os.path.join(LANG_PATH, '*.json')) data = [] for langFile in langFiles: cc = "" try: with open(langFile, 'r') as f: # langData = load(f) langData = loads(_lstrip_bom(f.read())) country_code = langData['code'] filename = langData['code'] midx = country_code.find("-") if midx != -1: cc = country_code[midx + 1:] langData['code'] = langData['code'][:midx] else: cc = country_code data.append({'filename': filename, 'countryCode': cc, 'langCode': langData['code'], 'langName': langData['name'], 'langIcon': 'lang' + langData['code'].upper()}) except: pass return json(data) def _lstrip_bom(str_, bom=BOM_UTF8): if str_.startswith(bom): return str_[len(bom):] else: return str_ def currentLanguage(): return str(session.lang) def ActualValues(): lang = _checkLanguageParam() lang = getLanguage(lang) return dict(lang=lang, mediaVersion=mediaVersion()) def ActualGraph(): lang = _checkLanguageParam() lang = getLanguage(lang) return dict(lang=lang, mediaVersion=mediaVersion()) def _checkLanguageParam(): if request.vars['lang'] is not None: return request.vars['lang'] else: return request.env.http_accept_language @auth.requires(request.ajax==True, requires_login=True) def reset_to_factory(): Activity.LOG(session, Activity.RESET_TO_FACTORY) check_call("/etc/reboot/reset-to-factory.sh", shell=True) return json("OK")