Updated stuff to the most recent server version

master
John Hammond 2017-01-11 20:35:54 -05:00
parent 0d925a0ae7
commit 96c493a679
57 changed files with 660 additions and 142 deletions

BIN
OLD_DATABASE.db Normal file

Binary file not shown.

View File

@ -844,8 +844,8 @@ piky
pimp
pimped
pimper
pimpjuic
pimpjuice
pimpjuic
pimpsimp
pindick
piss

Binary file not shown.

3
download_pictures.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
scp -r root@objeetrade.com:/root/uploads uploads

BIN
here.db

Binary file not shown.

View File

@ -17,8 +17,9 @@ create table products (
name text not null,
picture text not null,
description text not null,
price text not null,
date int not null,
price real not null,
seller text not null,
interested_people text not null,
uuid text not null
);
);

325
server.py
View File

@ -4,6 +4,9 @@ from flask import Flask
from flask import render_template, request, session, g, url_for, flash, get_flashed_messages, redirect, send_from_directory
import sqlite3
import json
import math
import datetime
import time
import sys, os
from colorama import *
import sys
@ -14,6 +17,7 @@ from uuid import uuid4
from textwrap import dedent
from PIL import Image # needed to resize the image they upload
import re # Used to verify phone numbers
from resizeimage import resizeimage
# Import smtplib for the actual sending function
@ -21,6 +25,8 @@ import smtplib
# Import the email modules we'll need
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from passlib.hash import sha256_crypt
from contextlib import closing
@ -29,6 +35,7 @@ from contextlib import closing
CERTIFICATE = 'certificate.crt'
PRIVATE_KEY = 'privateKey.key'
NUMBER_OF_PRODUCTS_ON_A_PAGE = 30
bad_word_found = ""
@ -49,7 +56,7 @@ def contains_bad_word( string ):
price_cap = 10000
debug = True
debug = False
init( autoreset = True )
email_from = 'ObjeeTrade'
@ -70,16 +77,35 @@ else:
def error( string ): pass
def warning( string ): pass
def get_available_pages( number_of_pages, page_number ):
available_pages = range( max(1, page_number-3), page_number )
available_pages += range( page_number, min(number_of_pages+1,page_number+4) )
return available_pages
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
return '.' in filename.lower() and \
filename.lower().rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
def send_email( to_address, subject, message ):
def send_email( to_address, subject, message, attachment = None ):
msg = MIMEText(message, 'html')
msg = MIMEMultipart()
msg["Subject"] = subject
msg['From'] = email_from
msg['To'] = to_address
if ( attachment != None ):
try:
image = MIMEImage( open(attachment).read(), attachment )
msg.attach(image)
except IOError:
message = message.replace("Picture attached", "THEY DID NOT ADD A PICTURE.");
msg.attach(MIMEText(message, 'html'))
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login('objeetrade@gmail.com', 'Go Coast Guard')
@ -88,7 +114,7 @@ def send_email( to_address, subject, message ):
# ===========================================================================
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif', 'PNG', 'JPG', 'JPEG', 'GIF'])
DATABASE = 'database.db'
UPLOAD_FOLDER = 'uploads'
PRIVATE_KEY = 'privateKey.key'
@ -256,19 +282,29 @@ def send_verification_link():
flash("An e-mail has been sent!")
return redirect("verify")
@app.route("/products")
def products():
@app.route('/products/', defaults={'page_number': 1})
@app.route("/products/<int:page_number>")
def products(page_number):
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
cur = g.db.execute('select name, picture, price, uuid from products')
products = [ [ row[0], row[1], row[2], row[3] ] for row in cur.fetchall()[::-1]]
cur = g.db.execute("select count(*) from products")
number_of_products = cur.fetchone()[0]
return render_template("products.html", products = products)
number_of_pages = int(math.ceil(float(number_of_products) / float(NUMBER_OF_PRODUCTS_ON_A_PAGE)))
available_pages = get_available_pages(number_of_pages, page_number)
cur = g.db.execute('select name, picture, price, uuid from products ORDER BY date DESC limit (?) offset (?) '
, [ NUMBER_OF_PRODUCTS_ON_A_PAGE, (page_number-1)*NUMBER_OF_PRODUCTS_ON_A_PAGE ])
products = [ [ row[0], row[1], row[2], row[3] ] for row in cur.fetchall()[::-1]]
for p in products: p[2] = '$' + format(p[2], '.2f')
return render_template("products.html", products = products, available_pages=available_pages, page_number = page_number, last_page=number_of_pages)
@app.route("/products/<uuid>")
def product(uuid):
@ -279,8 +315,10 @@ def product(uuid):
if not verified:
return redirect('verify')
cur = g.db.execute('select name, price, picture, description, seller, interested_people from products where uuid = (?)', [uuid] )
name, price, picture, description, seller, interested_people = cur.fetchone()
cur = g.db.execute('select name, price, date, picture, description, seller, interested_people from products where uuid = (?)', [uuid] )
name, price, date, picture, description, seller, interested_people = cur.fetchone()
price = '$' + format(price, '.2f')
date = datetime.datetime.fromtimestamp(date ).strftime('%A, %B %-d, %Y %-I:%M %p')
cur = g.db.execute('select uuid from users where name = (?)', [seller] )
seller_uuid = cur.fetchone()[0]
@ -288,7 +326,7 @@ def product(uuid):
interested_people = [ person for person in interested_people.split('\n') if person ]
return render_template('item.html', name=name, picture=picture, description=description, seller=seller, price=price, uuid=uuid, interested_people =interested_people, seller_uuid = seller_uuid)
return render_template('item.html', name=name, picture=picture, description=description, seller=seller, price=price, uuid=uuid, interested_people =interested_people, seller_uuid = seller_uuid, date = date)
@app.route("/remove_product/<uuid>")
def remove_product(uuid):
@ -310,7 +348,7 @@ def remove_product(uuid):
your_products = cur.fetchone()[0];
your_products = your_products.replace(uuid,'')
your_products = your_products.strip()
print your_products
cur = g.db.execute('update users set your_products = (?) where email = (?)', [
your_products,
session['email']
@ -356,13 +394,80 @@ def verify():
return render_template( 'verify.html', identifier = identifier)
@app.route("/search")
@app.route("/search", methods=["GET", "POST"])
def search():
if not 'logged_in' in session: return redirect('login')
cur = g.db.execute('select verified from users where uuid = (?)', [session['uuid']])
verified = cur.fetchone()[0]
if not verified:
return redirect('verify')
if ( request.method == "POST" ):
keywords = request.form['keywords']
price = request.form['price']
seller = request.form['seller']
if (contains_bad_word(keywords.lower()) or \
contains_bad_word(seller.lower()) or \
contains_bad_word(price.lower()) ):
flash("Detected a bad word: '" + bad_word_found + "'. Not accepting that.")
return render_template('search.html', keywords=keywords, price=price, seller=seller)
actual_price = price
price = actual_price.replace('<','').replace('>','')
if ( price != "" ):
if ( '.' in price ):
if ( price[-3] != '.' ):
flash("That does not look like a valid price!")
return render_template('search.html', keywords=keywords, price=price, seller=seller)
# try:
price_number = round(float(price),2)
warning(str(price_number))
if (price_number != abs(price_number)):
flash("That does not look like a valid price!")
return render_template('search.html', keywords=keywords, price=price, seller=seller)
elif ( price_number >= price_cap ):
flash("Please enter a cost less than $" + str(price_cap))
return render_template('search.html', keywords=keywords, price=price, seller=seller)
# except:
# flash("That does not look like a valid price!")
return render_template('search.html', keywords=keywords, price=price, seller=seller)
keywords = '%' + keywords.replace(' ','%') + '%'
seller = '%' + seller.replace(' ','%') + '%'
query = 'select name, picture, price, uuid from products where (description like (?) or name like (?) )'
add_on = ' COLLATE utf8_general_ci ORDER BY date DESC'
if ( price != "" ):
query += " and ( price = (?) )"
if ( '>' in actual_price ): query = query.replace('=', '>')
if ( '<' in actual_price ): query = query.replace('=', '<')
if ( seller != "" ):
query += " and ( seller like (?) )"
cur = g.db.execute(query + add_on, [ keywords, keywords, price, seller ])
else:
cur = g.db.execute(query + add_on, [ keywords, keywords, price ])
else:
if ( seller != "" ):
query += " and ( seller like (?) )"
cur = g.db.execute(query + add_on, [ keywords, keywords, seller ])
else:
cur = g.db.execute(query + add_on, [ keywords, keywords ])
products = [ [ row[0], row[1], row[2], row[3] ] for row in cur.fetchall()[::-1]]
for p in products: p[2] = '$' + format(p[2], '.2f')
return render_template("search_results.html", products = products)
return render_template("search.html")
@ -377,10 +482,11 @@ def edit(uuid):
if ( request.method == "GET" ):
cur = g.db.execute('select name, price, picture, description, seller from products where uuid = (?)', [uuid] )
cur = g.db.execute('select name, price, picture, description, seller from products where uuid = (?) ORDER BY date', [uuid] )
name, price, picture, description, seller = cur.fetchone()
price = format(price, '.2f')
return render_template('edit.html', name=name, picture=picture, description=description, seller=seller, price=price[1:], uuid=uuid)
return render_template('edit.html', name=name, picture=picture, description=description, seller=seller, price=price, uuid=uuid)
if ( request.method == "POST" ):
@ -401,65 +507,77 @@ def edit(uuid):
contains_bad_word(name.lower())
):
flash("Detected a bad word: '" + bad_word_found + "'. Not accepting that.")
return redirect(url_for('edit', uuid=uuid))
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
if ( name == "" ):
flash("Please enter a name of the product!")
return redirect(url_for('edit', uuid=uuid))
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
elif ( price == "" ):
flash("Please enter the price of the product in dollars!")
return redirect(url_for('edit', uuid=uuid))
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
elif ( description == "" ):
flash("Please enter a description of your product!")
return redirect(url_for('edit', uuid=uuid))
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
elif ( '.' in price ):
if ( price[-3] != '.' ):
flash("That does not look like a valid price!")
return redirect(url_for('edit', uuid=uuid))
try:
price_number = round(float(price),2)
warning(str(price_number))
if (price_number != abs(price_number)):
flash("That does not look like a valid price!")
return redirect(url_for('edit', uuid=uuid))
elif ( price_number >= price_cap ):
flash("Please enter a cost less than $" + str(price_cap))
return redirect(url_for('edit', uuid=uuid))
else:
# We should be good to process the form
price_number = '$' + format(price_number, '.2f')
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
# try:
if 'picture' not in request.files:
pass # They don't have to update the picture
else:
file = request.files['picture']
if file and allowed_file(file.filename):
filename = secure_filename(str(uuid4()) + "." + file.filename.split('.')[-1])
save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(save_location)
p = Image.open(save_location)
try:
p = resizeimage.resize_cover(p, (350, 350))
except:
pass
p.save(save_location)
# return redirect(url_for('uploaded_file', filename=filename))
picture = (url_for('uploaded_file', filename=filename))
cur = g.db.execute("update products set name = (?), picture = (?), description = (?), price = (?) where uuid = (?)", [
name,
str(picture),
description,
price_number,
uuid
] );
g.db.commit()
except:
# print price
price_number = round(float(price),2)
warning(str(price_number))
if (price_number != abs(price_number)):
flash("That does not look like a valid price!")
return redirect(url_for('edit', uuid=uuid))
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
elif ( price_number >= price_cap ):
flash("Please enter a cost less than $" + str(price_cap))
return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
else:
# We should be good to process the form
if 'picture' not in request.files:
pass # They don't have to update the picture
else:
file = request.files['picture']
if file and allowed_file(file.filename.lower()):
filename = secure_filename(str(uuid4()) + "." + file.filename.split('.')[-1])
save_location = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(save_location)
p = Image.open(save_location)
try:
p = resizeimage.resize_cover(p, (350, 350))
except:
# flash("Couldn't handle your picture. Try something smaller!")
pass
p.save(save_location)
picture = (url_for('uploaded_file', filename=filename))
date = int(time.time())
cur = g.db.execute("update products set name = (?), picture = (?), description = (?), price = (?), date = (?) where uuid = (?)", [
name,
str(picture),
description,
price_number,
date,
uuid
] );
g.db.commit()
send_email("johnhammond010@gmail.com", "New Product on ObjeeTrade",
render_template("new_product.html", name= session['name'], product_name = name, price = price, description = description ),
os.getcwd() + picture )
# except:
# flash("That does not look like a valid price!")
# return render_template("edit.html", uuid=uuid, price = price, name = name, description = description, picture=picture, seller = product_seller)
else:
flash("This is not your own product!")
@ -482,7 +600,7 @@ def profile(uuid):
your_products = your_products.split(" ")
products = []
for product in your_products:
cur = g.db.execute('select name from products where uuid = (?)', [product])
cur = g.db.execute('select name from products where uuid = (?) ORDER BY date DESC', [product])
product_name = cur.fetchone()
if product_name != None:
product_name = product_name[0]
@ -570,44 +688,49 @@ def sell():
name = request.form['name']
price = request.form['price']
description = request.form['description']
if 'picture' not in request.files:
picture=""
else:
picture = request.files['picture']
if ( contains_bad_word(price.lower()) or \
contains_bad_word(description.lower()) or \
contains_bad_word(name.lower())
):
flash("Detected a bad word: '" + bad_word_found + "'. Not accepting that.")
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
if ( name == "" ):
flash("Please enter a name of the product!")
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
elif ( price == "" ):
flash("Please enter the price of the product in dollars!")
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
elif ( description == "" ):
flash("Please enter a description of your product!")
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
elif ( '.' in price ):
if ( price[-3] != '.' ):
flash("That does not look like a valid price!")
return render_template("sell.html", name=name, price = price, description = description)
try:
price_number = round(float(price),2)
warning(str(price_number))
except:
print price
flash("That does not look like a valid price!")
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
# try:
price_number = round(float(price),2)
# except:
# flash("That does not look like a valid price!")
# return render_template("sell.html", name=name, price = price, description = description, picture=picture)
if (price_number != abs(price_number)):
flash("That does not look like a valid price!")
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
elif ( price_number >= price_cap ):
flash("Please enter a cost less than $" + str(price_cap))
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
else:
# We should be good to process the form
price_number = '$' + format(price_number, '.2f')
if 'picture' not in request.files:
pass # We make it optional for them to upload files, remember?
@ -622,19 +745,22 @@ def sell():
try:
p = resizeimage.resize_cover(p, (350, 350))
except:
# The image is small already; we don;t have to convert it.
pass
p.save(save_location)
# return redirect(url_for('uploaded_file', filename=filename))
picture = (url_for('uploaded_file', filename=filename))
uuid = str(uuid4())
cur = g.db.execute('insert into products (name, picture, description, price, seller, interested_people, uuid) values ( ?, ?, ?, ?, ?, ?, ? )', [
date = int(time.time())
cur = g.db.execute('insert into products (name, picture, description, date, price, seller, interested_people, uuid) values ( ?, ?, ?, ?, ?, ?, ?, ? )', [
name,
str(picture),
description,
price_number, # Since you are just selling this product, no one is interested yet!
description,
date,
price_number,
session['name'],
"",
"", # Since you are just now selling this product, no one is interested yet!
uuid
] );
@ -643,16 +769,27 @@ def sell():
your_products = cur.fetchone()[0];
your_products += ' ' + uuid
your_products = your_products.strip()
print your_products
cur = g.db.execute('update users set your_products = (?) where email = (?)', [
your_products,
session['email']
])
g.db.commit()
# def send_email( to_address, subject, message, attachment = None ):
if ( repr(type(picture)) == "<class 'werkzeug.datastructures.FileStorage'>" ):
send_email("johnhammond010@gmail.com", "New Product on ObjeeTrade",
render_template("new_product.html", name= session['name'], product_name = name, price = str(price), description = description ),
)
else:
send_email("johnhammond010@gmail.com", "New Product on ObjeeTrade",
render_template("new_product.html", name= session['name'], product_name = name, price = str(price), description = description ),
os.getcwd() + picture )
return redirect('products')
return render_template("sell.html", name=name, price = price, description = description)
return render_template("sell.html", name=name, price = price, description = description, picture=picture)
@app.route("/log_out", methods=["GET", "POST"])
def log_out():
@ -675,15 +812,13 @@ def session_logout():
flash("You have been successfully logged out.")
session.pop('logged_in')
session.pop('email')
session.pop('uuid')
session.pop('name')
if session.has_key('logged_in'): session.pop('logged_in')
if session.has_key('email'): session.pop('email')
if session.has_key('uuid'): session.pop('uuid')
if session.has_key('name'): session.pop('name')
if ( __name__ == "__main__" ):
context = (CERTIFICATE, PRIVATE_KEY)
app.run( host="0.0.0.0", debug=True, ssl_context=context, port = 444, threaded = True )
app.run( host="0.0.0.0", debug=True, ssl_context=context, port = 443, threaded = True )

View File

@ -2,29 +2,68 @@ html{
height: 100%;
width: 100%;
font-size: 100%;
}
@font-face {
font-family: 'Share Tech';
src: url('../fonts/Share Tech.ttf');
/*src: url('../fonts/Share Tech.ttf');*/
src: url('../fonts/Montserrat-ExtraLight.otf');
}
@font-face {
font-family: 'Share Tech';
/*src: url('../fonts/Share Tech.ttf');*/
src: url('../fonts/Montserrat-SemiBold.otf');
font-weight: bold;
}
body{
font-family: 'Share Tech';
/*font-family: 'Share Tech';*/
font-family: 'Roboto Slab', serif;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ed9017+0,f6e6b4+40,f6e6b4+99 */
background: #ed9017; /* Old browsers */
background: -moz-linear-gradient(top, #ed9017 0%, #f6e6b4 40%, #f6e6b4 99%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ed9017 0%,#f6e6b4 40%,#f6e6b4 99%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ed9017 0%,#f6e6b4 40%,#f6e6b4 99%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ed9017', endColorstr='#f6e6b4',GradientType=0 ); /* IE6-9 */
margin: 0px 0px;
padding: 0px 0px;
background-color: white;
min-height: 70%;
margin: 0;
background-repeat: no-repeat;
background-attachment: fixed;
}
.page_navigation{
display: block;
margin-left: auto;
margin-right: auto;
width: 100%;
text-align: center;
}
.page_button{
margin: 0px 5px;
padding-bottom:10px;
border:1px solid silver;
color:black;
padding: 0px 6px;
text-align: center;
cursor:pointer;
background-color: rgba(255,255,255,0.5);
}
.page_button:hover{
text-decoration: underline;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#0043af+0,0056ce+46,ffb76b+52,ffa73d+57,ff7c00+88,ff7f04+100 */
/*background: #0043af;
background: -moz-linear-gradient(top, #0043af 0%, #0056ce 46%, #ffb76b 52%, #ffa73d 57%, #ff7c00 88%, #ff7f04 100%);
background: -webkit-linear-gradient(top, #0043af 0%,#0056ce 46%,#ffb76b 52%,#ffa73d 57%,#ff7c00 88%,#ff7f04 100%);
background: linear-gradient(to bottom, #0043af 0%,#0056ce 46%,#ffb76b 52%,#ffa73d 57%,#ff7c00 88%,#ff7f04 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0043af', endColorstr='#ff7f04',GradientType=0 );
*/
}
a{
@ -42,14 +81,25 @@ a:visited{
#navigation{
width: 100%;
color: white;
background-color: teal;
font-size: 35px;
font-size: 31px;
padding: 5px;
font-weight: bold;
position:fixed;
top: 0px;
box-shadow: 0px 0px 30px black;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#00437f+27,001159+95,0c1f6d+100 */
background: #00437f; /* Old browsers */
background: -moz-linear-gradient(top, #00437f 27%, #001159 95%, #0c1f6d 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #00437f 27%,#001159 95%,#0c1f6d 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #00437f 27%,#001159 95%,#0c1f6d 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00437f', endColorstr='#0c1f6d',GradientType=0 ); /* IE6-9 */
}
#navigation ul{
@ -59,8 +109,8 @@ a:visited{
}
#navigation ul li{
padding-left: 20px;
padding-right: 20px;
padding-left: 15px;
padding-right: 15px;
display: inline;
float: right;
@ -89,7 +139,14 @@ a:visited{
position: fixed;
top: 30px;
left:0px;
box-shadow: 0px 0px 150px black;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#7f0e6a+0,ad1283+16,7f0e6a+93 */
background: #7f0e6a; /* Old browsers */
background: -moz-linear-gradient(top, #7f0e6a 0%, #ad1283 16%, #7f0e6a 93%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #7f0e6a 0%,#ad1283 16%,#7f0e6a 93%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #7f0e6a 0%,#ad1283 16%,#7f0e6a 93%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7f0e6a', endColorstr='#7f0e6a',GradientType=0 ); /* IE6-9 */
}
#disclaimer{
@ -149,26 +206,21 @@ a:visited{
color: #222;
font-size: larger;
font-size: large;
border-right: 1px solid black;
border-left: 1px solid black;
max-width: 1250px;
min-width: 600px;
/*max-height: 420px;*/
height: 100%;
min-height: 100%;
/*min-height: 99%;*/
padding: 2%;
padding-top:20px;
/*position: absolute;*/
/*top:30px;*/
/*bottom: 0;*/
/*left: 0;*/
/*right: 0;*/
margin: auto;
margin-top: 100px;
margin-bottom: 100px;
}
@ -190,9 +242,30 @@ textarea{
font-family: 'Share Tech';
}
h1{
text-decoration: italic;
border-bottom: 1px solid white;
}
*[id$="button"]:hover{
box-shadow: 0px 0px 5px gray;
text-decoration: underline;
}
*[id$="link"]:hover{
box-shadow: 0px 0px 5px gray;
text-decoration: underline;
}
*[id$="button"]{
font-weight: bold;
font-family: 'Roboto Slab', serif;
}
*[id$="link"]{
font-weight: bold;
font-family: 'Roboto Slab', serif;
}
#red_button{
text-transform: uppercase;
@ -206,9 +279,15 @@ h1{
font-size: xx-large;
color: white;
/*vertical-align: middle;*/
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ff3019+0,cf0404+100;Red+3D */
background: #ff3019; /* Old browsers */
background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff3019', endColorstr='#cf0404',GradientType=0 ); /* IE6-9 */
}
#green_button{
@ -223,9 +302,15 @@ h1{
font-size: xx-large;
color: white;
/*vertical-align: middle;*/
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#627d4d+0,1f3b08+100;Olive+3D */
background: #627d4d; /* Old browsers */
background: -moz-linear-gradient(top, #627d4d 0%, #1f3b08 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #627d4d 0%,#1f3b08 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #627d4d 0%,#1f3b08 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#627d4d', endColorstr='#1f3b08',GradientType=0 ); /* IE6-9 */
}
#blue_button{
@ -243,6 +328,13 @@ h1{
/*vertical-align: middle;*/
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#00437f+27,001159+95,0c1f6d+100 */
background: #00437f; /* Old browsers */
background: -moz-linear-gradient(top, #00437f 27%, #001159 95%, #0c1f6d 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #00437f 27%,#001159 95%,#0c1f6d 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #00437f 27%,#001159 95%,#0c1f6d 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00437f', endColorstr='#0c1f6d',GradientType=0 ); /* IE6-9 */
}
#blue_button_link{
text-transform: uppercase;
@ -256,6 +348,13 @@ h1{
font-size: xx-large;
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#00437f+27,001159+95,0c1f6d+100 */
background: #00437f; /* Old browsers */
background: -moz-linear-gradient(top, #00437f 27%, #001159 95%, #0c1f6d 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #00437f 27%,#001159 95%,#0c1f6d 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #00437f 27%,#001159 95%,#0c1f6d 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00437f', endColorstr='#0c1f6d',GradientType=0 ); /* IE6-9 */
}
#teal_button{
@ -270,7 +369,6 @@ h1{
font-size: xx-large;
color: white;
/*vertical-align: middle;*/
margin: 10px auto;
cursor: pointer;
}
@ -300,9 +398,10 @@ h1{
font-size: xx-large;
color: white;
/*vertical-align: middle;*/
margin: 10px auto;
cursor: pointer;
}
#darkorange_button_link{
text-transform: uppercase;
@ -316,6 +415,13 @@ h1{
font-size: xx-large;
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ff7400+0,dd5100+83,ff7400+100 */
background: #ff7400; /* Old browsers */
background: -moz-linear-gradient(top, #ff7400 0%, #dd5100 83%, #ff7400 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ff7400 0%,#dd5100 83%,#ff7400 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ff7400 0%,#dd5100 83%,#ff7400 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff7400', endColorstr='#ff7400',GradientType=0 ); /* IE6-9 */
}
#grey_button{
@ -333,6 +439,13 @@ h1{
/*vertical-align: middle;*/
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ff7400+0,dd5100+83,ff7400+100 */
background: #ff7400; /* Old browsers */
background: -moz-linear-gradient(top, #ff7400 0%, #dd5100 83%, #ff7400 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ff7400 0%,#dd5100 83%,#ff7400 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ff7400 0%,#dd5100 83%,#ff7400 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff7400', endColorstr='#ff7400',GradientType=0 ); /* IE6-9 */
}
#grey_button_link{
text-transform: uppercase;
@ -359,6 +472,13 @@ h1{
font-size: xx-large;
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ff3019+0,cf0404+100;Red+3D */
background: #ff3019; /* Old browsers */
background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff3019', endColorstr='#cf0404',GradientType=0 ); /* IE6-9 */
}
#green_button_link{
@ -373,11 +493,23 @@ h1{
font-size: xx-large;
margin: 10px auto;
cursor: pointer;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#627d4d+0,1f3b08+100;Olive+3D */
background: #627d4d; /* Old browsers */
background: -moz-linear-gradient(top, #627d4d 0%, #1f3b08 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #627d4d 0%,#1f3b08 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #627d4d 0%,#1f3b08 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#627d4d', endColorstr='#1f3b08',GradientType=0 ); /* IE6-9 */
}
#sell_box{
font-size: medium;
font-size: larger;
}
#sell_box p{
padding: 0px 50px;
}
#sell_box img{
@ -400,7 +532,14 @@ h1{
min-width: 400px;
/*margin: 0px 0px 10px;*/
margin: 10px auto;
background-color: rgba(255,255,255,.5);
}
.product:hover{
text-decoration: underline;
box-shadow: 0px 0px 8px silver;
}
.product img{
vertical-align: middle;
display: block;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,46 @@
Copyright (c) 2011-2012, Julieta Ulanovsky (julieta.ulanovsky@gmail.com), with Reserved Font Names 'Montserrat'
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

BIN
static/objeetrade_memo.pdf Normal file

Binary file not shown.

View File

@ -10,6 +10,7 @@
<script src="{{ url_for('static', filename='js/notify.js' ) }}"></script>
<script src="{{ url_for('static', filename='js/jquery-ui.min.js' ) }}"></script>
<script src="{{ url_for('static', filename='js/control.js' ) }}"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab" rel="stylesheet">
</head>
<body>
@ -19,7 +20,7 @@
<!-- {{ session.name }} -->
<ul>
<li> <a href="{{url_for('log_out')}}">LOG OUT</a> </li>
<!-- <li> <a href="{{url_for('search')}}">SEARCH</a> </li> -->
<li> <a href="{{url_for('search')}}">SEARCH</a> </li>
<li> <a href="{{url_for('sell')}}">SELL</a> </li>
<li> <a href="{{url_for('products')}}">SALES</a> </li>
</ul>
@ -36,7 +37,12 @@
{% endblock %}
<div style="position:fixed;bottom:10px;width:100%;text-align:center;color:rgba(0,0,0,.3);z-index: -5">
<small> This web application was developed solely by John Hammond</small>
<small>
This web application was developed entirely by John Hammond.
The original proposal was brought forth by
<a style="color:gray; text-decoration: underline;" href="{{ url_for('static', filename='objeetrade_memo.pdf' ) }}">Will Colomb</a>.
</small>
<div>
</body>

View File

@ -26,8 +26,19 @@
<input type="submit" value="SAVE CHANGES" style="font-size:xx-large" id="green_button">
</form>
<a href="{{ url_for('remove_product', uuid=uuid)}}"><span id="red_button_link"> REMOVE PRODUCT </span></a>
<!-- <a href="{{ url_for('remove_product', uuid=uuid)}}"><span id="red_button_link"> REMOVE PRODUCT </span></a> -->
<span id="red_button_link"> REMOVE PRODUCT </span>
<script>
$('#red_button_link').click(function(){
if (confirm('Are you sure you would like to remove this product?')) {
document.location = "{{ url_for('remove_product', uuid=uuid)}}"
} else {
// Do nothing!
}
});
</script>
</div>
{% endblock %}

View File

@ -9,6 +9,11 @@
<strong>Seller:</strong> <a href="{{url_for('profile',uuid=seller_uuid)}}">{{ seller }}</a>
</p>
<p>
<strong>Date Posted:</strong> {{ date }} </a>
</p>
<img id="product_image" src="{{picture}}" alt="No image is available">
<p>

View File

@ -0,0 +1,32 @@
<html>
<head></head>
<body>
<h2>A new product is available on <a href="https://www.objeetrade.com">
ObjeeTrade!</a></h2>
<p>
{{name}} is now selling the product: "{{product_name}}".
</p>
<p>
The price is currently: <b> {{ price }} </b>
</p>
<p>
The description is as follows:
</p>
<p>
<em> {{description}} </em>
</p>
<p>
Picture attached.
</p>
<p>
- John Hammond
</p>
</body>
</html>

View File

@ -3,12 +3,46 @@
<!-- <div id="login_box_background"></div> -->
<div id="vertical">
<div class="page_navigation">
<b>Page: </b>
<a href="{{url_for('products' )}}">
<span class="page_button">First</span>
</a>
{% for page in available_pages %}
{% if page == page_number %}
<a href="{{url_for('products', page_number=page )}}">
<span class="page_button" style="border-color:black;color:black;text-decoration: underline;">{{ page }}</span>
</a>
{% else %}
<a href="{{url_for('products', page_number=page )}}">
<span class="page_button"> {{ page }}</span>
</a>
{% endif %}
{% endfor %}
<a href="{{url_for('products', page_number = last_page )}}">
<span class="page_button">Last</span>
</a>
<br><br>
</div>
<div style="text-align:center">
{% if products|length == 0 %}
<h2 style="color:silver; text-align:center">
There is currently nothing for sale. :(
<h2 style="color:gray; text-align:center">
There is currently nothing for sale :(
</h2>
{% else %}
{% for product in products %}
@ -22,6 +56,37 @@
</div>
<div class="page_navigation">
<br><br>
<b>Page: </b>
<a href="{{url_for('products' )}}">
<span class="page_button">First</span>
</a>
{% for page in available_pages %}
{% if page == page_number %}
<a href="{{url_for('products', page_number=page )}}">
<span class="page_button" style="border-color:black;color:black;text-decoration: underline;">{{ page }}</span>
</a>
{% else %}
<a href="{{url_for('products', page_number=page )}}">
<span class="page_button"> {{ page }}</span>
</a>
{% endif %}
{% endfor %}
<a href="{{url_for('products', page_number = last_page )}}">
<span class="page_button">Last</span>
</a>
</div>
</div>
{% endblock %}

View File

@ -9,7 +9,7 @@
{% if name == session.name %}
<p>
To make communication easier once you show interest in some one else's product, you can enter your phone number or room number here. </p>
To make communication easier once you show interest in someone else's product, you can enter your phone number or room number here. </p>
<p>
<b>This information will be included in any e-mail sent to notify interest, but it is completely optional for you to supply the information.</b>
@ -36,7 +36,7 @@
{% if products|length == 0 %}
<h2 style="color:silver; text-align: center">
<h2 style="color:gray; text-align: center">
Unfortunately, no products...
</h2>

View File

@ -2,18 +2,54 @@
{% block content %}
<div id="login_box_background"></div>
<div id="login_box">
<!-- <div id="login_box_background"></div> -->
<div id="vertical">
<!--
{% for message in get_flashed_messages() %}
<p class='flashed_messages'><{{message}}</p>
{% endfor %}
<h2 style="color:silver; text-align:center">
Unfortunately this feature is not yet available.
</h2>
-->
<h1> Search for a Product </h1>
<div id="sell_box">
<form method="POST">
<p>
All of the fields below are optional. Note that results are not "paged," so all of the results (no matter how many there are!) will be presented all at once.
</p>
<p>
You can search by keywords, separated by spaces. These will be matched in both the name and the description of the product.
</p>
<input type="text" name="keywords" placeholder="Keywords" value="{{keywords}}">
<p>
You can use special operators in the price to denote price greater than or less than, like <code> &lt; 20 </code> or
<code> &gt; 5</code>.
</p>
<input style="color:darkgreen" type="text" name="price" placeholder="Price $" value="{{price}}">
<p> If you know the name of the seller (the one given in their e-mail), you can narrow your search here. </p>
<input type="text" name="seller" placeholder="Seller Name" value="{{seller}}">
<p></p>
<p style="padding: 0px 50px">
</p>
<input type="submit" value="SEARCH" style="font-size:xx-large" id="blue_button">
</form>
</div>
<!-- <h2 style="color:silver; text-align:center">
Unfortunately this feature is not yet available.
</h2> -->
</div>
{% endblock %}

View File

@ -0,0 +1,33 @@
{% extends "base_page.html" %}
{% block content %}
<!-- <div id="login_box_background"></div> -->
<div id="vertical">
<br><br>
<div style="text-align:center">
{% if products|length == 0 %}
<h2 style="color:silver; text-align:center">
There is currently nothing for sale. :(
</h2>
{% else %}
{% for product in products %}
<a href="{{ url_for('product', uuid=product[3] )}}"><div class="product">
<img width=325px height=325px src="{{product[1]}}" alt="No image is available">
<h2> {{ product[0] }} <span> {{ product[2] }} </span> </h2>
</div></a>
{% endfor %}
{% endif %}
</div>
<br><br>
</div>
{% endblock %}

View File

@ -10,7 +10,7 @@
<form method="POST" enctype="multipart/form-data">
<img src="" alt="Upload a picture! (optional)">
<br> <br>
<input style="display:inline; width:auto;" type="file" name="picture" value="">
<input style="display:inline; width:auto;" type="file" name="picture" value="{{picture}}">
<p></p>
<input type="text" name="name" placeholder="Product Name" value="{{name}}">
<p></p>

3
update_server.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
scp server.py root@objeetrade.com:/root/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

3
verify_account.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
sqlite3 -line database.db 'update users set verified=1 where name="John Hammond";'