qasim 0.1.11.dev.2014102811

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +31 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE-GPL-3 +674 -0
  5. data/Makefile +180 -0
  6. data/README.md +81 -0
  7. data/Rakefile +1 -0
  8. data/TODO.md +28 -0
  9. data/bin/qasim-cli +89 -0
  10. data/bin/qasim-gui +300 -0
  11. data/conf/config +2 -0
  12. data/conf/default.map +32 -0
  13. data/conf/qasim.desktop +13 -0
  14. data/data/icons/qasim.128.png +0 -0
  15. data/data/icons/qasim.16.png +0 -0
  16. data/data/icons/qasim.256.png +0 -0
  17. data/data/icons/qasim.32.png +0 -0
  18. data/data/icons/qasim.64.png +0 -0
  19. data/data/icons/qasim.png +0 -0
  20. data/data/icons/qasim.svg +192 -0
  21. data/data/text/authors.html +7 -0
  22. data/data/text/gpl-3.0-standalone.html +694 -0
  23. data/data/text/thanks.html +0 -0
  24. data/debian/changelog +73 -0
  25. data/debian/compat +1 -0
  26. data/debian/control +13 -0
  27. data/debian/copyright +38 -0
  28. data/debian/dirs +3 -0
  29. data/debian/docs +0 -0
  30. data/debian/rules +80 -0
  31. data/debian/source/format +1 -0
  32. data/demo.map +29 -0
  33. data/examples/config +2 -0
  34. data/examples/default.map +32 -0
  35. data/lib/qasim.rb +11 -0
  36. data/lib/qasim/config.rb +56 -0
  37. data/lib/qasim/configold.rb +123 -0
  38. data/lib/qasim/constants.rb +11 -0
  39. data/lib/qasim/map.rb +225 -0
  40. data/lib/qasim/qasim.qrc +8 -0
  41. data/lib/qasim/ui.rb +7 -0
  42. data/lib/qasim/ui/about.rb +58 -0
  43. data/lib/qasim/ui/about.ui +192 -0
  44. data/lib/qasim/ui/listmaps.ui +59 -0
  45. data/lib/qasim/ui/preferences.rb +12 -0
  46. data/lib/qasim/ui/preferences.ui +90 -0
  47. data/lib/qasim/version.rb +5 -0
  48. data/man/qasim-cli.1 +98 -0
  49. data/man/qasim-gui.1 +98 -0
  50. data/man/sshfs-mapper.1 +98 -0
  51. data/mapparser.y +155 -0
  52. data/qasim.gemspec +34 -0
  53. data/sshfs-mapper.completion +24 -0
  54. data/sshfs-mapper.sh +253 -0
  55. metadata +147 -0
@@ -0,0 +1,11 @@
1
+ module Qasim
2
+ APP_ICON_PATH = File.join QASIM_DATA_DIR, "icons"
3
+
4
+ APP_SYSCONFIG_DIR = "/etc/qasim/maps.d"
5
+
6
+ APP_CONFIG_DIR = if ENV['XDG_CONFIG_HOME'] then
7
+ File.join ENV['XDG_CONFIG_HOME'], 'qasim'
8
+ else
9
+ File.join ENV['HOME'], '.config', 'qasim'
10
+ end
11
+ end
data/lib/qasim/map.rb ADDED
@@ -0,0 +1,225 @@
1
+
2
+ require 'fileutils'
3
+
4
+ #require 'rdebug/base'
5
+ require 'qasim'
6
+
7
+ module Qasim
8
+
9
+ class Map
10
+ attr_reader :path,
11
+ :host,
12
+ :port,
13
+ :enable,
14
+ :user,
15
+ :map,
16
+ :name
17
+
18
+ class MapParseError < RuntimeError ; end
19
+ class ConnectError < RuntimeError ; end
20
+
21
+ CYPHER_ARCFOUR = :arcfour
22
+ CYPHER_AES256CBC = "aes-256-cbc".to_sym
23
+ CYPHERS = [ CYPHER_ARCFOUR, CYPHER_AES256CBC ]
24
+
25
+
26
+ #
27
+ # Set defaults properties for maps
28
+ #
29
+ def initialize config, map_path
30
+ @config = config
31
+ @path = map_path
32
+ @host = nil
33
+ @port = 22
34
+ @enable = false
35
+ @user = nil
36
+ @cypher = :arcfour
37
+ @links = {}
38
+ @debug = false
39
+ @name = (File.basename map_path).gsub(/\.map$/,'')
40
+
41
+ self.load @path
42
+ end
43
+
44
+
45
+ #
46
+ # Load map description from file
47
+ #
48
+ def load path=nil
49
+ @path=path unless path.nil?
50
+ #rdebug "Parsing map #{@path}"
51
+ f = File.open @path
52
+ linect = 0
53
+ local_env = ENV.clone
54
+ f.each do |line|
55
+ line = line.strip
56
+ linect += 1
57
+
58
+ while line =~ /\$(\w+)/ do
59
+ #puts "FOUND PATTERN %s => %s" % [$1, local_env[$1]]
60
+ case line
61
+ when /\$\{(.+)\}/ then
62
+ pattern = $1
63
+ puts pattern
64
+ line.gsub!(/\$\{#{pattern}\}/,local_env[pattern])
65
+ when /\$(\w+)/ then
66
+ pattern = $1
67
+ line.gsub!(/\$#{pattern}/,local_env[pattern])
68
+ else
69
+ puts "w: unknown pattern: %s" % line
70
+ end
71
+ end
72
+
73
+ case line
74
+ when /^\s*REMOTE_USER\s*=\s*(.*)\s*$/ then
75
+ @user = $1
76
+ #rdebug "d: remote_user => #{$1}"
77
+ when /^\s*REMOTE_PORT\s*=\s*(.*)\s*$/ then
78
+ @port = $1.to_i
79
+ #rdebug "d: remote_port => #{$1}"
80
+ when /^\s*REMOTE_HOST\s*=\s*(.*)\s*$/ then
81
+ @host = $1
82
+ #rdebug "d: remote_host => #{$1}"
83
+ when /^\s*REMOTE_CYPHER\s*=\s*(.*)\s*$/ then
84
+ if CYPHERS.map{|x| x.to_s}.include? $1 then
85
+ @host = $1.to_sym
86
+ end
87
+ when /^\s*MAP\s*=\s*(.*)\s+(.*)\s*$/ then
88
+ @links[$1] = $2
89
+ #rdebug "d: link #{$1} => #{$2}"
90
+ when /^\s*$/,/^\s*#/ then
91
+ #rdebug "d: dropping empty line"
92
+ else
93
+ raise MapParseError, "parse error at #{@path}:#{linect}"
94
+ end
95
+ end
96
+ f.close
97
+ end
98
+
99
+
100
+ #
101
+ # Write map description to file
102
+ #
103
+ def write path=nil
104
+ @path=path unless path.nil?
105
+
106
+ File.open(@path, "w") do |f|
107
+ f.puts "REMOTE_USER=%s" % @user
108
+ f.puts "REMOTE_PORT=%s" % @port
109
+ f.puts "REMOTE_HOST=%s" % @host
110
+ f.puts "REMOTE_CYPHER=%s" % @cypher
111
+ end
112
+ end
113
+
114
+
115
+ #
116
+ # Test map liveness (how ?)
117
+ # FIXME: not implemented
118
+ #
119
+ def online?
120
+ #rdebug "testing online? %s " % self.inspect
121
+ #FIXME: test liveness
122
+ end
123
+
124
+
125
+ #
126
+ # Test if map is connected / mounted
127
+ #
128
+ def connected?
129
+ f = File.open("/proc/mounts")
130
+ sshfs_mounted = (f.readlines.select do |line|
131
+ line =~ /\s+fuse.sshfs\s+/
132
+ end).map do |line|
133
+ line.split(/\s+/)[1]
134
+ end
135
+ f.close
136
+
137
+ score = 0
138
+ @links.each do |name, remotepath|
139
+ score += 1
140
+ local_path = File.join @config.mnt_dir, name
141
+
142
+ if sshfs_mounted.include? local_path then
143
+ score -= 1
144
+ end
145
+ end
146
+ if score == 0 then return true
147
+ else return false
148
+ # FIXME: explain why ?
149
+ end
150
+ end
151
+
152
+
153
+ #
154
+ # Connect map
155
+ #
156
+ def connect &block
157
+ puts "[#{File.basename @path}] Connecting..."
158
+ puts " #{@user}@#{@host}:#{@port}"
159
+ #puts " links = %s" % @links.map{ |k,v| "%s => %s" % [ k, v ] }.join(', ')
160
+ # do something
161
+ # test server connection
162
+ # mount
163
+ #
164
+ # FIXME: test connexion with Net::SSH + timeout or ask password
165
+ @links.each do |name, remotepath|
166
+ localpath = File.join ENV['HOME'], "mnt", name
167
+ FileUtils.mkdir_p localpath
168
+ cmd = "sshfs"
169
+ cmd_args = [
170
+ "-o","allow_root" ,
171
+ "-o","idmap=user" ,
172
+ "-o","uid=%s" % Process.uid,
173
+ "-o","gid=%s" % Process.gid,
174
+ "-o","reconnect", # auto-reconnection
175
+ "-o","workaround=all",
176
+ "-o","cache_timeout=900", # 15 min cache for files
177
+ "-o","cache_stat_timeout=1800", # 30 min cache for directories
178
+ "-o","cache_link_timout=1800", # 30 min cache for links
179
+ "-o","attr_timeout=1800", # 30 min attr cache
180
+ "-o","entry_timeout=1800", # 30 min entry cache
181
+ "-o","ServerAliveInterval=15", # prevent I/O hang
182
+ "-o","ServerAliveCountMax=3", # prevent I/O hang
183
+ "-o","no_readahead",
184
+ #"-o","Ciphers=arcfour", # force cypher
185
+ "-o","Port=%s" % @port,
186
+ "%s@%s:%s" % [@user,@host,remotepath],
187
+ localpath ]
188
+ #rdebug "command: %s" % [ cmd, cmd_args ].flatten.join(' ')
189
+ if block_given? then
190
+ yield name, cmd, cmd_args
191
+ else
192
+ system cmd, cmd_args
193
+ if $?.exitstatus != 0 then
194
+ raise ConnectError, self
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+
201
+ #
202
+ # Disconnect map
203
+ #
204
+ def disconnect &block
205
+ puts "Disconnecting map #{@path}"
206
+ @links.each do |name, remotepath|
207
+ localpath = File.join ENV['HOME'], "mnt", name
208
+ cmd = "fusermount"
209
+ cmd_args = [
210
+ "-u", #umount
211
+ "-z" ,#lazy
212
+ localpath ]
213
+ #rdebug "command: %s" % [ cmd, cmd_args ].flatten.join(' ')
214
+ if block_given? then
215
+ yield name, cmd, cmd_args
216
+ else
217
+ system cmd, cmd_args
218
+ if $?.exitstatus != 0 then
219
+ raise ConnectError, self
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,8 @@
1
+ <RCC>
2
+ <qresource prefix="qasim">
3
+ <file alias="authors">../../data/text/authors.html</file>
4
+ <file alias="thanks">../../data/text/thanks.html</file>
5
+ <file alias="licence-gpl3">../../data/text/gpl-3.0-standalone.html</file>
6
+ <file alias="qasim-icon">../../data/icons/qasim.svg</file>
7
+ </qresource>
8
+ </RCC>
data/lib/qasim/ui.rb ADDED
@@ -0,0 +1,7 @@
1
+
2
+ require 'qasim/constants'
3
+
4
+ module Qasim ; module Ui
5
+ autoload :About, 'qasim/ui/about'
6
+ autoload :Preferences, 'qasim/ui/preferences'
7
+ end ; end
@@ -0,0 +1,58 @@
1
+
2
+ require 'qasim/ui/about_ui'
3
+
4
+ module Qasim ; module Ui
5
+ class About < Qt::Dialog
6
+ def initialize(parent = nil)
7
+ super
8
+ @ui = Ui_About.new
9
+ @ui.setup_ui(self)
10
+
11
+ #FIXME: attach button events to dialog.close
12
+ #Qt::Object.connect( w, SIGNAL( :clicked ), a, SLOT( :quit ) )
13
+
14
+ # Change title according to current version
15
+ title_str = "Qasim v%s (%s)" % [ Qasim::APP_VERSION, Qasim::APP_DATE ]
16
+ @ui.title_label.text = Qt::Application.translate(
17
+ "About",
18
+ title_str,
19
+ nil,
20
+ Qt::Application::UnicodeUTF8
21
+ )
22
+
23
+ # Read Authors
24
+ file = Qt::File.new(':/qasim/authors')
25
+ if file.open(Qt::File::ReadOnly | Qt::File::Text)
26
+ stream = Qt::TextStream.new( file )
27
+ @ui.authors_textedit.text = stream.readAll()
28
+ file.close
29
+ else
30
+ # FIXME handle error on authors reading
31
+ end
32
+
33
+ # Read Thanks
34
+ file = Qt::File.new(':/qasim/thanks')
35
+ if file.open(Qt::File::ReadOnly | Qt::File::Text)
36
+ stream = Qt::TextStream.new( file )
37
+ @ui.thanks_textedit.text = stream.readAll()
38
+ file.close
39
+ else
40
+ # FIXME handle error on thanks reading
41
+ end
42
+
43
+ # Read License
44
+ file = Qt::File.new(':/qasim/licence-gpl3')
45
+ if file.open(Qt::File::ReadOnly | Qt::File::Text)
46
+ stream = Qt::TextStream.new( file )
47
+ @ui.license_textedit.text = stream.readAll()
48
+ file.close
49
+ else
50
+ # FIXME handle error on licence reading
51
+ end
52
+
53
+ # set first tab
54
+ @ui.tab_widget.setCurrentIndex(0)
55
+ end
56
+
57
+ end
58
+ end ; end
@@ -0,0 +1,192 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>About</class>
4
+ <widget class="QDialog" name="About">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>470</width>
10
+ <height>500</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>About</string>
15
+ </property>
16
+ <property name="windowIcon">
17
+ <iconset resource="../qasim.qrc">
18
+ <normaloff>:/qasim/qasim-icon</normaloff>:/qasim/qasim-icon</iconset>
19
+ </property>
20
+ <property name="sizeGripEnabled">
21
+ <bool>true</bool>
22
+ </property>
23
+ <layout class="QVBoxLayout" name="verticalLayout_2">
24
+ <item>
25
+ <layout class="QVBoxLayout" name="vertical_layout">
26
+ <item>
27
+ <layout class="QHBoxLayout" name="horizontal_layout">
28
+ <item>
29
+ <widget class="QLabel" name="icon_label">
30
+ <property name="text">
31
+ <string/>
32
+ </property>
33
+ <property name="pixmap">
34
+ <pixmap resource="../qasim.qrc">:/qasim/qasim-icon</pixmap>
35
+ </property>
36
+ </widget>
37
+ </item>
38
+ <item>
39
+ <widget class="QLabel" name="title_label">
40
+ <property name="sizePolicy">
41
+ <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
42
+ <horstretch>0</horstretch>
43
+ <verstretch>0</verstretch>
44
+ </sizepolicy>
45
+ </property>
46
+ <property name="font">
47
+ <font>
48
+ <weight>75</weight>
49
+ <bold>true</bold>
50
+ </font>
51
+ </property>
52
+ <property name="text">
53
+ <string>Qasim vVERSION (DATE)</string>
54
+ </property>
55
+ </widget>
56
+ </item>
57
+ </layout>
58
+ </item>
59
+ <item>
60
+ <widget class="QTabWidget" name="tab_widget">
61
+ <property name="currentIndex">
62
+ <number>0</number>
63
+ </property>
64
+ <widget class="QWidget" name="about_tab">
65
+ <attribute name="title">
66
+ <string>About</string>
67
+ </attribute>
68
+ <layout class="QGridLayout" name="gridLayout">
69
+ <item row="0" column="0">
70
+ <widget class="QLabel" name="about_label">
71
+ <property name="sizePolicy">
72
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
73
+ <horstretch>0</horstretch>
74
+ <verstretch>0</verstretch>
75
+ </sizepolicy>
76
+ </property>
77
+ <property name="minimumSize">
78
+ <size>
79
+ <width>300</width>
80
+ <height>200</height>
81
+ </size>
82
+ </property>
83
+ <property name="text">
84
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;A cross platform SSHFS Mapping tool.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Copyright © 2011-2012 The Qasim Team&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;http://github.com/Glenux/Qasim&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;http://github.com/Glenux/Qasim&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
85
+ </property>
86
+ <property name="scaledContents">
87
+ <bool>false</bool>
88
+ </property>
89
+ <property name="margin">
90
+ <number>10</number>
91
+ </property>
92
+ </widget>
93
+ </item>
94
+ </layout>
95
+ </widget>
96
+ <widget class="QWidget" name="authors_tab">
97
+ <attribute name="title">
98
+ <string>Authors</string>
99
+ </attribute>
100
+ <layout class="QVBoxLayout" name="_2">
101
+ <item>
102
+ <widget class="QTextEdit" name="authors_textedit">
103
+ <property name="sizePolicy">
104
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
105
+ <horstretch>0</horstretch>
106
+ <verstretch>0</verstretch>
107
+ </sizepolicy>
108
+ </property>
109
+ <property name="html">
110
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
111
+ &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
112
+ p, li { white-space: pre-wrap; }
113
+ &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
114
+ &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
115
+ </property>
116
+ </widget>
117
+ </item>
118
+ </layout>
119
+ </widget>
120
+ <widget class="QWidget" name="thanks_tab">
121
+ <attribute name="title">
122
+ <string>Thanks to</string>
123
+ </attribute>
124
+ <layout class="QVBoxLayout" name="verticalLayout_4">
125
+ <item>
126
+ <widget class="QTextEdit" name="thanks_textedit"/>
127
+ </item>
128
+ </layout>
129
+ </widget>
130
+ <widget class="QWidget" name="license_tab">
131
+ <attribute name="title">
132
+ <string>License</string>
133
+ </attribute>
134
+ <layout class="QVBoxLayout" name="verticalLayout_5">
135
+ <item>
136
+ <widget class="QTextEdit" name="license_textedit">
137
+ <property name="minimumSize">
138
+ <size>
139
+ <width>300</width>
140
+ <height>200</height>
141
+ </size>
142
+ </property>
143
+ <property name="html">
144
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
145
+ &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
146
+ p, li { white-space: pre-wrap; }
147
+ &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
148
+ &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
149
+ </property>
150
+ </widget>
151
+ </item>
152
+ </layout>
153
+ </widget>
154
+ </widget>
155
+ </item>
156
+ </layout>
157
+ </item>
158
+ <item>
159
+ <widget class="QDialogButtonBox" name="button_box">
160
+ <property name="orientation">
161
+ <enum>Qt::Horizontal</enum>
162
+ </property>
163
+ <property name="standardButtons">
164
+ <set>QDialogButtonBox::Close</set>
165
+ </property>
166
+ </widget>
167
+ </item>
168
+ </layout>
169
+ </widget>
170
+ <resources>
171
+ <include location="../qasim.qrc"/>
172
+ <include location="../../../qasim.qrc"/>
173
+ </resources>
174
+ <connections>
175
+ <connection>
176
+ <sender>button_box</sender>
177
+ <signal>clicked(QAbstractButton*)</signal>
178
+ <receiver>About</receiver>
179
+ <slot>accept()</slot>
180
+ <hints>
181
+ <hint type="sourcelabel">
182
+ <x>463</x>
183
+ <y>493</y>
184
+ </hint>
185
+ <hint type="destinationlabel">
186
+ <x>469</x>
187
+ <y>12</y>
188
+ </hint>
189
+ </hints>
190
+ </connection>
191
+ </connections>
192
+ </ui>