def profile(): with Connection(server, current_user.dn, current_user.get_password(), auto_bind=True) as conn: person = ObjectDef(["inetOrgPerson"], conn) r = Reader(conn, person, current_user.dn) r.search() # print(r[0].entry_attributes_as_dict) form = ProfileForm(request.form, obj=current_user) if request.method == "POST" and form.validate(): w = Writer.from_cursor(r) # print(w[0].entry_attributes_as_dict) current_user.email = form.email.data current_user.vorname = form.vorname.data current_user.nachname = form.nachname.data w[0].givenName = current_user.vorname w[0].sn = current_user.nachname w[0].mail = current_user.email result = w[0].entry_commit_changes(refresh=True, controls=None) if result: flash(u"Profiländerung erfolgreich", "success") return redirect(url_for("index")) else: flash(u"Profiländerung nicht erfolgreich", "danger") return render_template( "/admin/changeprofile.html", form=form, user=current_user, title=u"Profiländerung", )
def email2person(email): print(email) ldapclient = LdapClient( LDAP_SERVER, LDAP_BASEDN, current_user.dn, current_user.get_password() ) person = ldapclient.find_byEmail(email, "dc=users," + LDAP_BASEDN) print(person) return redirect(url_for("bsw_pages.management"))
def sendemail2event(eventid): davclient = DavCalendar( url=current_app.config[nextcloud] + "remote.php/dav/" + "principals/users/" + current_user.vorname + "_" + current_user.nachname + "/", username=current_user.username, password=current_user.get_password(), calendarname=current_app.config[bswcalendar], ) bsw_calendar = davclient.get_calendar() if bsw_calendar is None: flash(current_app.config[bswcalendar] + u" nicht zugreifbar", "danger") return redirect(url_for("index")) davclient.fetch_eventbyUID(eventid) attendees = davclient.get_attendeeList() urlnew = u"mailto:" for attendee in attendees: if attendee.params["PARTSTAT"][0] == "ACCEPTED" and ( attendee.params["ROLE"][0] == "REQ-PARTICIPANT" or attendee.params["ROLE"][0] == "CHAIR" ): urlnew = urlnew + attendee.value.split(":")[1] + u"," urlnew = ( urlnew + u"?Subject=" + davclient.get_eventStart() + u" " + davclient.get_eventSummary() ) if davclient.test_category(anfrageabgeschlossen): urlnew = ( urlnew + u"&body=Liebe Kamerad*innen,%0A" + u" vielen Dank für Eure Meldung!%0A%0AIhr seid für die" + u" Brandsicherheitswache eingeplant.%0AViele Grüße%0A" ) if davclient.test_category(durchgefuehrt): urlnew = ( urlnew + u"&body=Liebe Kamerad*innen,%0A" + u" vielen Dank für Eure Teilnahme an der" + u" Brandsicherheitswache!%0A%0AGab es besondere Ereignisse" + u" oder möchtet Ihr" + u" andere Informationen weitergeben?%0A%0AViele Grüße%0A" ) urlnew = urlnew + current_user.vorname + " " + current_user.nachname return redirect(urlnew)
def add(): form = BSWAddForm() # form.bedarf.data = current_app.config["DEFAULT_BSW_TEILNEHMER_BEDARF"] if request.method == "POST" and form.validate(): locale.setlocale(locale.LC_ALL, "de_DE") davclient = DavCalendar( url=current_app.config[nextcloud] + "remote.php/dav/" + "principals/users/" + current_user.vorname + "_" + current_user.nachname + "/", username=current_user.username, password=current_user.get_password(), calendarname=current_app.config[bswcalendar], ) bsw_calendar = davclient.get_calendar() if bsw_calendar is None: flash( current_app.config[bswcalendar] + u" nicht zugreifbar", "danger", ) return redirect(url_for("bsw_pages.management")) bswtemp = davclient.define_BSWEvent( form.sdatum.data, form.edatum.data, form.summary.data, location=form.location.data, description=form.beschreibung.data, anzteilnehmer=form.bedarf.data, organizer=( current_user.vorname + " " + current_user.nachname, current_user.email, ), ) bsw_event = davclient.save_event(bswtemp) return redirect(url_for("bsw_pages.management")) return render_template( "/bsw/add.html", user=current_user, form=form, do=url_for("bsw_pages.add"), management_form=BSWSearchForm(), )
def addmembers(eventid, months, entry, type, jetztdatumin=None): ldapclient = LdapClient( LDAP_SERVER, LDAP_BASEDN, current_user.dn, current_user.get_password() ) return render_template( "bsw/select_attendee.html", user=current_user, management_form=BSWSearchForm(), event_id=eventid, months=months, jetztdatumin=jetztdatumin, ldapclient=ldapclient, enumerate=enumerate, entry=entry, type=type, )
def share_MyHouse_Announcement_Page(): if request.method == "POST": if 'userSearchButton' in request.form: # if the search button is submitted session['search_username'] = request.form['usernameSearch'] return redirect(url_for('site.SearchUserPage')) formtype = request.form['form-name'] username = current_user.get_username() print( username ) # use print to check whether the correct data is retrieved by checking the terminal password = current_user.get_password() print(password) email = current_user.get_email() print(email) name = current_user.get_name() print(name) surname = current_user.get_surname() print(surname) faculty_id = current_user.get_faculty_id() print(faculty_id) if formtype == "SharedHouseAnnouncement": Location = request.form['InputLocationOfSharingHouse'] RentPrice = request.form['InputRentPriceOfSharingHouse'] NumberOfPeople = request.form['InputnumberOfPeopleInHouse'] NumberOfRoom = request.form['InputNumberOfRoomforSharingHouse'] Description = request.form['InputDescriptionOfSharingHouse'] with dbapi2.connect(current_app.config['dsn']) as connection: cursor = connection.cursor() #prevented sql injection statement = """SELECT ID FROM USERS WHERE(USERS.USERNAME = %s) AND(USERS.EMAIL = %s)""" cursor.execute(statement, (username, email)) currentuser_id = cursor.fetchone() sharingHouseAd = sharingHouseAnnouncement( Location, RentPrice, NumberOfPeople, NumberOfRoom, Description, currentuser_id) query = """INSERT INTO DATASHAREDHOUSE(LOCATION, RENTPRICE, NUMBEROFPEOPLE, NUMBEROFROOM, DESCRIPTION, USERID) VALUES (%s, %s, %s, %s, %s, %s)""" cursor.execute( query, (sharingHouseAd.LocationOfSharingHouse, sharingHouseAd.RentPriceOfSharingHouse, sharingHouseAd.NumberOfPeopleInSharingHouse, sharingHouseAd.NumberOfSharingHouseRoom, sharingHouseAd.DescriptionOfSharingHouse, sharingHouseAd.id_ownerOfSharingHouseAnnouncement)) connection.commit() return redirect(url_for('site.ShareHousePageAnnouncement')) elif formtype == "SharedHouseAnnouncementUpdate": with dbapi2.connect(current_app.config['dsn']) as connection: cursor = connection.cursor() # prevented sql injection statement = """SELECT ID FROM USERS WHERE (USERS.USERNAME = %s) AND (USERS.EMAIL = %s)""" cursor.execute(statement, (username, email)) sharingUser_id = cursor.fetchone() sharingHouseid = request.form['sharingHouse-id'] Location = request.form['InputLocationOfSharingHouse'] if not Location: statement = """SELECT LOCATION FROM DATASHAREDHOUSE WHERE DATASHAREDHOUSE.ID = %s""" cursor.execute(statement, sharingHouseid) Location = cursor.fetchone() RentPrice = request.form['InputRentPriceOfSharingHouse'] if not RentPrice: statement = """SELECT RENTPRICE FROM DATASHAREDHOUSE WHERE DATASHAREDHOUSE.ID = %s""" cursor.execute(statement, sharingHouseid) RentPrice = cursor.fetchone() NumberOfPeople = request.form['InputnumberOfPeopleInHouse'] if not NumberOfPeople: statement = """SELECT NUMBEROFPEOPLE FROM DATASHAREDHOUSE WHERE DATASHAREDHOUSE.ID = %s""" cursor.execute(statement, sharingHouseid) NumberOfPeople = cursor.fetchone() NumberOfRoom = request.form['InputNumberOfRoomforSharingHouse'] if not NumberOfRoom: statement = """SELECT NUMBEROFROOM FROM DATASHAREDHOUSE WHERE DATASHAREDHOUSE.ID = %s""" cursor.execute(statement, sharingHouseid) NumberOfRoom = cursor.fetchone() Description = request.form['InputDescriptionOfSharingHouse'] if not Description: statement = """SELECT DESCRIPTION FROM DATASHAREDHOUSE WHERE DATASHAREDHOUSE.ID = %s""" cursor.execute(statement, sharingHouseid) Description = cursor.fetchone() statement = """UPDATE DATASHAREDHOUSE SET LOCATION=%s, RENTPRICE=%s, NUMBEROFPEOPLE=%s, NUMBEROFROOM=%s, DESCRIPTION=%s, USERID=%s WHERE DATASHAREDHOUSE.ID=%s""" cursor.execute( statement, (Location, RentPrice, NumberOfPeople, NumberOfRoom, Description, sharingUser_id, sharingHouseid)) connection.commit() return redirect( url_for('site.selected_sharingHouse', id=sharingHouseid)) else: with dbapi2.connect(current_app.config['dsn']) as connection: cursor = connection.cursor() query = """SELECT LOCATION,RENTPRICE,NUMBEROFPEOPLE,NUMBEROFROOM,DESCRIPTION,USERS.NAME,USERS.SURNAME,USERS.EMAIL,FACULTIES.FACULTYNAME,FACULTIES.FACULTYCODE,DATASHAREDHOUSE.ID FROM DATASHAREDHOUSE,USERS,FACULTIES WHERE(DATASHAREDHOUSE.USERID = USERS.ID) AND(USERS.FACULTYID = FACULTIES.ID) """ cursor.execute(query) ALLSharingHouse = cursor.fetchall() return render_template('sharedmyhouse_announcement.html', ALLSharingHouse=ALLSharingHouse)
def searched_House_Announcement_Page(): if request.method == "POST": if 'userSearchButton' in request.form: # if the search button is submitted session['search_username'] = request.form['usernameSearch'] return redirect(url_for('site.SearchUserPage')) formtype = request.form['form-name'] username = current_user.get_username() print( username ) # use print to check whether the correct data is retrieved by checking the terminal password = current_user.get_password() print(password) email = current_user.get_email() print(email) name = current_user.get_name() print(name) surname = current_user.get_surname() print(surname) faculty_id = current_user.get_faculty_id() print(faculty_id) if formtype == "SearchingHouseAnnouncement": Location = request.form['InputLocationOfSearchingHouse'] MinRent = request.form['InputMinRentPriceOfSearchingHouse'] MaxRent = request.form['InputMaxRentPriceOfSearchingHouse'] Description = request.form['InputDescriptionOfSearchingHouse'] with dbapi2.connect(current_app.config['dsn']) as connection: cursor = connection.cursor() statement = """SELECT ID FROM USERS WHERE(USERS.USERNAME = %s) AND(USERS.EMAIL = %s)""" cursor.execute(statement, (username, email)) currentuser_id = cursor.fetchone() searchingHouseAd = searchingHouseAnnouncement( Location, MinRent, MaxRent, Description, currentuser_id) query = """INSERT INTO DATASEARCHEDHOUSE(LOCATION, MINRENTPRICE, MAXRENTPRICE,DESCRIPTION,USERID) VALUES (%s,%s,%s,%s,%s)""" cursor.execute( query, (searchingHouseAd.LocationOfSearchingHouse, searchingHouseAd.MinRentPriceOfSearchingHouse, searchingHouseAd.MaxRentPriceOfSearchingHouse, searchingHouseAd.DescriptionOfSearchingHouse, searchingHouseAd.id_ownerOfSearchingHouseAnnouncement)) connection.commit() return redirect(url_for('site.SearchedHousePageAnnouncement')) elif formtype == "SearchingHouseAnnouncementUpdate": with dbapi2.connect(current_app.config['dsn']) as connection: cursor = connection.cursor() # prevented sql injection statement = """SELECT ID FROM USERS WHERE (USERS.USERNAME = %s) AND (USERS.EMAIL = %s)""" cursor.execute(statement, (username, email)) searchingHouseUser_id = cursor.fetchone() searchingHouseid = request.form['searchingHouse-id'] Location = request.form['InputLocationOfSearchingHouse'] if not Location: statement = """SELECT LOCATION FROM DATASEARCHEDHOUSE WHERE DATASEARCHEDHOUSE.ID = %s""" cursor.execute(statement, searchingHouseid) Location = cursor.fetchone() MinRent = request.form['InputMinRentPriceOfSearchingHouse'] if not MinRent: statement = """SELECT MINRENT FROM DATASEARCHEDHOUSE WHERE DATASEARCHEDHOUSE.ID = %s""" cursor.execute(statement, searchingHouseid) MinRent = cursor.fetchone() MaxRent = request.form['InputMaxRentPriceOfSearchingHouse'] if not MaxRent: statement = """SELECT MAXRENT FROM DATASEARCHEDHOUSE WHERE DATASEARCHEDHOUSE.ID = %s""" cursor.execute(statement, searchingHouseid) MaxRent = cursor.fetchone() Description = request.form['InputDescriptionOfSearchingHouse'] if not Description: statement = """SELECT DESCRIPTION FROM DATASEARCHEDHOUSE WHERE DATASEARCHEDHOUSE.ID = %s""" cursor.execute(statement, searchingHouseid) Description = cursor.fetchone() statement = """UPDATE DATASEARCHEDHOUSE SET LOCATION=%s, MINRENTPRICE=%s, MAXRENTPRICE=%s, DESCRIPTION=%s, USERID=%s WHERE DATASEARCHEDHOUSE.ID=%s""" cursor.execute(statement, (Location, MinRent, MaxRent, Description, searchingHouseUser_id, searchingHouseid)) connection.commit() return redirect( url_for('site.selected_searchingHouse', id=searchingHouseid)) else: with dbapi2.connect(current_app.config['dsn']) as connection: cursor = connection.cursor() query = """SELECT LOCATION,MINRENTPRICE,MAXRENTPRICE,DESCRIPTION,USERS.NAME,USERS.SURNAME,USERS.EMAIL,FACULTIES.FACULTYNAME,FACULTIES.FACULTYCODE,DATASEARCHEDHOUSE.ID FROM DATASEARCHEDHOUSE,USERS,FACULTIES WHERE(DATASEARCHEDHOUSE.USERID = USERS.ID) AND(USERS.FACULTYID = FACULTIES.ID) """ cursor.execute(query) ALLSearchedHouse = cursor.fetchall() return render_template('searchedhouse_announcement.html', ALLSearchedHouse=ALLSearchedHouse)
def addeventmembers(eventid, months, jetztdatumin=None): ldapclient = LdapClient( LDAP_SERVER, LDAP_BASEDN, current_user.dn, current_user.get_password() ) if request.method == "POST": davclient = DavCalendar( url=current_app.config[nextcloud] + "remote.php/dav/" + "principals/users/" + current_user.vorname + "_" + current_user.nachname + "/", username=current_user.username, password=current_user.get_password(), calendarname=current_app.config[bswcalendar], ) bsw_calendar = davclient.get_calendar() if bsw_calendar is None: flash( current_app.config[bswcalendar] + u" nicht zugreifbar", "danger", ) return redirect(url_for("index")) davclient.fetch_eventbyUID(eventid) updateneeded = False for name, value in request.form.items(): entry = name.split("#")[0] # das muss noch geändert werden .. if entry == "csrf_token": continue if value == "listselect": memberlist = ldapclient.get_listMembers( entry.split(",")[0].split("=")[1], entry.partition(",")[2] ) if value == "groupselect": memberlist = ldapclient.get_groupMembers( entry.split(",")[0].split("=")[1], entry.partition(",")[2] ) if value == "attendeeselect": memberlist = [literal_eval(entry)] # print(memberlist) for (cn, mail) in memberlist: member = davclient.create_attendee( cn, "INDIVIDUAL", "OPT-PARTICIPANT", "mailto:" + mail ) davclient.add_uniqueAttendee(member) updateneeded = True if updateneeded: event = davclient.get_currentEvent() # print(event.data) event.save() return redirect( url_for( "bsw_pages.bswreview", months=months, jetztdatumin=jetztdatumin ) ) return render_template( "bsw/select_attendee_base.html", user=current_user, management_form=BSWSearchForm(), event_id=eventid, months=months, jetztdatumin=jetztdatumin, ldapclient=ldapclient, enumerate=enumerate, lists_base_dn="dc=lists," + LDAP_BASEDN, groups_base_dn="dc=groups," + LDAP_BASEDN, )
def bswreview(months="-12", jetztdatumin=None): locale.setlocale(locale.LC_ALL, "de_DE") davclient = DavCalendar( url=current_app.config[nextcloud] + "remote.php/dav/" + "principals/users/" + current_user.vorname + "_" + current_user.nachname + "/", username=current_user.username, password=current_user.get_password(), calendarname=current_app.config[bswcalendar], ) bsw_calendar = davclient.get_calendar() if bsw_calendar is None: flash(current_app.config[bswcalendar] + u" nicht zugreifbar", "danger") return redirect(url_for("index")) imonths = int(months) if jetztdatumin: jetztdatum = datetime.strptime(jetztdatumin, "%Y-%m-%d") else: jetztdatum = datetime.now() if imonths < 0: start = jetztdatum + relativedelta(months=imonths) end = jetztdatum + relativedelta(days=-1) bswAttendeeCount = {} elif imonths > 0: start = jetztdatum end = jetztdatum + relativedelta(months=imonths) bswAttendeeCount = None elif imonths == 0: start = jetztdatum end = jetztdatum + relativedelta(days=1) bswAttendeeCount = None davclient.fetch_events(start=start, end=end, expand=False) events = davclient.get_fetchedEvents() if request.method == "POST": saveexcel = False for name, value in request.form.items(): updateneeded = False event_uid = name.split("#")[0] # das muss noch geändert werden .. if event_uid == "csrf_token": continue # print(name, value, event_uid) if davclient.set_eventCursorfromUID(event_uid) is None: flash(event_uid + u" nicht gültig", "danger") return redirect(url_for("index")) if value == "accept": attendee = davclient.find_attendee(name.split(":")[1]) attendee.params["PARTSTAT"][0] = "ACCEPTED" attendee.params["ROLE"][0] = "REQ-PARTICIPANT" updateneeded = True if value == "promote": attendee = davclient.find_attendee(name.split(":")[1]) attendee.params["PARTSTAT"][0] = "ACCEPTED" attendee.params["ROLE"][0] = "CHAIR" updateneeded = True if value == "delete": attendee = davclient.find_attendee(name.split(":")[1]) attendee.params["ROLE"][0] = "NON-PARTICIPANT" updateneeded = True if value == "finalize": davclient.set_status("CONFIRMED") davclient.change_category(finalisieren, anfrageabgeschlossen) updateneeded = True if value == "abrechnen": if not saveexcel: date_format = xlwt.XFStyle() date_format.num_format_str = "dd.MM.yyyy hh:mm" response = Response() response.status_code = 200 workbook = xlwt.Workbook() sheet = workbook.add_sheet("BSW Abrechnung") ind = 0 writexlsheader(sheet, ind) saveexcel = True davclient.change_category(durchgefuehrt, abgerechnet) updateneeded = True startdatum = davclient.get_eventStart(string=False) dauer = davclient.get_eventDuration() insgesamt = dauer + timedelta(seconds=3600) for attendee in davclient.get_attendeeList(): if ( attendee.params["ROLE"][0] == "REQ-PARTICIPANT" or attendee.params["ROLE"][0] == "CHAIR" ): """ # persons = [] # emailfound = Email.query.filter_by( # eadress=attendee[u"email"] # ).all() # for entry in emailfound: # persons.append(entry.persons) # for pl in persons: # for p in pl: """ ind = ind + 1 sheet.write(ind, 0, davclient.get_eventSummary()) sheet.write( ind, 1, startdatum.replace(tzinfo=None), date_format, ) if "," in attendee.params["CN"][0]: name, vorname = attendee.params["CN"][0].split(",") else: vorname, name = attendee.params["CN"][0].split(" ") sheet.write(ind, 2, name) sheet.write(ind, 3, vorname) # a = p.adressen.filter_by(typ="Privat").first() # if a: # sheet.write( # ind, 4, a.strasse + " " + str(a.hausnr) # ) # sheet.write(ind, 5, a.plz) # sheet.write(ind, 6, a.ort) # a = p.anschluesse.filter_by(typ="Privat").first() # if a: # sheet.write( # ind, 7, str(a.phonenr.international) # ) # a = p.anschluesse.filter_by( # typ="Mobil-privat" # ).first() # if a: # sheet.write( # ind, 8, str(a.phonenr.international) # ) sheet.write(ind, 9, attendee.value.split(":")[1]) sheet.write(ind, 10, "Unbekannt") sheet.write(ind, 11, "Unbekannt") sheet.write(ind, 12, str(dauer)) sheet.write(ind, 13, str(insgesamt)) if updateneeded: event = davclient.get_currentEvent() event.save() if saveexcel: output = BytesIO() workbook.save(output) filename = "export.xls" response.data = output.getvalue() mimetype_tuple = mimetypes.guess_type(filename) response_headers = Headers( { "Pragma": "public", "Expires": "0", "Cache-Control": "must-revalidate, post-check=0," + " pre-check=0", "Cache-control": "private", "Content-Type": mimetype_tuple[0], "Content-Disposition": 'attachment; filename="%s";' % filename, "Content-Transfer-Encoding": "binary", "Content-Length": len(response.data), } ) if not mimetype_tuple[1] is None: response.update({"Content-Encoding": mimetype_tuple[1]}) response.headers = response_headers response.set_cookie("fileDownload", "true", path="/") return response return redirect( url_for( "bsw_pages.bswreview", months=months, jetztdatumin=jetztdatumin ) ) for id, entry in enumerate(events): davclient.set_eventCursor(id) updateneeded = False if imonths < 0: for attendee in davclient.get_attendeeList(): if "PARTSTAT" in attendee.params.keys(): if "ACCEPTED" not in attendee.params["PARTSTAT"]: updateneeded = True attendee.params["PARTSTAT"][0] = "ACCEPTED" # Count number of BSW's already attended if attendee.value.split(":")[1] in bswAttendeeCount: bswAttendeeCount[attendee.value.split(":")[1]] += 1 else: bswAttendeeCount[attendee.value.split(":")[1]] = 1 for category in [anfrage, finalisieren, anfrageabgeschlossen]: if davclient.delete_category(category): updateneeded = True if (not davclient.test_category(durchgefuehrt)) and ( not davclient.test_category(abgerechnet) ): davclient.add_uniqueCategory(durchgefuehrt) updateneeded = True else: attendeeCount = 0 form = BSWAddForm() bedarf = form.bedarf.data category_list = davclient.get_categoryList() for cl in category_list: for c in cl.value: if "Bedarf=" in c: bedarf = int(c.split("=")[1]) for attendee in davclient.get_attendeeList(): if "PARTSTAT" in attendee.params.keys(): if attendee.params["PARTSTAT"][0] == "DECLINED": davclient.delete_attendee(attendee) updateneeded = True if attendee.params["PARTSTAT"][0] == "ACCEPTED": attendeeCount += 1 if davclient.test_category(anfrage): if attendeeCount >= bedarf: davclient.change_category(anfrage, finalisieren) updateneeded = True if davclient.test_category(finalisieren): if attendeeCount >= bedarf: for attendee in davclient.get_attendeeList(): if "PARTSTAT" in attendee.params.keys(): if ( attendee.params["PARTSTAT"][0] == "NEEDS-ACTION" ): davclient.delete_attendee(attendee) updateneeded = True else: davclient.change_category(finalisieren, anfrage) davclient.set_status("TENTATIVE") updateneeded = True if davclient.test_category(anfrageabgeschlossen): if attendeeCount >= bedarf: for attendee in davclient.get_attendeeList(): if "PARTSTAT" in attendee.params.keys(): if attendee.params["PARTSTAT"][0] == "TENTATIVE": davclient.delete_attendee(attendee) updateneeded = True else: davclient.change_category(anfrageabgeschlossen, anfrage) davclient.set_status("TENTATIVE") updateneeded = True if updateneeded: event = davclient.get_currentEvent() event.save() return render_template( "bsw/BSW.html", events=events, user=current_user, months=imonths, jetztdatumin=jetztdatumin, terminStatus=terminStatus, anfrage=anfrage, anfrageabgeschlossen=anfrageabgeschlossen, finalisieren=finalisieren, durchgefuehrt=durchgefuehrt, abgerechnet=abgerechnet, datetime=datetime, enumerate=enumerate, davclient=davclient, statistik=bswAttendeeCount, management_form=BSWSearchForm(), nextcloud_calendar=current_app.config[nextcloud] + "apps/calendar/timeGridDay/", submitDef="bsw_pages.bswreview", )