information window
away messages support new jabberpy library
This commit is contained in:
		
							parent
							
								
									3fc824f87b
								
							
						
					
					
						commit
						194f989f1c
					
				
					 6 changed files with 1946 additions and 872 deletions
				
			
		
							
								
								
									
										408
									
								
								common/debug.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										408
									
								
								common/debug.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,408 @@
 | 
			
		|||
##   debug.py 
 | 
			
		||||
##
 | 
			
		||||
##   Copyright (C) 2003 Jacob Lundqvist
 | 
			
		||||
##
 | 
			
		||||
##   This program is free software; you can redistribute it and/or modify
 | 
			
		||||
##   it under the terms of the GNU Lesser General Public License as published
 | 
			
		||||
##   by the Free Software Foundation; either version 2, or (at your option)
 | 
			
		||||
##   any later version.
 | 
			
		||||
##
 | 
			
		||||
##   This program is distributed in the hope that it will be useful,
 | 
			
		||||
##   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
##   GNU Lesser General Public License for more details.
 | 
			
		||||
 | 
			
		||||
_version_ = '1.4.0'
 | 
			
		||||
 | 
			
		||||
"""\
 | 
			
		||||
 | 
			
		||||
Generic debug class
 | 
			
		||||
 | 
			
		||||
Other modules can always define extra debug flags for local usage, as long as
 | 
			
		||||
they make sure they append them to debug_flags
 | 
			
		||||
 | 
			
		||||
Also its always a good thing to prefix local flags with something, to reduce risk
 | 
			
		||||
of coliding flags. Nothing breaks if two flags would be identical, but it might 
 | 
			
		||||
activate unintended debugging.
 | 
			
		||||
 | 
			
		||||
flags can be numeric, but that makes analysing harder, on creation its
 | 
			
		||||
not obvious what is activated, and when flag_show is given, output isnt
 | 
			
		||||
really meaningfull.
 | 
			
		||||
 | 
			
		||||
This Debug class can either be initialized and used on app level, or used independantly
 | 
			
		||||
by the individual classes.
 | 
			
		||||
 | 
			
		||||
For samples of usage, see samples subdir in distro source, and selftest
 | 
			
		||||
in this code
 | 
			
		||||
    
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import time
 | 
			
		||||
from string import join
 | 
			
		||||
 | 
			
		||||
import types
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
debug_flags = []
 | 
			
		||||
 | 
			
		||||
color_none         = chr(27) + "[0m"
 | 
			
		||||
color_black        = chr(27) + "[30m"
 | 
			
		||||
color_red          = chr(27) + "[31m"
 | 
			
		||||
color_green        = chr(27) + "[32m"
 | 
			
		||||
color_brown        = chr(27) + "[33m"
 | 
			
		||||
color_blue         = chr(27) + "[34m"
 | 
			
		||||
color_magenta      = chr(27) + "[35m"
 | 
			
		||||
color_cyan         = chr(27) + "[36m"
 | 
			
		||||
color_light_gray   = chr(27) + "[37m"
 | 
			
		||||
color_dark_gray    = chr(27) + "[30;1m"
 | 
			
		||||
color_bright_red   = chr(27) + "[31;1m"
 | 
			
		||||
color_bright_green = chr(27) + "[32;1m"
 | 
			
		||||
color_yellow       = chr(27) + "[33;1m"
 | 
			
		||||
color_bright_blue  = chr(27) + "[34;1m"
 | 
			
		||||
color_purple       = chr(27) + "[35;1m"
 | 
			
		||||
color_bright_cyan  = chr(27) + "[36;1m"
 | 
			
		||||
color_white        = chr(27) + "[37;1m"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Define your flags in yor modules like this:
 | 
			
		||||
 | 
			
		||||
from debug import *
 | 
			
		||||
 | 
			
		||||
DBG_INIT = 'init'                ; debug_flags.append( DBG_INIT )
 | 
			
		||||
DBG_CONNECTION = 'connection'    ; debug_flags.append( DBG_CONNECTION )
 | 
			
		||||
 | 
			
		||||
 The reason for having a double statement wis so we can validate params
 | 
			
		||||
 and catch all undefined debug flags
 | 
			
		||||
 
 | 
			
		||||
 This gives us control over all used flags, and makes it easier to allow
 | 
			
		||||
 global debugging in your code, just do something like
 | 
			
		||||
 
 | 
			
		||||
 foo = Debug( debug_flags )
 | 
			
		||||
 
 | 
			
		||||
 group flags, that is a flag in it self containing multiple flags should be
 | 
			
		||||
 defined without the debug_flags.append() sequence, since the parts are already
 | 
			
		||||
 in the list, also they must of course be defined after the flags they depend on ;)
 | 
			
		||||
 example:
 | 
			
		||||
 | 
			
		||||
DBG_MULTI = [ DBG_INIT, DBG_CONNECTION ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  NoDebug
 | 
			
		||||
  -------
 | 
			
		||||
  To speed code up, typically for product releases or such
 | 
			
		||||
  use this class instead if you globaly want to disable debugging
 | 
			
		||||
"""
 | 
			
		||||
DBG_INIT = 'init'        ; debug_flags.append( DBG_INIT )
 | 
			
		||||
DBG_ALWAYS = 'always'    ; debug_flags.append( DBG_ALWAYS )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoDebug:
 | 
			
		||||
    def __init__( self, *args, **kwargs ):
 | 
			
		||||
        pass
 | 
			
		||||
    def show( self,  *args, **kwargs):
 | 
			
		||||
        pass
 | 
			
		||||
    def is_active( self, flag ):
 | 
			
		||||
        pass
 | 
			
		||||
    def active_set( self, active_flags = None ):
 | 
			
		||||
        return 0
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
LINE_FEED = '\n'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Debug:      
 | 
			
		||||
    def __init__( self,
 | 
			
		||||
                  #
 | 
			
		||||
                  # active_flags are those that will trigger output
 | 
			
		||||
                  #
 | 
			
		||||
                  active_flags = None, 
 | 
			
		||||
                  #
 | 
			
		||||
                  # Log file should be file object or file namne
 | 
			
		||||
                  #
 | 
			
		||||
                  log_file = sys.stderr,
 | 
			
		||||
                  #
 | 
			
		||||
                  # prefix and sufix can either be set globaly or per call.
 | 
			
		||||
                  # personally I use this to color code debug statements
 | 
			
		||||
                  # with prefix = chr(27) + '[34m'
 | 
			
		||||
                  #      sufix = chr(27) + '[37;1m\n'
 | 
			
		||||
                  #
 | 
			
		||||
                  prefix = 'DEBUG: ', 
 | 
			
		||||
                  sufix = '\n',
 | 
			
		||||
                  #
 | 
			
		||||
                  # If you want unix style timestamps, 
 | 
			
		||||
                  #  0 disables timestamps
 | 
			
		||||
                  #  1 before prefix, good when prefix is a string
 | 
			
		||||
                  #  2 after prefix, good when prefix is a color
 | 
			
		||||
                  #
 | 
			
		||||
                  time_stamp = 0,		  
 | 
			
		||||
                  #
 | 
			
		||||
                  # flag_show should normaly be of, but can be turned on to get a
 | 
			
		||||
                  # good view of what flags are actually used for calls,
 | 
			
		||||
                  # if it is not None, it should be a string
 | 
			
		||||
                  # flags for current call will be displayed 
 | 
			
		||||
                  # with flag_show as separator                  
 | 
			
		||||
                  # recomended values vould be '-' or ':', but any string goes
 | 
			
		||||
                  #
 | 
			
		||||
                  flag_show = None,
 | 
			
		||||
                  #
 | 
			
		||||
                  # If you dont want to validate flags on each call to
 | 
			
		||||
                  # show(), set this to 0
 | 
			
		||||
                  #
 | 
			
		||||
                  validate_flags = 1,
 | 
			
		||||
                  #
 | 
			
		||||
                  # If you dont want the welcome message, set to 0
 | 
			
		||||
                  # default is to show welcome if any flags are active
 | 
			
		||||
                  welcome = -1,
 | 
			
		||||
                  #
 | 
			
		||||
                  # Non plain-ascii encodings can benefit from it
 | 
			
		||||
                  encoding = None
 | 
			
		||||
                  ):
 | 
			
		||||
 | 
			
		||||
        if type(active_flags) not in [type([]), type(())]:
 | 
			
		||||
            print  '***' 
 | 
			
		||||
            print  '*** Invalid or oldformat debug param given: %s' % active_flags
 | 
			
		||||
            print  '*** please correct your param, should be of [] type!'
 | 
			
		||||
            print  '*** Due to this, full debuging is enabled'
 | 
			
		||||
            active_flags=[DBG_ALWAYS]
 | 
			
		||||
 | 
			
		||||
        if welcome == -1:
 | 
			
		||||
            if active_flags and len(active_flags):
 | 
			
		||||
                welcome = 1
 | 
			
		||||
            else:
 | 
			
		||||
                welcome = 0
 | 
			
		||||
            
 | 
			
		||||
        self._remove_dupe_flags()
 | 
			
		||||
        if log_file:
 | 
			
		||||
            if type( log_file ) is type(''):
 | 
			
		||||
                try:
 | 
			
		||||
                    self._fh = open(log_file,'w')
 | 
			
		||||
                except:
 | 
			
		||||
                    print 'ERROR: can open %s for writing'
 | 
			
		||||
                    sys.exit(0)
 | 
			
		||||
            else: ## assume its a stream type object
 | 
			
		||||
                self._fh = log_file
 | 
			
		||||
        else:
 | 
			
		||||
            self._fh = sys.stdout
 | 
			
		||||
         
 | 
			
		||||
        if time_stamp not in (0,1,2):
 | 
			
		||||
            msg2 = '%s' % time_stamp
 | 
			
		||||
            raise 'Invalid time_stamp param', msg2
 | 
			
		||||
        self.prefix = prefix
 | 
			
		||||
        self.sufix = sufix
 | 
			
		||||
        self.time_stamp = time_stamp
 | 
			
		||||
        self.flag_show = None # must be initialised after possible welcome
 | 
			
		||||
        self.validate_flags = validate_flags
 | 
			
		||||
        self.encoding = encoding
 | 
			
		||||
 | 
			
		||||
        self.active_set( active_flags )
 | 
			
		||||
        if welcome:
 | 
			
		||||
            self.show('')
 | 
			
		||||
            caller = sys._getframe(1) # used to get name of caller
 | 
			
		||||
            try:
 | 
			
		||||
                mod_name= ":%s" % caller.f_locals['__name__']
 | 
			
		||||
            except:
 | 
			
		||||
                mod_name = ""
 | 
			
		||||
            self.show('Debug created for %s%s' % (caller.f_code.co_filename,
 | 
			
		||||
                                                   mod_name ))
 | 
			
		||||
            self.show(' flags defined: %s' % join( self.active ))
 | 
			
		||||
            
 | 
			
		||||
        if type(flag_show) in (type(''), type(None)):
 | 
			
		||||
            self.flag_show = flag_show
 | 
			
		||||
        else:
 | 
			
		||||
            msg2 = '%s' % type(flag_show )
 | 
			
		||||
            raise 'Invalid type for flag_show!', msg2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def show( self, msg, flag = None, prefix = None, sufix = None,
 | 
			
		||||
              lf = 0 ):
 | 
			
		||||
        """
 | 
			
		||||
        flag can be of folowing types:
 | 
			
		||||
            None - this msg will always be shown if any debugging is on
 | 
			
		||||
            flag - will be shown if flag is active
 | 
			
		||||
            (flag1,flag2,,,) - will be shown if any of the given flags 
 | 
			
		||||
                               are active
 | 
			
		||||
 | 
			
		||||
        if prefix / sufix are not given, default ones from init will be used
 | 
			
		||||
        
 | 
			
		||||
        lf = -1 means strip linefeed if pressent
 | 
			
		||||
        lf = 1 means add linefeed if not pressent
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        if self.validate_flags:
 | 
			
		||||
            self._validate_flag( flag )
 | 
			
		||||
            
 | 
			
		||||
        if not self.is_active(flag):
 | 
			
		||||
            return
 | 
			
		||||
        if prefix:
 | 
			
		||||
            pre = prefix
 | 
			
		||||
        else:
 | 
			
		||||
            pre = self.prefix
 | 
			
		||||
        if sufix:
 | 
			
		||||
            suf = sufix
 | 
			
		||||
        else:
 | 
			
		||||
            suf = self.sufix
 | 
			
		||||
 | 
			
		||||
        if self.time_stamp == 2:
 | 
			
		||||
            output = '%s%s ' % ( pre,
 | 
			
		||||
                                 time.strftime('%b %d %H:%M:%S',
 | 
			
		||||
                                 time.localtime(time.time() )),
 | 
			
		||||
                                 )
 | 
			
		||||
        elif self.time_stamp == 1:
 | 
			
		||||
            output = '%s %s' % ( time.strftime('%b %d %H:%M:%S',
 | 
			
		||||
                                 time.localtime(time.time() )),
 | 
			
		||||
                                 pre,
 | 
			
		||||
                                 )
 | 
			
		||||
        else:
 | 
			
		||||
            output = pre
 | 
			
		||||
            
 | 
			
		||||
        if self.flag_show:
 | 
			
		||||
            if flag:
 | 
			
		||||
                output = '%s%s%s' % ( output, flag, self.flag_show )
 | 
			
		||||
            else:
 | 
			
		||||
                # this call uses the global default,
 | 
			
		||||
                # dont print "None", just show the separator
 | 
			
		||||
                output = '%s %s' % ( output, self.flag_show )
 | 
			
		||||
 | 
			
		||||
        if type(msg)==type(u'') and self.encoding:
 | 
			
		||||
            msg=msg.encode(self.encoding, 'replace')
 | 
			
		||||
 | 
			
		||||
        output = '%s%s%s' % ( output, msg, suf )
 | 
			
		||||
        if lf:
 | 
			
		||||
            # strip/add lf if needed
 | 
			
		||||
            last_char = output[-1]
 | 
			
		||||
            if lf == 1 and last_char != LINE_FEED:
 | 
			
		||||
                output = output + LINE_FEED
 | 
			
		||||
            elif lf == -1 and last_char == LINE_FEED:
 | 
			
		||||
                output = output[:-1]
 | 
			
		||||
        try:
 | 
			
		||||
            self._fh.write( output )
 | 
			
		||||
        except:
 | 
			
		||||
            # unicode strikes again ;)
 | 
			
		||||
            s=u''
 | 
			
		||||
            for i in range(len(output)):
 | 
			
		||||
                if ord(output[i]) < 128:
 | 
			
		||||
                    c = output[i]
 | 
			
		||||
                else:
 | 
			
		||||
                    c = '?'
 | 
			
		||||
                s=s+c
 | 
			
		||||
            self._fh.write( '%s%s%s' % ( pre, s, suf ))
 | 
			
		||||
        self._fh.flush()
 | 
			
		||||
            
 | 
			
		||||
                
 | 
			
		||||
    def is_active( self, flag ):
 | 
			
		||||
        'If given flag(s) should generate output.'
 | 
			
		||||
 | 
			
		||||
        # try to abort early to quicken code
 | 
			
		||||
        if not self.active:
 | 
			
		||||
            return 0
 | 
			
		||||
        if not flag or flag in self.active or DBG_ALWAYS in  self.active:
 | 
			
		||||
            return 1
 | 
			
		||||
        else:
 | 
			
		||||
            # check for multi flag type:
 | 
			
		||||
            if type( flag ) in ( type(()), type([]) ):
 | 
			
		||||
                for s in flag:
 | 
			
		||||
                    if s in self.active:
 | 
			
		||||
                        return 1
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    def active_set( self, active_flags = None ):
 | 
			
		||||
        "returns 1 if any flags where actually set, otherwise 0."
 | 
			
		||||
        r = 0
 | 
			
		||||
        ok_flags = []
 | 
			
		||||
        if not active_flags:
 | 
			
		||||
            #no debuging at all
 | 
			
		||||
            self.active = []
 | 
			
		||||
        elif type( active_flags ) in ( types.TupleType, types.ListType ):
 | 
			
		||||
            flags = self._as_one_list( active_flags )
 | 
			
		||||
            for t in flags:
 | 
			
		||||
                if t not in debug_flags:
 | 
			
		||||
                    print 'Invalid debugflag given', t
 | 
			
		||||
                else:
 | 
			
		||||
                    ok_flags.append( t )
 | 
			
		||||
                
 | 
			
		||||
            self.active = ok_flags
 | 
			
		||||
            r = 1
 | 
			
		||||
        else:
 | 
			
		||||
            # assume comma string
 | 
			
		||||
            try:
 | 
			
		||||
                flags = active_flags.split(',')
 | 
			
		||||
            except:
 | 
			
		||||
                self.show( '***' )
 | 
			
		||||
                self.show( '*** Invalid debug param given: %s' % active_flags )
 | 
			
		||||
                self.show( '*** please correct your param!' )
 | 
			
		||||
                self.show( '*** due to this, full debuging is enabled' )
 | 
			
		||||
                self.active = debug_flags
 | 
			
		||||
            
 | 
			
		||||
            for f in flags:
 | 
			
		||||
                s = f.strip()
 | 
			
		||||
                ok_flags.append( s )
 | 
			
		||||
            self.active = ok_flags
 | 
			
		||||
 | 
			
		||||
        self._remove_dupe_flags()
 | 
			
		||||
        return r
 | 
			
		||||
    
 | 
			
		||||
    def active_get( self ):
 | 
			
		||||
        "returns currently active flags."
 | 
			
		||||
        return self.active
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    def _as_one_list( self, items ):
 | 
			
		||||
        """ init param might contain nested lists, typically from group flags.
 | 
			
		||||
        
 | 
			
		||||
        This code organises lst and remves dupes
 | 
			
		||||
        """
 | 
			
		||||
        if type( items ) <> type( [] ) and type( items ) <> type( () ):
 | 
			
		||||
            return [ items ]
 | 
			
		||||
        r = []
 | 
			
		||||
        for l in items:
 | 
			
		||||
            if type( l ) == type([]):
 | 
			
		||||
                lst2 = self._as_one_list( l )
 | 
			
		||||
                for l2 in lst2: 
 | 
			
		||||
                    self._append_unique_str(r, l2 )
 | 
			
		||||
            elif l == None:
 | 
			
		||||
                continue
 | 
			
		||||
            else:
 | 
			
		||||
                self._append_unique_str(r, l )
 | 
			
		||||
        return r
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    def _append_unique_str( self, lst, item ):
 | 
			
		||||
        """filter out any dupes."""
 | 
			
		||||
        if type(item) <> type(''):
 | 
			
		||||
            msg2 = '%s' % item
 | 
			
		||||
            raise 'Invalid item type (should be string)',msg2
 | 
			
		||||
        if item not in lst:
 | 
			
		||||
            lst.append( item )
 | 
			
		||||
        return lst
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    def _validate_flag( self, flags ):
 | 
			
		||||
        'verify that flag is defined.'
 | 
			
		||||
        if flags:
 | 
			
		||||
            for f in self._as_one_list( flags ):
 | 
			
		||||
                if not f in debug_flags:
 | 
			
		||||
                    msg2 = '%s' % f
 | 
			
		||||
                    raise 'Invalid debugflag given', msg2
 | 
			
		||||
 | 
			
		||||
    def _remove_dupe_flags( self ):
 | 
			
		||||
        """
 | 
			
		||||
        if multiple instances of Debug is used in same app, 
 | 
			
		||||
        some flags might be created multiple time, filter out dupes
 | 
			
		||||
        """
 | 
			
		||||
        global debug_flags
 | 
			
		||||
        
 | 
			
		||||
        unique_flags = []
 | 
			
		||||
        for f in debug_flags:
 | 
			
		||||
            if f not in unique_flags:
 | 
			
		||||
                unique_flags.append(f)
 | 
			
		||||
        debug_flags = unique_flags
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										985
									
								
								common/jabber.py
									
										
									
									
									
								
							
							
						
						
									
										985
									
								
								common/jabber.py
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -28,16 +28,16 @@ case.
 | 
			
		|||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# $Id: xmlstream.py,v 1.26 2003/02/20 10:22:33 shire Exp $
 | 
			
		||||
# $Id: xmlstream.py,v 1.42 2004/01/08 15:47:40 snakeru Exp $
 | 
			
		||||
 | 
			
		||||
import site
 | 
			
		||||
site.encoding = 'UTF-8'
 | 
			
		||||
import time, sys, re, socket
 | 
			
		||||
from select import select
 | 
			
		||||
from string import split,find,replace,join
 | 
			
		||||
from base64 import encodestring
 | 
			
		||||
import xml.parsers.expat
 | 
			
		||||
import debug
 | 
			
		||||
_debug=debug
 | 
			
		||||
 | 
			
		||||
VERSION = 0.3
 | 
			
		||||
VERSION = "0.5-rc1"
 | 
			
		||||
 | 
			
		||||
False = 0
 | 
			
		||||
True  = 1
 | 
			
		||||
| 
						 | 
				
			
			@ -46,24 +46,31 @@ TCP     = 1
 | 
			
		|||
STDIO   = 0
 | 
			
		||||
TCP_SSL = 2
 | 
			
		||||
 | 
			
		||||
ENCODING = site.encoding 
 | 
			
		||||
ENCODING = 'utf-8'      # Though it is uncommon, this is the only right setting.
 | 
			
		||||
ustr = str
 | 
			
		||||
 | 
			
		||||
BLOCK_SIZE  = 1024     ## Number of bytes to get at at time via socket
 | 
			
		||||
                       ## transactions
 | 
			
		||||
 | 
			
		||||
DBG_INIT, DBG_ALWAYS = debug.DBG_INIT, debug.DBG_ALWAYS
 | 
			
		||||
DBG_CONN_ERROR = 'conn-error'    ; debug.debug_flags.append( DBG_CONN_ERROR )
 | 
			
		||||
DBG_XML_PARSE = 'xml-parse'      ; debug.debug_flags.append( DBG_XML_PARSE )
 | 
			
		||||
DBG_XML_RAW = 'xml-raw'          ; debug.debug_flags.append( DBG_XML_RAW )
 | 
			
		||||
DBG_XML = [ DBG_XML_PARSE, DBG_XML_RAW ] # sample multiflag
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def XMLescape(txt):
 | 
			
		||||
    "Escape XML entities"
 | 
			
		||||
    txt = replace(txt, "&", "&")
 | 
			
		||||
    txt = replace(txt, "<", "<")
 | 
			
		||||
    txt = replace(txt, ">", ">")
 | 
			
		||||
    txt = txt.replace("&", "&")
 | 
			
		||||
    txt = txt.replace("<", "<")
 | 
			
		||||
    txt = txt.replace(">", ">")
 | 
			
		||||
    return txt
 | 
			
		||||
 | 
			
		||||
def XMLunescape(txt):
 | 
			
		||||
    "Unescape XML entities"
 | 
			
		||||
    txt = replace(txt, "<", "<")
 | 
			
		||||
    txt = replace(txt, ">", ">")
 | 
			
		||||
    txt = replace(txt, "&", "&")
 | 
			
		||||
    txt = txt.replace(">", ">")
 | 
			
		||||
    txt = txt.replace("<", "<")
 | 
			
		||||
    txt = txt.replace("&", "&")
 | 
			
		||||
    return txt
 | 
			
		||||
 | 
			
		||||
class error:
 | 
			
		||||
| 
						 | 
				
			
			@ -74,23 +81,28 @@ class error:
 | 
			
		|||
    
 | 
			
		||||
class Node:
 | 
			
		||||
    """A simple XML DOM like class"""
 | 
			
		||||
    def __init__(self, tag='', parent=None, attrs=None ):
 | 
			
		||||
        bits = split(tag)
 | 
			
		||||
        if len(bits) == 1:
 | 
			
		||||
            self.name = tag
 | 
			
		||||
            self.namespace = ''
 | 
			
		||||
    def __init__(self, tag=None, parent=None, attrs={}, payload=[], node=None):
 | 
			
		||||
        if node:
 | 
			
		||||
            if type(node)<>type(self): node=NodeBuilder(node).getDom()
 | 
			
		||||
            self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = \
 | 
			
		||||
                node.name,node.namespace,node.attrs,node.data,node.kids,node.parent
 | 
			
		||||
        else:
 | 
			
		||||
            self.namespace, self.name = bits
 | 
			
		||||
            self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = 'tag','',{},[],[],None
 | 
			
		||||
 | 
			
		||||
        if tag: self.namespace, self.name = (['']+tag.split())[-2:]
 | 
			
		||||
 | 
			
		||||
        if parent: self.parent = parent
 | 
			
		||||
 | 
			
		||||
#        if self.parent and not self.namespace: self.namespace=self.parent.namespace	# Doesn't checked if this neccessary
 | 
			
		||||
 | 
			
		||||
        for attr in attrs.keys():
 | 
			
		||||
            self.attrs[attr]=attrs[attr]
 | 
			
		||||
 | 
			
		||||
        for i in payload:
 | 
			
		||||
            if type(i)==type(self): self.insertNode(i)
 | 
			
		||||
            else: self.insertXML(i)
 | 
			
		||||
#            self.insertNode(Node(node=i))	# Alternative way. Needs perfomance testing.
 | 
			
		||||
 | 
			
		||||
        if attrs is None:
 | 
			
		||||
            self.attrs = {}
 | 
			
		||||
        else:
 | 
			
		||||
            self.attrs = attrs
 | 
			
		||||
            
 | 
			
		||||
        self.data = []
 | 
			
		||||
        self.kids = []
 | 
			
		||||
        self.parent = parent
 | 
			
		||||
        
 | 
			
		||||
    def setParent(self, node):
 | 
			
		||||
        "Set the nodes parent node."
 | 
			
		||||
        self.parent = node
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +138,7 @@ class Node:
 | 
			
		|||
 | 
			
		||||
    def getData(self):
 | 
			
		||||
        "Return the nodes textual data" 
 | 
			
		||||
        return join(self.data, '')
 | 
			
		||||
        return ''.join(self.data)
 | 
			
		||||
 | 
			
		||||
    def getDataAsParts(self):
 | 
			
		||||
        "Return the node data as an array" 
 | 
			
		||||
| 
						 | 
				
			
			@ -140,12 +152,12 @@ class Node:
 | 
			
		|||
        "Set the nodes namespace." 
 | 
			
		||||
        self.namespace = namespace
 | 
			
		||||
 | 
			
		||||
    def insertTag(self, name):
 | 
			
		||||
    def insertTag(self, name=None, attrs={}, payload=[], node=None):
 | 
			
		||||
        """ Add a child tag of name 'name' to the node.
 | 
			
		||||
 | 
			
		||||
            Returns the newly created node.
 | 
			
		||||
        """
 | 
			
		||||
        newnode = Node(tag=name, parent=self)
 | 
			
		||||
        newnode = Node(tag=name, parent=self, attrs=attrs, payload=payload, node=node)
 | 
			
		||||
        self.kids.append(newnode)
 | 
			
		||||
        return newnode
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +183,7 @@ class Node:
 | 
			
		|||
            if parent and parent.namespace != self.namespace:
 | 
			
		||||
                s = s + " xmlns = '%s' " % self.namespace
 | 
			
		||||
        for key in self.attrs.keys():
 | 
			
		||||
            val = str(self.attrs[key])
 | 
			
		||||
            val = ustr(self.attrs[key])
 | 
			
		||||
            s = s + " %s='%s'" % ( key, XMLescape(val) )
 | 
			
		||||
        s = s + ">"
 | 
			
		||||
        cnt = 0 
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +193,10 @@ class Node:
 | 
			
		|||
                s = s + a._xmlnode2str(parent=self)
 | 
			
		||||
                cnt=cnt+1
 | 
			
		||||
        if (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt])
 | 
			
		||||
        s = s + "</" + self.name + ">"
 | 
			
		||||
        if not self.kids and s[-1:]=='>':
 | 
			
		||||
            s=s[:-1]+' />'
 | 
			
		||||
        else:
 | 
			
		||||
            s = s + "</" + self.name + ">"
 | 
			
		||||
        return s
 | 
			
		||||
 | 
			
		||||
    def getTag(self, name):
 | 
			
		||||
| 
						 | 
				
			
			@ -200,105 +215,123 @@ class Node:
 | 
			
		|||
               nodes.append(node)
 | 
			
		||||
        return nodes
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    def getChildren(self):
 | 
			
		||||
        """Returns a nodes children"""
 | 
			
		||||
        return self.kids
 | 
			
		||||
 | 
			
		||||
    def removeTag(self,tag):
 | 
			
		||||
        """Pops out specified child and returns it."""
 | 
			
		||||
        if type(tag)==type(self):
 | 
			
		||||
            try:
 | 
			
		||||
                self.kids.remove(tag)
 | 
			
		||||
                return tag
 | 
			
		||||
            except: return None
 | 
			
		||||
        for node in self.kids:
 | 
			
		||||
            if node.getName()==tag:
 | 
			
		||||
                self.kids.remove(node)
 | 
			
		||||
                return node
 | 
			
		||||
 | 
			
		||||
class NodeBuilder:
 | 
			
		||||
    """builds a 'minidom' from data parsed to it. Primarily for insertXML
 | 
			
		||||
       method of Node"""
 | 
			
		||||
    def __init__(self,data):
 | 
			
		||||
    def __init__(self,data=None):
 | 
			
		||||
        self._parser = xml.parsers.expat.ParserCreate(namespace_separator=' ')
 | 
			
		||||
        self._parser.StartElementHandler  = self.unknown_starttag
 | 
			
		||||
        self._parser.EndElementHandler    = self.unknown_endtag
 | 
			
		||||
        self._parser.CharacterDataHandler = self.handle_data
 | 
			
		||||
 | 
			
		||||
        self.__depth = 0
 | 
			
		||||
        self.__done  = 0 #needed ?
 | 
			
		||||
        self.__space_regex = re.compile('^\s+$')
 | 
			
		||||
        self._dispatch_depth = 1
 | 
			
		||||
        
 | 
			
		||||
        self._parser.Parse(data,1)
 | 
			
		||||
        if data: self._parser.Parse(data,1)
 | 
			
		||||
 | 
			
		||||
    def unknown_starttag(self, tag, attrs):
 | 
			
		||||
        """XML Parser callback"""
 | 
			
		||||
        self.__depth = self.__depth + 1
 | 
			
		||||
        if self.__depth == 1:
 | 
			
		||||
        self.DEBUG("DEPTH -> %i , tag -> %s, attrs -> %s" % \
 | 
			
		||||
                   (self.__depth, tag, str(attrs)),DBG_XML_PARSE )
 | 
			
		||||
        if self.__depth == self._dispatch_depth:
 | 
			
		||||
            self._mini_dom = Node(tag=tag, attrs=attrs)
 | 
			
		||||
            self._ptr = self._mini_dom
 | 
			
		||||
        elif self.__depth > 1:
 | 
			
		||||
            self._ptr.kids.append(Node(tag   =tag,
 | 
			
		||||
                                       parent=self._ptr,
 | 
			
		||||
                                       attrs =attrs ))
 | 
			
		||||
        elif self.__depth > self._dispatch_depth:
 | 
			
		||||
            self._ptr.kids.append(Node(tag=tag,parent=self._ptr,attrs=attrs))
 | 
			
		||||
            self._ptr = self._ptr.kids[-1]
 | 
			
		||||
        else:                           ## fix this ....
 | 
			
		||||
            pass 
 | 
			
		||||
        else:                           ## it the stream tag:
 | 
			
		||||
            if attrs.has_key('id'):
 | 
			
		||||
                self._incomingID = attrs['id']
 | 
			
		||||
        self.last_is_data = False
 | 
			
		||||
 | 
			
		||||
    def unknown_endtag(self, tag ):
 | 
			
		||||
        self.__depth = self.__depth - 1
 | 
			
		||||
        if self.__depth == 0:
 | 
			
		||||
        """XML Parser callback"""
 | 
			
		||||
        self.DEBUG("DEPTH -> %i" % self.__depth,DBG_XML_PARSE)
 | 
			
		||||
        if self.__depth == self._dispatch_depth:
 | 
			
		||||
            self.dispatch(self._mini_dom)
 | 
			
		||||
        elif self.__depth > 0:
 | 
			
		||||
        elif self.__depth > self._dispatch_depth:
 | 
			
		||||
            self._ptr = self._ptr.parent
 | 
			
		||||
        else:
 | 
			
		||||
            pass
 | 
			
		||||
            self.DEBUG("*** Stream terminated ? ****",DBG_CONN_ERROR)
 | 
			
		||||
        self.__depth = self.__depth - 1
 | 
			
		||||
        self.last_is_data = False
 | 
			
		||||
 | 
			
		||||
    def handle_data(self, data):
 | 
			
		||||
        if not self.__space_regex.match(data):  ## check its not all blank 
 | 
			
		||||
        """XML Parser callback"""
 | 
			
		||||
        self.DEBUG("data-> " + data,DBG_XML_PARSE)
 | 
			
		||||
        if self.last_is_data:
 | 
			
		||||
            self._ptr.data[-1] += data
 | 
			
		||||
        else:
 | 
			
		||||
            self._ptr.data.append(data)
 | 
			
		||||
            self.last_is_data = True
 | 
			
		||||
 | 
			
		||||
    def dispatch(self,dom):
 | 
			
		||||
        self.__done = 1
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def DEBUG(self,dup1,dup2=None):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def getDom(self):
 | 
			
		||||
        return self._mini_dom
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Stream:
 | 
			
		||||
    def __init__(
 | 
			
		||||
                 self, host, port, namespace,
 | 
			
		||||
                 debug=True,
 | 
			
		||||
class Stream(NodeBuilder):
 | 
			
		||||
    """Extention of NodeBuilder class. Handles stream of XML stanzas. 
 | 
			
		||||
       Calls dispatch method for every child of root node 
 | 
			
		||||
       (stream:stream for jabber stream).
 | 
			
		||||
       attributes _read, _write and _reader must be set by external entity
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, namespace,
 | 
			
		||||
                 debug=[DBG_ALWAYS],
 | 
			
		||||
                 log=None,
 | 
			
		||||
                 sock=None,
 | 
			
		||||
                 id=None,
 | 
			
		||||
                 connection=TCP
 | 
			
		||||
                 ):
 | 
			
		||||
                 timestampLog=True):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        self._parser = xml.parsers.expat.ParserCreate(namespace_separator=' ')
 | 
			
		||||
        self._parser.StartElementHandler  = self._unknown_starttag
 | 
			
		||||
        self._parser.EndElementHandler    = self._unknown_endtag
 | 
			
		||||
        self._parser.CharacterDataHandler = self._handle_data
 | 
			
		||||
 | 
			
		||||
        self._host = host
 | 
			
		||||
        self._port = port 
 | 
			
		||||
        self._namespace = namespace
 | 
			
		||||
        self.__depth = 0
 | 
			
		||||
        self._sock = sock
 | 
			
		||||
 | 
			
		||||
        self._sslObj    = None
 | 
			
		||||
        self._sslIssuer = None
 | 
			
		||||
        self._sslServer = None
 | 
			
		||||
        self._read , self._reader , self._write = None , None , None
 | 
			
		||||
 | 
			
		||||
        self._incomingID = None
 | 
			
		||||
        self._outgoingID = id
 | 
			
		||||
        
 | 
			
		||||
        self._debug = debug
 | 
			
		||||
        self._connection=connection
 | 
			
		||||
 | 
			
		||||
        self.DEBUG("stream init called")
 | 
			
		||||
        self._debug = _debug.Debug(debug,encoding=ENCODING)
 | 
			
		||||
        self.DEBUG = self._debug.show # makes it backwards compatible with v0.4 code
 | 
			
		||||
 | 
			
		||||
        self.DEBUG("stream init called",DBG_INIT)
 | 
			
		||||
 | 
			
		||||
        if log:
 | 
			
		||||
            if type(log) is type(""):
 | 
			
		||||
                try:
 | 
			
		||||
                    self._logFH = open(log,'w')
 | 
			
		||||
                except:
 | 
			
		||||
                    print "ERROR: can open %s for writing"
 | 
			
		||||
                    print "ERROR: can open %s for writing" % log
 | 
			
		||||
                    sys.exit(0)
 | 
			
		||||
            else: ## assume its a stream type object
 | 
			
		||||
                self._logFH = log
 | 
			
		||||
        else:
 | 
			
		||||
            self._logFH = None
 | 
			
		||||
        self._timestampLog = True
 | 
			
		||||
        self._timestampLog = timestampLog
 | 
			
		||||
 | 
			
		||||
    def connect(self):
 | 
			
		||||
        NodeBuilder.__init__(self)
 | 
			
		||||
        self._dispatch_depth = 2
 | 
			
		||||
 | 
			
		||||
    def timestampLog(self,timestamp):
 | 
			
		||||
        """ Enable or disable the showing of a timestamp in the log.
 | 
			
		||||
| 
						 | 
				
			
			@ -306,179 +339,64 @@ class Stream:
 | 
			
		|||
        """
 | 
			
		||||
        self._timestampLog = timestamp
 | 
			
		||||
 | 
			
		||||
    def DEBUG(self,txt):
 | 
			
		||||
        if self._debug:
 | 
			
		||||
            try:
 | 
			
		||||
                sys.stderr.write("DEBUG: %s\n" % txt)
 | 
			
		||||
            except:
 | 
			
		||||
                # unicode strikes again ;)
 | 
			
		||||
                s=u''
 | 
			
		||||
                for i in range(len(txt)):
 | 
			
		||||
                    if ord(txt[i]) < 128:
 | 
			
		||||
                        c = txt[i]
 | 
			
		||||
                    else:
 | 
			
		||||
                        c = '?'
 | 
			
		||||
                    s=s+c
 | 
			
		||||
                sys.stderr.write("DEBUG: %s\n" % s )
 | 
			
		||||
 | 
			
		||||
    def getSocket(self):
 | 
			
		||||
        return self._sock
 | 
			
		||||
 | 
			
		||||
    def header(self):    
 | 
			
		||||
        self.DEBUG("stream: sending initial header")
 | 
			
		||||
        str = u"<?xml version='1.0' encoding='UTF-8' ?>   \
 | 
			
		||||
                <stream:stream to='%s' xmlns='%s'" % ( self._host,
 | 
			
		||||
                                                       self._namespace )
 | 
			
		||||
        
 | 
			
		||||
        if self._outgoingID: str = str + " id='%s' " % self._outgoingID 
 | 
			
		||||
        str = str + " xmlns:stream='http://etherx.jabber.org/streams'>"
 | 
			
		||||
        self.write (str)
 | 
			
		||||
        self.read()
 | 
			
		||||
 | 
			
		||||
    def _handle_data(self, data):
 | 
			
		||||
        """XML Parser callback"""
 | 
			
		||||
        self.DEBUG("data-> " + data)
 | 
			
		||||
        ## TODO: get rid of empty space
 | 
			
		||||
        ## self._ptr.data = self._ptr.data + data 
 | 
			
		||||
        self._ptr.data.append(data)
 | 
			
		||||
        
 | 
			
		||||
    def _unknown_starttag(self, tag, attrs):
 | 
			
		||||
        """XML Parser callback"""
 | 
			
		||||
        self.__depth = self.__depth + 1
 | 
			
		||||
        self.DEBUG("DEPTH -> %i , tag -> %s, attrs -> %s" % \
 | 
			
		||||
                   (self.__depth, tag, str(attrs)) )
 | 
			
		||||
        if self.__depth == 2:
 | 
			
		||||
            self._mini_dom = Node(tag=tag, attrs=attrs)
 | 
			
		||||
            self._ptr = self._mini_dom
 | 
			
		||||
        elif self.__depth > 2:
 | 
			
		||||
            self._ptr.kids.append(Node(tag=tag,parent=self._ptr,attrs=attrs))
 | 
			
		||||
            self._ptr = self._ptr.kids[-1]
 | 
			
		||||
        else:                           ## it the stream tag:
 | 
			
		||||
            if attrs.has_key('id'):
 | 
			
		||||
                self._incomingID = attrs['id']
 | 
			
		||||
 | 
			
		||||
    def _unknown_endtag(self, tag ):
 | 
			
		||||
        """XML Parser callback"""
 | 
			
		||||
        self.__depth = self.__depth - 1
 | 
			
		||||
        self.DEBUG("DEPTH -> %i" % self.__depth)
 | 
			
		||||
        if self.__depth == 1:
 | 
			
		||||
            self.dispatch(self._mini_dom)
 | 
			
		||||
        elif self.__depth > 1:
 | 
			
		||||
            self._ptr = self._ptr.parent
 | 
			
		||||
        else:
 | 
			
		||||
            self.DEBUG("*** Server closed connection ? ****")
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, nodes, depth = 0):
 | 
			
		||||
        """Overide with the method you want to called with
 | 
			
		||||
        a node structure of a 'protocol element."""
 | 
			
		||||
 | 
			
		||||
        padding = ' '
 | 
			
		||||
        padding = padding * depth
 | 
			
		||||
        depth = depth + 1
 | 
			
		||||
        for n in nodes:
 | 
			
		||||
            if n.kids != None:
 | 
			
		||||
                self.dispatch(n.kids, depth)
 | 
			
		||||
                
 | 
			
		||||
    ##def syntax_error(self, message):
 | 
			
		||||
    ##    self.DEBUG("error " + message)
 | 
			
		||||
 | 
			
		||||
    def _do_read( self, action, buff_size ):
 | 
			
		||||
        """workhorse for read() method.
 | 
			
		||||
 | 
			
		||||
        added 021231 by jaclu"""
 | 
			
		||||
        data=''
 | 
			
		||||
        data_in = action(buff_size)
 | 
			
		||||
        while data_in:
 | 
			
		||||
            data = data + data_in
 | 
			
		||||
            if len(data_in) != buff_size:
 | 
			
		||||
                break
 | 
			
		||||
            data_in = action(buff_size)
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def read(self):
 | 
			
		||||
        """Reads incoming data. Called by process() so nonblocking
 | 
			
		||||
        """Reads incoming data. Blocks until done. Calls self.disconnected(self) if appropriate."""
 | 
			
		||||
        try: received = self._read(BLOCK_SIZE)
 | 
			
		||||
        except: received = ''
 | 
			
		||||
 | 
			
		||||
        changed 021231 by jaclu
 | 
			
		||||
        """
 | 
			
		||||
        if self._connection == TCP:
 | 
			
		||||
            raw_data = self._do_read(self._sock.recv, BLOCK_SIZE)
 | 
			
		||||
        elif self._connection == TCP_SSL:
 | 
			
		||||
            raw_data = self._do_read(self._sslObj.read, BLOCK_SIZE)
 | 
			
		||||
        elif self._connection == STDIO:
 | 
			
		||||
            raw_data = self._do_read(self.stdin.read, 1024)
 | 
			
		||||
        else:
 | 
			
		||||
            raw_data = '' # should never get here
 | 
			
		||||
        while select([self._reader],[],[],0)[0]:
 | 
			
		||||
            add = self._read(BLOCK_SIZE)
 | 
			
		||||
            received +=add
 | 
			
		||||
            if not add: break
 | 
			
		||||
 | 
			
		||||
        # just encode incoming data once!
 | 
			
		||||
        data = unicode(raw_data,'utf-8').encode(ENCODING,'replace')
 | 
			
		||||
        self.DEBUG("got data %s" % data )
 | 
			
		||||
        self.log(data, 'RECV:')
 | 
			
		||||
        self._parser.Parse(data)
 | 
			
		||||
        return data
 | 
			
		||||
        if len(received): # length of 0 means disconnect
 | 
			
		||||
            self.DEBUG("got data " + received , DBG_XML_RAW )
 | 
			
		||||
            self.log(received, 'RECV:')
 | 
			
		||||
        else: self.disconnected(self)
 | 
			
		||||
        return received
 | 
			
		||||
 | 
			
		||||
    def write(self,raw_data=u''):
 | 
			
		||||
        """Writes raw outgoing data. blocks
 | 
			
		||||
 | 
			
		||||
        changed 021231 by jaclu, added unicode encoding
 | 
			
		||||
        """
 | 
			
		||||
        if type(raw_data) == type(u''):
 | 
			
		||||
            data_out = raw_data.encode('utf-8','replace')
 | 
			
		||||
        else:
 | 
			
		||||
            # since not suplied as unicode, we must guess at
 | 
			
		||||
            # what the data is, iso-8859-1 seems reasonable.
 | 
			
		||||
            # To avoid this auto assumption,
 | 
			
		||||
            # send your data as a unicode string!
 | 
			
		||||
            data_out = unicode(raw_data,'iso-8859-1').encode(ENCODING,'replace')
 | 
			
		||||
    def write(self,raw_data):
 | 
			
		||||
        """Writes raw outgoing data. Blocks until done.
 | 
			
		||||
           If supplied data is not unicode string, ENCODING
 | 
			
		||||
           is used for convertion. Avoid this!
 | 
			
		||||
           Always send your data as a unicode string."""
 | 
			
		||||
        if type(raw_data) == type(''):
 | 
			
		||||
            self.DEBUG('Non-utf-8 string "%s" passed to Stream.write! Treating it as %s encoded.'%(raw_data,ENCODING))
 | 
			
		||||
            raw_data = unicode(raw_data,ENCODING)
 | 
			
		||||
        data_out = raw_data.encode('utf-8')
 | 
			
		||||
        try:
 | 
			
		||||
            if self._connection == TCP:
 | 
			
		||||
                self._sock.send (data_out)
 | 
			
		||||
            elif self._connection == TCP_SSL:
 | 
			
		||||
                self._sslObj.write(data_out)
 | 
			
		||||
            elif self._connection == STDIO:
 | 
			
		||||
                self.stdout.write(data_out)
 | 
			
		||||
            else:
 | 
			
		||||
                pass
 | 
			
		||||
            self._write(data_out)
 | 
			
		||||
            self.log(data_out, 'SENT:')
 | 
			
		||||
            self.DEBUG("sent %s" % data_out)
 | 
			
		||||
            self.DEBUG("sent %s" % data_out,DBG_XML_RAW)
 | 
			
		||||
        except:
 | 
			
		||||
            self.DEBUG("xmlstream write threw error")
 | 
			
		||||
            self.disconnected()
 | 
			
		||||
            self.DEBUG("xmlstream write threw error",DBG_CONN_ERROR)
 | 
			
		||||
            self.disconnected(self)
 | 
			
		||||
            
 | 
			
		||||
    def process(self,timeout):
 | 
			
		||||
        
 | 
			
		||||
        reader=Node
 | 
			
		||||
 | 
			
		||||
        if self._connection == TCP: 
 | 
			
		||||
            reader = self._sock
 | 
			
		||||
        elif self._connection == TCP_SSL:
 | 
			
		||||
            reader = self._sock
 | 
			
		||||
        elif self._connection == STDIO:
 | 
			
		||||
            reader = sys.stdin
 | 
			
		||||
        else:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        ready_for_read,ready_for_write,err = \
 | 
			
		||||
                        select( [reader],[],[],timeout)
 | 
			
		||||
        for s in ready_for_read:
 | 
			
		||||
            if s == reader:
 | 
			
		||||
                if not len(self.read()): # length of 0 means disconnect
 | 
			
		||||
                    ## raise error("network error") ?
 | 
			
		||||
                    self.disconnected()
 | 
			
		||||
                    return False
 | 
			
		||||
                return True
 | 
			
		||||
        return False
 | 
			
		||||
    def process(self, timeout=0):
 | 
			
		||||
        """Receives incoming data (if any) and processes it.
 | 
			
		||||
           Waits for data no more than timeout seconds."""
 | 
			
		||||
        if select([self._reader],[],[],timeout)[0]:
 | 
			
		||||
            data = self.read()
 | 
			
		||||
            self._parser.Parse(data)
 | 
			
		||||
            return len(data)
 | 
			
		||||
        return '0'	# Zero means that nothing received but link is alive.
 | 
			
		||||
 | 
			
		||||
    def disconnect(self):
 | 
			
		||||
        """Close the stream and socket"""
 | 
			
		||||
        self.write ( "</stream:stream>" )
 | 
			
		||||
        self.write ( u"</stream:stream>" )
 | 
			
		||||
        while self.process(): pass
 | 
			
		||||
        self._sock.close()
 | 
			
		||||
        self._sock = None
 | 
			
		||||
        
 | 
			
		||||
    def disconnected(self): ## To be overidden ##
 | 
			
		||||
    def disconnected(self,conn):
 | 
			
		||||
        """Called when a Network Error or disconnection occurs."""
 | 
			
		||||
        try: self.disconnectHandler(conn)
 | 
			
		||||
        except TypeError: self.disconnectHandler()
 | 
			
		||||
 | 
			
		||||
    def disconnectHandler(self,conn): ## To be overidden ##
 | 
			
		||||
        """Called when a Network Error or disconnection occurs.
 | 
			
		||||
        Designed to be overidden"""
 | 
			
		||||
        self.DEBUG("Network Disconnection")
 | 
			
		||||
        pass
 | 
			
		||||
        raise error("Standart disconnectionHandler called. Replace it with appropriate for your client.")
 | 
			
		||||
 | 
			
		||||
    def log(self, data, inout=''):
 | 
			
		||||
        """Logs data to the specified filehandle. Data is time stamped 
 | 
			
		||||
| 
						 | 
				
			
			@ -501,36 +419,114 @@ class Stream:
 | 
			
		|||
 | 
			
		||||
class Client(Stream):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, host, port, namespace,
 | 
			
		||||
                 debug=[DBG_ALWAYS],
 | 
			
		||||
                 log=None,
 | 
			
		||||
                 sock=None,
 | 
			
		||||
                 id=None,
 | 
			
		||||
                 connection=TCP,
 | 
			
		||||
                 hostIP=None,
 | 
			
		||||
                 proxy=None):
 | 
			
		||||
 | 
			
		||||
        Stream.__init__(self, namespace, debug, log, id)
 | 
			
		||||
 | 
			
		||||
        self._host = host
 | 
			
		||||
        self._port = port 
 | 
			
		||||
        self._sock = sock
 | 
			
		||||
        self._connection = connection
 | 
			
		||||
        if hostIP: self._hostIP = hostIP
 | 
			
		||||
        else: self._hostIP = host
 | 
			
		||||
        self._proxy = proxy
 | 
			
		||||
 | 
			
		||||
        self._sslObj    = None
 | 
			
		||||
        self._sslIssuer = None
 | 
			
		||||
        self._sslServer = None
 | 
			
		||||
 | 
			
		||||
    def getSocket(self):
 | 
			
		||||
        return self._sock
 | 
			
		||||
 | 
			
		||||
    def connect(self):
 | 
			
		||||
        """Attempt to connect to specified host"""
 | 
			
		||||
 | 
			
		||||
        self.DEBUG("client connect called to %s %s type %i" % (self._host,
 | 
			
		||||
                                                               self._port,
 | 
			
		||||
                                                               self._connection) )
 | 
			
		||||
                                                               self._connection), DBG_INIT )
 | 
			
		||||
        Stream.connect(self)
 | 
			
		||||
 | 
			
		||||
        ## TODO: check below that stdin/stdout are actually open
 | 
			
		||||
        if self._connection == STDIO: return
 | 
			
		||||
        if self._connection == STDIO:
 | 
			
		||||
            self._setupComms()
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
			
		||||
        try:
 | 
			
		||||
            self._sock.connect((self._host, self._port))
 | 
			
		||||
            if self._proxy: self._sock.connect((self._proxy['host'], self._proxy['port']))
 | 
			
		||||
            else: self._sock.connect((self._hostIP, self._port))
 | 
			
		||||
        except socket.error, e:
 | 
			
		||||
            self.DEBUG("socket error")
 | 
			
		||||
            raise error(e)
 | 
			
		||||
            self.DEBUG("socket error: "+str(e),DBG_CONN_ERROR)
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
        if self._connection == TCP_SSL:
 | 
			
		||||
            try:
 | 
			
		||||
                self.DEBUG("Attempting to create ssl socket")
 | 
			
		||||
                self.DEBUG("Attempting to create ssl socket",DBG_INIT)
 | 
			
		||||
                self._sslObj    = socket.ssl( self._sock, None, None )
 | 
			
		||||
                self._sslIssuer = self._sslObj.issuer()
 | 
			
		||||
                self._sslServer = self._sslObj.server()
 | 
			
		||||
            except:
 | 
			
		||||
                self.DEBUG("Socket Error: No SSL Support")
 | 
			
		||||
                raise error("No SSL Support")
 | 
			
		||||
                self.DEBUG("Socket Error: No SSL Support",DBG_CONN_ERROR)
 | 
			
		||||
                raise
 | 
			
		||||
 | 
			
		||||
        self.DEBUG("connected")
 | 
			
		||||
        self._setupComms()
 | 
			
		||||
 | 
			
		||||
        if self._proxy:
 | 
			
		||||
            self.DEBUG("Proxy connected",DBG_INIT)
 | 
			
		||||
            if self._proxy.has_key('type'): type = self._proxy['type'].upper()
 | 
			
		||||
            else: type = 'CONNECT'
 | 
			
		||||
            connector = []
 | 
			
		||||
            if type == 'CONNECT':
 | 
			
		||||
                connector.append(u'CONNECT %s:%s HTTP/1.0'%(self._hostIP,self._port))
 | 
			
		||||
            elif type == 'PUT':
 | 
			
		||||
                connector.append(u'PUT http://%s:%s/ HTTP/1.0'%(self._hostIP,self._port))
 | 
			
		||||
            else:
 | 
			
		||||
                self.DEBUG("Proxy Error: unknown proxy type",DBG_CONN_ERROR)
 | 
			
		||||
                raise error('Unknown proxy type: '+type)
 | 
			
		||||
            connector.append('Proxy-Connection: Keep-Alive')
 | 
			
		||||
            connector.append('Pragma: no-cache')
 | 
			
		||||
            connector.append('Host: %s:%s'%(self._hostIP,self._port))
 | 
			
		||||
            connector.append('User-Agent: Jabberpy/'+VERSION)
 | 
			
		||||
            if self._proxy.has_key('user') and self._proxy.has_key('password'):
 | 
			
		||||
                credentials = '%s:%s'%(self._proxy['user'],self._proxy['password'])
 | 
			
		||||
                credentials = encodestring(credentials).strip()
 | 
			
		||||
                connector.append('Proxy-Authorization: Basic '+credentials)
 | 
			
		||||
            connector.append('\r\n')
 | 
			
		||||
            bak = self._read , self._write
 | 
			
		||||
            self.write('\r\n'.join(connector))
 | 
			
		||||
            reply = self.read().replace('\r','')
 | 
			
		||||
            self._read , self._write = bak
 | 
			
		||||
            try: proto,code,desc=reply.split('\n')[0].split(' ',2)
 | 
			
		||||
            except: raise error('Invalid proxy reply')
 | 
			
		||||
            if code<>'200': raise error('Invalid proxy reply: %s %s %s'%(proto,code,desc))
 | 
			
		||||
            while reply.find('\n\n') == -1: reply += self.read().replace('\r','')
 | 
			
		||||
 | 
			
		||||
        self.DEBUG("Jabber server connected",DBG_INIT)
 | 
			
		||||
        self.header()
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def _setupComms(self):
 | 
			
		||||
        if self._connection == TCP:
 | 
			
		||||
            self._read = self._sock.recv
 | 
			
		||||
            self._write = self._sock.sendall
 | 
			
		||||
            self._reader = self._sock
 | 
			
		||||
        elif self._connection == TCP_SSL:
 | 
			
		||||
            self._read = self._sslObj.read
 | 
			
		||||
            self._write = self._sslObj.write
 | 
			
		||||
            self._reader = self._sock
 | 
			
		||||
        elif self._connection == STDIO:
 | 
			
		||||
            self._read = self.stdin.read
 | 
			
		||||
            self._write = self.stdout.write
 | 
			
		||||
            self._reader = sys.stdin
 | 
			
		||||
        else:
 | 
			
		||||
            self.DEBUG('unknown connection type',DBG_CONN_ERROR)
 | 
			
		||||
            raise IOError('unknown connection type')
 | 
			
		||||
 | 
			
		||||
class Server:    
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								core/core.py
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								core/core.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -58,23 +58,25 @@ class GajimCore:
 | 
			
		|||
			else:
 | 
			
		||||
				show = 'online'
 | 
			
		||||
			self.hub.sendPlugin('NOTIFY', \
 | 
			
		||||
			(prs.getFrom().getBasic(), show, prs.getStatus()))
 | 
			
		||||
			(prs.getFrom().getBasic(), show, prs.getStatus(), prs.getFrom().getResource()))
 | 
			
		||||
		elif type == 'unavailable':
 | 
			
		||||
			self.hub.sendPlugin('NOTIFY', \
 | 
			
		||||
				(prs.getFrom().getBasic(), 'offline', prs.getStatus()))
 | 
			
		||||
				(prs.getFrom().getBasic(), 'offline', prs.getStatus(), prs.getFrom().getResource()))
 | 
			
		||||
		elif type == 'subscribe':
 | 
			
		||||
			log.debug("subscribe request from %s" % who)
 | 
			
		||||
			if self.cfgParser.Core_alwaysauth == 1 or string.find(who, "@") <= 0:
 | 
			
		||||
				self.con.send(common.jabber.Presence(who, 'subscribed'))
 | 
			
		||||
				if string.find(who, "@") <= 0:
 | 
			
		||||
					self.hub.sendPlugin('NOTIFY', (who, 'offline', 'offline'))
 | 
			
		||||
					self.hub.sendPlugin('NOTIFY', (who, 'offline', 'offline', prs.getFrom().getResource()))
 | 
			
		||||
			else:
 | 
			
		||||
				self.hub.sendPlugin('SUBSCRIBE', who)
 | 
			
		||||
		elif type == 'subscribed':
 | 
			
		||||
			jid = prs.getFrom()
 | 
			
		||||
			self.hub.sendPlugin('SUBSCRIBED', {'jid':jid.getBasic(), \
 | 
			
		||||
				'nom':jid.getNode()})
 | 
			
		||||
			self.con.updateRosterItem(jid=jid.getBasic(), name=jid.getNode())
 | 
			
		||||
				'nom':jid.getNode(), 'ressource':jid.getResource()})
 | 
			
		||||
			self.hub.queueIn.put(('UPDUSER', (jid.getBasic(), \
 | 
			
		||||
				jid.getNode(), ['general'])))
 | 
			
		||||
#			self.con.updateRosterItem(jid=jid.getBasic(), name=jid.getNode(), groups=['general'])
 | 
			
		||||
			log.debug("we are now subscribed to %s" % who)
 | 
			
		||||
		elif type == 'unsubscribe':
 | 
			
		||||
			log.debug("unsubscribe request from %s" % who)
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +99,10 @@ class GajimCore:
 | 
			
		|||
 | 
			
		||||
	def disconnectedCB(self, con):
 | 
			
		||||
		log.debug("disconnectedCB")
 | 
			
		||||
		self.con.disconnect()
 | 
			
		||||
		if self.connected == 1:
 | 
			
		||||
			self.connected = 0
 | 
			
		||||
			self.con.disconnect()
 | 
			
		||||
#		self.con.disconnect()
 | 
			
		||||
	# END disconenctedCB
 | 
			
		||||
 | 
			
		||||
	def connect(self, account):
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +112,7 @@ class GajimCore:
 | 
			
		|||
		password = self.cfgParser.__getattr__("%s" % account+"_password")
 | 
			
		||||
		ressource = self.cfgParser.__getattr__("%s" % account+"_ressource")
 | 
			
		||||
		self.con = common.jabber.Client(host = \
 | 
			
		||||
			hostname, debug = False, log = sys.stderr)
 | 
			
		||||
			hostname, debug = [common.jabber.DBG_ALWAYS], log = sys.stderr)
 | 
			
		||||
		try:
 | 
			
		||||
			self.con.connect()
 | 
			
		||||
		except IOError, e:
 | 
			
		||||
| 
						 | 
				
			
			@ -118,9 +123,12 @@ class GajimCore:
 | 
			
		|||
		else:
 | 
			
		||||
			log.debug("Connected to server")
 | 
			
		||||
 | 
			
		||||
			self.con.setMessageHandler(self.messageCB)
 | 
			
		||||
			self.con.setPresenceHandler(self.presenceCB)
 | 
			
		||||
			self.con.registerHandler('message', self.messageCB)
 | 
			
		||||
			self.con.registerHandler('presence', self.presenceCB)
 | 
			
		||||
			self.con.setDisconnectHandler(self.disconnectedCB)
 | 
			
		||||
#			self.con.setMessageHandler(self.messageCB)
 | 
			
		||||
#			self.con.setPresenceHandler(self.presenceCB)
 | 
			
		||||
#			self.con.setDisconnectHandler(self.disconnectedCB)
 | 
			
		||||
			#BUG in jabberpy library : if hostname is wrong : "boucle"
 | 
			
		||||
			if self.con.auth(name, password, ressource):
 | 
			
		||||
				self.con.requestRoster()
 | 
			
		||||
| 
						 | 
				
			
			@ -144,20 +152,22 @@ class GajimCore:
 | 
			
		|||
				ev = self.hub.queueIn.get()
 | 
			
		||||
				if ev[0] == 'QUIT':
 | 
			
		||||
					if self.connected == 1:
 | 
			
		||||
						self.connected = 0
 | 
			
		||||
						self.con.disconnect()
 | 
			
		||||
					self.hub.sendPlugin('QUIT', ())
 | 
			
		||||
					return
 | 
			
		||||
				#('STATUS', (status, account))
 | 
			
		||||
				#('STATUS', (status, msg, account))
 | 
			
		||||
				elif ev[0] == 'STATUS':
 | 
			
		||||
					if (ev[1][0] != 'offline') and (self.connected == 0):
 | 
			
		||||
						self.connect(ev[1][1])
 | 
			
		||||
						self.connect(ev[1][2])
 | 
			
		||||
					elif (ev[1][0] == 'offline') and (self.connected == 1):
 | 
			
		||||
						self.connected = 0
 | 
			
		||||
						self.con.disconnect()
 | 
			
		||||
						self.hub.sendPlugin('STATUS', 'offline')
 | 
			
		||||
						self.connected = 0
 | 
			
		||||
					if ev[1][0] != 'offline' and self.connected == 1:
 | 
			
		||||
						p = common.jabber.Presence()
 | 
			
		||||
						p.setShow(ev[1][0])
 | 
			
		||||
						p.setStatus(ev[1][1])
 | 
			
		||||
						self.con.send(p)
 | 
			
		||||
						self.hub.sendPlugin('STATUS', ev[1][0])
 | 
			
		||||
				#('MSG', (jid, msg))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
 | 
			
		||||
 | 
			
		||||
<glade-interface>
 | 
			
		||||
<requires lib="gnome"/>
 | 
			
		||||
 | 
			
		||||
<widget class="GtkWindow" id="Gajim">
 | 
			
		||||
  <property name="visible">True</property>
 | 
			
		||||
| 
						 | 
				
			
			@ -494,15 +493,11 @@
 | 
			
		|||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkLabel" id="label_contact">
 | 
			
		||||
	    <widget class="GtkImage" id="image">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="label" translatable="yes">Anonymous <id@server/res></property>
 | 
			
		||||
	      <property name="use_underline">False</property>
 | 
			
		||||
	      <property name="use_markup">False</property>
 | 
			
		||||
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	      <property name="wrap">False</property>
 | 
			
		||||
	      <property name="selectable">False</property>
 | 
			
		||||
	      <property name="xalign">0.95</property>
 | 
			
		||||
	      <property name="stock">gtk-no</property>
 | 
			
		||||
	      <property name="icon_size">4</property>
 | 
			
		||||
	      <property name="xalign">0.5</property>
 | 
			
		||||
	      <property name="yalign">0.5</property>
 | 
			
		||||
	      <property name="xpad">0</property>
 | 
			
		||||
	      <property name="ypad">0</property>
 | 
			
		||||
| 
						 | 
				
			
			@ -515,11 +510,15 @@
 | 
			
		|||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkImage" id="image">
 | 
			
		||||
	    <widget class="GtkLabel" id="label_contact">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="stock">gtk-no</property>
 | 
			
		||||
	      <property name="icon_size">4</property>
 | 
			
		||||
	      <property name="xalign">0.5</property>
 | 
			
		||||
	      <property name="label" translatable="yes">Anonymous <id@server/res></property>
 | 
			
		||||
	      <property name="use_underline">False</property>
 | 
			
		||||
	      <property name="use_markup">False</property>
 | 
			
		||||
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	      <property name="wrap">False</property>
 | 
			
		||||
	      <property name="selectable">False</property>
 | 
			
		||||
	      <property name="xalign">0.95</property>
 | 
			
		||||
	      <property name="yalign">0.5</property>
 | 
			
		||||
	      <property name="xpad">0</property>
 | 
			
		||||
	      <property name="ypad">0</property>
 | 
			
		||||
| 
						 | 
				
			
			@ -542,6 +541,7 @@
 | 
			
		|||
	<widget class="GtkVPaned" id="vpaned1">
 | 
			
		||||
	  <property name="visible">True</property>
 | 
			
		||||
	  <property name="can_focus">True</property>
 | 
			
		||||
	  <property name="position">170</property>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkScrolledWindow" id="scrolledwindow3">
 | 
			
		||||
| 
						 | 
				
			
			@ -3228,4 +3228,741 @@ when NOT onlie</property>
 | 
			
		|||
  </child>
 | 
			
		||||
</widget>
 | 
			
		||||
 | 
			
		||||
<widget class="GtkDialog" id="Away_msg">
 | 
			
		||||
  <property name="visible">True</property>
 | 
			
		||||
  <property name="title" translatable="yes">dialog1</property>
 | 
			
		||||
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
 | 
			
		||||
  <property name="window_position">GTK_WIN_POS_NONE</property>
 | 
			
		||||
  <property name="modal">False</property>
 | 
			
		||||
  <property name="resizable">True</property>
 | 
			
		||||
  <property name="destroy_with_parent">False</property>
 | 
			
		||||
  <property name="has_separator">True</property>
 | 
			
		||||
 | 
			
		||||
  <child internal-child="vbox">
 | 
			
		||||
    <widget class="GtkVBox" id="dialog-vbox3">
 | 
			
		||||
      <property name="visible">True</property>
 | 
			
		||||
      <property name="homogeneous">False</property>
 | 
			
		||||
      <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
      <child internal-child="action_area">
 | 
			
		||||
	<widget class="GtkHButtonBox" id="dialog-action_area2">
 | 
			
		||||
	  <property name="visible">True</property>
 | 
			
		||||
	  <property name="layout_style">GTK_BUTTONBOX_END</property>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkButton" id="okbutton1">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="can_default">True</property>
 | 
			
		||||
	      <property name="can_focus">True</property>
 | 
			
		||||
	      <property name="label">gtk-ok</property>
 | 
			
		||||
	      <property name="use_stock">True</property>
 | 
			
		||||
	      <property name="relief">GTK_RELIEF_NORMAL</property>
 | 
			
		||||
	      <property name="response_id">-5</property>
 | 
			
		||||
	      <signal name="clicked" handler="on_ok_clicked" last_modification_time="Thu, 08 Jan 2004 12:04:44 GMT"/>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	  </child>
 | 
			
		||||
	</widget>
 | 
			
		||||
	<packing>
 | 
			
		||||
	  <property name="padding">0</property>
 | 
			
		||||
	  <property name="expand">False</property>
 | 
			
		||||
	  <property name="fill">True</property>
 | 
			
		||||
	  <property name="pack_type">GTK_PACK_END</property>
 | 
			
		||||
	</packing>
 | 
			
		||||
      </child>
 | 
			
		||||
 | 
			
		||||
      <child>
 | 
			
		||||
	<widget class="GtkVBox" id="vbox16">
 | 
			
		||||
	  <property name="visible">True</property>
 | 
			
		||||
	  <property name="homogeneous">False</property>
 | 
			
		||||
	  <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkLabel" id="label51">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="label" translatable="yes">Enter your message :</property>
 | 
			
		||||
	      <property name="use_underline">False</property>
 | 
			
		||||
	      <property name="use_markup">False</property>
 | 
			
		||||
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	      <property name="wrap">False</property>
 | 
			
		||||
	      <property name="selectable">False</property>
 | 
			
		||||
	      <property name="xalign">0.02</property>
 | 
			
		||||
	      <property name="yalign">0.5</property>
 | 
			
		||||
	      <property name="xpad">0</property>
 | 
			
		||||
	      <property name="ypad">0</property>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="padding">10</property>
 | 
			
		||||
	      <property name="expand">False</property>
 | 
			
		||||
	      <property name="fill">True</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkScrolledWindow" id="scrolledwindow11">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="can_focus">True</property>
 | 
			
		||||
	      <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 | 
			
		||||
	      <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 | 
			
		||||
	      <property name="shadow_type">GTK_SHADOW_NONE</property>
 | 
			
		||||
	      <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkTextView" id="textview">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="can_focus">True</property>
 | 
			
		||||
		  <property name="editable">True</property>
 | 
			
		||||
		  <property name="justification">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap_mode">GTK_WRAP_NONE</property>
 | 
			
		||||
		  <property name="cursor_visible">True</property>
 | 
			
		||||
		  <property name="pixels_above_lines">0</property>
 | 
			
		||||
		  <property name="pixels_below_lines">0</property>
 | 
			
		||||
		  <property name="pixels_inside_wrap">0</property>
 | 
			
		||||
		  <property name="left_margin">0</property>
 | 
			
		||||
		  <property name="right_margin">0</property>
 | 
			
		||||
		  <property name="indent">0</property>
 | 
			
		||||
		  <property name="text" translatable="yes"></property>
 | 
			
		||||
		</widget>
 | 
			
		||||
	      </child>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="padding">0</property>
 | 
			
		||||
	      <property name="expand">True</property>
 | 
			
		||||
	      <property name="fill">True</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkLabel" id="label52">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="label" translatable="yes">Or choose your message :</property>
 | 
			
		||||
	      <property name="use_underline">False</property>
 | 
			
		||||
	      <property name="use_markup">False</property>
 | 
			
		||||
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	      <property name="wrap">False</property>
 | 
			
		||||
	      <property name="selectable">False</property>
 | 
			
		||||
	      <property name="xalign">0.02</property>
 | 
			
		||||
	      <property name="yalign">0.5</property>
 | 
			
		||||
	      <property name="xpad">0</property>
 | 
			
		||||
	      <property name="ypad">0</property>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="padding">10</property>
 | 
			
		||||
	      <property name="expand">False</property>
 | 
			
		||||
	      <property name="fill">False</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkCombo" id="combo2">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="value_in_list">False</property>
 | 
			
		||||
	      <property name="allow_empty">True</property>
 | 
			
		||||
	      <property name="case_sensitive">False</property>
 | 
			
		||||
	      <property name="enable_arrow_keys">True</property>
 | 
			
		||||
	      <property name="enable_arrows_always">False</property>
 | 
			
		||||
 | 
			
		||||
	      <child internal-child="entry">
 | 
			
		||||
		<widget class="GtkEntry" id="entry1">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="can_focus">True</property>
 | 
			
		||||
		  <property name="editable">True</property>
 | 
			
		||||
		  <property name="visibility">True</property>
 | 
			
		||||
		  <property name="max_length">0</property>
 | 
			
		||||
		  <property name="text" translatable="yes"></property>
 | 
			
		||||
		  <property name="has_frame">True</property>
 | 
			
		||||
		  <property name="invisible_char" translatable="yes">*</property>
 | 
			
		||||
		  <property name="activates_default">False</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child internal-child="list">
 | 
			
		||||
		<widget class="GtkList" id="list1">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="selection_mode">GTK_SELECTION_BROWSE</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
	      </child>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="padding">0</property>
 | 
			
		||||
	      <property name="expand">False</property>
 | 
			
		||||
	      <property name="fill">False</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
	</widget>
 | 
			
		||||
	<packing>
 | 
			
		||||
	  <property name="padding">0</property>
 | 
			
		||||
	  <property name="expand">True</property>
 | 
			
		||||
	  <property name="fill">True</property>
 | 
			
		||||
	</packing>
 | 
			
		||||
      </child>
 | 
			
		||||
    </widget>
 | 
			
		||||
  </child>
 | 
			
		||||
</widget>
 | 
			
		||||
 | 
			
		||||
<widget class="GtkWindow" id="Info_user">
 | 
			
		||||
  <property name="visible">True</property>
 | 
			
		||||
  <property name="title" translatable="yes">Information</property>
 | 
			
		||||
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
 | 
			
		||||
  <property name="window_position">GTK_WIN_POS_NONE</property>
 | 
			
		||||
  <property name="modal">False</property>
 | 
			
		||||
  <property name="resizable">True</property>
 | 
			
		||||
  <property name="destroy_with_parent">False</property>
 | 
			
		||||
 | 
			
		||||
  <child>
 | 
			
		||||
    <widget class="GtkVBox" id="vbox17">
 | 
			
		||||
      <property name="visible">True</property>
 | 
			
		||||
      <property name="homogeneous">False</property>
 | 
			
		||||
      <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
      <child>
 | 
			
		||||
	<widget class="GtkLabel" id="label_name">
 | 
			
		||||
	  <property name="visible">True</property>
 | 
			
		||||
	  <property name="label" translatable="yes">name</property>
 | 
			
		||||
	  <property name="use_underline">False</property>
 | 
			
		||||
	  <property name="use_markup">False</property>
 | 
			
		||||
	  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	  <property name="wrap">False</property>
 | 
			
		||||
	  <property name="selectable">False</property>
 | 
			
		||||
	  <property name="xalign">0.01</property>
 | 
			
		||||
	  <property name="yalign">0.5</property>
 | 
			
		||||
	  <property name="xpad">0</property>
 | 
			
		||||
	  <property name="ypad">0</property>
 | 
			
		||||
	</widget>
 | 
			
		||||
	<packing>
 | 
			
		||||
	  <property name="padding">5</property>
 | 
			
		||||
	  <property name="expand">False</property>
 | 
			
		||||
	  <property name="fill">False</property>
 | 
			
		||||
	</packing>
 | 
			
		||||
      </child>
 | 
			
		||||
 | 
			
		||||
      <child>
 | 
			
		||||
	<widget class="GtkNotebook" id="notebook3">
 | 
			
		||||
	  <property name="visible">True</property>
 | 
			
		||||
	  <property name="can_focus">True</property>
 | 
			
		||||
	  <property name="show_tabs">True</property>
 | 
			
		||||
	  <property name="show_border">True</property>
 | 
			
		||||
	  <property name="tab_pos">GTK_POS_TOP</property>
 | 
			
		||||
	  <property name="scrollable">False</property>
 | 
			
		||||
	  <property name="enable_popup">False</property>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkTable" id="table4">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="n_rows">4</property>
 | 
			
		||||
	      <property name="n_columns">2</property>
 | 
			
		||||
	      <property name="homogeneous">False</property>
 | 
			
		||||
	      <property name="row_spacing">0</property>
 | 
			
		||||
	      <property name="column_spacing">0</property>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label56">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">ID</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">5</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">0</property>
 | 
			
		||||
		  <property name="right_attach">1</property>
 | 
			
		||||
		  <property name="top_attach">0</property>
 | 
			
		||||
		  <property name="bottom_attach">1</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label_id">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">id</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">5</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">1</property>
 | 
			
		||||
		  <property name="right_attach">2</property>
 | 
			
		||||
		  <property name="top_attach">0</property>
 | 
			
		||||
		  <property name="bottom_attach">1</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label_status">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">status</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">5</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">1</property>
 | 
			
		||||
		  <property name="right_attach">2</property>
 | 
			
		||||
		  <property name="top_attach">3</property>
 | 
			
		||||
		  <property name="bottom_attach">4</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label59">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">Status</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">5</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">0</property>
 | 
			
		||||
		  <property name="right_attach">1</property>
 | 
			
		||||
		  <property name="top_attach">3</property>
 | 
			
		||||
		  <property name="bottom_attach">4</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label58">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">Name</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">6</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">0</property>
 | 
			
		||||
		  <property name="right_attach">1</property>
 | 
			
		||||
		  <property name="top_attach">2</property>
 | 
			
		||||
		  <property name="bottom_attach">3</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkEntry" id="entry_name">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="can_focus">True</property>
 | 
			
		||||
		  <property name="editable">True</property>
 | 
			
		||||
		  <property name="visibility">True</property>
 | 
			
		||||
		  <property name="max_length">0</property>
 | 
			
		||||
		  <property name="text" translatable="yes"></property>
 | 
			
		||||
		  <property name="has_frame">True</property>
 | 
			
		||||
		  <property name="invisible_char" translatable="yes">*</property>
 | 
			
		||||
		  <property name="activates_default">False</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">1</property>
 | 
			
		||||
		  <property name="right_attach">2</property>
 | 
			
		||||
		  <property name="top_attach">2</property>
 | 
			
		||||
		  <property name="bottom_attach">3</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label62">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">Resource :</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">5</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">0</property>
 | 
			
		||||
		  <property name="right_attach">1</property>
 | 
			
		||||
		  <property name="top_attach">1</property>
 | 
			
		||||
		  <property name="bottom_attach">2</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkLabel" id="label_resource">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label" translatable="yes">resource</property>
 | 
			
		||||
		  <property name="use_underline">False</property>
 | 
			
		||||
		  <property name="use_markup">False</property>
 | 
			
		||||
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		  <property name="wrap">False</property>
 | 
			
		||||
		  <property name="selectable">False</property>
 | 
			
		||||
		  <property name="xalign">0</property>
 | 
			
		||||
		  <property name="yalign">0.5</property>
 | 
			
		||||
		  <property name="xpad">5</property>
 | 
			
		||||
		  <property name="ypad">5</property>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="left_attach">1</property>
 | 
			
		||||
		  <property name="right_attach">2</property>
 | 
			
		||||
		  <property name="top_attach">1</property>
 | 
			
		||||
		  <property name="bottom_attach">2</property>
 | 
			
		||||
		  <property name="x_options">fill</property>
 | 
			
		||||
		  <property name="y_options"></property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="tab_expand">False</property>
 | 
			
		||||
	      <property name="tab_fill">True</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkLabel" id="label54">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="label" translatable="yes">General</property>
 | 
			
		||||
	      <property name="use_underline">False</property>
 | 
			
		||||
	      <property name="use_markup">False</property>
 | 
			
		||||
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	      <property name="wrap">False</property>
 | 
			
		||||
	      <property name="selectable">False</property>
 | 
			
		||||
	      <property name="xalign">0.5</property>
 | 
			
		||||
	      <property name="yalign">0.5</property>
 | 
			
		||||
	      <property name="xpad">0</property>
 | 
			
		||||
	      <property name="ypad">0</property>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="type">tab</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkHBox" id="hbox25">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="homogeneous">False</property>
 | 
			
		||||
	      <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkFrame" id="frame5">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label_xalign">0</property>
 | 
			
		||||
		  <property name="label_yalign">0.5</property>
 | 
			
		||||
		  <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
 | 
			
		||||
 | 
			
		||||
		  <child>
 | 
			
		||||
		    <widget class="GtkVBox" id="vbox18">
 | 
			
		||||
		      <property name="border_width">5</property>
 | 
			
		||||
		      <property name="visible">True</property>
 | 
			
		||||
		      <property name="homogeneous">False</property>
 | 
			
		||||
		      <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
		      <child>
 | 
			
		||||
			<widget class="GtkHBox" id="hbox26">
 | 
			
		||||
			  <property name="visible">True</property>
 | 
			
		||||
			  <property name="homogeneous">False</property>
 | 
			
		||||
			  <property name="spacing">4</property>
 | 
			
		||||
 | 
			
		||||
			  <child>
 | 
			
		||||
			    <widget class="GtkLabel" id="label65">
 | 
			
		||||
			      <property name="visible">True</property>
 | 
			
		||||
			      <property name="label" translatable="yes">New Group :</property>
 | 
			
		||||
			      <property name="use_underline">False</property>
 | 
			
		||||
			      <property name="use_markup">False</property>
 | 
			
		||||
			      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
			      <property name="wrap">False</property>
 | 
			
		||||
			      <property name="selectable">False</property>
 | 
			
		||||
			      <property name="xalign">0.5</property>
 | 
			
		||||
			      <property name="yalign">0.5</property>
 | 
			
		||||
			      <property name="xpad">0</property>
 | 
			
		||||
			      <property name="ypad">0</property>
 | 
			
		||||
			    </widget>
 | 
			
		||||
			    <packing>
 | 
			
		||||
			      <property name="padding">0</property>
 | 
			
		||||
			      <property name="expand">False</property>
 | 
			
		||||
			      <property name="fill">False</property>
 | 
			
		||||
			    </packing>
 | 
			
		||||
			  </child>
 | 
			
		||||
 | 
			
		||||
			  <child>
 | 
			
		||||
			    <widget class="GtkEntry" id="entry_new">
 | 
			
		||||
			      <property name="visible">True</property>
 | 
			
		||||
			      <property name="can_focus">True</property>
 | 
			
		||||
			      <property name="editable">True</property>
 | 
			
		||||
			      <property name="visibility">True</property>
 | 
			
		||||
			      <property name="max_length">0</property>
 | 
			
		||||
			      <property name="text" translatable="yes"></property>
 | 
			
		||||
			      <property name="has_frame">True</property>
 | 
			
		||||
			      <property name="invisible_char" translatable="yes">*</property>
 | 
			
		||||
			      <property name="activates_default">False</property>
 | 
			
		||||
			      <property name="width_chars">5</property>
 | 
			
		||||
			      <signal name="key_press_event" handler="on_entry_new_key_press_event" last_modification_time="Sun, 11 Jan 2004 23:35:08 GMT"/>
 | 
			
		||||
			    </widget>
 | 
			
		||||
			    <packing>
 | 
			
		||||
			      <property name="padding">0</property>
 | 
			
		||||
			      <property name="expand">True</property>
 | 
			
		||||
			      <property name="fill">True</property>
 | 
			
		||||
			    </packing>
 | 
			
		||||
			  </child>
 | 
			
		||||
			</widget>
 | 
			
		||||
			<packing>
 | 
			
		||||
			  <property name="padding">5</property>
 | 
			
		||||
			  <property name="expand">False</property>
 | 
			
		||||
			  <property name="fill">True</property>
 | 
			
		||||
			</packing>
 | 
			
		||||
		      </child>
 | 
			
		||||
 | 
			
		||||
		      <child>
 | 
			
		||||
			<widget class="GtkScrolledWindow" id="scrolledwindow14">
 | 
			
		||||
			  <property name="visible">True</property>
 | 
			
		||||
			  <property name="can_focus">True</property>
 | 
			
		||||
			  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 | 
			
		||||
			  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 | 
			
		||||
			  <property name="shadow_type">GTK_SHADOW_NONE</property>
 | 
			
		||||
			  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
 | 
			
		||||
 | 
			
		||||
			  <child>
 | 
			
		||||
			    <widget class="GtkTreeView" id="treeview_available">
 | 
			
		||||
			      <property name="visible">True</property>
 | 
			
		||||
			      <property name="can_focus">True</property>
 | 
			
		||||
			      <property name="headers_visible">False</property>
 | 
			
		||||
			      <property name="rules_hint">False</property>
 | 
			
		||||
			      <property name="reorderable">False</property>
 | 
			
		||||
			      <property name="enable_search">False</property>
 | 
			
		||||
			    </widget>
 | 
			
		||||
			  </child>
 | 
			
		||||
			</widget>
 | 
			
		||||
			<packing>
 | 
			
		||||
			  <property name="padding">0</property>
 | 
			
		||||
			  <property name="expand">True</property>
 | 
			
		||||
			  <property name="fill">True</property>
 | 
			
		||||
			</packing>
 | 
			
		||||
		      </child>
 | 
			
		||||
		    </widget>
 | 
			
		||||
		  </child>
 | 
			
		||||
 | 
			
		||||
		  <child>
 | 
			
		||||
		    <widget class="GtkLabel" id="label63">
 | 
			
		||||
		      <property name="visible">True</property>
 | 
			
		||||
		      <property name="label" translatable="yes">Available groups</property>
 | 
			
		||||
		      <property name="use_underline">False</property>
 | 
			
		||||
		      <property name="use_markup">False</property>
 | 
			
		||||
		      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		      <property name="wrap">False</property>
 | 
			
		||||
		      <property name="selectable">False</property>
 | 
			
		||||
		      <property name="xalign">0.5</property>
 | 
			
		||||
		      <property name="yalign">0.5</property>
 | 
			
		||||
		      <property name="xpad">0</property>
 | 
			
		||||
		      <property name="ypad">0</property>
 | 
			
		||||
		    </widget>
 | 
			
		||||
		    <packing>
 | 
			
		||||
		      <property name="type">label_item</property>
 | 
			
		||||
		    </packing>
 | 
			
		||||
		  </child>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="padding">3</property>
 | 
			
		||||
		  <property name="expand">True</property>
 | 
			
		||||
		  <property name="fill">True</property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkVButtonBox" id="vbuttonbox1">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
 | 
			
		||||
		  <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
		  <child>
 | 
			
		||||
		    <widget class="GtkButton" id="button_add">
 | 
			
		||||
		      <property name="visible">True</property>
 | 
			
		||||
		      <property name="can_default">True</property>
 | 
			
		||||
		      <property name="can_focus">True</property>
 | 
			
		||||
		      <property name="label" translatable="yes">Add -></property>
 | 
			
		||||
		      <property name="use_underline">True</property>
 | 
			
		||||
		      <property name="relief">GTK_RELIEF_NORMAL</property>
 | 
			
		||||
		      <signal name="clicked" handler="on_add_clicked" last_modification_time="Sun, 11 Jan 2004 21:32:59 GMT"/>
 | 
			
		||||
		    </widget>
 | 
			
		||||
		  </child>
 | 
			
		||||
 | 
			
		||||
		  <child>
 | 
			
		||||
		    <widget class="GtkButton" id="button_remove">
 | 
			
		||||
		      <property name="visible">True</property>
 | 
			
		||||
		      <property name="can_default">True</property>
 | 
			
		||||
		      <property name="can_focus">True</property>
 | 
			
		||||
		      <property name="label" translatable="yes"><- Remove</property>
 | 
			
		||||
		      <property name="use_underline">True</property>
 | 
			
		||||
		      <property name="relief">GTK_RELIEF_NORMAL</property>
 | 
			
		||||
		      <signal name="clicked" handler="on_remove_clicked" last_modification_time="Sun, 11 Jan 2004 21:33:15 GMT"/>
 | 
			
		||||
		    </widget>
 | 
			
		||||
		  </child>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="padding">0</property>
 | 
			
		||||
		  <property name="expand">True</property>
 | 
			
		||||
		  <property name="fill">True</property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
 | 
			
		||||
	      <child>
 | 
			
		||||
		<widget class="GtkFrame" id="frame6">
 | 
			
		||||
		  <property name="visible">True</property>
 | 
			
		||||
		  <property name="label_xalign">0</property>
 | 
			
		||||
		  <property name="label_yalign">0.5</property>
 | 
			
		||||
		  <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
 | 
			
		||||
 | 
			
		||||
		  <child>
 | 
			
		||||
		    <widget class="GtkScrolledWindow" id="scrolledwindow13">
 | 
			
		||||
		      <property name="visible">True</property>
 | 
			
		||||
		      <property name="can_focus">True</property>
 | 
			
		||||
		      <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 | 
			
		||||
		      <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 | 
			
		||||
		      <property name="shadow_type">GTK_SHADOW_NONE</property>
 | 
			
		||||
		      <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
 | 
			
		||||
 | 
			
		||||
		      <child>
 | 
			
		||||
			<widget class="GtkTreeView" id="treeview_current">
 | 
			
		||||
			  <property name="visible">True</property>
 | 
			
		||||
			  <property name="can_focus">True</property>
 | 
			
		||||
			  <property name="headers_visible">False</property>
 | 
			
		||||
			  <property name="rules_hint">False</property>
 | 
			
		||||
			  <property name="reorderable">False</property>
 | 
			
		||||
			  <property name="enable_search">False</property>
 | 
			
		||||
			</widget>
 | 
			
		||||
		      </child>
 | 
			
		||||
		    </widget>
 | 
			
		||||
		  </child>
 | 
			
		||||
 | 
			
		||||
		  <child>
 | 
			
		||||
		    <widget class="GtkLabel" id="label64">
 | 
			
		||||
		      <property name="visible">True</property>
 | 
			
		||||
		      <property name="label" translatable="yes">Current groups</property>
 | 
			
		||||
		      <property name="use_underline">False</property>
 | 
			
		||||
		      <property name="use_markup">False</property>
 | 
			
		||||
		      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
		      <property name="wrap">False</property>
 | 
			
		||||
		      <property name="selectable">False</property>
 | 
			
		||||
		      <property name="xalign">0.5</property>
 | 
			
		||||
		      <property name="yalign">0.5</property>
 | 
			
		||||
		      <property name="xpad">0</property>
 | 
			
		||||
		      <property name="ypad">0</property>
 | 
			
		||||
		    </widget>
 | 
			
		||||
		    <packing>
 | 
			
		||||
		      <property name="type">label_item</property>
 | 
			
		||||
		    </packing>
 | 
			
		||||
		  </child>
 | 
			
		||||
		</widget>
 | 
			
		||||
		<packing>
 | 
			
		||||
		  <property name="padding">3</property>
 | 
			
		||||
		  <property name="expand">True</property>
 | 
			
		||||
		  <property name="fill">True</property>
 | 
			
		||||
		</packing>
 | 
			
		||||
	      </child>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="tab_expand">False</property>
 | 
			
		||||
	      <property name="tab_fill">True</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkLabel" id="label55">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="label" translatable="yes">Groups</property>
 | 
			
		||||
	      <property name="use_underline">False</property>
 | 
			
		||||
	      <property name="use_markup">False</property>
 | 
			
		||||
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
 | 
			
		||||
	      <property name="wrap">False</property>
 | 
			
		||||
	      <property name="selectable">False</property>
 | 
			
		||||
	      <property name="xalign">0.5</property>
 | 
			
		||||
	      <property name="yalign">0.5</property>
 | 
			
		||||
	      <property name="xpad">0</property>
 | 
			
		||||
	      <property name="ypad">0</property>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	    <packing>
 | 
			
		||||
	      <property name="type">tab</property>
 | 
			
		||||
	    </packing>
 | 
			
		||||
	  </child>
 | 
			
		||||
	</widget>
 | 
			
		||||
	<packing>
 | 
			
		||||
	  <property name="padding">0</property>
 | 
			
		||||
	  <property name="expand">True</property>
 | 
			
		||||
	  <property name="fill">True</property>
 | 
			
		||||
	</packing>
 | 
			
		||||
      </child>
 | 
			
		||||
 | 
			
		||||
      <child>
 | 
			
		||||
	<widget class="GtkHButtonBox" id="hbuttonbox9">
 | 
			
		||||
	  <property name="border_width">6</property>
 | 
			
		||||
	  <property name="visible">True</property>
 | 
			
		||||
	  <property name="layout_style">GTK_BUTTONBOX_END</property>
 | 
			
		||||
	  <property name="spacing">0</property>
 | 
			
		||||
 | 
			
		||||
	  <child>
 | 
			
		||||
	    <widget class="GtkButton" id="button13">
 | 
			
		||||
	      <property name="visible">True</property>
 | 
			
		||||
	      <property name="can_default">True</property>
 | 
			
		||||
	      <property name="can_focus">True</property>
 | 
			
		||||
	      <property name="label">gtk-close</property>
 | 
			
		||||
	      <property name="use_stock">True</property>
 | 
			
		||||
	      <property name="relief">GTK_RELIEF_NORMAL</property>
 | 
			
		||||
	      <signal name="clicked" handler="on_close_clicked" last_modification_time="Sat, 10 Jan 2004 02:34:46 GMT"/>
 | 
			
		||||
	    </widget>
 | 
			
		||||
	  </child>
 | 
			
		||||
	</widget>
 | 
			
		||||
	<packing>
 | 
			
		||||
	  <property name="padding">0</property>
 | 
			
		||||
	  <property name="expand">False</property>
 | 
			
		||||
	  <property name="fill">True</property>
 | 
			
		||||
	</packing>
 | 
			
		||||
      </child>
 | 
			
		||||
    </widget>
 | 
			
		||||
  </child>
 | 
			
		||||
</widget>
 | 
			
		||||
 | 
			
		||||
<widget class="GtkWindow" id="window1">
 | 
			
		||||
  <property name="visible">True</property>
 | 
			
		||||
  <property name="title" translatable="yes">window1</property>
 | 
			
		||||
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
 | 
			
		||||
  <property name="window_position">GTK_WIN_POS_NONE</property>
 | 
			
		||||
  <property name="modal">False</property>
 | 
			
		||||
  <property name="resizable">True</property>
 | 
			
		||||
  <property name="destroy_with_parent">False</property>
 | 
			
		||||
 | 
			
		||||
  <child>
 | 
			
		||||
    <placeholder/>
 | 
			
		||||
  </child>
 | 
			
		||||
</widget>
 | 
			
		||||
 | 
			
		||||
</glade-interface>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,13 +38,15 @@ class user:
 | 
			
		|||
			self.show = ''
 | 
			
		||||
			self.status = ''
 | 
			
		||||
			self.sub == ''
 | 
			
		||||
		elif len(args) == 6:
 | 
			
		||||
			self.resource == ''
 | 
			
		||||
		elif len(args) == 7:
 | 
			
		||||
			self.jid = args[0]
 | 
			
		||||
			self.name = args[1]
 | 
			
		||||
			self.groups = args[2]
 | 
			
		||||
			self.show = args[3]
 | 
			
		||||
			self.status = args[4]
 | 
			
		||||
			self.sub = args[5]
 | 
			
		||||
			self.resource = args[6]
 | 
			
		||||
#		elif ((len(args)) and (type (args[0]) == type (self)) and
 | 
			
		||||
#			(self.__class__ == args[0].__class__)):
 | 
			
		||||
#			self.name = args[0].name
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +56,87 @@ class user:
 | 
			
		|||
#			self.sub = args[0].sub
 | 
			
		||||
		else: raise TypeError, 'bad arguments'
 | 
			
		||||
 | 
			
		||||
class info_user:
 | 
			
		||||
	def delete_event(self, widget):
 | 
			
		||||
		self.window.destroy()
 | 
			
		||||
 | 
			
		||||
	def add_grp_to_user(self, model, path, iter):
 | 
			
		||||
		self.user.groups.append(model.get_value(iter, 0))
 | 
			
		||||
 | 
			
		||||
	def on_close(self, widget):
 | 
			
		||||
		for i in self.r.l_contact[self.user.jid]['iter']:
 | 
			
		||||
			self.r.treestore.remove(i)
 | 
			
		||||
		self.r.l_contact[self.user.jid]['iter'] = []
 | 
			
		||||
		self.user.groups = []
 | 
			
		||||
		self.store2.foreach(self.add_grp_to_user)
 | 
			
		||||
		self.r.add_user(self.user)
 | 
			
		||||
		self.r.queueOUT.put(('UPDUSER', (self.user.jid, self.user.name, \
 | 
			
		||||
			self.user.groups)))
 | 
			
		||||
		self.delete_event(self)
 | 
			
		||||
 | 
			
		||||
	def add_grp(self, model, path, iter, stors):
 | 
			
		||||
		i = stors[1].append()
 | 
			
		||||
		stors[1].set(i, 0, stors[0].get_value(iter, 0))
 | 
			
		||||
		stors[0].remove(iter)
 | 
			
		||||
 | 
			
		||||
	def on_add(self, widget):
 | 
			
		||||
		select = self.list1.get_selection()
 | 
			
		||||
		select.selected_foreach(self.add_grp, (self.store1, self.store2))
 | 
			
		||||
 | 
			
		||||
	def on_remove(self, widget):
 | 
			
		||||
		select = self.list2.get_selection()
 | 
			
		||||
		select.selected_foreach(self.add_grp, (self.store2, self.store1))
 | 
			
		||||
 | 
			
		||||
	def on_new_key_pressed(self, widget, event):
 | 
			
		||||
		if event.keyval == gtk.keysyms.Return:
 | 
			
		||||
			txt = self.entry_new.get_text()
 | 
			
		||||
			iter = self.store1.append()
 | 
			
		||||
			self.store1.set(iter, 0, txt)
 | 
			
		||||
			self.entry_new.set_text('')
 | 
			
		||||
 | 
			
		||||
	def init_lists(self):
 | 
			
		||||
		#list available
 | 
			
		||||
		self.store1 = gtk.ListStore(gobject.TYPE_STRING)
 | 
			
		||||
		for i in self.r.l_group.keys():
 | 
			
		||||
			if i != 'Agents' and i not in self.user.groups:
 | 
			
		||||
				iter = self.store1.append()
 | 
			
		||||
				self.store1.set(iter, 0, i)
 | 
			
		||||
		self.list1.set_model(self.store1)
 | 
			
		||||
		column = gtk.TreeViewColumn('Available', gtk.CellRendererText(), text=0)
 | 
			
		||||
		self.list1.append_column(column)
 | 
			
		||||
 | 
			
		||||
		#list_current
 | 
			
		||||
		self.store2 = gtk.ListStore(gobject.TYPE_STRING)
 | 
			
		||||
		for i in self.user.groups:
 | 
			
		||||
			iter = self.store2.append()
 | 
			
		||||
			self.store2.set(iter, 0, i)
 | 
			
		||||
		self.list2.set_model(self.store2)
 | 
			
		||||
		column = gtk.TreeViewColumn('Available', gtk.CellRendererText(), text=0)
 | 
			
		||||
		self.list2.append_column(column)
 | 
			
		||||
 | 
			
		||||
	def __init__(self, user, roster):
 | 
			
		||||
		self.xml = gtk.glade.XML('plugins/gtkgui/gtkgui.glade', 'Info_user')
 | 
			
		||||
		self.window = self.xml.get_widget("Info_user")
 | 
			
		||||
		self.r = roster
 | 
			
		||||
		self.user = user
 | 
			
		||||
		self.list1 = self.xml.get_widget("treeview_available")
 | 
			
		||||
		self.list2 = self.xml.get_widget("treeview_current")
 | 
			
		||||
		self.entry_new = self.xml.get_widget("entry_new")
 | 
			
		||||
 | 
			
		||||
		self.xml.get_widget('label_name').set_text(user.name)
 | 
			
		||||
		self.xml.get_widget('label_id').set_text(user.jid)
 | 
			
		||||
		self.xml.get_widget('label_resource').set_text(user.resource)
 | 
			
		||||
		self.xml.get_widget('entry_name').set_text(user.name)
 | 
			
		||||
		self.xml.get_widget('label_status').set_text(user.show + ' : ' + user.status)
 | 
			
		||||
		self.init_lists()
 | 
			
		||||
		
 | 
			
		||||
		self.xml.signal_connect('gtk_widget_destroy', self.delete_event)
 | 
			
		||||
		self.xml.signal_connect('on_close_clicked', self.on_close)
 | 
			
		||||
		self.xml.signal_connect('on_add_clicked', self.on_add)
 | 
			
		||||
		self.xml.signal_connect('on_remove_clicked', self.on_remove)
 | 
			
		||||
		self.xml.signal_connect('on_entry_new_key_press_event', self.on_new_key_pressed)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
class prefs:
 | 
			
		||||
	def delete_event(self, widget):
 | 
			
		||||
		self.window.destroy()
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +323,29 @@ class prefs:
 | 
			
		|||
		self.xml.signal_connect('on_but_col_clicked', self.on_color_button_clicked)
 | 
			
		||||
		self.xml.signal_connect('on_ok_clicked', self.on_ok)
 | 
			
		||||
 | 
			
		||||
class away_msg:
 | 
			
		||||
	def delete_event(self, widget):
 | 
			
		||||
		self.window.destroy()
 | 
			
		||||
 | 
			
		||||
	def on_ok(self):
 | 
			
		||||
		beg, end = self.txtBuffer.get_bounds()
 | 
			
		||||
		self.msg = self.txtBuffer.get_text(beg, end, 0)
 | 
			
		||||
		self.window.destroy()
 | 
			
		||||
	
 | 
			
		||||
	def run(self):
 | 
			
		||||
		rep = self.window.run()
 | 
			
		||||
		if rep == gtk.RESPONSE_OK:
 | 
			
		||||
			self.on_ok()
 | 
			
		||||
		return self.msg
 | 
			
		||||
	
 | 
			
		||||
	def __init__(self):
 | 
			
		||||
		self.xml = gtk.glade.XML('plugins/gtkgui/gtkgui.glade', 'Away_msg')
 | 
			
		||||
		self.window = self.xml.get_widget("Away_msg")
 | 
			
		||||
		self.txt = self.xml.get_widget("textview")
 | 
			
		||||
		self.msg = ""
 | 
			
		||||
		self.txtBuffer = self.txt.get_buffer()
 | 
			
		||||
		self.xml.signal_connect('gtk_widget_destroy', self.delete_event)
 | 
			
		||||
 | 
			
		||||
class add:
 | 
			
		||||
	def delete_event(self, widget):
 | 
			
		||||
		self.Wadd.destroy()
 | 
			
		||||
| 
						 | 
				
			
			@ -339,6 +445,7 @@ class account_pref:
 | 
			
		|||
		self.cfgParser.writeCfgFile()
 | 
			
		||||
		self.cfgParser.parseCfgFile()
 | 
			
		||||
		self.accs.init_accounts()
 | 
			
		||||
		self.delete_event(self)
 | 
			
		||||
	
 | 
			
		||||
	#info must be a dictionnary
 | 
			
		||||
	def __init__(self, accs, infos = {}):
 | 
			
		||||
| 
						 | 
				
			
			@ -699,7 +806,7 @@ class roster:
 | 
			
		|||
			show = tab[jid]['show']
 | 
			
		||||
			if not show:
 | 
			
		||||
				show = 'offline'
 | 
			
		||||
			user1 = user(ji, name, tab[jid]['groups'], show, tab[jid]['status'], tab[jid]['sub'])
 | 
			
		||||
			user1 = user(ji, name, tab[jid]['groups'], show, tab[jid]['status'], tab[jid]['sub'], '')
 | 
			
		||||
			self.l_contact[ji] = {'user':user1, 'iter':[]}
 | 
			
		||||
 | 
			
		||||
	def update_iter(self, widget, path, iter, data):
 | 
			
		||||
| 
						 | 
				
			
			@ -733,6 +840,9 @@ class roster:
 | 
			
		|||
				self.tab_messages[jid].img.set_from_pixbuf(self.pixbufs[show])
 | 
			
		||||
		u.show = show
 | 
			
		||||
		u.status = status
 | 
			
		||||
 | 
			
		||||
	def on_info(self, widget, jid):
 | 
			
		||||
		info_user(self.l_contact[jid]['user'], self)
 | 
			
		||||
	
 | 
			
		||||
	def mk_menu_c(self, event, iter):
 | 
			
		||||
		jid = self.treestore.get_value(iter, 2)
 | 
			
		||||
| 
						 | 
				
			
			@ -763,6 +873,13 @@ class roster:
 | 
			
		|||
		item = gtk.MenuItem("Remove")
 | 
			
		||||
		self.menu_c.append(item)
 | 
			
		||||
		item.connect("activate", self.on_req_usub, iter)
 | 
			
		||||
 | 
			
		||||
		item = gtk.MenuItem()
 | 
			
		||||
		self.menu_c.append(item)
 | 
			
		||||
		item = gtk.MenuItem("Informations")
 | 
			
		||||
		self.menu_c.append(item)
 | 
			
		||||
		item.connect("activate", self.on_info, jid)
 | 
			
		||||
 | 
			
		||||
		self.menu_c.popup(None, None, None, event.button, event.time)
 | 
			
		||||
		self.menu_c.show_all()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -789,7 +906,7 @@ class roster:
 | 
			
		|||
	def req_sub(self, widget, jid, txt):
 | 
			
		||||
		self.queueOUT.put(('SUB', (jid, txt)))
 | 
			
		||||
		if not self.l_contact.has_key(jid):
 | 
			
		||||
			user1 = user(jid, jid, ['general'], 'requested', 'requested', 'sub')
 | 
			
		||||
			user1 = user(jid, jid, ['general'], 'requested', 'requested', 'sub', '')
 | 
			
		||||
			self.add_user(user1)
 | 
			
		||||
	
 | 
			
		||||
	def init_tree(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -823,9 +940,12 @@ class roster:
 | 
			
		|||
	def on_status_changed(self, widget):
 | 
			
		||||
		accountsStr = self.cfgParser.Profile_accounts
 | 
			
		||||
		accounts = string.split(accountsStr, ' ')
 | 
			
		||||
		self.queueOUT.put(('STATUS',(widget.name, accounts[0])))
 | 
			
		||||
#		if (not self.showOffline) and widget.name == 'offline':
 | 
			
		||||
#			self.treestore.clear()
 | 
			
		||||
		if widget.name != 'online' and widget.name != 'offline':
 | 
			
		||||
			w = away_msg()
 | 
			
		||||
			txt = w.run()
 | 
			
		||||
		else:
 | 
			
		||||
			txt = ""
 | 
			
		||||
		self.queueOUT.put(('STATUS',(widget.name, txt, accounts[0])))
 | 
			
		||||
 | 
			
		||||
	def on_prefs(self, widget):
 | 
			
		||||
		window = prefs(self)
 | 
			
		||||
| 
						 | 
				
			
			@ -1025,6 +1145,9 @@ class plugin:
 | 
			
		|||
 | 
			
		||||
			elif ev[0] == 'NOTIFY':
 | 
			
		||||
				jid = string.split(ev[1][0], '/')[0]
 | 
			
		||||
				res = ev[1][3]
 | 
			
		||||
				if not res:
 | 
			
		||||
					res = ''
 | 
			
		||||
				if string.find(jid, "@") <= 0:
 | 
			
		||||
					#It must be an agent
 | 
			
		||||
					ji = string.replace(jid, '@', '')
 | 
			
		||||
| 
						 | 
				
			
			@ -1035,6 +1158,7 @@ class plugin:
 | 
			
		|||
					u = self.r.l_contact[ji]['user']
 | 
			
		||||
					u.show = ev[1][1]
 | 
			
		||||
					u.status = ev[1][2]
 | 
			
		||||
					u.resource = res
 | 
			
		||||
					#Print status in chat window
 | 
			
		||||
					if self.r.tab_messages.has_key(ji):
 | 
			
		||||
						self.r.tab_messages[ji].print_conversation(\
 | 
			
		||||
| 
						 | 
				
			
			@ -1042,7 +1166,7 @@ class plugin:
 | 
			
		|||
				if string.find(jid, "@") <= 0:
 | 
			
		||||
					#It must be an agent
 | 
			
		||||
					if not self.r.l_contact.has_key(ji):
 | 
			
		||||
						user1 = user(ji, ji, ['Agents'], ev[1][1], ev[1][2], 'from')
 | 
			
		||||
						user1 = user(ji, ji, ['Agents'], ev[1][1], ev[1][2], 'from', res)
 | 
			
		||||
						self.r.add_user(user1)
 | 
			
		||||
					else:
 | 
			
		||||
						#Update existing line
 | 
			
		||||
| 
						 | 
				
			
			@ -1091,7 +1215,7 @@ class plugin:
 | 
			
		|||
					for i in self.r.l_contact[u.jid]['iter']:
 | 
			
		||||
						self.r.treestore.set_value(i, 1, u.name)
 | 
			
		||||
				else:
 | 
			
		||||
					user1 = user(jid, jid, ['general'], 'online', 'online', 'to')
 | 
			
		||||
					user1 = user(jid, jid, ['general'], 'online', 'online', 'to', ev[1]['ressource'])
 | 
			
		||||
					self.r.add_user(user1)
 | 
			
		||||
				#TODO: print 'you are now authorized'
 | 
			
		||||
			elif ev[0] == 'AGENTS':
 | 
			
		||||
| 
						 | 
				
			
			@ -1130,15 +1254,15 @@ class plugin:
 | 
			
		|||
				if state == common.sleepy.STATE_AWAKE:
 | 
			
		||||
					#on repasse online
 | 
			
		||||
					self.r.optionmenu.set_history(0)
 | 
			
		||||
					self.r.queueOUT.put(('STATUS',('online', accounts[0])))
 | 
			
		||||
					self.r.queueOUT.put(('STATUS',('online', '', accounts[0])))
 | 
			
		||||
				if state == common.sleepy.STATE_AWAY and self.autoaway:
 | 
			
		||||
					#on passe away
 | 
			
		||||
					self.r.optionmenu.set_history(1)
 | 
			
		||||
					self.r.queueOUT.put(('STATUS',('away', accounts[0])))
 | 
			
		||||
					self.r.queueOUT.put(('STATUS',('away', 'auto away (idle)', accounts[0])))
 | 
			
		||||
				if state == common.sleepy.STATE_XAWAY and self.autoxa:
 | 
			
		||||
					#on passe away
 | 
			
		||||
					self.r.optionmenu.set_history(2)
 | 
			
		||||
					self.r.queueOUT.put(('STATUS',('xa', accounts[0])))
 | 
			
		||||
					self.r.queueOUT.put(('STATUS',('xa', 'auto away (idel)', accounts[0])))
 | 
			
		||||
			self.sleeper_state = state
 | 
			
		||||
		return 1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue