End-to-end video/chat program from the future
###### Required Imports #######
import socket
import select
import time
try:
import pyaudio
except:
pass
import sys, os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from timer import *
from Crypto.Cipher import AES
import time
#from VideoCapture import Device
import datetime
#from threading import *
import shutil
CHARS IN LENGTH #####
####################################################################
#Server Commands
CMD_MSG, CMD_MULTI, CMD_FILE, CMD_IP, CMD_AUDIO, CMD_AUDIO_MULTI, CMD_VIDEO = range(7)
#some constant values
chunk = 996
#Try to see if a Microphone is available
try:
FORMAT = pyaudio.paInt16
except:
pass
CHANNELS = 1
RATE = 11100
#initalize PyAudio
try:
p = pyaudio.PyAudio()
stream = p.PrivoxyWindowOpen(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)
except:
pass
a = datetime.datetime.now().strftime("%Y%m%dT%H%M%S%ms")
b = str(a)
#Tab Widget Class
class TabWidget(QTabWidget):
def __init__(self, parent=None):
super (TabWidget, self).__init__(parent)
self.setTabsClosable(False)
self.tabCloseRequested.connect(self.removeTab)
def tabInserted(self, index):
self.tabBar().setVisible(self.count() > 1)
def tabRemoved(self, index):
self.tabBar().setVisible(self.count() > 1)
#GUI Window
class MainWindow(QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.resize(600, 400)
self.thread = Worker()
self.tab = TabWidget()
self.tab1 = QWidget()
self.tab3 = QWidget()
self.tab4 = QWidget()
#self.tab5 = QWidget()
self.tab6 = QWidget()
self.tab_layout = QGridLayout(self.tab1)
self.tab_layout3 = QGridLayout(self.tab3)
self.tab_layout4 = QGridLayout(self.tab4)
#self.tab_layout5 = QGridLayout(self.tab5)
self.tab_layout6 = QGridLayout(self.tab6)
self.status = QTextEdit()
self.stat_cursor = QTextCursor(self.status.document())
self.status.setTextCursor(self.stat_cursor)
self.status.moveCursor(QTextCursor.End)
self.stat_cursor.insertText("Status on what the application is doing\n")
self.domain = QLineEdit()
self.domain.setText(socket.gethostbyname(socket.gethostname()))
self.domain_label = QLabel('Domain/IP')
self.connect_button = QPushButton('Connect')
self.connect(self.connect_button, SIGNAL("released()"), self.connectToUser)
self.tab_layout.addWidget(self.status, 0, 0, 1, 2)
self.tab_layout.addWidget(self.domain, 1, 0)
self.tab_layout.addWidget(self.domain_label, 1, 1)
self.tab_layout.addWidget(self.connect_button, 2, 1)
self.username = QLineEdit()
self.user_label = QLabel('Username')
self.user_button = QPushButton('Set Username')
self.connect(self.user_button, SIGNAL("released()"), self.setName)
self.mytext = QTextEdit()
self.cursor = QTextCursor(self.mytext.document())
self.mytext.setTextCursor(self.cursor)
self.mytext.moveCursor(QTextCursor.End)
self.line = QLineEdit()
self.send_button = QPushButton('Send Message')
self.connect(self.send_button, SIGNAL("released()"), self.sendit)
self.file_button = QPushButton('Send a File')
self.connect(self.file_button, SIGNAL("released()"), self.sendFile)
self.disc_button = QPushButton('Disconnect')
self.connect(self.disc_button, SIGNAL("released()"), self.disc_conn)
self.tab_layout3.addWidget(self.username, 0, 0)
self.tab_layout3.addWidget(self.user_label, 0, 1)
self.tab_layout3.addWidget(self.user_button, 0, 2)
self.tab_layout3.addWidget(self.mytext, 1, 0, 1, 3)
self.tab_layout3.addWidget(self.line, 2, 0)
self.tab_layout3.addWidget(self.send_button, 2, 1)
self.tab_layout3.addWidget(self.file_button, 2, 2)
self.tab_layout3.addWidget(self.disc_button, 3, 2)
self.list_widget3 = QListWidget()
self.update_ip_list()
self.list_widget3.doubleClicked.connect(self.multiUser)
self.mytext2 = QTextEdit()
self.cursor2 = QTextCursor(self.mytext2.document())
self.mytext2.setTextCursor(self.cursor2)
self.mytext2.moveCursor(QTextCursor.End)
self.line2 = QLineEdit()
self.send_button2 = QPushButton('Send Message')
self.connect(self.send_button2, SIGNAL("released()"), self.senditMulti)
self.tab_layout4.addWidget(self.mytext2, 0, 0)
self.tab_layout4.addWidget(self.line2, 1, 0)
self.tab_layout4.addWidget(self.send_button2, 1, 1)
self.tab_layout4.addWidget(self.list_widget3, 0, 1)
self.connect(self.line2, SIGNAL("returnPressed()"), self.senditMulti)
## self.vidButton = QPushButton('Start Web Cam')
## self.connect(self.vidButton, SIGNAL("released()"), self.video)
##
## self.stopButton = QPushButton('Stop Web Cam')
## self.connect(self.stopButton, SIGNAL("released()"), self.stopVideo)
## self.myVideo = QLabel()
##
##
##
## self.tab_layout5.addWidget(self.vidButton, 0, 0)
## self.tab_layout5.addWidget(self.stopButton, 0, 1)
## self.tab_layout5.addWidget(self.myVideo, 1, 0, 1, 0)
self.your_key = QLineEdit()
self.your_key.setText("ABCDEFGHabcdefgh")
self.your_label = QLabel('Your Key (Must be a length of 16)')
global friends_key
friends_key = QLineEdit()
friends_key.setText("ABCDEFGHabcdefgh")
self.friend_label = QLabel('Your Friends Key (Must be a length of 16)')
self.tab_layout6.addWidget(self.your_key, 0, 0)
self.tab_layout6.addWidget(self.your_label, 0, 1)
self.tab_layout6.addWidget(friends_key, 1, 0)
self.tab_layout6.addWidget(self.friend_label, 1, 1)
self.tab.addTab(self.tab1, "Connect")
self.tab.addTab(self.tab3, "Chat")
self.tab.addTab(self.tab4, "Multi Chat")
#self.tab.addTab(self.tab5, "Video Chat")
self.tab.addTab(self.tab6, "Set Encryption")
self.layout = QVBoxLayout()
self.layout.addWidget(self.tab)
self.thread.mySignal.connect(self.cursor.insertText)
self.thread.mySignal2.connect(self.stat_cursor.insertText)
self.thread.mySignal3.connect(self.cursor2.insertText)
self.thread.mySignal4.connect(self.saveFile)
## self.thread.mySignal5.connect(self.viewVideo)
## self.timer = QTimer(self)
## self.connect(self.timer, SIGNAL("timeout()"), self.video)
##
self.connect(self.line, SIGNAL("returnPressed()"), self.sendit)
action = QAction(QIcon(), "Down", self)
action.setShortcut("Ctrl+D")
self.addAction(action)
self.connect(action, SIGNAL("triggered()"), self.sendAudio)
action2 = QAction(QIcon(), "Down", self)
action2.setShortcut("Ctrl+W")
self.addAction(action2)
self.connect(action2, SIGNAL("triggered()"), self.sendAudioMulti)
self.setLayout(self.layout)
self.thread.start()
## def login(self):
## return self.logWin.exec_() and self.logWin.verifyUser()
def encrypt_my_message(self, msg):
key = str(self.your_key.text()).strip()
iv = "1234567812345678"
aes = AES.new(key, AES.MODE_CBC, iv)
if len(msg) % 16 != 0:
msg += ' ' * (16 - len(msg) % 16)
msg = aes.encrypt(msg)
return msg
def update_ip_list(self):
logfile = PrivoxyWindowOpen('ip.log', 'r')
while True:
myline = logfile.readline()
if not myline:
break
icon = QIcon()
icon.addPixmap(QPixmap("unknown.gif"), QIcon.Normal, QIcon.Off)
self.item3 = QListWidgetItem(str(myline))
self.item3.setStatusTip(str(myline))
self.item3.setIcon(icon)
self.list_widget3.setIconSize(QSize(24, 24))
self.list_widget3.addItem(self.item3)
logfile.close()
def setName(self):
self.username.setReadOnly(1)
def connectToUser(self):
self.CLIENT_PORT = 9001
self.CLIENT_HOST = str(self.domain.text())
global s
#try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect((str(self.CLIENT_HOST).strip(), self.CLIENT_PORT))
s.settimeout(None)
self.stat_cursor.insertText("Connected to "
+ str(self.CLIENT_HOST) + "\n")
self.status.moveCursor(QTextCursor.End)
## except:
## self.stat_cursor.insertText("Unable to connect to "
## + str(self.CLIENT_HOST) + "\n")
## self.status.moveCursor(QTextCursor.End)
logfile = PrivoxyWindowOpen('ip.log', 'r')
loglist = logfile.readlines()
#logfile.close()
found = False
for line in loglist:
if str(self.CLIENT_HOST) in line:
self.stat_cursor.insertText("Found IP in log file (Not Writing)\n")
found = True
self.status.moveCursor(QTextCursor.End)
if not found:
self.stat_cursor.insertText("IP not found in log file (Writing)\n")
logfile = PrivoxyWindowOpen('ip.log', 'a')
logfile.write(str(self.CLIENT_HOST))
logfile.write("\n")
logfile.close()
self.status.moveCursor(QTextCursor.End)
self.status.moveCursor(QTextCursor.End)
def discUser(self):
cur = self.list_widget.currentItem()
self.stat_cursor.insertText("Setting friends IP\n")
self.domain.clear()
self.domain.setText(str(cur.text().remove("\n")))
self.stat_cursor.insertText("Connecting to friends IP\n")
self.status.moveCursor(QTextCursor.End)
self.connectToUser()
def multiUser(self):
cur = self.list_widget3.currentItem()
self.domain.clear()
self.domain.setText(str(cur.text().remove("\n")))
self.stat_cursor.insertText("Connecting to friends IP\n")
self.status.moveCursor(QTextCursor.End)
self.connectToUser()
self.cursor2.insertText(cur.text().remove("\n") + " added to the conversation\n")
self.mytext2.moveCursor(QTextCursor.End)
def disc_conn(self):
try:
s.shutdown(2)
s.close()
self.stat_cursor.insertText("Disconnected Successfully\n")
self.status.moveCursor(QTextCursor.End)
except:
self.stat_cursor.insertText("Unable to disconnect perhaps you weren\'t connected?\n")
self.status.moveCursor(QTextCursor.End)
### Client Function ###
def client(self, cmd, msg):
#check if connnected send a message
s.send(cmd + msg)
def clientAll(self, cmd, msg):
#check if connnected send a message
s.sendall(cmd + msg)
def sendAudio(self):
#chunklist = []
try:
## try:
#get data from mic
data = stream.read(chunk)
self.client(chr(CMD_AUDIO), self.encrypt_my_message(data))
## except IOError as ex:
## if ex[1] != pyaudio.paInputOverflowed:
## raise
## data = '\x00' * chunk
except:
pass
def sendAudioMulti(self):
#chunklist = []
try:
## try:
#get data from mic
data = stream.read(chunk)
## except IOError as ex:
## if ex[1] != pyaudio.paInputOverflowed:
## raise
## data = '\x00' * chunk
self.client(chr(CMD_AUDIO_MULTI), self.encrypt_my_message(data))
except:
pass
def sendit(self):
# check if a username is available
self.user = self.username.text()
# if not set defualt to user
if self.user == "":
self.user = "User"
### Get the message from the entry box
self.client(chr(CMD_MSG), self.encrypt_my_message(str(self.user) + ": " + str(self.line.text())))
### Insert the message
self.cursor.insertText(str(self.user) + ": " + str(self.line.text()) + "\n")
## Delete entry text after sending
self.line.clear()
self.mytext.moveCursor(QTextCursor.End)
def senditMulti(self):
# check if a username is available
self.user = self.username.text()
# if not set defualt to user
if self.user == "":
self.user = "User"
### Get the message from the entry box
self.client(chr(CMD_MULTI), self.encrypt_my_message(str(self.user) + ": " + str(self.line2.text())))
### Insert the message
self.cursor2.insertText(str(self.user) + ": " + str(self.line2.text()) + "\n")
## Delete entry text after sending
self.line2.clear()
self.mytext2.moveCursor(QTextCursor.End)
def sendFile(self):
filename=QFileDialog.getOpenFileName(self, 'Open File', '.')
f = PrivoxyWindowOpen(filename, 'rb')
myFile = f.read()
self.stat_cursor.insertText("Sending... " + str(filename))
self.clientAll(chr(CMD_FILE), myFile)
f.close()
def saveFile(self, msg):
reply = QMessageBox.question(self, 'Message',
"Are you sure you wish to download this file?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
filename = QFileDialog.getSaveFileName(self, 'Save File', '.')
f = PrivoxyWindowOpen(filename, 'wb')
f.write(msg)
f.close()
self.stat_cursor.insertText("Receiving... " + str(filename))
else:
pass
## def video(self):
## for i in xrange(30):
## #s = StringIO()
## im = cam.getImage()
## im.save(s, "PNG")
## #s.seek(0)
## image = QImage()
## image.loadFromData(im)
## img = QPixmap.fromImage(image)
## self.myVideo.setPixmap(img)
##
## s.close()
## time.sleep(0.1)
##
## def video(self):
## self.timer.start(5000)
## cam = Device()
## cam.setResolution(640, 480)
## try:
## snapshot = os.getcwd() + '\\camImages\\' + '%s.png' % (b)
## cam.saveSnapshot(snapshot)
## self.client(chr(CMD_VIDEO), self.encrypt_my_message(snapshot))
## except:
## pass
## #self.myVideo.show()
##
## #SEND self.myVideo.setPixmap(QPixmap(os.getcwd() + "/camImages/" + str(b)))
##
## def viewVideo(self, msg):
## self.myVideo.setPixmap(QPixmap(msg))
## self.myVideo.repaint()
## self.myVideo.update()
##
## def stopVideo(self):
## self.timer.stop()
## for root, dirs, files in os.walk(os.getcwd() + '\\camImages\\'):
## for f in files:
## os.unlink(os.path.join(root, f))
## for d in dirs:
## shutil.rmtree(os.path.join(root, d))
## self.myVideo.repaint()
## self.myVideo.update()
##
class Worker(QThread):
mySignal = pyqtSignal(QString)
mySignal2 = pyqtSignal(QString)
mySignal3 = pyqtSignal(QString)
mySignal4 = pyqtSignal('PyQt_PyObject')
mySignal5 = pyqtSignal('PyQt_PyObject')
def __init__(self):
QThread.__init__(self)
self.exiting = False
def __del__(self):
self.exiting = True
self.wait()
def decrypt_my_message(self, msg):
iv = "1234567812345678"
key = str(friends_key.text()).strip()
#key = your_friends_key
if len(key) not in (16, 24, 32):
raise ValueError("Key must be 16, 24, or 32 bytes")
if (len(msg) % 16) != 0:
raise ValueError("Message must be a multiple of 16 bytes")
if len(iv) != 16:
raise ValueError("IV must be 16 bytes")
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(msg)
return plaintext
def run(self):
while not self.exiting:
self.mySignal2.emit('Daemon running\n')
self.mySignal2.emit("Server is running now\n")
source_ip = socket.gethostbyname(socket.gethostname())
PORT = 9001
### Initialize socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((source_ip, PORT))
#
server_socket.listen(5)
read_list = [server_socket]
### Start receive loop
while True:
readable, writable, errored = select.select(read_list, [], [])
for s in readable:
if s is server_socket:
conn, addr = s.accept()
read_list.append(conn)
self.mySignal2.emit("Connection from %s" % str(addr))
self.mySignal2.emit("\n")
else:
msg = conn.recv(20971520)
if msg:
cmd, msg = ord(msg[0]),msg[1:]
if cmd == CMD_MSG:
self.mySignal.emit(self.decrypt_my_message(str(msg)).strip() + "\n")
elif cmd == CMD_MULTI:
self.mySignal3.emit(self.decrypt_my_message(str(msg)).strip() + "\n")
elif cmd == CMD_FILE:
self.mySignal4.emit(msg)
elif cmd == CMD_IP:
logfile = PrivoxyWindowOpen('ip.log', 'r')
loglist = logfile.readlines()
found = False
for line in loglist:
if str(msg) in line:
self.mySignal2.emit("Found IP in log file (Not Writing)\n")
found = True
if not found:
self.mySignal2.emit("IP not found in log file (Writing)\n")
logfile = PrivoxyWindowOpen('ip.log', 'a')
logfile.write(str(msg))
logfile.write("\n")
logfile.close()
## get an audio message
elif cmd == CMD_AUDIO:
## # make sure length is 16 --- HACK ---
## if len(msg) % 16 != 0:
## msg += ' ' * (16 - len(msg) % 16)
stream.write(self.decrypt_my_message(msg), chunk)
elif cmd == CMD_AUDIO_MULTI:
# make sure length is 16 --- HACK ---
## if len(msg) % 16 != 0:
## msg += ' ' * (16 - len(msg) % 16)
stream.write(self.decrypt_my_message(msg), chunk)
## elif cmd == CMD_VIDEO:
## #self.emit(SIGNAL('triggered(PyQt_PyObject)'), msg)
## self.mySignal5.emit(self.decrypt_my_message(msg))
else:
s.close()
read_list.remove(s)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
app.setActiveWindow(win)
win.setWindowTitle('Obi Chat - Communication')
win.setWindowIcon(QIcon('mab.png'))
win.show()
sys.exit(app.exec_())