Find the answer to your Linux question:
Results 1 to 6 of 6
Hi all, I decided to start a new thread because the previous one (started by Cogitati) on "Simulating pressed keys in shell script" , had too many posts. The objectives ...
  1. #1
    Just Joined!
    Join Date
    Oct 2004
    Posts
    62

    Macro programming: working examples ...and a security concern.

    Hi all,
    I decided to start a new thread because the previous one (started by Cogitati) on
    "Simulating pressed keys in shell script", had too many posts.
    The objectives of the present thread are:
    - to demonstrate that macro programming works and is easy (now... is the contrary)
    - to supply hence "working examples"
    - to propose new utilization of this technique.
    - to get the advice of security experts on its possible malicious use (I am thinking
    to the difficulty to recognize "strange" routines in a JavaScript
    embedded in a innocent web file)

    A brief history of macro programming;
    this technique has a long-time history... (I refer only as I know).
    Well known under Windows (more relaxed in terms of security), was used extensively
    in Office divided in two steps; recording phase and playing back).
    Under Windows a full language (Basic-like), not to be confused with VBA was born
    to support macro programming (AutoIt... the best solution IMHO).
    Under Linux, macro programming had more difficulty also for the opposition of
    "gurus", because in theory by-passed great part of the programming and was directly
    interfaced with the input-output... or for security reasons (I don't know... I'm not a guru).
    Then came OpenOffice and also Sourceforge began a project on it ...xmacro,

    Thanks to Cogitati who proposed the simple function xsendkeycode (you'd better
    to read the corresponding thread), I changed my mind and reverted to simulate only keys
    and not mouse (which can be emulated by keybooard).

    I don't have yet a "working example", but I hope that with your help we will
    soon succeed.
    The problem in macro programming is the correct synchronizing among simulated keys and
    the correct application window (which must have focus).

    If you supply an example, use, as application, an editor and simulate writing to it.
    I know it is rather silly but in this manner there is an immediate understanding .
    Demonstrate your example together with other working windows...

    I give you only a small suggestion: use wctrl to activate the target window.
    For mouse and X operations I have found interesting tools. I'll speak of them
    next time.
    At last, to more encourage you, I briefly list some perspectives:
    - to automatically translate a list of words (to build a glossary for example or, in my case,
    to translate particular words to be searched in English sites)
    - to make extensive queries to famous databases
    - to navigate in Internet like a spider
    - to download manuals or tutorials (or code samples) also scattered in various web pages
    - to search and register the results (filtering them if you want)
    - to automatize every operation long or annoying...
    Bye.

  2. #2
    Just Joined!
    Join Date
    May 2008
    Posts
    30
    I'd like to post those scripts I mentions earlier. So here they are. Place them in /usr/local/bin if you want them to work without modification. I think they could also be placed in any location that's part of the PATH variable.

    Code:
    #!/usr/bin/env python
    
    from types import *		# Import the types, sys, and relevent modules.
    import keysend
    import os
    
    def send():
    	
    	i = 0		# i and x are just for looping purposes.
    	x = 0
    	words = []	# words will store a list of the words in the file.
    	
    	filename = raw_input('Input a filepath >>')	# Prompt the user for a
    	os.system('sleep 5')				# filepath. Then open 
    	file = open(filename)				# the path the user 
    	words = file.read().split()			# specifies. Read the 
    	file.close()					# file, splitting it at
    							# spaces, and store that
    	for i in range(0,len(words) - 1):		# in 'words'. Then send
    		keysend.do(words[i],words[i + 1])	# those words to another
    							# script.
    if __name__ == '__main__': send()
    The above one should be called "fileread.py", and it is the one you execute in order for the program to work as intended.
    Code:
    ###########################################################################
    ###########################################################################
    #									  #
    # When this program is called, another program send it a character or 	  #
    # keyname. Afterwards, this program takes that character or keyname, and  #
    # opens a file, containing a list of keys and their keycodes. It then	  #
    # searches through that file looking for a match. If it finds a match, it #
    # sends whatever is right next to that entry, which is supposed to be the #
    # key's keycode.							  #
    #									  #
    ###########################################################################
    ###########################################################################
    def convert(key):
    	
    	i = 0
    	keycode = None
    	
    	keylistfile = open('/usr/local/bin/keylist')	# Open the file containing
    	keylist = keylistfile.read()				# the keycodes and read it.
    	keylistfile.close()					# Close the file, then split
    	keylist = keylist.split()				# the read file at whitespace.
    
    	for i in range (0,len(keylist)):		# For every entry, check if the character of
    		if key == keylist[i]:			# keyname matches the entry. If it does match,
    			keycode = keylist[i + 1]	# keycode equals the entry next to the matching
    							# entry (the entry's keycode).
    	return keycode					# Return the keycode to the program that called it.
    	
    
    if __name__ == '__main__':
    	
    	key = raw_input('Input key >> ')	# If this is the main program, for testing purposes,
    	keycode = convert(key)			# get a character or keyname from the user, then send
    	print keycode				# it to the main part of the program. It then prints
    						# what is returned.
    The above should be named "keyconvert.py", and is called upon by another part of the program.
    Code:
    # Import all the needed modules
    from types import *
    import os
    import keyconvert
    
    # This function is for testing purposes. It simply gets some input from the user
    # and sends it to the next function.
    def main():
    	
    	entries = []
    	usrinput = raw_input('Input a command (entries separated by commas)>> ')
    	entries = usrinput.split(',')
    	do(entries[0],entries[1])
    	
    # This function gets passed two variables: word and key. Looking at it from file
    # read.py's point of view, these two variables equate to the first and second 
    # word that it extracts from the file that it reads.
    def do(word,key):
    	
    	code = 0
    # This is what the keycode will be stored in.
    	i = 0
    # This is just for counting in a for loop.
    	delay= 0.01
    # This is the delay between each key being sent.
    	
    	os.system('sleep ' + str(delay))
    	if word == 'keypress':
    		event = 'xsendkeycode '
    		code = keyconvert.convert(key)
    		if code == None:	
    			print 'syntax error'
    			os.system('sleep 3')
    			return 0	
    		else: errval = None
    		os.system(event + str(code) + ' 1')
    		os.system(event + str(code) + ' 0')
    # Each of these if statements checks to see if 'word' equals a recognized keyword
    # If it does, then it does the command associated with it. If the 'code' (storing the
    # keycode retrieved from keyconvert) is None, then the program tells the user that
    # there is a syntax error in their file. (It will only return none if the key they told
    # the program to simulate does not match any keys in the keylist file. This particular if
    # statement will press down a key, and subsequently lift it back up.
    	elif word == 'keydown':			
    		event = 'xsendkeycode '		
    		code = keyconvert.convert(key)	
    		if code == None:	
    			print 'syntax error'
    			os.system('sleep 3')
    			return 0
    		else: errval = None
    		os.system(event + str(code) + ' 1')
    # This if statement will press a key down, but never lift it back up.
    	elif word == 'keyup':
    		event = 'xsendkeycode '
    		code = keyconvert.convert(key)
    		if code == None:
    			print 'syntax error'
    			os.system('sleep 3')
    			return 0
    		else: errval = None
    		os.system(event + str(code) + ' 0')
    # This if statement will lift a key back up. Usually used in conjunction
    # with the previous statement.
    	elif word == 'presskeys:':
    		event = 'xsendkeycode '
    		for i in range(0,len(key)):
    			code = keyconvert.convert(key[i])
    			os.system(event + code + ' 1')
    			os.system(event + code + ' 0')
    # This statement will press a series of keys.
    
    if __name__ == '__main__': main()
    The above should be named "keysend.py", and is also called upon by another variable.
    It is important that they are all in the same directory.

    In order for this program to work, it must have a file for it to read. Which should be formatted like this:
    Code:
    command keyname
    Where command is either "keyup", "keydown", "presskeys:", or "keypress". Keypress presses down and lifts up on one key. Keydown presses down on one key. Keyup lifts up one key. Presskeys: presses down and lifts up multiple keys.
    It can have multiple lines like this.

    An example:
    Code:
    keydown shift_l
    keypress a
    keyup shift_l
    That should press down the left shift key, then press a, producing a capital a, and then let go of the shift key.

    EDIT:

    Oh yes, and you'll need this:
    Code:
    a	38
    b	56
    c	54
    d	40
    e	26
    f	41
    g	42
    h	43
    i	31
    j	44
    k	45
    l	46
    m	58
    n	57
    o	32
    p	33
    q	24
    r	27
    s	39
    t	28
    u	30
    v	55
    w	25
    x	53
    y	29
    z	52
    1	10
    2	11
    3	12
    4	13
    5	14
    6	15
    7	16
    8	17
    9	18
    0	19
    alt_l	64
    alt_r	108
    space	65
    ctrl_l	37
    ctrl_r	105
    super_l	115
    super_r	134
    shift_l	50
    shift_r	62
    caps	66
    tab	23
    back	22
    enter	36
    up	115
    down	116
    left	113
    right	114
    f1	67
    f2	68
    f3	69
    f4	70
    f5	71
    f6	72
    f7	73
    f8	74
    f9	75
    f10	76
    f11	95
    f12	96
    home	110
    insert	118
    delete	119
    end	115
    page_up	112
    page_dn	117
    pause	127
    print	107
    num	77
    escape	9
    `	49
    '	48
    /	61
    \	51
    .	60
    ,	59
    [	34
    ]	35
    -	20
    =	21
    ;	47
    The above is a list of keys, (named keylist), that is required for the program to work. If you want, you can change the names of the keys, or add new ones from there. To find out the keycode (which is placed next to the keyname) use the command "xev". Make sure this is in /usr/local/bin in order for it to work. I forgot to program into the scripts for the keylist to be able to be anywhere in the PATH and still work, so it will only work in /usr/local/bin.

    EDIT:
    Oh, and you'll also need to have lineakd installed. I was having some trouble getting xsendkeycode.c to compile. I hope to get it working soon.

  3. #3
    Just Joined!
    Join Date
    Oct 2004
    Posts
    62
    Hi Cogitati,
    thank you for joining! Thanks also for the examples in Python!... you are great!
    However, telling the truth... they are not "working examples":
    1) they must run in a home directory of the user (no /usr/local/bin or other dir
    even if reachable with environmental variable $PATH !)
    2) for that, you must supply files or the necessary informations (for example... import
    keysend... what module is keysend? I don't know it! What version of Python do you have?)
    3) if you derived your example from internet... give the references!
    4) follow, if possible, the guidelines of the thread: use an editor as a target for
    writing to it your simulated keys and demonstrate the working of your example also
    in presence of other applications/windows, possibly interfering).
    5)the best would be to end your demo with saving as a file what you wrote and give also
    example of output. in intermediate important points of your program.
    I greatly need this technique (I have to translate in English over 200 special words
    not easily found in a dictionary and then feed these words in a dialog box in different
    Internet sites go get back unique informations, like making a lot of queries).
    I hope to find soon a solution...
    Bye.

  4. #4
    Just Joined!
    Join Date
    May 2008
    Posts
    30
    1) With some minor changes, you can make it work in the home directory. The only reason that I didn't do this is because it would make it hard for it to be usable across computers without having to play with the code. If in every script where I put all the imported modules, you add "import sys", then "sys.path.append("/your/home/directory/here")", you can move all the files but keylist to your home directory. For keylist, you must go into keyconvert, find the line that says, "keylistfile = open('/usr/local/bin/keylist')", and change it to "keylistfile = open('/your/home/directory/keylist')", then that one will be able to be placed in the home directory, too.

    2) The module keysend isn't really a module, it is one of the other files that I posted. I am using Python 2.5.2. Look at the names of the files (under the code of each file, I told you what to name them in my post), the unknown modules being imported should correspond with the other files.

    3) I did not derive any of my examples from the internet.

    4) It's not really complete right now, and will send keys to whatever window and text field you have focus on. When I've gotten far enough for it to distinguish between windows, then I'll post updated scripts.

    5) When you say "demo" do you mean you want a script that is specialized for a specific use? I have not done this. I, from the beginning, tried to make my program as flexible as possible. It will not run any keys unless given a file to read, which should contain a properly formatted list of commands and keys (I showed how this list should be formatted in an earlier post). I've attached an example list. In order to make the program work, run fileread.py, and when it asks for a filepath, give it the path of the file I've attached, then switch the focus to what you want to type it into within 5 seconds. After that time, it will play the keys.

    I will continue working on my scripts and post them again when I think I have made some progress.
    Attached Files Attached Files

  5. #5
    Just Joined!
    Join Date
    May 2008
    Posts
    30
    I have found a nice python module that I think will accelerate the project. I have not read very much into it, but it seems that it might make it possible to get rid of xsendkeycode entirely.

    Also, I have updated one of the files so that now you can run the program while it is in the home directory. You can kick the program off with fileread.py. example.txt, which I posted earlier is a good file to use.

    I have attached the only file that needs an upgrade. Just replace the old one with it and remove the ".txt" file extension.

    I will continue working on this. I think the mouse can be simulated with this new python module I found. That module, by the way, is called python-xlib if you want to look at it.
    Attached Files Attached Files

  6. #6
    Just Joined!
    Join Date
    Oct 2004
    Posts
    62
    Hi Cogitati,
    I feel guilty... I'm not collaborating, that is I'm not sharing my trials and
    my failures... but if ever I succeed... I will let you know.

    I tried the function xsendkeycode and I discovered that keycodes are
    different from one type of keyboard (for ex. USA... my previous keyboard) to
    another (for example my actual keyboard... Italian).
    Also I had found the way to emulate mouse by keyboard with kde using the
    numeric keypad on the right... but xev can't find the keycodes!
    I found a new function xsendkey (w/out keycodes) but I didn't had time to test it.
    I was very busy making searches in Internet for a friend of mine, and macro
    programming would have sped all my work considerably.
    I even thought to go back to Windows and AutoIt, but the poor security of Windows,
    especially for my connection "always on", with optical fiber, discouraged me.
    About your python trials... I'm not optimistic. It's up to you to demonstrate the
    contrary with a "working" example applied to an easy case (like writing to an editor).

    My last involvement with forums has confirmed the reasons why I left forums for 3 years...

    But till I'll have intellectual curiosity I will go on (also in the field of python modules
    like python xlib which suffers only for its youth...).
    Bye.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...