aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/chrome_loader.rs
blob: 544e9a64f4a94521c9190d994ff62acbade26c0e (plain) (blame)
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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use file_loader;
use mime_classifier::MIMEClassifier;
use net_traits::{LoadConsumer, LoadData, NetworkError};
use resource_thread::{CancellationListener, send_error};
use std::fs::canonicalize;
use std::sync::Arc;
use url::Url;
use url::percent_encoding::percent_decode;
use util::resource_files::resources_dir_path;

pub fn resolve_chrome_url(url: &Url) -> Result<Url, ()> {
    assert_eq!(url.scheme(), "chrome");
    if url.host_str() != Some("resources") {
        return Err(())
    }
    let resources = canonicalize(resources_dir_path())
        .expect("Error canonicalizing path to the resources directory");
    let mut path = resources.clone();
    for segment in url.path_segments().unwrap() {
        match percent_decode(segment.as_bytes()).decode_utf8() {
            // Check ".." to prevent access to files outside of the resources directory.
            Ok(segment) => path.push(&*segment),
            _ => return Err(())
        }
    }
    match canonicalize(path) {
        Ok(ref path) if path.starts_with(&resources) && path.exists() => {
            Ok(Url::from_file_path(path).unwrap())
        }
        _ => Err(())
    }
}

pub fn factory(mut load_data: LoadData,
               start_chan: LoadConsumer,
               classifier: Arc<MIMEClassifier>,
               cancel_listener: CancellationListener) {
    let file_url = match resolve_chrome_url(&load_data.url) {
        Ok(url) => url,
        Err(_) => {
            send_error(load_data.url,
                       NetworkError::Internal("Invalid chrome URL.".to_owned()),
                       start_chan);
            return;
        }
    };
    load_data.url = file_url;
    file_loader::factory(load_data, start_chan, classifier, cancel_listener)
}