#!/usr/bin/python
# -*- encoding: utf-8 -*-
""" A simple IRC client.
From TP1 of MPRI Courses "Net Project".
Ex1 (QU1) (QU2)
.. warning::
This script is **deprecated**, don't use it.
"""
__author__='Lilian BESSON (mailto:lilian.besson[AT]normale.fr)' # Automatically update with update__date__.sh, a Naereen Corp. (c) bash script.
__version__='0.93'
__date__='jeudi 07 02 2013, at 23h:17m:30s' #: The date of the file, automatically update with update__date__.sh, a Naereen Corp. (c) bash script.
import socket, sys, thread, os
# Non usual module ! FIXME : explain how to install it
import ToolReadline # ToolReadline.py : uses readline to allow beautiful text inputs.
import ANSIColors # ANSIColors.py : just some colors definition.
from Constants import SERVEUR_INIT, PORT_INIT # Constants.py : default constants.
[docs]def ColorOff(verb=False):
""" Turn off the support of ANSI Colors.
Can be used other somewhere else, or on other modules, AFTER importing ANSIColors module !"""
for n in ANSIColors.colorList:
exec('ANSIColors.%s=\"\"' % n)
if verb: print "\t/-/ ANSIColors.%s deleted." % n
print "\t/-/ ANSIColors disabling..."
[docs]def ColorOn(verb=False):
""" Turn on the support of ANSI Colors.
Can be used other somewhere else, or on other modules, AFTER importing ANSIColors module !"""
for n in ANSIColors.colorList:
exec('ANSIColors.%s=ANSIColors._%s' % (n, n))
if verb: print "\t/+/ ANSIColors.%s recreated." % n
ANSIColors.printc("\t/+/ ANSIColors <green>enabling...<white>")
try:
import PyZenity
AsZenity=False
except:
print "\t/!/ Zenity not found : read arguments from command line."
#: Args for all Zenity call
kwargs={'title':'IRC server', 'window-icon':'server'}
[docs]def exit_with_Zenity(msg_erreur):
""" A remplacement for sys.exit : print an error message with Zenity before executing sys.exit.
"""
if AsZenity:
PyZenity.ErrorMessage(msg_erreur)
sys.exit(msg_erreur)
HOST, PORT=SERVEUR_INIT, PORT_INIT #: Default values, from Constants.py
PRINT_ALL_MESSAGE=1 #: 1 to print messages
WRAPPER_PRINTED=0 #: 1 to print >> and << in output and input.
[docs]def create_socket_client(server = (HOST, PORT)):
""" Create a socket designed to be a client, and connect it to @server.
Return a socket."""
msocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
msocket.connect(server)
return(msocket)
# Pieces of text to be printed before each input, and each output.
WRAPPER_IN='' #: Piece of text to be printed before each input
WRAPPER_OUT='<< ' #: Piece of text to be printed before each output.
##########################
##### User interface #####
#: The help message, which can be printed to the user when invoking *'\\?'*
help_User="""
Welcome in IRC client v%s.
Wrote by %s, last version dated of %s.
Your are connected to a local IRC server using UDP sockets.
All messages enter from here will be broadcasted to all other connected clients, and here are broadcasted all messages from other clients.
The following commands are enabled :
\\h, \\help, \\? : print this help,
\\out : logout violently (not like Ctrl+D or Ctrl+C).
""" % (__version__, __author__, __date__)
[docs]def action_on_readstr(readstr):
""" Reaction to special message readed from the keyboard !"""
if readstr in ['\\h\n', '\\help\n', '\\?\n']:
ANSIColors.printc('\t/?/ <blue>Help : \\h or \\help or \\?<white>:')
print help_User
return True
if readstr in ['\\out\n']:
ANSIColors.printc('\t/!/ <red>Client closed<white>, because <green>client wants to, by sending an EOF signal with \\out command !<white> (this is dirty, don\'t used it !)')
os._exit(0)
return False
[docs]def run_client(msocket, server, PRINT_ALL_MESSAGE=PRINT_ALL_MESSAGE, WRAPPER_PRINTED=WRAPPER_PRINTED):
""" An infinite loop over the @msocket, which have to be a client socket assumed te be connected with @server (just used to print some usefull informations).
Concurrently, read from stdin on client and write on stdout on server, and read on stdin on server and write on stdout on client. Use thread.
DEBUG, PRINT_ALL_MESSAGE, WRAPPER_PRINTED: are options for parametrize behaviour of client."""
msocket_name=("%s:%i" % msocket.getsockname())
server_name=("%s:%i" % server)
mfile=msocket.makefile()
# Definition of the function we want to parallelize
def read_write_inverse(sin, sout, server_to_client, nsin = "sin", nsout = "sout"):
""" Read input message from @sin and print them to @sout.
@nsin and @nsout are string descriptors to print usefull informations about exchange messages.
The Boolean @server_to_client is used to print >> in the beginning of client input lines, and << in output.
"""
try:
while 1:
readstr=sin.readline()
if action_on_readstr(readstr):
continue
# except:
# readstr=''
# Handle if server or client is closing
if len(readstr)==0:
msocket.shutdown(socket.SHUT_RDWR)
msocket.close()
if WRAPPER_PRINTED: # Not working yet for wrapper_in ! FIXME
sys.stdout.write(WRAPPER_IN)
sout.write(WRAPPER_IN)
sys.stdout.flush()
sout.flush()
if PRINT_ALL_MESSAGE:
ANSIColors.printc('\t/2/ Message [<yellow>%s<white>] readed from <blue>%s<white>,' % ((readstr[:(len(readstr) - 1)] ), nsin))
# We remove the last caracter to avoir printing the last \n
sys.stdout.flush()
if WRAPPER_PRINTED:
sout.write(WRAPPER_OUT+readstr+WRAPPER_IN) # This works but USELESS now
else:
sout.write(readstr)
sout.flush()
except:
#print server_to_client
if server_to_client:
exit_with_Zenity('\t/5/ Client closed, because server closed !')
else:
try:
len(readstr)
except:
exit_with_Zenity('\t/5/ Client closed, because client wants to<white> (^C or process kill by another way) !')
exit_with_Zenity('\t/5/ Client closed, because reads an EOF signal!')
try:
ANSIColors.printc("\t/0/ <blue>Connection seems to be <green><u>well<U><blue> established<white> with the server <green><u>%s<U><white>," % server_name)
ANSIColors.printc("\t/0/ You are identified as the client <green><u>%s<U><white>." % msocket_name)
ANSIColors.printc("\t/?/ Enter <blue>\\?<white> for <u>more help<U>.")
# Start parallelization with threads
thread.start_new_thread(read_write_inverse, (sys.stdin, mfile, 1, msocket_name, server_name))
read_write_inverse (mfile, sys.stdout, 0, server_name, msocket_name)
except SystemExit: # Was surely raised by one of the previous exit_with_Zenity
raise
except:
# if some connexion problems appears but not properly handled previously
mfile.close()
msocket.shutdown(socket.SHUT_RDWR)
msocket.close()
exit_with_Zenity('/!\\ Connection refused or closed very badly /!\\ Reason : '+str(sys.exc_info()[0])+'.') # Exit
# In case the sys.exit doesn't work
#: Help message for this program or this module
#: (Keep in mind that it's mainly designed to be a program, called from the command line)
HELP="""./IRCclient.py [HOST PORT [OPTIONS]] | -z [OPTIONS]
Create a socket on HOST at PORT, and run it a client socket.
Options:
========
* -i, --interactive, -z, --zenity
Force Zenity interactivity : read args HOST and PORT interactively.
with Zenity and PyZenity (don't use it unless you are sure to have both).
* -ni, --non-interactive Disable Zenity interactivity : read args HOST and PORT from command line, Default.
* -w Print << in beginning of every output (experimental).
* -v Be verbous (print usefull informations about connections).
* -h, --help Print this help message.
* -a Print all message incomming from the client or outcomming to the server.
* --debug Launch program in debug mod with pygdb.
Example:
========
$ ./PyRlwrap.py ./IRCclient.py naereen-corp.crans.org 9312 -v -a
Copyrigths:
===========
(c) 09/2012
By Lilian BESSON
ENS de Cachan (M1 Mathematics & M1 Computer Science MPRI)
mailto:lbesson[AT]ens-cachan.fr
For Naereen Corp.
mailto:naereen-corporation[AT]laposte.net
https:sites.google.com/site/naereencorp/liste-des-projets/irc.
"""
__doc__=HELP
[docs]def main(args, HOST=HOST, PORT=PORT):
""" Create a socket on an host=args[1] with port=int(args[2]), and run a client on it."""
PRINT_ALL_MESSAGE=('-a' in args)
WRAPPER_PRINTED=('-w' in args)
try:
if len(args)>1:
HOST=args[1]
if len(args)>2:
PORT=int(args[2])
server=(HOST, PORT)
ANSIColors.printc("\t/./ <blue>Connection is establishing<white> with the server <green><u>%s:%i<U><white>," % server)
msocket=create_socket_client(server)
except socket.error:
exit_with_Zenity('/!\\ Connection refused because server was not responding ! /!\\')
except: # If connexion couldn't properly initialized
exit_with_Zenity('/!\\ Connection refused /!\\ Reason : '+str(sys.exc_info()[0]))
run_client(msocket, server, PRINT_ALL_MESSAGE, WRAPPER_PRINTED)
[docs]def ask_arg(HOST, PORT):
""" Use PyZenity to ask interactivly the arguments of the program."""
try:
ZHOST=PyZenity.GetText("Please, entry the IPv4 address of the IRC server you want to connect :", HOST, False)
ZPORT=PyZenity.GetText("Please, entry the TCP port of the IRC server you want to connect :", str(PORT), False)
if (ZHOST is None) or (ZPORT is None):
raise KeyboardInterrupt
#print(ZHOST, ZPORT)
return ['<ZenityInteractivity>', ZHOST, str(ZPORT), '-a']
except:
PyZenity.ErrorMessage("Error : you must enter both a valid address and a valid port !")
PyZenity.InfoMessage( ("The default values %s:%i will be used !" % (HOST, PORT) ))
return ['<DefaultValues>', HOST, PORT, '-a']
if __name__ == '__main__':
if ('-h' in sys.argv) or ('--help' in sys.argv):
sys.exit(HELP)
# Try to know if the current terminal supports ANSI escaped colored codes.
ANSISupported=(os.getenv('TERM') in ['xterm', 'screen-bce', 'screen', 'linux', 'xterm256']) and (sys.platform in ['linux', 'linux2'])
# Disable all escape codes for color to be generated
if not(ANSISupported):
ColorOff()
else: ColorOn()
if ('--interactive' in sys.argv) or ('-i' in sys.argv) or ('-z' in sys.argv) or ('--zenity' in sys.argv): # Force Zenity mod
AsZenity=True
# Determine ARGS
if ('--non-interactive' in sys.argv) or ('-ni' in sys.argv) or not(AsZenity):
ARGS=sys.argv
else:
ARGS=ask_arg(HOST, PORT)
#print ARGS
if '--debug' in ARGS:
import pdb
pdb.run('main(ARGS)')
else:
main(ARGS)
#END