bygdis.fi

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

server.py (66426B)


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