mirror of
https://github.com/vidarh/ruby-x11
synced 2024-11-16 07:48:12 +01:00
first commit
This commit is contained in:
commit
943eb399c7
6 changed files with 171 additions and 0 deletions
5
README
Normal file
5
README
Normal file
|
@ -0,0 +1,5 @@
|
|||
(under-development) Pure Ruby implementation of the X Window System Protocol.
|
||||
This library is based off of Mathieu Bouchard's work on his RubyX11 project.
|
||||
|
||||
The entire X Window Protocol is here located here for contributors :)
|
||||
http://cvs.freedesktop.org/*checkout*/xorg/xc/doc/hardcopy/XProtocol/proto.PS.gz
|
14
lib/X11.rb
Normal file
14
lib/X11.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
require 'rubygems'
|
||||
require 'socket'
|
||||
require 'active_support'
|
||||
require 'hexdump'
|
||||
require 'X11/protocol'
|
||||
require 'X11/auth'
|
||||
require 'X11/display'
|
||||
|
||||
module X11
|
||||
# Return a format string, suitable for pack(), for a string padded to a multiple
|
||||
# of 4 bytes. For instance, C<pack(padded('Hello'), 'Hello')> gives
|
||||
# C<"Hello\0\0\0">.
|
||||
def self.pad(x); x + "\0"*(-x.length & 3); end
|
||||
end
|
72
lib/X11/auth.rb
Normal file
72
lib/X11/auth.rb
Normal file
|
@ -0,0 +1,72 @@
|
|||
# This module is an approximate ruby replacement for the libXau C library and the
|
||||
# xauth(1) program. It reads and interprets the files (usually '~/.Xauthority') that
|
||||
# hold authorization data used in connecting to X servers. Since it was written mainly
|
||||
# for the use of X11::Protocol, its functionality is currently restricted to reading,
|
||||
# not writing, of these files.
|
||||
|
||||
module X11
|
||||
class Auth
|
||||
|
||||
FAILED = 0
|
||||
AUTHENTICATE = 1
|
||||
SUCCESS = 2
|
||||
|
||||
ADDRESS_TYPES = {
|
||||
256 => :Local,
|
||||
65535 => :Wild,
|
||||
254 => :Netname,
|
||||
253 => :Krb5Principal,
|
||||
252 => :LocalHost,
|
||||
0 => :Internet,
|
||||
1 => :DECnet,
|
||||
2 => :Chaos
|
||||
}
|
||||
|
||||
AuthInfo = Struct.new :family, :address, :display, :auth_name, :auth_data
|
||||
|
||||
# Open an authority file, and create an object to handle it.
|
||||
# The filename will be taken from the XAUTHORITY environment variable,
|
||||
# if present, or '.Xauthority' in the user's home directory, or it may be overridden
|
||||
# by an argument.
|
||||
def initialize(path = ENV['XAUTHORITY'] || ENV['HOME'] + "/Xauthority")
|
||||
@file = File.open(path)
|
||||
end
|
||||
|
||||
# Get authentication data for a connection of type family to display display_id on host.
|
||||
# If family is 'Internet', the host will be translated into an appropriate address by gethostbyname().
|
||||
# If no data is found, returns nil
|
||||
def get_by_hostname(host, family, display_id)
|
||||
host = `hostname`.chomp if host == 'localhost' or host == '127.0.0.1'
|
||||
address = TCPSocket.gethostbyname(host) if family == :Internet # this line does nothing for now
|
||||
|
||||
auth_data = nil
|
||||
displays.each do |entry|
|
||||
auth_data = entry if display_id.to_i == entry.display.to_i
|
||||
end
|
||||
|
||||
reset
|
||||
return auth_data
|
||||
end
|
||||
|
||||
# returns one entry from Xauthority file
|
||||
def read
|
||||
auth_info = []
|
||||
auth_info << ADDRESS_TYPES[ @file.read(2).unpack('n').first ]
|
||||
4.times { length = @file.read(2).unpack('n').first; auth_info << @file.read(length).first }
|
||||
AuthInfo[*auth_info]
|
||||
end
|
||||
|
||||
# returns all entries from XAuthority file
|
||||
def displays
|
||||
collection = []
|
||||
collection << read while !@file.eof?
|
||||
reset
|
||||
collection
|
||||
end
|
||||
|
||||
def reset
|
||||
@file.seek(0, IO::SEEK_SET)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
62
lib/X11/display.rb
Normal file
62
lib/X11/display.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
module X11
|
||||
class Display
|
||||
|
||||
# Open a connection to the specified display (numbered from 0) on the specified host
|
||||
def initialize(target = ENV['DISPLAY'])
|
||||
target =~ /^([\w.-]*):(\d+)(?:.(\d+))?$/
|
||||
host, display_id, screen_id = $1, $2, $3
|
||||
family = nil
|
||||
|
||||
if host.empty?
|
||||
@socket = UNIXSocket.new("/tmp/.X11-unix/X#{display_id}")
|
||||
family = :Local
|
||||
host = nil
|
||||
else
|
||||
@socket = TCPSocket.new(host,6000+display_id)
|
||||
family = :Internet
|
||||
end
|
||||
|
||||
authorize(host, family, display_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# authorization packet sent to X11 server:
|
||||
# [:proto_major, Uint16],
|
||||
# [:proto_minor, Uint16],
|
||||
# [:auth_proto_name, Uint16, :length],
|
||||
# [:auth_proto_data, Uint16, :length],
|
||||
# [:auth_proto_name, String8],
|
||||
# [:auth_proto_data, String8]
|
||||
def authorize(host, family, display_id)
|
||||
auth_info = Auth.new.get_by_hostname(host||"localhost", family, display_id)
|
||||
auth_name, auth_data = auth_info.address, auth_info.auth_data
|
||||
puts auth_name
|
||||
puts auth_data
|
||||
|
||||
@socket.write([
|
||||
Protocol::BYTE_ORDER,
|
||||
Protocol::MAJOR,
|
||||
Protocol::MINOR,
|
||||
auth_name.length,
|
||||
auth_data.length,
|
||||
X11::pad(auth_name),
|
||||
X11::pad(auth_data)
|
||||
].pack("A2 SS SS xx") + X11::pad(auth_name) + X11::pad(auth_data))
|
||||
|
||||
case @socket.read(1).unpack("w").first
|
||||
when X11::Auth::FAILED
|
||||
len, major, minor, xlen = @socket.read(7).unpack("CSSS")
|
||||
reason = @socket.read(xlen * 4)
|
||||
reason = reason[0..len]
|
||||
raise "Connection to server failed -- (version #{major}.#{minor}) #{reason}"
|
||||
when X11::Auth::AUTHENTICATE
|
||||
raise "Connection requires authentication"
|
||||
when X11::Auth::SUCCESS
|
||||
raise "fix me"
|
||||
else
|
||||
raise "received unknown opcode #{type}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
0
lib/X11/event.rb
Normal file
0
lib/X11/event.rb
Normal file
18
lib/X11/protocol.rb
Normal file
18
lib/X11/protocol.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module X11
|
||||
class Protocol
|
||||
|
||||
# endiness of your machine
|
||||
BYTE_ORDER = case [1].pack("L")
|
||||
when "\0\0\0\1"
|
||||
"B"
|
||||
when "\1\0\0\0"
|
||||
"l"
|
||||
else
|
||||
raise "Cannot determine byte order"
|
||||
end
|
||||
|
||||
MAJOR = 11
|
||||
MINOR = 0
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue