1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which
// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be
// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use app::App;

use errors::*;
use std::ascii::AsciiExt;
use std::fs::{File, create_dir_all};
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
use xdg_basedir::dirs::get_data_home;

/// Open a given URI on Linux systems
pub fn open<S: Into<String>>(uri: S) -> Result<()> {
    let uri = uri.into();

    let output = Command::new("xdg-open")
        .arg(uri.clone())
        .output()
        .chain_err(|| "Could not execute xdg-open")?;

    if output.status.success() {
        Ok(())
    } else {
        Err(
            format!(
                "Executing `xdg-open {}` failed: {}",
                uri,
                String::from_utf8_lossy(&output.stdout)
            ).into(),
        )
    }

}

/// Clean URI for xdg-open
fn clean_string(input: &str) -> String {
    input.replace(".", "").replace("/", "").to_ascii_lowercase()
}

/// Register the given App for the given schemes on Linux
pub fn install(app: &App, schemes: &[String]) -> Result<()> {
    let home = get_data_home().chain_err(|| "Home directory not found")?;
    let ascii_name = format!(
        "{}-{}.desktop",
        clean_string(&app.vendor).as_str(),
        clean_string(&app.name).as_str()
    );

    let mut desktop_target = PathBuf::new();
    desktop_target.push(home);
    desktop_target.push("applications");

    let apps_dir = desktop_target.clone();

    create_dir_all(apps_dir.clone()).chain_err(
        || "Could not create app directory",
    )?;

    desktop_target.push(ascii_name.clone());
    let mut f = File::create(desktop_target.as_path()).chain_err(
        || "Could not create app desktop file",
    )?;
    let schemes_list = schemes
        .iter()
        .map(|s| match s.matches(char::is_uppercase).next() {
            Some(_) => {
                println!("[WARN] system-uri: converting schema '{}' to lowercase", s);
                format!("x-scheme-handler/{}", s.to_lowercase())
            }
            None => format!("x-scheme-handler/{}", s),
        })
        .collect::<Vec<String>>();

    f.write_fmt(format_args!(
        include_str!("./template.desktop"),
        name = app.name,
        exec = app.exec,
        // app.icon.unwrap_or("".to_string()),
        mime_types = schemes_list.join(";")
    )).chain_err(|| " Could not write app desktop file")?;

    let status = Command::new("update-desktop-database")
        .arg(apps_dir)
        .status()
        .chain_err(|| "Could not run update-desktop-database")?;


    for scheme in schemes_list {
        let _ = Command::new("xdg-mime")
            .arg("default")
            .arg(ascii_name.clone())
            .arg(scheme)
            .status()
            .chain_err(|| "Could not run xdg-mime")?;
    }

    if status.success() {
        Ok(())
    } else {
        Err(
            ("Executing update-desktop-database failed. See terminal output for errors.").into(),
        )
    }
}