bygdis.fi

git clone https://git.tarina.org/bygdis.fi
Log | Files | Refs | README

server.py (66559B)


      1 # -*- coding: utf-8 -*-
      2 #
      3 import web
      4 import json
      5 import time
      6 import datetime
      7 import re
      8 import base64
      9 import os
     10 import subprocess
     11 import urllib
     12 from PIL import Image
     13 import hashlib
     14 import random
     15 import bcrypt
     16 import sys
     17 from virtuaaliviivakoodi import virtuaaliviivakoodi
     18 from bs4 import BeautifulSoup
     19 import requests
     20 basedir = os.path.dirname(os.path.realpath(__file__))
     21 sys.path.append(basedir)
     22 import settings
     23 
     24 #web.config.session_parameters['cookie_name'] = 'bygdis.fi'
     25 #web.config.session_parameters['cookie_domain'] = None
     26 #web.config.session_parameters['cookie_path'] = None
     27 #web.config.session_parameters['timeout'] = 839808000  # in seconds
     28 #web.config.session_parameters['ignore_expiry'] = True
     29 #web.config.session_parameters['ignore_change_ip'] = True
     30 #web.config.session_parameters['secret_key'] = 'fLjUfxqXtfNoIldA0A0R'
     31 #web.config.session_parameters['expired_message'] = 'Session expired'
     32 
     33 urls = (
     34     "/", "index",
     35     "/login?", "login",
     36     "/logout", "logout",
     37     "/addevent?", "addevent",
     38     "/event", "event",
     39     "/undo", "undo",
     40     "/roskis", "undo",
     41     "/removeevent/(\d+)", "removeevent",
     42     "/editevent/(\d+)", "editevent",
     43     "/removepost/(\d+)", "removepost",
     44     "/old", "old",
     45     "/bilder?", "bilder",
     46     "/upload?", "upload",
     47     "/bild/(.*)?", "bild",
     48     "/bildinfo/(.*)?", "bildinfo",
     49     "/om", "om",
     50     "/remove/(.*)?","remove",
     51     "/tuning?", "tuning",
     52     "/senaste", "senaste",
     53     "/admin?", "admin",
     54     "/boka?", "boka",
     55     "/fakturor?", "fakturor",
     56     "/dorrkoder?", "dorrkoder",
     57     "/nydorrkod?", "nydorrkod",
     58     "/dorrkoderapi?", "dorrkoderapi",
     59     "/kod?","kod",
     60     "/register?", "register",
     61     "/forgotpass?", "forgotpass",
     62     "/ny", "ny",
     63     "/tack", "tack",
     64     "/protokoll?", "protokoll",
     65     "/nope", "nope"
     66 )
     67 
     68 #from settings.py
     69 postadmin = settings.postadmin
     70 postadmin_signature = settings.postadmin_signature
     71 mlinvoice_db = settings.mlinvoice_db
     72 mlinvoice_db_user = settings.mlinvoice_db_user
     73 mlinvoice_db_pass = settings.mlinvoice_db_pass
     74 mlinvoice_login=settings.mlinvoice_login
     75 mlinvoice_passwd=settings.mlinvoice_passwd
     76 
     77 render = web.template.render(basedir + "/public_html/html/", base="base")
     78 render2 = web.template.render(basedir + "/public_html/html/", base="base2")
     79 render3 = web.template.render(basedir + "/public_html/html/", base="base3")
     80 web.config.debug = False
     81 app = web.application(urls, globals())
     82 store = web.session.DiskStore(basedir + '/sessions')
     83 db = web.database(dbn="sqlite", db=basedir + "/db/bygdis.db")
     84 db2 = web.database(dbn="mysql", db=mlinvoice_db, user=mlinvoice_db_user, pw=mlinvoice_db_pass)
     85 session = web.session.Session(app,store,initializer={'login': 0, 'user': '', 'backurl': '', 'bildsida': 0, 'search': ''})
     86 
     87 def logged():
     88     if session.login == 5:
     89         return True
     90     else:
     91         return False
     92 
     93 def curdate():
     94     today = datetime.datetime.now().date().strftime('%s')
     95     return today
     96 
     97 def getkalender():
     98     events = db.query("SELECT * FROM kalender WHERE datumtid > DATETIME('now') ORDER BY datumtid ASC")
     99     #events = db.select('kalender', what='id, datumtid, event', order='datumtid ASC')
    100     return events
    101 
    102 def getkalenderall():
    103     events = db.query("SELECT * FROM kalender ORDER BY datumtid ASC")
    104     #events = db.select('kalender', what='id, datumtid, event', order='datumtid ASC')
    105     return events
    106 
    107 def nyevent(id, datumtid, event, admin_visible, info):
    108     f = '%Y-%m-%d %H:%M:%S'
    109     try:
    110         datumtid.weekday()
    111         print('not datetime object make it')
    112     except:
    113         datumtid = datetime.datetime.strptime(datumtid,f)
    114     veckodagar = u'Måndag', u'Tisdag', u'Onsdag', u'Torsdag', u'Fredag', u'Lördag', u'Söndag'
    115     veckodag = datumtid.weekday()
    116     if id==None:
    117         db.insert('kalender', datumtid=datumtid, veckodag=veckodagar[veckodag], event=event, admin=admin_visible, info=info)
    118     else:
    119         db.update('kalender', where='id="'+id+'"', datumtid=datumtid, veckodag=veckodagar[veckodag], event=event, admin=admin_visible, info=info)
    120     print("event added to database")
    121     return
    122 
    123 def copyevent(id, datumtid, event, admin_visible, info):
    124     veckodagar = u'Måndag', u'Tisdag', u'Onsdag', u'Torsdag', u'Fredag', u'Lördag', u'Söndag'
    125     veckodag = datumtid.weekday()
    126     db.insert('kalender', datumtid=datumtid, veckodag=veckodagar[veckodag], event=event, admin=admin_visible, info=info)
    127     print("event added to database")
    128     return
    129 
    130 def getbokningar():
    131     bokningar = db.query("SELECT * FROM bokningar ORDER BY datumtid DESC")
    132     #events = db.select('kalender', what='id, datumtid, event', order='datumtid ASC')
    133     return bokningar
    134 
    135 def getposts():
    136     posts = db.query("SELECT * FROM posts ORDER BY datumtid DESC")
    137     #events = db.select('kalender', what='id, datumtid, event', order='datumtid ASC')
    138     return posts
    139 
    140 def nypost(datumtid, post):
    141     db.insert('posts',  datumtid=datumtid, post=post, likes=0)
    142     print("post added to database")
    143     return
    144 
    145 def getprotokoll(year):
    146     listmodtime = []
    147     for a in os.scandir(basedir + '/protokoll/' + year):
    148         filename = a.name
    149         modtime = a.stat().st_mtime
    150         listmodtime.append((filename, modtime))
    151     listmodtime.sort(key=lambda tup: tup[0])
    152     protokoll = []
    153     for a in listmodtime:
    154         if a[0][0] != '.':
    155             protokoll.append(a[0])
    156     return protokoll
    157 
    158 def getprotokoll_lastmodified(year):
    159     listmodtime = []
    160     for a in os.scandir(basedir + '/protokoll/' + year):
    161         filename = a.name
    162         modtime = a.stat().st_mtime
    163         listmodtime.append((filename, modtime))
    164     listmodtime.sort(key=lambda tup: tup[1])
    165     protokoll = []
    166     for a in listmodtime:
    167         protokoll.append(a[0])
    168     return protokoll
    169 
    170 def md_to_html(markdownfile):
    171     #make html from markdown
    172     pandoc_html = ['pandoc', basedir + '/'+markdownfile, '-f', 'markdown', '-t', 'html']
    173     #make pdf from markdown
    174     viewfile = subprocess.check_output(pandoc_html)
    175     view = viewfile.decode()
    176     return view
    177 
    178 def md_to_pdf(markdownfile):
    179     randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    180     pandoc_pdf = ['pandoc', '--verbose', basedir + '/'+markdownfile, '-f', 'markdown', '-V', 'papersize:a4', '-V', 'geometry:margin=0.8in','-s', '-o', basedir + '/public_html/static/pdf/'+randhash+'.pdf']
    181     subprocess.Popen(pandoc_pdf, cwd=basedir + '/public_html/static/pdf/')
    182     time.sleep(3)
    183     raise web.seeother('/static/pdf/'+randhash+'.pdf?nocache='+randhash)
    184 
    185 def md_to_text(markdownfile):
    186     read_p=basedir + '/'+markdownfile
    187     with open(read_p, 'r') as file:
    188         p_list=file.readlines()
    189     pr=''
    190     for p in p_list:
    191         pr=pr+p
    192     return pr
    193 
    194 def adduser(name, password, mail):
    195     password = password.encode("utf-8")
    196     salt = bcrypt.gensalt()
    197     password_hashed = bcrypt.hashpw(password, salt)
    198     #check user db, if empty create admin
    199     users = db.query("SELECT COUNT(*) AS users FROM bildadmin")[0]
    200     tot = int(users.users)
    201     print('users alltsomallt: ' + str(tot))
    202     if tot > 1:
    203         db.insert('bildadmin', name=name, displayname=name, password=password_hashed, mail=mail, subscribe='aldrig', adminlevel=3)
    204     else:
    205         db.insert('bildadmin', name=name, displayname=name, password=password_hashed, mail=mail, subscribe='aldrig', adminlevel=5)
    206     print("new user added")
    207     return
    208 
    209 def bildhistoriker():
    210     bildhistoriker = db.query("SELECT name, displayname, mail, password FROM bildadmin")
    211     return bildhistoriker
    212 
    213 def adminlevel(user):
    214     level = db.query("SELECT adminlevel FROM bildadmin WHERE name='"+user+"';")[0]
    215     #1 session logout, web.py bug
    216     #2 rights to see pics and comment
    217     #3 rights to upoload
    218     #5 superadmin
    219     session.login = int(level.adminlevel)
    220     return
    221 
    222 def getdisplayname(user):
    223     displayname = db.query("SELECT displayname FROM bildadmin WHERE name='"+user+"';")[0]
    224     return displayname.displayname
    225 
    226 def getkund(id):
    227     try:
    228         name = db2.query("SELECT company_name FROM mlinvoice_company WHERE id='"+str(id)+"';")[0]
    229     except:
    230         name = ''
    231     return name.company_name
    232 
    233 def getmaksuja(id):
    234     try:
    235         maksut = db2.query("SELECT * FROM mlinvoice_invoice_row WHERE invoice_id='"+str(id)+"';")
    236     except:
    237         maksut = ''
    238     return maksut
    239 
    240 def getprodukt(id):
    241     try:
    242         str(int(id))
    243         produkt = db2.query("SELECT * FROM mlinvoice_product WHERE id='"+str(id)+"';")[0]
    244         return produkt
    245     except:
    246         produkt = ''
    247     try:
    248         produkt = db2.query("SELECT * FROM mlinvoice_product WHERE product_name LIKE '%"+id[:-14]+"%';")[0]
    249         return produkt
    250     except:
    251         produkt = ''
    252     return produkt
    253 
    254 def getbilder():
    255     bilder = db.query("SELECT * FROM bilder ORDER BY uploaddate DESC")
    256     return bilder
    257 
    258 def addbild(filename, titel, namn, year, fotograf, beskrivning, uppladdare, personer):
    259     db.insert('bilder', filename=filename, titel=titel, uploaddate=datetime.datetime.now(), namn=namn, year=year, fotograf=fotograf, beskrivning=beskrivning, uppladdare=uppladdare, personer=personer)
    260 
    261 def addDorrkod(dorrkod, name, mail):
    262     db.insert('dorrkoder', dorrkod=dorrkod, name=name, mail=mail, datum=datetime.datetime.now())
    263 
    264 def dorrLogger(dorrkod):
    265     db.insert('dorrlogger', dorrkod=dorrkod, datum=datetime.datetime.now())
    266 
    267 def getDorrlog(limit):
    268     if limit == 0:
    269         log=db.query("SELECT * FROM dorrlogger ORDER BY datum DESC")
    270     else:
    271         log=db.query("SELECT * FROM dorrlogger ORDER BY datum DESC LIMIT "+str(limit))
    272     return log
    273 
    274 def getDorrkoduser(dorrkod):
    275     try:
    276         user = db.query("SELECT name FROM dorrkoder WHERE dorrkod='"+str(dorrkod)+"';")[0]
    277         return user.name
    278     except:
    279         user = 'unknown'
    280         return user
    281 
    282 def getDorrkoder():
    283     dorrkoder=db.query("SELECT * FROM dorrkoder ORDER BY datum DESC")
    284     return dorrkoder
    285 
    286 def sendmail(email, subject, msg, bilaga):
    287     #Send mail
    288     echomsg = subprocess.Popen(('echo', msg+'\n'+postadmin_signature), stdout=subprocess.PIPE)
    289     if bilaga != '':
    290         sendmsg = subprocess.check_output(('mail.mailutils', '-A', bilaga, '-a', 'From:'+postadmin, '-r', postadmin, '-s', subject, email),stdin=echomsg.stdout)
    291     else:
    292         sendmsg = subprocess.check_output(('mail.mailutils', '-r', postadmin, '-a', "Content-Type: text/plain;", '-a', 'From:'+postadmin, '-s', subject, email), stdin=echomsg.stdout)
    293         #sendmsg = subprocess.check_output(('mail.mailutils', '-r', postadmin, '-a', "Content-Type: text/plain; charset='utf-8'", '-a', 'From:'+postadmin, '-s', subject, email), stdin=echomsg.stdout)
    294     echomsg.wait()
    295     #subprocess.call(['echo', msg, '|', 'mail', '-r', 'rob@tarina.org','-s', subject, email])
    296 
    297 def stopflood(ip,referer):
    298     try:
    299         t = db.select('stopflood', where='ip="'+ip+'"', what='tid')[0]
    300     except:
    301         pass
    302     try:
    303         db.update('stopflood', where='ip="'+ip+'"', tid=time.time())
    304     except:
    305         db.insert('stopflood', ip=ip, tid=time.time())
    306     try:
    307         senast = time.time() - t.tid
    308         print(senast)
    309         if senast < 2:
    310             return web.seeother(referer)
    311         else:
    312             return
    313     except:
    314         return
    315 
    316 def stopresetpass(mail):
    317     try:
    318         t = db.select('stopresetpass', where='mail="'+mail+'"', what='tid')[0]
    319         print(t)
    320     except Exception as e:
    321         print(e)
    322     try:
    323         db.update('stopresetpass', where='mail="'+mail+'"', tid=time.time())
    324     except Exception as e:
    325         print(e)
    326         db.insert('stopresetpass', mail=mail, tid=time.time())
    327     try:
    328         senast = time.time() - t.tid
    329         print(senast)
    330         if senast < 604800:
    331             print('mail is in password reset spam filter')
    332             return True
    333         else:
    334             return False
    335     except Exception as e:
    336         print(e)
    337         return True
    338 
    339 class om():
    340     def GET(self):
    341         return render.om()
    342 
    343 class admin():
    344     form = web.form.Form(
    345     web.form.Textarea('post', web.form.notnull, description="", width="500px", height="200px", autocomplete="off"),
    346     web.form.Button('skicka'))
    347     def GET(self):
    348         print(session.login)
    349         if session.login == 5:
    350             doordebug = db.select('doordebug')[0]
    351             saysomething = self.form()
    352             anslagstavla = getposts()
    353             bokningar = getbokningar()
    354             roskis=db.select('roskis')[0]
    355             i = web.input(approve=None,sendrules=None,fakturera=None,doorcode=None,remove=None,emptytrash=None)
    356             if i.approve != None:
    357                 #Send mail to admin
    358                 bokning = db.select('bokningar', where='id="'+i.approve+'"')[0]
    359                 msg = "Bokning godkänd av " + bokning.namn + ' epost: ' + bokning.epost
    360                 sendmail(postadmin, 'Bokning godkänd!', msg, '')
    361                 #Send mail to user
    362                 msg = "Hej " + bokning.namn + " bokning " + bokning.datumtid + " godkändes, Tack!"
    363                 sendmail(bokning.epost, 'Bokning av Bygdegården lyckades och är godkänd', msg, '')
    364                 #update booking
    365                 db.update('bokningar', where='id="'+i.approve+'"', approved=datetime.datetime.now())
    366                 #add to kalender events as privat bokning
    367                 print(bokning.datumtid)
    368                 nyevent(None, bokning.datumtid, 'privat bokning', bokning.namn, 'privat bokning')
    369                 raise web.seeother('/admin')
    370             if i.sendrules != None:
    371                 #Send mail to admin
    372                 bokning = db.select('bokningar', where='id="'+i.sendrules+'"')[0]
    373                 msg = "Skickar regler och villkor till " + bokning.namn + ' epost: ' + bokning.epost
    374                 sendmail(postadmin, 'Skickar villkor och regler', msg,'')
    375                 #Send mail to user
    376                 msg = "Hej " + bokning.namn + "! Gå in här https://bygdis.fi/boka?id="+bokning.bokningshash+" och godkänn regler och villkor för din bokning, du får fakturan inom kort och en dörrkod när fakturan är betald. Tack!"
    377                 sendmail(bokning.epost, 'Regler och villkor för Bygdegården', msg,'')
    378                 #update booking
    379                 db.update('bokningar', where='id="'+i.sendrules+'"', approved="")
    380                 raise web.seeother('/admin')
    381             if i.fakturera != None:
    382                 db.update('bokningar', where='id="'+i.fakturera+'"', faktura=datetime.datetime.now())
    383                 raise web.seeother('/admin')
    384             if i.doorcode != None:
    385                 raise web.seeother('/admin?kakka')
    386             if i.remove != None:
    387                 db.update('bokningar', where='id="'+i.remove+'"', deleted=1)
    388                 raise web.seeother('/admin')
    389             if i.emptytrash == 'now':
    390                 msg = "Hej, kan vi få avfallshämtning till Påvalsbyvägen 679, 07870 Skinnarby? ingen brådska, bara så fort som möjligt, tack! ;)"
    391                 sendmail('asiakaspalvelu@rosknroll.fi', 'Roskistömning till Påvalsbyvägen 679', msg,'')
    392                 db.update('roskis',  where='id=1',datum=datetime.datetime.now())
    393                 raise web.seeother('/admin')
    394             log = getDorrlog(10)
    395             return render2.admin(anslagstavla,saysomething,bokningar,doordebug,str,log,getDorrkoduser,roskis)
    396         else:
    397             raise web.seeother('/login')
    398     def POST(self):
    399         if session.login == 5:
    400             i = web.input(post=None,approve=None,sendrules=None,fakturera=None,doorcode=None,remove=None)
    401             saysomething = self.form()
    402             if i.post != None:
    403                 print('ADDDDDDDDDDDDDING TO database post ' + i.post)
    404                 now = datetime.datetime.now()
    405                 print('ADDDDDDDDDDDDDING TO database date' + str(now))
    406                 nypost(now, i.post)
    407             raise web.seeother('/admin')
    408         else:
    409             raise web.seeother('/login')
    410 
    411 class boka():
    412     produkter = []
    413     p = db2.select('mlinvoice_product')
    414     for i in p:
    415         if i.product_name != None and i.deleted == 0:
    416             produkter.append(i.product_name+' | '+str(round(i.unit_price,2))+' €')
    417     form = web.form.Form(
    418     web.form.Textbox('year', web.form.notnull, web.form.regexp('\d+', 'yyyy'), description="år:"),
    419     web.form.Textbox('day', web.form.notnull, web.form.regexp('\d+', 'dd'), description="dag:", autofocus="autofocus"),
    420     web.form.Textbox('month', web.form.notnull, web.form.regexp('\d+', 'MM'), description="månad:"),
    421     web.form.Dropdown('boka', produkter, web.form.notnull, description="hyr"),
    422     web.form.Textarea('event', web.form.notnull, description="beskrivning och uppskattat antal gäster:"),
    423     web.form.Textbox('namn', web.form.notnull, description="namn:"),
    424     web.form.Textbox('epost', web.form.notnull, description="e-post:"),
    425     web.form.Textbox('telefon', web.form.regexp('\d+', 'nummer tack'), description="telefon:"),
    426     web.form.Radio('villkor', [u'Nej', u'Ja'], web.form.notnull, description="Jag har läst och godkänner alla ovannämnda regler och villkor."),
    427     web.form.Radio('privat', [u'Privat', u'Offentligt'], web.form.notnull, description="I hurudant syfte?:"),
    428     web.form.Button('Skicka'))
    429     def GET(self):
    430         i = web.input(id=None, cp=None, pdf=None, kod=None)
    431         form_boka = self.form()
    432         if i.id==None:
    433             now = datetime.datetime.now()
    434             form_boka.fill(year=now.year, month=now.month, day=now.day)
    435             if i.kod=='jep':
    436                 form_boka.fill(year=now.year, month=now.month, day=now.day ,boka='Dörrkod / Ovikoodi | 10.00 €', privat='Privat', event='Dörrkod för användning av Bygdegården i privat syfte.') 
    437         else:
    438             event = db.select('bokningar', where='bokningshash="'+i.id+'"')[0]
    439             now=datetime.datetime.strptime(event.datumtid, '%Y-%m-%d %H:%M:%S')
    440             form_boka.fill(year=now.year, month=now.month, day=now.day, boka=event.boka, event=event.event, namn=event.namn, epost=event.epost, telefon=event.telefon, villkor=event.villkor, privat=event.privat)
    441         regler = md_to_html('protokoll/dokument/hyreskontrakt_regler_och_villkor.md')
    442         if i.pdf != None:
    443             md_to_pdf('protokoll/dokument/hyreskontrakt_regler_och_villkor.md')
    444         return render.boka(form_boka, regler)
    445     def POST(self):
    446         form_boka = self.form()
    447         if not form_boka.validates():
    448             return render.nope()
    449             #regler = md_to_html('protokoll/dokument/hyreskontrakt_regler_och_villkor.md')
    450             #return render.boka(form_boka,regler)
    451         else:
    452             i = web.input(id=None, copyevent=None)
    453             try:
    454                 year = int(i.year)
    455                 month = int(i.month)
    456                 day = int(i.day)
    457                 datum = datetime.datetime(year, month, day)
    458             except ValueError:
    459                 return render.nope()
    460             if i.id == None:
    461                 bokningshash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    462                 db.insert('bokningar', datumtid=datetime.datetime(year, month, day), boka=i.boka, event=i.event, namn=i.namn, epost=i.epost, telefon=i.telefon, villkor=i.villkor, privat=i.privat, bokningshash=bokningshash)
    463             else:
    464                 db.update('bokningar', where='bokningshash="'+i.id+'"', datumtid=datetime.datetime(year, month, day), boka=i.boka, event=i.event, namn=i.namn, epost=i.epost, telefon=i.telefon, villkor=i.villkor, privat=i.privat, approved='')
    465             if i.villkor=='Ja':
    466                 #Send mail to admin
    467                 msg = "Ny bokning! " + i.namn + ' epost: ' + i.epost
    468                 sendmail(postadmin, 'Ny bokning!', msg,'')
    469                 #Send mail to user
    470                 rules_and_regulations = md_to_text('protokoll/dokument/hyreskontrakt_regler_och_villkor.md')
    471                 msg = "Hej " + i.namn + "! Tack för att du valde Bygdegården. Vi kontaktar dej som snarast om din boknings förfrågan och du får faktura per epost och en dörrkod när fakturan är betald. Tack! Här under är regler och villkor vilka du har läst och godkänner då du hyr hos oss. \n\n" + rules_and_regulations
    472                 sendmail(i.epost, 'Regler och villkor för Bygdegården', msg,'')
    473             raise web.seeother('/tack') 
    474 
    475 class tack():
    476     def GET(self):
    477         return render.tack()
    478 
    479 class fakturor():
    480     def GET(self):
    481         if session.login == 5:
    482             viewfile = ''
    483             i = web.input(radera=None,uppdatera=None,fakturera=None,add=None,faktura=None,yes=None,epost=None, kund=None, produkt=None)
    484             #
    485             # MLINVOICE COpy Faktura och Lägg till kund och vara i fakturan
    486             #
    487             #curl -b -X https://bygdis.fi/static/mlinvoice/login.php -i -b ~/cookies.txt -c ~/cookies.txt -d 'backlink=0&csrf=pcCFor0ic9KfoQ4jWQ3s&login=???&passwd=????&logon=Kirjaudu'
    488             #
    489             #get session and login to mlinvoice with csrf lol
    490             url='https://bygdis.fi/static/mlinvoice/login.php'
    491             r = ['curl','-b','X', url , '-i', '-b', basedir+'/sessions/cookies.txt', '-c',basedir+'/sessions/cookies.txt', '-d', 'backlink=0&csrf=&login='+mlinvoice_login+'&passwd='+mlinvoice_passwd+'&logon=Kirjaudu']
    492             view_csrf = subprocess.check_output(r)
    493             view = view_csrf.decode()
    494             soup = BeautifulSoup(view, "html.parser")
    495             csrf = soup.find(id="csrf")['value']
    496             login_mlinvoice = ['curl','-b','X', url , '-i', '-b', basedir+'/sessions/cookies.txt', '-c',basedir+'/sessions/cookies.txt', '-d', 'backlink=0&csrf='+csrf+'&login='+mlinvoice_login+'&passwd='+mlinvoice_passwd+'&logon=Kirjaudu']
    497             subprocess.check_output(login_mlinvoice)
    498             #yes
    499             #
    500             if i.add == 'faktura' and i.epost != None and i.kund != None and i.produkt != None:
    501                 url='https://bygdis.fi/static/mlinvoice/copy_invoice.php'
    502                 copy_mlinvoice = ['curl','-b','X', url , '-i', '-b', basedir+'/sessions/cookies.txt', '-c',basedir+'/sessions/cookies.txt', '-d', 'id=40']
    503                 viewfile = subprocess.check_output(copy_mlinvoice)
    504                 print(viewfile)
    505                 #
    506                 # GET LATEST INVOICE NR and ref
    507                 #
    508                 senaste = db2.query("SELECT * FROM mlinvoice_invoice ORDER BY id DESC LIMIT 1;")[0]
    509                 print(senaste)
    510                 url='https://bygdis.fi/static/mlinvoice/json.php'
    511                 get_nr_mlinvoice = ['curl','-b','X', url , '-b', basedir+'/sessions/cookies.txt', '-c',basedir+'/sessions/cookies.txt', '-d', 'func=get_invoice_defaults']
    512                 next_invoice=subprocess.check_output(get_nr_mlinvoice)
    513                 #print(next_invoice['invoice_no']
    514                 invoice = json.loads(next_invoice.decode())
    515                 #print(invoice)
    516                 #print(invoice['invoice_no'])
    517                 #
    518                 #KOLLA OM KUNDUPPGIFTER FINNS (lägg till annors)
    519                 try:
    520                     payer = db2.select('mlinvoice_company', where='email="'+str(i.epost)+'"')[0]
    521                 except:
    522                     db2.insert('mlinvoice_company', email=i.epost, company_name=i.kund)
    523                     payer = db2.select('mlinvoice_company', where='email="'+str(i.epost)+'"')[0]
    524                     #payer = db2.query("SELECT * FROM mlinvoice_company ORDER BY id DESC LIMIT 1;")[0]
    525                 #LÄGG TILL VAROR
    526                 #
    527                 produkt=getprodukt(i.produkt)
    528                 pris=produkt.unit_price
    529                 db2.insert('mlinvoice_invoice_row', invoice_id=senaste.id, product_id=produkt.id, pcs=1.00, price=float(pris))
    530                 #
    531                 db2.update('mlinvoice_invoice',where='id="'+str(senaste.id)+'"', invoice_no=invoice['invoice_no'], ref_number=invoice['ref_no'], company_id=payer.id, state_id=2)
    532                 #
    533                 #### Skicka epost
    534                 #
    535                 url='https://bygdis.fi/static/mlinvoice/invoice.php'
    536                 open_mlinvoice = ['curl','-b','X', url , '-i', '-b', basedir+'/sessions/cookies.txt', '-c',basedir+'/sessions/cookies.txt', '-d', 'id='+str(senaste.id)+'&template=15']
    537                 pdf_file = subprocess.check_output(open_mlinvoice)
    538                 pdfhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    539                 bilaga=basedir+'/public_html/static/pdf/'+pdfhash+'.pdf'
    540                 with open(bilaga,'wb') as binary_file:
    541                     binary_file.write(pdf_file)
    542                 #
    543                 #Laga epost faktura me virtuellstreckod
    544                 #
    545                 base_company=db2.select('mlinvoice_base', where='id="'+str(2)+'"' )[0]
    546                 faktura = db2.query("SELECT * FROM mlinvoice_invoice WHERE id='"+str(senaste.id)+"' ;")[0]
    547                 msg='Hej '
    548                 if faktura.deleted == 0:
    549                     if faktura.company_id:
    550                         msg+=getkund(faktura.company_id)+', här är fakturan\n\n'
    551                     msg+='nr:'+str(faktura.invoice_no)+'\n'
    552                     msg+='ref:'+str(faktura.ref_number)+'\n'
    553                     msg+='datum:'+str(faktura.invoice_date)+'\n'
    554                     msg+='sista betalningsdag:'+str(faktura.due_date)+'\n'
    555                     tot = 0
    556                     for p in getmaksuja(faktura.id):
    557                         if p.deleted != 1:
    558                             tot = tot + p.price
    559                             if p.product_id:
    560                                 msg+=getprodukt(p.product_id).product_name+' '
    561                             else:
    562                                 msg+=p.description+' '
    563                             msg+=str(round(p.price,2))+' € \n'
    564                     msg+='totalt: '+str(round(tot,2))+' € \n'
    565                 due_date=datetime.datetime.strptime(str(faktura.due_date), '%Y%m%d')
    566                 vs = virtuaaliviivakoodi(base_company.bank_iban,faktura.ref_number,due_date=due_date,euro_amount=float(tot))
    567                 msg += ' \nVirtuell streckkod: '+vs
    568                 sendmail(i.epost, 'Faktura', msg, bilaga)
    569             if i.fakturera != None:
    570                 db.update('bokningar', where='id="'+i.fakturera+'"', faktura=datetime.datetime.now())
    571                 raise web.seeother('/admin?fakturera='+i.fakturera)
    572             if i.faktura != None:
    573                 url='https://bygdis.fi/static/mlinvoice/invoice.php'
    574                 open_mlinvoice = ['curl','-b','X', url , '-i', '-b', basedir+'/sessions/cookies.txt', '-c',basedir+'/sessions/cookies.txt', '-d', 'id='+i.faktura+'&template=15']
    575                 pdf_file = subprocess.check_output(open_mlinvoice)
    576                 pdfhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    577                 bilaga=basedir+'/public_html/static/pdf/'+pdfhash+'.pdf'
    578                 with open(bilaga,'wb') as binary_file:
    579                     binary_file.write(pdf_file)
    580                 raise web.seeother('/static/pdf/'+pdfhash+'.pdf')
    581             alla_fakturor = db2.query("SELECT * FROM mlinvoice_invoice ORDER BY id DESC;")
    582             return render.fakturor(alla_fakturor,getkund,getmaksuja,round,getprodukt)
    583         else:
    584             web.seeother('/')
    585 
    586 class event():
    587     def GET(self):
    588         if session.login == 5:
    589             upcomingevents = getkalender()
    590             return render2.event(upcomingevents)
    591         else:
    592             raise web.seeother('/login')
    593 
    594 class addevent():
    595     form = web.form.Form(
    596     web.form.Textbox('year', web.form.notnull, web.form.regexp('\d+', 'yyyy'), description="år:"),
    597     web.form.Textbox('day', web.form.notnull, web.form.regexp('\d+', 'dd'), description="dag:", autofocus="autofocus"),
    598     web.form.Textbox('month', web.form.notnull, web.form.regexp('\d+', 'MMM'), description="månad:"),
    599     web.form.Textbox('tid', web.form.notnull, web.form.regexp('^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$', 'Skriv tiden såhär 07:20'), description="klockslag:"),
    600     web.form.Dropdown('upprepa', [u'Nej', u'Varje vecka', u'Varannan vecka', u'Varje månad'], web.form.notnull, description="återkommande"),
    601     web.form.Textbox('antal', web.form.regexp('\d+', 'nummer tack'), description="hur många gånger:"),
    602     web.form.Textarea('event', description="beskrivning:"),
    603     web.form.Textarea('info', description="mer info:"),
    604     web.form.Textarea('admin', description="synligt för admin:"),
    605     web.form.Button('skicka'))
    606     def GET(self):
    607         i = web.input(id=None, cp=None)
    608         if session.login == 5:
    609             kalender = self.form()
    610             if i.id==None:
    611                 now = datetime.datetime.now()
    612                 kalender.fill(year=now.year, month=now.month, day=now.day, tid=str(now.hour).zfill(2) + ':00', antal='1')
    613             else:
    614                 event = db.select('kalender', where='id="'+i.id+'"')[0]
    615                 now=datetime.datetime.strptime(event.datumtid, '%Y-%m-%d %H:%M:%S')
    616                 kalender.fill(year=now.year, month=now.month, day=now.day, tid=str(now.hour).zfill(2) + ':00', antal='1', event=event.event, admin=event.admin, info=event.info)
    617             return render.addevent(kalender)
    618         else:
    619             raise web.seeother('/login')
    620     def POST(self):
    621         if session.login == 5:
    622             kalender = self.form()
    623             if not kalender.validates():
    624                 return render.addevent(kalender)
    625             else:
    626                 i = web.input(id=None, copyevent=None)
    627                 try:
    628                     tidh = int(i.tid[:2])
    629                     tidm = int(i.tid[-2:])
    630                     year = int(i.year)
    631                     month = int(i.month)
    632                     day = int(i.day)
    633                     antal = int(i.antal)
    634                     datum = datetime.datetime(year, month, day, tidh, tidm)
    635                 except ValueError:
    636                     return render.nope()
    637                 manydatum = []
    638                 dayz = 0
    639                 c = 0
    640                 if 'Varje v' in i.upprepa:
    641                     dayz = 7
    642                 if 'Varannan' in i.upprepa:
    643                     dayz = 14
    644                 if 'Varje m' in i.upprepa:
    645                     dayz = 28
    646                 if 'Nej' in i.upprepa:
    647                     antal = 1
    648                 for a in range(0, antal):
    649                     manydatum.append(datum + datetime.timedelta(days=c))
    650                     c = c + dayz
    651                 for d in manydatum:
    652                     if copyevent != None:
    653                         copyevent(i.id, d, i.event, i.admin, i.info)
    654                     else:
    655                         nyevent(i.id, d, i.event, i.admin, i.info)
    656                 return web.seeother('/event')
    657         else:
    658             raise web.seeother('/login')
    659 
    660 class removeevent():
    661     def GET(self, id):
    662         if session.login == 5:
    663             e = db.select('kalender', where='id="'+str(id)+'"')[0]
    664             db.insert('kalroskis', datumtid=e.datumtid, event=e.event, admin=e.admin, info=e.info)
    665             db.delete('kalender', where="id=" + id)
    666             raise web.seeother('/event')
    667         else:
    668             raise web.seeother('/login')
    669 
    670 class undo():
    671     def GET(self):
    672         if session.login == 5:
    673             e = db.query("SELECT * FROM kalroskis ORDER BY id DESC LIMIT 1;")[0]
    674             db.insert('kalender', datumtid=e.datumtid, event=e.event, admin=e.admin, info=e.info)
    675             e = db.query("DELETE FROM kalroskis ORDER BY id DESC LIMIT 1;")
    676             raise web.seeother('/event')
    677         else:
    678             raise web.seeother('/login')
    679 
    680 class editevent():
    681     def POST(self):
    682         s = web.input().signal
    683         print(s)
    684         if session.login == 5:
    685             return
    686         else:
    687             return
    688 
    689 class removepost():
    690     def POST(self, id):
    691         if session.login == 5:
    692             db.delete('posts', where="id=" + id)
    693             raise web.seeother('/admin')
    694         else:
    695             raise web.seeother('/login')
    696 
    697 class login():
    698     form = web.form.Form(
    699     web.form.Textbox('user', web.form.notnull, description="namn eller e-post:"),
    700     web.form.Password('password', web.form.notnull, description="lösenord:"),
    701     web.form.Button('Logga in'))
    702     def GET(self):
    703         fejl = ''
    704         resetpasslink = False
    705         i = web.input(error=None)
    706         if i.error == 'fejl':
    707             fejl = 'fejl lösenord! / Väärä salasana'
    708             resetpasslink = True
    709         if i.error == 'tom':
    710             fejl = 'hmm.. he funkka inga! / Ei toimi'
    711         if session.login < 3:
    712             loginform = self.form()
    713             return render.login(loginform, fejl, resetpasslink)
    714         if session.login == 3:
    715             return web.seeother('/')
    716         if session.login == 5:
    717             raise web.seeother('/admin')
    718     def POST(self):
    719         referer = web.ctx.env.get('HTTP_REFERER','https://bygdis.fi')
    720         ip = web.ctx['ip']
    721         stopflood(ip, referer)
    722         loginform = self.form()
    723         i = web.input()
    724         if i.user == '' or i.password == '':
    725             raise web.seeother('/login?error=tom')
    726         bildadmin = []
    727         bildadmins = bildhistoriker()
    728         for p in bildadmins:
    729             if p.name.lower() == i.user.lower() or p.mail.lower() == i.user.lower():
    730                 try:
    731                     encodepass = p.password.encode("utf-8")
    732                 except:
    733                     encodepass = p.password
    734                 if bcrypt.checkpw(i.password.encode('utf-8'), encodepass):
    735                     session.user = p.name
    736                     adminlevel(p.name)
    737                     print('BACKURL: '+session.backurl)
    738                     if session.login == 5:
    739                         raise web.seeother('/admin')
    740                     if session.backurl != '':
    741                         backurl = session.backurl
    742                         session.backurl = ''
    743                         raise web.seeother(backurl)
    744                     else:
    745                         if i.user == "byyssare":
    746                             raise web.seeother('/register')
    747                         raise web.seeother('/')
    748         else:
    749             return web.seeother('/login?error=fejl')
    750 
    751 class forgotpass():
    752     form = web.form.Form(
    753     web.form.Textbox('mail', web.form.notnull, description="e-post:"),
    754     web.form.Button('Skicka nytt lösenord / Lähetä uusi salasana'))
    755     def GET(self):
    756         fejl = ''
    757         i = web.input(error=None)
    758         if i.error == 'fejl':
    759             fejl = 'hittar inga e-post / ei löydy email'
    760         elif i.error == 'done':
    761             fejl = 'ditt lösenord e uppdaterat å skickat till din e-post / salasanasi on vaihdettu ja lähetetty mailiisi'
    762         elif i.error == 'nej':
    763             fejl = 'nej hörru dedär gaar inga / ei käy'
    764         elif i.error == 'stopresetpass':
    765             fejl = 'Nytt lösenord ha skickats åt dej! int ha du väl nu igen tappat bort ditt lösen? hmm.. om de e problematiskt ta kontakt med '+postadmin+' / sama på finska'
    766         if session.login < 3:
    767             loginform = self.form()
    768             return render.forgotpass(loginform, fejl)
    769         if session.login == 3:
    770             return web.seeother('/bilder')
    771         if session.login == 5:
    772             raise web.seeother('/admin')
    773     def POST(self):
    774         referer = web.ctx.env.get('HTTP_REFERER','https://bygdis.fi')
    775         ip = web.ctx['ip']
    776         stopflood(ip, referer)
    777         sendpassform = self.form()
    778         if not sendpassform.validates():
    779             return render.login(sendpassform, '')
    780         else:
    781             i = web.input()
    782             bildadmin = []
    783             bildadmins = bildhistoriker()
    784             if i.mail.lower() == 'byyssare':
    785                 raise web.seeother('/forgotpass?error=nej')
    786             for p in bildadmins:
    787                 if p.mail.lower() == i.mail.lower():
    788                     passfilter = stopresetpass(i.mail.lower())
    789                     if passfilter == True:
    790                         raise web.seeother('/forgotpass?error=stopresetpass')
    791                     unencrypted_password = ('%06x' % random.randrange(16**6))
    792                     password = unencrypted_password.encode("utf-8")
    793                     salt = bcrypt.gensalt()
    794                     password_hashed = bcrypt.hashpw(password, salt)
    795                     db.update('bildadmin', where='name="'+p.name+'"', password=password_hashed)
    796                     print("lösenordet uppdaterat!")
    797                     msg = "Ditt nya lösenord till bygdis.fi e: " + unencrypted_password + ' , om du vill ändra lösenordet ti någå ana som du minns så tryck på namne ditt högst op på ruutån efter du loggat in.'
    798                     sendmail(p.mail, 'Nytt lösenord till byyns fotoalbum', msg,'')
    799                     raise web.seeother('/forgotpass?error=done')
    800             raise web.seeother('/forgotpass?error=fejl')
    801 
    802 class register():
    803     form = web.form.Form(
    804     web.form.Textbox('user', description="användarnamn:"),
    805     web.form.Password('password', description="lösenord:"),
    806     web.form.Textbox('mail', description="e-post:"),
    807     web.form.Button('Skapa konto'))
    808     def GET(self):
    809         registerform = self.form()
    810         w = web.input()
    811         formfail = ''
    812         n = ''
    813         m = ''
    814         try:
    815             if w.fail == 'namn':
    816                 formfail = 'du måst hiitt opa eitt namn åt te!'
    817             if w.namn:
    818                 n = w.namn
    819             if w.epost:
    820                 m = w.epost
    821             elif w.epost == '':
    822                 formfail = 'tu måst lägg din epost address tär i ruuton, he e nu bara så...'
    823             if w.fail == 'notmail':
    824                 formfail = 'jusså, tetär e no inga nån mejl adress.'
    825             elif w.fail == 'nametaken':
    826                 formfail = 'Nån anan ha tagi de namme, hitt opa någå ana!'
    827             elif w.fail == 'mailtaken':
    828                 formfail = 'tu ha redan laga ett användarnamn me tetta epost konto!'
    829             elif w.fail == 'kortlosen':
    830                 print('kakkaka')
    831                 formfail = 'he va no för uuslit lösenord, minst 5 bokstäver'
    832         except:
    833             pass
    834         #check user db, if empty create admin
    835         users = db.query("SELECT COUNT(*) AS users FROM bildadmin")[0]
    836         totusers = int(users.users)
    837         registerform.fill(user=urllib.parse.unquote_plus(n), mail=urllib.parse.unquote_plus(m))
    838         if session.login > 1:
    839             return render.register(registerform, formfail, totusers)
    840         else:
    841             raise web.seeother('/')
    842     def POST(self):
    843         if session.login > 1:
    844             registerform = self.form()
    845             i = web.input()
    846             r = '&namn=' + i.user + '&epost=' + i.mail
    847             urllib.parse.quote_plus(r)
    848             if i.user == '':
    849                 raise web.seeother('/register?fail=namn'+r)
    850             if '@' not in i.mail:
    851                 raise web.seeother('/register?fail=notmail'+r)
    852             if len(i.password) < 5:
    853                 raise web.seeother('/register?fail=kortlosen'+r)
    854             bildadmins = db.select('bildadmin', what='name, mail')
    855             for p in bildadmins:
    856                 if p.name.lower() == i.user.lower():
    857                     raise web.seeother('/register?fail=nametaken' +r)
    858                 if p.mail.lower() == i.mail.lower():
    859                     raise web.seeother('/register?fail=mailtaken' +r)
    860             adduser(i.user, i.password, i.mail.lower())
    861             #Send mail to Madbaker
    862             msg = "Wowowowoweeewaaa! Ny användare på bygdis.fi! " + i.user + ' ' + i.mail
    863             sendmail(postadmin, 'Wowowoweewaaa!', msg,'')
    864             #Send mail to new user
    865             msg = "Gratulis " + i.user + ", du har nu ett konto opa bygdis.fi! Logga in med användarnamn å lösenord på sidan https://bygdis.fi/login"
    866             sendmail(i.mail, 'Byyns eji fotoalbum', msg,'')
    867             session.login = 3
    868             session.user = i.user
    869             return web.seeother('/ny')
    870 
    871 class nydorrkod():
    872     form = web.form.Form(
    873     web.form.Textbox('namn', description="användarnamn:"),
    874     web.form.Textbox('mail', description="e-post:"),
    875     web.form.Textbox('dorrkod', description="Dörrkod:"),
    876     web.form.Button('Skapa ny Dörrkod'))
    877     def GET(self):
    878         registerform = self.form()
    879         w = web.input()
    880         formfail = ''
    881         n = ''
    882         m = ''
    883         try:
    884             if w.fail == 'namn':
    885                 formfail = 'du måst hiitt opa eitt namn åt te!'
    886             if w.fail == 'notmail':
    887                 formfail = 'jusså, tetär e no inga nån mejl adress.'
    888             if w.fail == 'kod':
    889                 formfail = 'koden måst vara 4 siffror!'
    890         except:
    891             pass
    892         if session.login == 5:
    893             return render.nydorrkod(registerform, formfail)
    894         else:
    895             raise web.seeother('/')
    896     def POST(self):
    897         if session.login == 5:
    898             registerform = self.form()
    899             i = web.input(namn=None, mail=None, dorrkod=None, bokning=None)
    900             if i.namn == '':
    901                 raise web.seeother('/nydorrkod?fail=namn')
    902             if '@' not in i.mail:
    903                 raise web.seeother('/nydorrkod?fail=notmail')
    904             if i.dorrkod == None or i.dorrkod == '':
    905                 dorrkod = random.randint(1111,9999)
    906             elif isinstance(int(i.dorrkod), int) and len(i.dorrkod) == 4:
    907                 dorrkod = str(i.dorrkod)
    908             else:
    909                 raise web.seeother('/nydorrkod?fail=kod')
    910             addDorrkod(dorrkod, i.namn, i.mail.lower())
    911             #Send mail to Madbaker
    912             msg = "Wowowowoweeewaaa! Ny dörrkod! " + i.namn + ' ' + i.mail + ' ' + str(dorrkod)
    913             sendmail(postadmin, 'Wowowoweewaaa!', msg,'')
    914             #Send mail to new user
    915             msg = "Gratulis " + i.namn + ", du har en dörrkod till Bygdegården: \n\n" + str(dorrkod)
    916             sendmail(i.mail, 'Dörrkod till Bygdegården', msg,'')
    917             if i.bokning != None:
    918                 db.update('bokningar', where='id="'+i.bokning+'"', doorcode=datetime.datetime.now())
    919             return web.seeother('/dorrkoder')
    920 
    921 class dorrkoder():
    922     def GET(self):
    923         if session.login == 5:
    924             dorrkoder = getDorrkoder()
    925             log = getDorrlog(0)
    926             i = web.input(radera=None,uppdatera=None,fakturera=None,emptytrash=None)
    927             if i.radera != None:
    928                 db.delete('dorrkoder', where='id="'+i.radera+'"')
    929                 raise web.seeother('/dorrkoder')
    930             print(dorrkoder)
    931             return render.dorrkoder(dorrkoder,log,getDorrkoduser)
    932         else:
    933             web.seeother('/')
    934 
    935 class dorrkoderapi():
    936     def GET(self): 
    937         global basedir
    938         f = open(basedir+"/apikey", "r")
    939         apikey = f.readline().strip()
    940         i = web.input(apikey=None,logger=None,doorstate=None,debug=None)
    941         if i.apikey == apikey:
    942             if i.logger != None:
    943                 if len(i.logger) == 4:
    944                     if getDorrkoduser(i.logger) != '':
    945                         print('logging dorrkod!')
    946                         dorrLogger(i.logger)
    947                         print(i.logger)
    948                         print(i.doorstate)
    949                         print(i.debug)
    950             if i.doorstate != None:
    951                 print('yes, bygdis is online')
    952                 id=1
    953                 db.update('doordebug', where='id="'+str(id)+'"', doorstate=i.doorstate, debug=i.debug, datum=datetime.datetime.now())
    954             else:
    955                 dorrkoder = getDorrkoder()
    956                 #encoding = response.info().get_content_charset('utf8')
    957                 #apireq = data['icestats']['source'][1][i.req]
    958                 p = []
    959                 for i in dorrkoder:
    960                     p.append(i.dorrkod)
    961                     #print(i)
    962                 return json.dumps(p) 
    963 
    964 class ny():
    965     def GET(self):
    966         if session.login > 2:
    967             backurl = ''
    968             if session.backurl != '':
    969                 backurl = session.backurl
    970                 session.backurl = ''
    971             return render.ny(session.user, backurl)
    972 
    973 class tuning():
    974     form = web.form.Form(
    975     web.form.Textbox('user', description="synligt namn:"),
    976     web.form.Password('password', description="lösenord:"),
    977     web.form.Password('newpassword', description="nytt lösen (ifall du vill byta):"),
    978     web.form.Password('newpassword2', description="nytt lösen igen:"),
    979     web.form.Textbox('mail', description="epost:"), 
    980     web.form.Radio('subscribe', ['dagligen', 'aldrig'], description="Få epost brejv ifall de hänt någå"),
    981     web.form.Button('Spara'))
    982     def GET(self):
    983         if session.login > 2:
    984             print('asdfasdfasdf')
    985             user = db.select('bildadmin', where='name="'+session.user+'"')[0]
    986             tuningform = self.form()
    987             w = web.input(namn=None,epost=None,fail=None,upd=None)
    988             print('asdfasdfasdfkdakkakka')
    989             formfail = ''
    990             if w.fail == 'wrongpass':
    991                 formfail = formfail + 'fel lösenord'
    992             if w.fail == 'nopass':
    993                 formfail = formfail + 'Du måst skriv in ditt lösenord!'
    994             if w.namn == '':
    995                 formfail = formfail + 'du måst hiitt opa eitt namn åt te!'
    996             if w.epost == '':
    997                 formfail = formfail + 'tu måst lägg din epost address tär i ruuton, he e nu bara så...'
    998             elif w.fail == 'notmail':
    999                 formfail = formfail + 'jusså, tetär e no inga nån mejl adress.'
   1000             if w.fail == 'nametaken':
   1001                 formfail = formfail + 'Nån anan ha tagi de namme, hitt opa någå ana!'
   1002             if w.fail == 'mailtaken':
   1003                 formfail = formfail + 'He finns eitt konto me te epost adressn!'
   1004             if w.fail == 'kortlosen':
   1005                 formfail = formfail + 'he va no för uuslit lösenord, minst 5 bokstäver'
   1006             if w.fail == 'newpass':
   1007                 formfail = formfail + 'nya lösenordet stämmer inte överens med varann, pröva pånytt!'
   1008             if w.upd == 'yes':
   1009                 formfail = 'Yes, ditt konto e tuunat!'
   1010             tuningform.fill(user=user.displayname, mail=user.mail, subscribe=user.subscribe)
   1011             return render.tuning(tuningform, formfail, user.name)
   1012         else:
   1013             return web.seeother('/register')
   1014     def POST(self):
   1015         if session.login > 1:
   1016             tuningform = self.form()
   1017             i = web.input()
   1018             if i.password == '':
   1019                 raise web.seeother('/tuning?fail=nopass')
   1020             bildadmins = bildhistoriker()
   1021             for p in bildadmins:
   1022                 print(p)
   1023                 if p.name == session.user:
   1024                     if bcrypt.checkpw(i.password.encode('utf-8'), p.password):
   1025                         #check if display name taken
   1026                         b_displayname = bildhistoriker()
   1027                         for a in b_displayname:
   1028                             if i.user in a.displayname and a.name != session.user:
   1029                                 raise web.seeother('/tuning?fail=nametaken')
   1030                             if i.mail in a.mail and i.mail != p.mail:
   1031                                 raise web.seeother('/tuning?fail=mailtaken')
   1032                         if i.newpassword != '':
   1033                             if i.newpassword != i.newpassword2:
   1034                                 raise web.seeother('/tuning?fail=newpass')
   1035                             if len(i.newpassword) < 5:
   1036                                 raise web.seeother('/tuning?fail=kortlosen')
   1037                             else:
   1038                                 #update with password change
   1039                                 password = i.newpassword.encode("utf-8")
   1040                                 salt = bcrypt.gensalt()
   1041                                 password_hashed = bcrypt.hashpw(password, salt)
   1042                                 db.update('bildadmin', where='name="'+session.user+'"', displayname=i.user, password=password_hashed, mail=i.mail.lower(), subscribe=i.subscribe)
   1043                                 return web.seeother('/tuning?upd=yes')
   1044                         if '@' not in i.mail:
   1045                             raise web.seeother('/tuning?fail=notmail')
   1046                         #update without passwordchange
   1047                         db.update('bildadmin', where='name="'+session.user+'"', displayname=i.user, mail=i.mail.lower(), subscribe=i.subscribe)
   1048                         return web.seeother('/tuning?upd=yes')
   1049                     else:
   1050                         raise web.seeother('/tuning?fail=wrongpass')
   1051 
   1052 class bilder():
   1053     def GET(self):
   1054         bildpersida = 100
   1055         i = web.input()
   1056         try:
   1057             bilder_totalt = db.query("SELECT COUNT(*) AS bilder FROM bilder")[0]
   1058             tot = int(bilder_totalt.bilder)
   1059             print('bilder alltsomallt: ' + str(tot))
   1060         except:
   1061             print("inga bilder")
   1062             tot = 0
   1063         print('session search: ' + session.search)
   1064         try:
   1065             if i.search == '':
   1066                 session.search = ''
   1067                 session.bildsida = 0
   1068             elif i.search != "":
   1069                 session.search = urllib.parse.unquote_plus(i.search)
   1070                 session.bildsida = 0
   1071         except:
   1072             pass
   1073         if session.search != '':
   1074             search_result = []
   1075             tot = 0
   1076             b1, b2, b3, b4, b5, = 0,0,0,0,0
   1077             try:
   1078                 search_result.append(db.query("SELECT * FROM bilder WHERE personer LIKE '%"+session.search+"%';"))
   1079                 tot = db.query("SELECT Count(*) AS bilder FROM bilder WHERE personer LIKE '%"+session.search+"%';")[0]
   1080                 b1 = tot.bilder
   1081             except:
   1082                 pass
   1083             try:
   1084                 search_result.append(db.query("SELECT * FROM bilder WHERE fotograf LIKE '%"+session.search+"%';"))
   1085                 tot = db.query("SELECT Count(*) AS bilder FROM bilder WHERE fotograf LIKE '%"+session.search+"%';")[0]
   1086                 b2 = tot.bilder
   1087             except:
   1088                 pass
   1089             try:
   1090                 search_result.append(db.query("SELECT * FROM bilder WHERE plats LIKE '%"+session.search+"%';"))
   1091                 tot = db.query("SELECT Count(*) AS bilder FROM bilder WHERE plats LIKE '%"+session.search+"%';")[0]
   1092                 b3 = tot.bilder
   1093             except:
   1094                 pass
   1095             try:
   1096                 search_result.append(db.query("SELECT * FROM bilder WHERE titel LIKE '%"+session.search+"%';"))
   1097                 tot = db.query("SELECT Count(*) AS bilder FROM bilder WHERE titel LIKE '%"+session.search+"%';")[0]
   1098                 b4 = tot.bilder
   1099             except:
   1100                 pass
   1101             try:
   1102                 search_result.append(db.query("SELECT * FROM bilder WHERE year LIKE '%"+session.search+"%';"))
   1103                 tot = db.query("SELECT Count(*) AS bilder FROM bilder WHERE year LIKE '%"+session.search+"%';")[0]
   1104                 b5 = tot.bilder
   1105             except:
   1106                 pass
   1107             tot = b1 + b2 + b3 + b4 + b5
   1108             try:
   1109                 print(search_result)
   1110                 print('sökta bilder: ' + str(tot))
   1111             except:
   1112                 pass
   1113         try:
   1114             if i.page == "next":
   1115                 if session.bildsida < tot:
   1116                     session.bildsida += bildpersida
   1117             if i.page == "back":
   1118                 if session.bildsida > bildpersida:
   1119                     session.bildsida -= bildpersida
   1120                 else:
   1121                     session.bildsida = 0
   1122         except:
   1123             pass
   1124         if session.login > 1:
   1125             limit = session.bildsida + bildpersida
   1126             offset = session.bildsida
   1127             print(session.bildsida)
   1128             if session.search == '':
   1129                 bilder = db.query("SELECT * FROM bilder ORDER BY uploaddate DESC LIMIT " + str(limit) + " OFFSET " + str(offset))
   1130             else:
   1131                 bilder = search_result
   1132             if session.login > 3:
   1133                 try:
   1134                     if i.delete != '':
   1135                         return web.seeother('/remove/' + i.delete)
   1136                 except:
   1137                     pass
   1138                 rights = 'admin'
   1139             elif session.login > 2:
   1140                 rights = 'mod'
   1141             elif session.login > 1:
   1142                 rights = 'byyssare'
   1143 
   1144             return render.bilder(bilder, rights, session.user, tot, limit, bildpersida, session.search, db, str, print)
   1145         else:
   1146             return web.seeother('/login')
   1147 
   1148 class remove():
   1149     def GET(self, imghash):
   1150         if session.login > 1:
   1151             referer = web.ctx.env.get('HTTP_REFERER', 'none')
   1152             i = web.input(sure=None)
   1153             if i.sure == 'yes':
   1154                 db.delete('bilder', where='filename="' + imghash + '"')
   1155                 db.delete('allaversioner', where='filename="' + imghash + '"')
   1156                 db.delete('likes', where='bild="' + imghash + '"')
   1157                 db.delete('hates', where='bild="' + imghash + '"')
   1158                 db.delete('bildkommentar', where='filename="' + imghash + '"')
   1159                 return web.seeother('/bilder')
   1160             return render.remove(imghash, referer)
   1161 
   1162 class upload():
   1163     def GET(self):
   1164         if session.login == 2:
   1165             session.backurl = '/upload'
   1166             return web.seeother('register')
   1167         elif session.login > 2:
   1168             return render.upload()
   1169         else:
   1170             return web.seeother('/login')
   1171     def POST(self):
   1172         if session.login > 2:
   1173             i = web.input(imgfile={},edit=None)
   1174             for p in i:
   1175                 print(p)
   1176             if i.edit != None:
   1177                 imgname=i.edit
   1178                 if '.jpg' in i.edit:
   1179                     imghash=i.edit.replace('.jpg','')
   1180                 elif '.jpeg' in i.edit:
   1181                     imghash=i.edit.replace('.jpeg','')
   1182             else:
   1183                 imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
   1184                 imgname = imghash + '.jpeg'
   1185             if i.imgfile != {}:
   1186                 print(i.imgfile.filename)
   1187                 if i.imgfile.filename == '':
   1188                     print('hmmm... no image to upload')
   1189                     raise web.seeother('/upload?fail=noimg')
   1190                 print('YEAH, Upload image!')
   1191 
   1192                 ##---------- UPLOAD IMAGE ----------
   1193 
   1194                 imgdir = basedir + '/public_html/static/bilder/'
   1195                 imgpath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
   1196                 #filename=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
   1197 
   1198                 #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
   1199                 fout = open(imgdir +'/'+ imgname,'wb') # creates the file where the uploaded file should be stored
   1200                 fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
   1201                 fout.close() # closes the file, upload complete.
   1202                 os.chmod(imgdir+'/'+imgname, 0o755)
   1203 
   1204                 ##---------- OPEN FILE & CHEKC IF JPEG --------
   1205                 image = Image.open(imgdir +'/'+ imgname)
   1206                 if image.format != 'JPEG':
   1207                     os.remove(imgdir +'/'+ imgname)
   1208                     raise web.seeother('/upload?fail=notjpeg')
   1209 
   1210                 ##---------- RESIZE IMAGE -----------
   1211                 image.thumbnail((900,900), Image.ANTIALIAS)
   1212                 image.save(imgdir + '/web/' + imgname)
   1213                 image.thumbnail((300,300), Image.ANTIALIAS)
   1214                 image.save(imgdir + '/thumb/' + imgname)
   1215                 if i.edit == None:
   1216                     db.insert('bilder', filename=imghash, uploaddate=datetime.datetime.now(), uppladdare=session.user, lastmod=datetime.datetime.now(), moddedby=session.user)
   1217                 raise web.seeother('/bildinfo/' + imghash)
   1218             else:
   1219                 return render.upload()
   1220         else:
   1221             session.backurl = '/upload'
   1222             return render.register()
   1223 
   1224 class bildinfo():
   1225     form = web.form.Form(
   1226     web.form.Textbox('titel', web.form.notnull, description="Bild titel:"),
   1227     web.form.Textbox('year', web.form.notnull, description="År:"),
   1228     web.form.Textbox('fotograf', web.form.notnull, description="Fotograf:"),
   1229     web.form.Textbox('plats', web.form.notnull, description="Plats:"),
   1230     web.form.Textarea('beskrivning', web.form.notnull, description="Beskrivning:"),
   1231     web.form.Textarea('personer', web.form.notnull, description="Personer fr.v. (lägg ett komma mellan varje typ):"),
   1232     web.form.Button('Spara'))
   1233     def GET(self, imghash):
   1234         if session.login > 2:
   1235             infoform = self.form()
   1236             v = web.input()
   1237             if v:
   1238                 oldinfo = db.select('allaversioner', where="id='" + v.id +"'", what='titel, year, fotograf, beskrivning, personer, moddedby, lastmod, plats')
   1239             else:
   1240                 oldinfo = db.select('bilder', where="filename='" + imghash +"'", what='titel, year, fotograf, beskrivning, personer, moddedby, lastmod, plats')
   1241             print('fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu')
   1242             oldinfo = oldinfo[0]
   1243             allaversioner = db.select('allaversioner', where="filename='" + imghash +"'", what='id, moddedby, lastmod', order='id DESC')
   1244             infoform.fill(titel=oldinfo.titel, year=oldinfo.year, fotograf=oldinfo.fotograf, plats=oldinfo.plats, beskrivning=oldinfo.beskrivning, personer=oldinfo.personer)
   1245 
   1246             return render.bildinfo(infoform, imghash, oldinfo.moddedby, oldinfo.lastmod, allaversioner)
   1247         else:
   1248             session.backurl = '/bildinfo/' + imghash
   1249             return web.seeother("/register")
   1250     def POST(self, imghash):
   1251         ip = web.ctx['ip']
   1252         referer = web.ctx.env.get('HTTP_REFERER','https://bygdis.fi')
   1253         stopflood(ip, referer)
   1254         if session.login > 2:
   1255             i = web.input()
   1256             db.update('bilder', where="filename='" + imghash +"'", titel=i.titel, year=i.year, fotograf=i.fotograf, plats=i.plats, beskrivning=i.beskrivning, personer=i.personer, lastmod=datetime.datetime.now(), moddedby=session.user)
   1257             db.insert('allaversioner', filename=imghash, titel=i.titel, year=i.year, fotograf=i.fotograf, plats=i.plats, beskrivning=i.beskrivning, personer=i.personer, lastmod=datetime.datetime.now(), moddedby=session.user)
   1258             return web.seeother('/bildinfo/' + imghash)
   1259 
   1260 class bild():
   1261     form = web.form.Form(
   1262     web.form.Textarea('kommentar', web.form.notnull, description=""),
   1263     web.form.Button('kommentera'))
   1264     def GET(self, imghash):
   1265         i = web.input(unlike=None, like=None, hate=None, unhate=None)
   1266         kform = self.form()
   1267         if session.login > 1:
   1268             l = db.query("SELECT * FROM likes WHERE bild='"+imghash+"' AND user='"+session.user+"';")
   1269             h = db.query("SELECT * FROM hates WHERE bild='"+imghash+"' AND user='"+session.user+"';") 
   1270             if l:
   1271                 user_likes = True
   1272             else:
   1273                 user_likes = False
   1274             if h:
   1275                 user_hates = True
   1276             else:
   1277                 user_hates = False
   1278             try:
   1279                 if i.delete != '':
   1280                     allow_del = db.select('bildkommentar', where="id='"+i.delete+"'", what='user')[0]
   1281                     print(allow_del)
   1282                     if allow_del.user == session.user:
   1283                         db.delete('bildkommentar', where='id="' + i.delete + '"')
   1284             except:
   1285                 print('something wrong with input in class bild, så att du veit')
   1286             if i.like != None and user_likes == False:
   1287                 db.insert('likes', user=session.user, bild=imghash, datum=datetime.datetime.now())
   1288                 user_likes = True
   1289             elif i.unlike != None and user_likes == True:
   1290                 db.query("DELETE FROM likes WHERE bild='"+imghash+"' AND user='"+session.user+"';")
   1291                 user_likes = False
   1292             if i.hate != None and user_hates == False:
   1293                 db.insert('hates', user=session.user, bild=imghash, datum=datetime.datetime.now())
   1294                 user_hates = True
   1295             elif i.unhate != None and user_hates == True:
   1296                 db.query("DELETE FROM hates WHERE bild='"+imghash+"' AND user='"+session.user+"';")
   1297                 user_hates = False
   1298             likes = db.query("SELECT Count(*) AS likes FROM likes WHERE bild='"+imghash+"';")[0]
   1299             hates = db.query("SELECT Count(*) AS hates FROM hates WHERE bild='"+imghash+"';")[0]
   1300             b = db.select('bilder', where="filename='" + imghash +"'", what='titel, year, fotograf, plats, beskrivning, personer, moddedby, lastmod, uppladdare')[0]
   1301             text = db.select('allaversioner', where="filename='" + imghash +"'", what='moddedby')
   1302             comments = db.select('bildkommentar', where="filename='" + imghash +"'", what='id, user, comment, upvotes, datumtid', order='datumtid DESC')
   1303             try:
   1304                 personer = b.personer.replace(', ', ',').split(',')
   1305             except:
   1306                 personer = ''
   1307             back_next = db.query('SELECT prev, next from (SELECT id, LAG(filename) OVER (ORDER BY id) AS next, filename, LEAD(filename) OVER (ORDER BY id) AS prev FROM bilder) AS t WHERE filename="'+imghash+'";')[0]
   1308             print(back_next)
   1309             return render.bild(b, imghash, personer, kform, comments, session.user, user_likes, likes, user_hates, hates, back_next, text, getdisplayname)
   1310         else:
   1311             session.backurl="/bild/"+imghash
   1312             raise web.seeother("/login")
   1313     def POST(self, imghash):
   1314         ip = web.ctx['ip']
   1315         referer = web.ctx.env.get('HTTP_REFERER','https://bygdis.fi')
   1316         stopflood(ip, referer)
   1317         komm = self.form()
   1318         if session.login > 1:
   1319             i = web.input()
   1320             if i.kommentar != '':
   1321                 db.insert('bildkommentar', filename=imghash, user=session.user, comment=i.kommentar, datumtid=datetime.datetime.now())
   1322             raise web.seeother("/bild/"+imghash+"#comments")
   1323 
   1324 class senaste():
   1325     def GET(self):
   1326         if session.login > 1:
   1327             comments = db.select('bildkommentar', what='id, filename, user, comment, upvotes, datumtid', order='datumtid DESC')
   1328             b = db.select('bilder', what='filename, titel, year, fotograf, plats, beskrivning, personer, moddedby, lastmod, uppladdare, uploaddate', order='lastmod DESC')
   1329             binfo = db.select('allaversioner', what='filename, titel, year, fotograf, plats, beskrivning, personer, moddedby, lastmod, uppladdare, uploaddate', order='lastmod DESC')
   1330             return render.senaste(b, comments, binfo, getdisplayname)
   1331 
   1332 class logout():
   1333     def GET(self):
   1334         session.login = 1
   1335         session.backurl = ''
   1336         session.user = ''
   1337         session.bildsida = 0
   1338         print(session.login)
   1339         raise web.seeother('/')
   1340 
   1341 class index():
   1342     def GET(self):
   1343         upcomingevents = getkalender()
   1344         if session.login > 1:
   1345             displayname = db.query("SELECT displayname FROM bildadmin WHERE name='"+session.user+"';")[0]
   1346         else:
   1347             displayname = ''
   1348         return render2.index(upcomingevents, displayname)
   1349 
   1350 class old():
   1351     def GET(self):
   1352         oldevents = getkalenderall()
   1353         return render2.old(oldevents)
   1354 
   1355 class nope():
   1356     def GET(self):
   1357         #print curdate()
   1358         return render.nope()
   1359 
   1360 class protokoll():
   1361     form = web.form.Form(
   1362     web.form.Textarea('protokoll', web.form.notnull, description=""),
   1363     web.form.Button('spara'))
   1364     def GET(self):
   1365         if session.login == 5:
   1366             protokoll_edit = self.form()
   1367             webdata = web.input(year=None, nr=0, cp=None, rm=None, pdf=None)
   1368             view = ''
   1369             years = os.listdir(basedir + '/protokoll/')
   1370             years.remove('.gitignore')
   1371             years.sort()
   1372             if webdata.year:
   1373                 protokoll = getprotokoll(webdata.year)
   1374                 if webdata.cp == "protokoll":
   1375                     print('copy protokoll')
   1376                     os.system("cp "+basedir + '/protokoll/' + webdata.year + '/' + protokoll[int(webdata.nr)] +' '+basedir+'/protokoll/'+webdata.year+'/0'+str(len(protokoll))+'.md')
   1377                     protokoll = getprotokoll(webdata.year)
   1378                 if webdata.rm == "protokoll":
   1379                     print('remove protokoll')
   1380                     os.system("rm "+basedir + '/protokoll/' + webdata.year + '/' + protokoll[int(webdata.nr)])
   1381                     raise web.seeother('/protokoll?year='+webdata.year)
   1382             else:
   1383                 protokoll = []
   1384             if len(protokoll) > 0:
   1385                 #make html from markdown
   1386                 pandoc_html = ['pandoc', basedir + '/protokoll/' + webdata.year + '/' + protokoll[int(webdata.nr)], '-f', 'markdown', '-t', 'html']
   1387                 #make pdf from markdown
   1388                 viewfile = subprocess.check_output(pandoc_html)
   1389                 view = viewfile.decode()
   1390                 if webdata.pdf == "protokoll":
   1391                     randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
   1392                     pandoc_pdf = ['pandoc', '--verbose', basedir + '/protokoll/' + webdata.year + '/' + protokoll[int(webdata.nr)], '-f', 'markdown', '-V', 'papersize:a4', '-V', 'geometry:margin=0.8in','-s', '-o', basedir + '/public_html/static/pdf/'+randhash+'.pdf']
   1393                     process=subprocess.Popen(pandoc_pdf, cwd=basedir + '/public_html/static/pdf/')
   1394                     process.wait()
   1395                     raise web.seeother('/static/pdf/'+randhash+'.pdf?nocache='+randhash)
   1396                 #read protokoll
   1397                 read_p=basedir + '/protokoll/' + webdata.year + '/' + protokoll[int(webdata.nr)]
   1398                 with open(read_p, 'r') as file:
   1399                     p_list=file.readlines()
   1400                 pr=''
   1401                 for p in p_list:
   1402                     pr=pr+p
   1403                 protokoll_edit.fill(protokoll=pr)
   1404             return render3.protokoll(webdata.year, years, protokoll, view, protokoll_edit, webdata.nr)
   1405         else:
   1406             raise web.seeother('/login')
   1407     def POST(self):
   1408         if session.login == 5:
   1409             i = web.input(year=None, nr=0, cp=None)
   1410             protokoll = []
   1411             if i.year != None:
   1412                 protokoll = getprotokoll(i.year)
   1413             write_p=basedir + '/protokoll/' + i.year + '/' + protokoll[int(i.nr)]
   1414             if i.protokoll:
   1415                 with open(write_p, 'w') as file:
   1416                     file.write(i.protokoll)
   1417             print('ADDDDDDDDDDDDDING TO database post ' + i.protokoll)
   1418             raise web.seeother('/protokoll?year='+str(i.year)+'&nr='+str(i.nr))
   1419         else:
   1420             raise web.seeother('/login')
   1421 
   1422 
   1423 class protokollredirect():
   1424     def GET(self):
   1425         raise web.seeother('/protokoll/')
   1426 
   1427 application = app.wsgifunc()