~elementary-apps/slingshot/synapse-desktop-only

« back to all changes in this revision

Viewing changes to lib/synapse-plugins/ssh-plugin.vala

  • Committer: Tom Beckmann
  • Date: 2014-06-12 09:14:57 UTC
  • Revision ID: tomjonabc@gmail.com-20140612091457-1spb2qtytxybnvkg
Remove all plugins but desktop-file and command one, fix code style

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2011 Antono Vasiljev <self@antono.info>
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License as published by
6
 
 * the Free Software Foundation; either version 3 of the License, or
7
 
 * (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
17
 
 *
18
 
 * Authored by Antono Vasiljev <self@antono.info>
19
 
 *
20
 
 */
21
 
 
22
 
using Gee;
23
 
 
24
 
namespace Synapse
25
 
{
26
 
  public class SshPlugin: Object, Activatable, ItemProvider
27
 
  {
28
 
    public  bool      enabled { get; set; default = true; }
29
 
    private HashMap<string, SshHost> hosts;
30
 
    
31
 
    protected File config_file;
32
 
    protected FileMonitor monitor;
33
 
 
34
 
    static construct
35
 
    {
36
 
      register_plugin ();
37
 
    }
38
 
    
39
 
    construct
40
 
    {
41
 
      hosts = new HashMap<string, SshHost> ();
42
 
    }
43
 
 
44
 
    public void activate ()
45
 
    {
46
 
      this.config_file = File.new_for_path (Environment.get_home_dir () + "/.ssh/config");
47
 
 
48
 
      parse_ssh_config.begin ();
49
 
 
50
 
      try {
51
 
        this.monitor = config_file.monitor_file (FileMonitorFlags.NONE);
52
 
        this.monitor.changed.connect (this.handle_ssh_config_update);
53
 
      }
54
 
      catch (IOError e)
55
 
      {
56
 
        Utils.Logger.warning (this, "Failed to start monitoring changes of ssh client config file");
57
 
      }
58
 
    }
59
 
 
60
 
    public void deactivate () {}
61
 
 
62
 
    static void register_plugin ()
63
 
    {
64
 
      DataSink.PluginRegistry.get_default ().register_plugin (
65
 
        typeof (SshPlugin),
66
 
                "SSH", // Plugin title
67
 
        _ ("Connect to host with SSH"), // description
68
 
        "terminal",     // icon name
69
 
        register_plugin, // reference to this function
70
 
                // true if user's system has all required components which the plugin needs
71
 
        (Environment.find_program_in_path ("ssh") != null),
72
 
        _ ("ssh is not installed") // error message
73
 
      );
74
 
    }
75
 
 
76
 
    private async void parse_ssh_config ()
77
 
    {
78
 
      hosts.clear ();
79
 
 
80
 
      try
81
 
      {
82
 
        var dis = new DataInputStream (config_file.read ());
83
 
 
84
 
        // TODO: match key boundary
85
 
        Regex host_key_re = new Regex ("(host\\s)", RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS);
86
 
        Regex comment_re  = new Regex ("#.*$", RegexCompileFlags.OPTIMIZE);
87
 
        Regex ws_re = new Regex ("[\\s]+", RegexCompileFlags.OPTIMIZE);
88
 
 
89
 
        string line;
90
 
 
91
 
        while ((line = yield dis.read_line_async (Priority.DEFAULT)) != null)
92
 
        {
93
 
          /* Delete comments */
94
 
          line = comment_re.replace (line, -1, 0, "");
95
 
          if (host_key_re.match (line))
96
 
          {
97
 
            /* remove "Host" key */
98
 
            line = host_key_re.replace (line, -1, 0, "");
99
 
            /* Replace multiple whitespaces with a single space char */
100
 
            line = ws_re.replace (line, -1, 0, " ").strip ();
101
 
            /* split to find multiple host definition */
102
 
            foreach (var host in line.split (" "))
103
 
            {
104
 
              string host_stripped = host.strip ();
105
 
              if (host_stripped != "" && host_stripped.index_of ("*") == -1 && host_stripped.index_of ("?") == -1)
106
 
              {
107
 
                Utils.Logger.debug (this, "host added: %s\n", host_stripped);
108
 
                hosts.set (host_stripped, new SshHost (host_stripped));
109
 
              }
110
 
            }
111
 
          }
112
 
        }
113
 
      }
114
 
      catch (Error e)
115
 
      {
116
 
        Utils.Logger.warning (this, "%s: %s", config_file.get_path (), e.message);
117
 
      }
118
 
    }
119
 
    
120
 
    public void handle_ssh_config_update (FileMonitor monitor,
121
 
                                          File file,
122
 
                                          File? other_file,
123
 
                                          FileMonitorEvent event_type)
124
 
    {
125
 
      if (event_type == FileMonitorEvent.CHANGES_DONE_HINT)
126
 
      {
127
 
        Utils.Logger.log (this, "ssh_config is changed, reparsing");
128
 
        parse_ssh_config.begin ();
129
 
      }
130
 
    }
131
 
 
132
 
    public bool handles_query (Query query)
133
 
    {
134
 
      return hosts.size > 0 && 
135
 
            ( QueryFlags.ACTIONS in query.query_type ||
136
 
              QueryFlags.INTERNET in query.query_type);
137
 
    }
138
 
 
139
 
    public async ResultSet? search (Query q) throws SearchError
140
 
    {
141
 
      Idle.add (search.callback);
142
 
      yield;
143
 
      q.check_cancellable ();
144
 
 
145
 
      var results = new ResultSet ();
146
 
      
147
 
      var matchers = Query.get_matchers_for_query (q.query_string, 0,
148
 
        RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS);
149
 
 
150
 
      foreach (var host in hosts.values) //workaround for missing HashMap.iterator() method
151
 
      {
152
 
        foreach (var matcher in matchers)
153
 
        {
154
 
          if (matcher.key.match (host.host_query))
155
 
          {
156
 
            results.add (host, matcher.value - Match.Score.INCREMENT_SMALL);
157
 
            break;
158
 
          }
159
 
        }
160
 
      }
161
 
 
162
 
      q.check_cancellable ();
163
 
 
164
 
      return results;
165
 
    }
166
 
 
167
 
    private class SshHost : Object, Match
168
 
    {
169
 
      public string title           { get; construct set; }
170
 
      public string description     { get; set; }
171
 
      public string icon_name       { get; construct set; }
172
 
      public bool   has_thumbnail   { get; construct set; }
173
 
      public string thumbnail_path  { get; construct set; }
174
 
      public string host_query      { get; construct set; }
175
 
      public MatchType match_type   { get; construct set; }
176
 
 
177
 
      public void execute (Match? match)
178
 
      {
179
 
        try
180
 
        {
181
 
          AppInfo ai = AppInfo.create_from_commandline (
182
 
            "ssh %s".printf (this.title),
183
 
            "ssh", AppInfoCreateFlags.NEEDS_TERMINAL);
184
 
          ai.launch (null, new Gdk.AppLaunchContext ());
185
 
        }
186
 
        catch (Error err)
187
 
        {
188
 
          warning ("%s", err.message);
189
 
        }
190
 
      }
191
 
 
192
 
      public SshHost (string host_name)
193
 
      {
194
 
        Object (
195
 
          match_type: MatchType.ACTION,
196
 
          title: host_name,
197
 
          description: _("Connect with SSH"),
198
 
          has_thumbnail: false,
199
 
          icon_name: "terminal",
200
 
          host_query: host_name
201
 
        );
202
 
        
203
 
      }
204
 
    }
205
 
  }
206
 
}
207
 
 
208
 
// vim: expandtab softtabstop tabstop=2
209