<commit_before>extern crate discord;

use std::env;
use discord::{Discord, State};
use discord::model::Event;

pub fn main() {
	// Log in to Discord using a bot token from the environment
	let discord = Discord::from_bot_token(
		&env::var("DISCORD_TOKEN").expect("Expected token"),
	).expect("login failed");

	// establish websocket and voice connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	println!("[Ready] {} is serving {} servers", ready.user.username, ready.servers.len());
	let mut state = State::new(ready);
	connection.sync_calls(&state.all_private_channels());

	// receive events forever
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("[Warning] Receive error: {:?}", err);
				if let discord::Error::WebSocket(..) = err {
					// Handle the websocket connection being dropped
					let (new_connection, ready) = discord.connect().expect("connect failed");
					connection = new_connection;
					state = State::new(ready);
					println!("[Ready] Reconnected successfully.");
				}
				if let discord::Error::Closed(..) = err {
					break
				}
				continue
			},
		};
		state.update(&event);

		match event {
			Event::MessageCreate(message) => {
				use std::ascii::AsciiExt;
				// safeguard: stop if the message is from us
				if message.author.id == state.user().id {
					continue
				}

				// reply to a command if there was one
				let mut split = message.content.split(' ');
				let first_word = split.next().unwrap_or("");
				let argument = split.next().unwrap_or("");

				//Section of avaliable commands.
                if first_word.eq_ignore_ascii_case("!help") {
                    if argument.eq_ignore_ascii_case("commands") {
                        warn(discord.send_message(message.channel_id, "help, about, uber, distrowiki, and sourcecode are the avaliable commands. (!dj is buggy)", "", false))
                    }
		    		else if argument.eq_ignore_ascii_case("about") {
			 			warn(discord.send_message(message.channel_id, "Displays info about me. No arguments available.", "", false))
		    		}
		    		else if argument.eq_ignore_ascii_case("uber") {
						warn(discord.send_message(message.channel_id, "Uber an object (I'm picky).", "", false))
		    		}
		    		else if argument.eq_ignore_ascii_case("distrowiki") {
						warn(discord.send_message(message.channel_id, "Finds the wiki of the specified distro. Arguments include Arch, Ubuntu, Debian, Antergos, Mint, CentOS, OpenBSD, Opensuse, Sabayon, KaliLinux, Solus, and Gentoo.", "", false))
		    		}
		    		else if argument.eq_ignore_ascii_case("sourcecode") {
						warn(discord.send_message(message.channel_id, "Displays where I am on GitHub. No arguments available", "", false))
	            	}
		    		else if argument.eq_ignore_ascii_case("help") {
						warn(discord.send_message(message.channel_id, "Are you trying to break me?", "", false))
	            	}
		    		else if argument.eq_ignore_ascii_case("[args]") {
						warn(discord.send_message(message.channel_id, "You're helpless.", "", false))
	            	}
                    else {
                    warn(discord.send_message(message.channel_id, "Umm, you gotta use it like this. !help [args] Try using the `commands` argument.", "", false))
                    }
                }

				//Fun Commands.
                if first_word.eq_ignore_ascii_case("!about") {
                    warn(discord.send_message(message.channel_id, "I have no clue. All I know is that I was written by Arroz in a language called Rust, and my code is still being developed.", "", false))
                }
		        if first_word.eq_ignore_ascii_case("!wheresteal") {
			        warn(discord.send_message(message.channel_id, "Go ask him, I know nothing ;_;", "", false))
		        }
                if first_word.eq_ignore_ascii_case("!hello") {
					          warn(discord.send_message(message.channel_id, "https://www.tenor.co/xA8B.gif", "", false))
				        }
                if first_word.eq_ignore_ascii_case("!uber"){
					if argument.eq_ignore_ascii_case("ddog75") {
                        warn(discord.send_message(message.channel_id, "Alright, 10 minutes.", "", false))
                    }
					else if argument.eq_ignore_ascii_case("aspire") {
						warn(discord.send_message(message.channel_id, "Not the meatballs.", "", false))
					}
					else if argument.eq_ignore_ascii_case("nic") {
					    warn(discord.send_message(message.channel_id, "NOT THE BEES!!!", "", false))
					}
					else {
                        warn(discord.send_message(message.channel_id, "Fuck off!", "", false))
                    }
                }
                if first_word.eq_ignore_ascii_case("!sourcecode") {
                    warn(discord.send_message(message.channel_id, "Okay, here you go. https://github.com/aarroz/rice_bot2", "", false))
                }
				//Section that prints wikis for linux distributions.
				if first_word.eq_ignore_ascii_case("!distrowiki") {
					if argument.eq_ignore_ascii_case("arch") {
						warn(discord.send_message(message.channel_id, "Here's the Arch Wiki! https://wiki.archlinux.org/", "", false))
					}
					else if argument.eq_ignore_ascii_case("ubuntu") {
						warn(discord.send_message(message.channel_id, "Here's the Ubuntu Wiki! https://wiki.ubuntu.com/", "", false))
					}
					else if argument.eq_ignore_ascii_case("debian") {
						warn(discord.send_message(message.channel_id, "Here's the Debian Wiki! https://wiki.debian.org/", "", false))
					}
					else if argument.eq_ignore_ascii_case("antergos") {
						warn(discord.send_message(message.channel_id, "Here's the Antergos Wiki! https://antergos.com/wiki/", "", false))
					}
					else if argument.eq_ignore_ascii_case("centos") {
						warn(discord.send_message(message.channel_id, "Here's the CentOS Wiki! https://wiki.centos.org/", "", false))
					}
					//Sorry OpenBSD users.
					else if argument.eq_ignore_ascii_case("openbsd") {
						warn(discord.send_message(message.channel_id, "No, just no.", "", false))
					}
					//Not sorry.
					else if argument.eq_ignore_ascii_case("gentoo") {
						warn(discord.send_message(message.channel_id, "Here's the Gentoo Wiki! https://wiki.gentoo.org/wiki/Main_Page", "", false))
					}
					else if argument.eq_ignore_ascii_case("opensuse") {
						warn(discord.send_message(message.channel_id, "Here's the OpenSuse Wiki! https://en.opensuse.org/Portal:Wiki", "", false))
					}
					else if argument.eq_ignore_ascii_case("sabayon") {
						warn(discord.send_message(message.channel_id, "Here's the Sabayon Wiki! https://wiki.sabayon.org/", "", false))
					}
					else if argument.eq_ignore_ascii_case("kalilinux") {
						warn(discord.send_message(message.channel_id, "Heres's the KaliLinux Wiki! https://en.wikipedia.org/wiki/Kali_Linux", "", false))
					}
					else if argument.eq_ignore_ascii_case("mint") {
						warn(discord.send_message(message.channel_id, "Here's the Mint newbie page! https://forums.linuxmint.com/viewforum.php?f=90", "", false))
					}
					else if argument.eq_ignore_ascii_case("solus") {
						warn(discord.send_message(message.channel_id, "There is no wiki for solus, however there is the help page! https://solus-project.com/help-center/home/", "", false))
					}
					else if argument.eq_ignore_ascii_case("windows") {
						warn(discord.send_message(message.channel_id, "Thats not a distro.", "", false))
					}
					else if argument.eq_ignore_ascii_case("macos") {
						warn(discord.send_message(message.channel_id, "Sure its close to linux, but I'm too tired to have that argument.", "", false))
					}
					else {
						warn(discord.send_message(message.channel_id, "Please use a distro from !help distrowiki.", "", false))
					}
				}

                // Command for using dj.
				if first_word.eq_ignore_ascii_case("!dj") {
					let vchan = state.find_voice_user(message.author.id);
					if argument.eq_ignore_ascii_case("stop") {
						vchan.map(|(sid, _)| connection.voice(sid).stop());
					} else if argument.eq_ignore_ascii_case("quit") {
						vchan.map(|(sid, _)| connection.drop_voice(sid));
					} else {
						let output = if let Some((server_id, channel_id)) = vchan {
							match discord::voice::open_ytdl_stream(argument) {
								Ok(stream) => {
									let voice = connection.voice(server_id);
									voice.set_deaf(true);
									voice.connect(channel_id);
									voice.play(stream);
									String::new()
								},
								Err(error) => format!("Error: {}", error),
							}
						} else {
							"You must be in a voice channel to DJ".to_owned()
						};
						if !output.is_empty() {
							warn(discord.send_message(message.channel_id, &output, "", false));
						}
					}
				}
			}
			Event::VoiceStateUpdate(server_id, _) => {
				// If someone moves/hangs up, and we are in a voice channel,
				if let Some(cur_channel) = connection.voice(server_id).current_channel() {
					// and our current voice channel is empty, disconnect from voice
					match server_id {
						Some(server_id) => if let Some(srv) = state.servers().iter().find(|srv| srv.id == server_id) {
							if srv.voice_states.iter().filter(|vs| vs.channel_id == Some(cur_channel)).count() <= 1 {
								connection.voice(Some(server_id)).disconnect();
							}
						},
						None => if let Some(call) = state.calls().get(&cur_channel) {
							if call.voice_states.len() <= 1 {
								connection.voice(server_id).disconnect();
							}
						}
					}
				}
			}
			_ => {}, // discard other events
		}
	}
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[Warning] {:?}", err)
	}
}
<commit_msg>Formatting, add !bye<commit_after>extern crate discord;

use std::env;
use discord::{Discord, State};
use discord::model::Event;

pub fn main() {
	// Log in to Discord using a bot token from the environment
	let discord = Discord::from_bot_token(
		&env::var("DISCORD_TOKEN").expect("Expected token"),
	).expect("login failed");

	// establish websocket and voice connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	println!("[Ready] {} is serving {} servers", ready.user.username, ready.servers.len());
	let mut state = State::new(ready);
	connection.sync_calls(&state.all_private_channels());

	// receive events forever
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("[Warning] Receive error: {:?}", err);
				if let discord::Error::WebSocket(..) = err {
					// Handle the websocket connection being dropped
					let (new_connection, ready) = discord.connect().expect("connect failed");
					connection = new_connection;
					state = State::new(ready);
					println!("[Ready] Reconnected successfully.");
				}
				if let discord::Error::Closed(..) = err {
					break
				}
				continue
			},
		};
		state.update(&event);

		match event {
			Event::MessageCreate(message) => {
				use std::ascii::AsciiExt;
				// safeguard: stop if the message is from us
				if message.author.id == state.user().id {
					continue
				}

				// reply to a command if there was one
				let mut split = message.content.split(' ');
				let first_word = split.next().unwrap_or("");
				let argument = split.next().unwrap_or("");

				//Section of avaliable commands.
                if first_word.eq_ignore_ascii_case("!help") {
                    if argument.eq_ignore_ascii_case("commands") {
                        warn(discord.send_message(message.channel_id, "help, about, uber, distrowiki, and sourcecode are the avaliable commands. (!dj is buggy)", "", false))
                    }
		    		else if argument.eq_ignore_ascii_case("about") {
			 			warn(discord.send_message(message.channel_id, "Displays info about me. No arguments available.", "", false))
		    		}
		    		else if argument.eq_ignore_ascii_case("uber") {
						warn(discord.send_message(message.channel_id, "Uber an object (I'm picky).", "", false))
		    		}
		    		else if argument.eq_ignore_ascii_case("distrowiki") {
						warn(discord.send_message(message.channel_id, "Finds the wiki of the specified distro. Arguments include Arch, Ubuntu, Debian, Antergos, Mint, CentOS, OpenBSD, Opensuse, Sabayon, KaliLinux, Solus, and Gentoo.", "", false))
		    		}
		    		else if argument.eq_ignore_ascii_case("sourcecode") {
						warn(discord.send_message(message.channel_id, "Displays where I am on GitHub. No arguments available", "", false))
	            	}
		    		else if argument.eq_ignore_ascii_case("help") {
						warn(discord.send_message(message.channel_id, "Are you trying to break me?", "", false))
	            	}
		    		else if argument.eq_ignore_ascii_case("[args]") {
						warn(discord.send_message(message.channel_id, "You're helpless.", "", false))
	            	}
                    else {
                    warn(discord.send_message(message.channel_id, "Umm, you gotta use it like this. !help [args] Try using the `commands` argument.", "", false))
                    }
                }

				//Fun Commands.
                if first_word.eq_ignore_ascii_case("!about") {
                    warn(discord.send_message(message.channel_id, "I have no clue. All I know is that I was written by Arroz in a language called Rust, and my code is still being developed.", "", false))
                }
		        if first_word.eq_ignore_ascii_case("!wheresteal") {
			        warn(discord.send_message(message.channel_id, "He's alive and well.", "", false)) //yay
		        }
                if first_word.eq_ignore_ascii_case("!hello") {
				warn(discord.send_message(message.channel_id, "https://www.tenor.co/xA8B.gif", "", false))
			}
		if first_word.eq_ignore ascii_case("!bye") {
				warn(discord.send_message(message.channel_id, "https://tenor.com/woQk.gif", "", false))
			}
                if first_word.eq_ignore_ascii_case("!uber"){
					if argument.eq_ignore_ascii_case("ddog75") {
                        warn(discord.send_message(message.channel_id, "Alright, 10 minutes.", "", false))
                    	}
					else if argument.eq_ignore_ascii_case("aspire") {
						warn(discord.send_message(message.channel_id, "Not the meatballs.", "", false))
					}
					else if argument.eq_ignore_ascii_case("nic") {
					    warn(discord.send_message(message.channel_id, "NOT THE BEES!!!", "", false))
					}
					else {
                        warn(discord.send_message(message.channel_id, "Fuck off!", "", false))
                    }
                }
                if first_word.eq_ignore_ascii_case("!sourcecode") {
                    warn(discord.send_message(message.channel_id, "Okay, here you go. https://github.com/aarroz/rice_bot2", "", false))
                }
				//Section that prints wikis for linux distributions.
				if first_word.eq_ignore_ascii_case("!distrowiki") {
					if argument.eq_ignore_ascii_case("arch") {
						warn(discord.send_message(message.channel_id, "Here's the Arch Wiki! https://wiki.archlinux.org/", "", false))
					}
					else if argument.eq_ignore_ascii_case("ubuntu") {
						warn(discord.send_message(message.channel_id, "Here's the Ubuntu Wiki! https://wiki.ubuntu.com/", "", false))
					}
					else if argument.eq_ignore_ascii_case("debian") {
						warn(discord.send_message(message.channel_id, "Here's the Debian Wiki! https://wiki.debian.org/", "", false))
					}
					else if argument.eq_ignore_ascii_case("antergos") {
						warn(discord.send_message(message.channel_id, "Here's the Antergos Wiki! https://antergos.com/wiki/", "", false))
					}
					else if argument.eq_ignore_ascii_case("centos") {
						warn(discord.send_message(message.channel_id, "Here's the CentOS Wiki! https://wiki.centos.org/", "", false))
					}
					//Sorry OpenBSD users.
					else if argument.eq_ignore_ascii_case("openbsd") {
						warn(discord.send_message(message.channel_id, "No, just no.", "", false))
					}
					//Not sorry.
					else if argument.eq_ignore_ascii_case("gentoo") {
						warn(discord.send_message(message.channel_id, "Here's the Gentoo Wiki! https://wiki.gentoo.org/wiki/Main_Page", "", false))
					}
					else if argument.eq_ignore_ascii_case("opensuse") {
						warn(discord.send_message(message.channel_id, "Here's the OpenSuse Wiki! https://en.opensuse.org/Portal:Wiki", "", false))
					}
					else if argument.eq_ignore_ascii_case("sabayon") {
						warn(discord.send_message(message.channel_id, "Here's the Sabayon Wiki! https://wiki.sabayon.org/", "", false))
					}
					else if argument.eq_ignore_ascii_case("kalilinux") {
						warn(discord.send_message(message.channel_id, "Heres's the KaliLinux Wiki! https://en.wikipedia.org/wiki/Kali_Linux", "", false))
					}
					else if argument.eq_ignore_ascii_case("mint") {
						warn(discord.send_message(message.channel_id, "Here's the Mint newbie page! https://forums.linuxmint.com/viewforum.php?f=90", "", false))
					}
					else if argument.eq_ignore_ascii_case("solus") {
						warn(discord.send_message(message.channel_id, "There is no wiki for solus, however there is the help page! https://solus-project.com/help-center/home/", "", false))
					}
					else if argument.eq_ignore_ascii_case("windows") {
						warn(discord.send_message(message.channel_id, "Thats not a distro.", "", false))
					}
					else if argument.eq_ignore_ascii_case("macos") {
						warn(discord.send_message(message.channel_id, "Sure its close to linux, but I'm too tired to have that argument.", "", false))
					}
					else {
						warn(discord.send_message(message.channel_id, "Please use a distro from !help distrowiki.", "", false))
					}
				}

                // Command for using dj.
				if first_word.eq_ignore_ascii_case("!dj") {
					let vchan = state.find_voice_user(message.author.id);
					if argument.eq_ignore_ascii_case("stop") {
						vchan.map(|(sid, _)| connection.voice(sid).stop());
					} else if argument.eq_ignore_ascii_case("quit") {
						vchan.map(|(sid, _)| connection.drop_voice(sid));
					} else {
						let output = if let Some((server_id, channel_id)) = vchan {
							match discord::voice::open_ytdl_stream(argument) {
								Ok(stream) => {
									let voice = connection.voice(server_id);
									voice.set_deaf(true);
									voice.connect(channel_id);
									voice.play(stream);
									String::new()
								},
								Err(error) => format!("Error: {}", error),
							}
						} else {
							"You must be in a voice channel to DJ".to_owned()
						};
						if !output.is_empty() {
							warn(discord.send_message(message.channel_id, &output, "", false));
						}
					}
				}
			}
			Event::VoiceStateUpdate(server_id, _) => {
				// If someone moves/hangs up, and we are in a voice channel,
				if let Some(cur_channel) = connection.voice(server_id).current_channel() {
					// and our current voice channel is empty, disconnect from voice
					match server_id {
						Some(server_id) => if let Some(srv) = state.servers().iter().find(|srv| srv.id == server_id) {
							if srv.voice_states.iter().filter(|vs| vs.channel_id == Some(cur_channel)).count() <= 1 {
								connection.voice(Some(server_id)).disconnect();
							}
						},
						None => if let Some(call) = state.calls().get(&cur_channel) {
							if call.voice_states.len() <= 1 {
								connection.voice(server_id).disconnect();
							}
						}
					}
				}
			}
			_ => {}, // discard other events
		}
	}
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[Warning] {:?}", err)
	}
}
<|endoftext|>


<commit_before>extern crate open_gl_bindings;
extern crate sdl2;

use open_gl_bindings::gl;

use std::ffi::CStr;
use std::str;

fn find_sdl_gl_driver() -> Option<u32> {
    for (index, item) in sdl2::render::drivers().enumerate() {
        if item.name == "opengl" {
            return Some(index as u32);
        }
    }
    None
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let window = video_subsystem
        .window("Window", 800, 600)
        .opengl()
        .build()
        .unwrap();
    let canvas = window
        .into_canvas()
        .index(find_sdl_gl_driver().unwrap())
        .build()
        .unwrap();

    let ctx = gl::Gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);
    canvas.window().gl_set_context_to_current();

    let char_ptr = unsafe { ctx.GetString(gl::VERSION) };
    let c_str: &CStr = unsafe { CStr::from_ptr(std::mem::transmute(char_ptr)) };
    let buf: &[u8] = c_str.to_bytes();
    let str_slice: &str = str::from_utf8(buf).unwrap();
    let version: String = str_slice.to_owned();

    println!("OpenGL version: {}", version);
}
<commit_msg>Window that stays open until you quit<commit_after>extern crate open_gl_bindings;
extern crate sdl2;

use open_gl_bindings::gl;

use sdl2::event::Event;

use std::ffi::CStr;
use std::str;

fn find_sdl_gl_driver() -> Option<u32> {
    for (index, item) in sdl2::render::drivers().enumerate() {
        if item.name == "opengl" {
            return Some(index as u32);
        }
    }
    None
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let window = video_subsystem
        .window("Window", 800, 600)
        .opengl()
        .build()
        .unwrap();
    let canvas = window
        .into_canvas()
        .index(find_sdl_gl_driver().unwrap())
        .build()
        .unwrap();

    let ctx = gl::Gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);
    canvas.window().gl_set_context_to_current().unwrap();

    let char_ptr = unsafe { ctx.GetString(gl::VERSION) };
    let c_str: &CStr = unsafe { CStr::from_ptr(std::mem::transmute(char_ptr)) };
    let buf: &[u8] = c_str.to_bytes();
    let str_slice: &str = str::from_utf8(buf).unwrap();
    let version: String = str_slice.to_owned();

    println!("OpenGL version: {}", version);

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(sdl2::keyboard::Keycode::Escape), .. } |
                Event::KeyDown { keycode: Some(sdl2::keyboard::Keycode::F10), .. } => {
                    break 'running;
                }
                _ => {}
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate alpm;
extern crate clap;
extern crate curl;
extern crate env_logger;
extern crate itertools;
extern crate json;
#[macro_use]
extern crate log;
extern crate select;

use clap::{Arg, App};
use curl::easy::Easy;
use itertools::Itertools;
use select::document::Document;
use select::predicate::Name;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::str;

#[derive(Debug)]
struct ASA {
    cve: Vec<String>,
    version: Option<String>,
}

impl Default for ASA {
    fn default() -> ASA {
        ASA {
            cve: Vec::new(),
            version: None,
        }
    }
}

#[derive(Debug)]
struct Options {
    format: Option<String>,
    quiet: u64,
    upgradable_only: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            format: None,
            quiet: 0,
            upgradable_only: false
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args = App::new("arch-audit")
                        .version("0.1.2")
                        .arg(Arg::with_name("format")
                             .short("f")
                             .long("format")
                             .takes_value(true)
                             .help("Specify a format to control the output. Placeholders are %n (pkgname) and %c (CVEs)"))
                        .arg(Arg::with_name("quiet")
                             .short("q")
                             .long("quiet")
                             .multiple(true)
                             .help("Show only vulnerable package names and their versions"))
                        .arg(Arg::with_name("upgradable")
                             .short("u")
                             .long("upgradable")
                             .help("Show only packages that have already been fixed"))
                        .get_matches();

    let options = Options {
        format: { match args.value_of("format") {
            Some(f) => { Some(f.to_string()) },
            None => { None },
            } },
        quiet: args.occurrences_of("quiet"),
        upgradable_only: args.is_present("upgradable"),
    };

    let mut wikipage = String::new();
    {
        info!("Downloading CVE wiki page...");
        let wikipage_url = "https://wiki.archlinux.org/api.php?format=json&action=parse&page=CVE&section=5";

        let mut easy = Easy::new();
        easy.url(wikipage_url).unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            wikipage.push_str(str::from_utf8(data).unwrap());
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }

    let mut infos: HashMap<String, Vec<_>> = HashMap::new();
    {
        let json = json::parse(wikipage.as_str()).unwrap();
        let document = Document::from(json["parse"]["text"]["*"].as_str().unwrap());

        for tr in document.find(Name("tbody")).find(Name("tr")).iter() {
            let tds = tr.find(Name("td"));

            match tds.first() {
                Some(td) => {
                    let mut next = tds.next().next();
                    let pkgname = next.first().unwrap().text().trim().to_string();
                    next = next.next().next().next().next().next().next();
                    let info = ASA {
                        cve: td.text().split_whitespace().filter(|s| s.starts_with("CVE")).map(|s| s.to_string()).collect(),
                        version: {
                            let v = next.first().unwrap().text().trim().to_string();
                            if !v.is_empty() && v != "?".to_string() && v != "-".to_string() { Some(v) } else { None }
                        },
                    };
                    next = next.next().next().next().next();
                    let status = next.first().unwrap().text().trim().to_string();

                    if !status.starts_with("Invalid") && !status.starts_with("Not Affected") {
                        match infos.entry(pkgname) {
                            Occupied(c) => { c.into_mut() },
                            Vacant(c) => { c.insert(vec![]) },
                        }.push(info);
                    }
                },
                None => {},
            };
        }
    }

    let pacman = alpm::Alpm::new().unwrap();
    for (pkg, cves) in infos {
        match pacman.query_package_version(pkg.clone()) {
            Ok(v) => {
                info!("Found installed version {} for package {}", v, pkg);
                for cve in cves {
                    match cve.version {
                        Some(version) => {
                            info!("Comparing with fixed version {}", version);
                            match pacman.vercmp(v.clone(), version.clone()).unwrap() {
                                Ordering::Less => { print_asa(&options, &pkg, cve.cve, Some(version) ) },
                                _ => {},
                            };
                        },
                        None => { print_asa(&options, &pkg, cve.cve, None) },
                    };
                };
            },
            Err(_) => { debug!("Package {} not installed", pkg) },
        }
    }
}

fn print_asa(options: &Options, pkgname: &String, cve: Vec<String>, version: Option<String>) {
    let msg = format!("Package {} is affected by {:?}", pkgname, cve);

    match version {
        Some(v) => {
            if options.quiet == 1 {
                println!("{}>={}", pkgname, v);
            } else if options.quiet >= 2 {
                println!("{}", pkgname);
            } else {
                match options.format {
                    Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                    None => { println!("{}. Update to {}!", msg, v) },
                }
            }
        }
        None => {
            if !options.upgradable_only {
                if options.quiet > 0 {
                    println!("{}", pkgname);
                } else {
                    match options.format {
                        Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                        None => { println!("{}. VULNERABLE!", msg) },
                    }
                }
            }
        }
    }
}
<commit_msg>'Invalid' is no more used as status<commit_after>extern crate alpm;
extern crate clap;
extern crate curl;
extern crate env_logger;
extern crate itertools;
extern crate json;
#[macro_use]
extern crate log;
extern crate select;

use clap::{Arg, App};
use curl::easy::Easy;
use itertools::Itertools;
use select::document::Document;
use select::predicate::Name;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::str;

#[derive(Debug)]
struct ASA {
    cve: Vec<String>,
    version: Option<String>,
}

impl Default for ASA {
    fn default() -> ASA {
        ASA {
            cve: Vec::new(),
            version: None,
        }
    }
}

#[derive(Debug)]
struct Options {
    format: Option<String>,
    quiet: u64,
    upgradable_only: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            format: None,
            quiet: 0,
            upgradable_only: false
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args = App::new("arch-audit")
                        .version("0.1.2")
                        .arg(Arg::with_name("format")
                             .short("f")
                             .long("format")
                             .takes_value(true)
                             .help("Specify a format to control the output. Placeholders are %n (pkgname) and %c (CVEs)"))
                        .arg(Arg::with_name("quiet")
                             .short("q")
                             .long("quiet")
                             .multiple(true)
                             .help("Show only vulnerable package names and their versions"))
                        .arg(Arg::with_name("upgradable")
                             .short("u")
                             .long("upgradable")
                             .help("Show only packages that have already been fixed"))
                        .get_matches();

    let options = Options {
        format: { match args.value_of("format") {
            Some(f) => { Some(f.to_string()) },
            None => { None },
            } },
        quiet: args.occurrences_of("quiet"),
        upgradable_only: args.is_present("upgradable"),
    };

    let mut wikipage = String::new();
    {
        info!("Downloading CVE wiki page...");
        let wikipage_url = "https://wiki.archlinux.org/api.php?format=json&action=parse&page=CVE&section=5";

        let mut easy = Easy::new();
        easy.url(wikipage_url).unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            wikipage.push_str(str::from_utf8(data).unwrap());
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }

    let mut infos: HashMap<String, Vec<_>> = HashMap::new();
    {
        let json = json::parse(wikipage.as_str()).unwrap();
        let document = Document::from(json["parse"]["text"]["*"].as_str().unwrap());

        for tr in document.find(Name("tbody")).find(Name("tr")).iter() {
            let tds = tr.find(Name("td"));

            match tds.first() {
                Some(td) => {
                    let mut next = tds.next().next();
                    let pkgname = next.first().unwrap().text().trim().to_string();
                    next = next.next().next().next().next().next().next();
                    let info = ASA {
                        cve: td.text().split_whitespace().filter(|s| s.starts_with("CVE")).map(|s| s.to_string()).collect(),
                        version: {
                            let v = next.first().unwrap().text().trim().to_string();
                            if !v.is_empty() && v != "?".to_string() && v != "-".to_string() { Some(v) } else { None }
                        },
                    };
                    next = next.next().next().next().next();
                    let status = next.first().unwrap().text().trim().to_string();

                    if !status.starts_with("Not Affected") {
                        match infos.entry(pkgname) {
                            Occupied(c) => { c.into_mut() },
                            Vacant(c) => { c.insert(vec![]) },
                        }.push(info);
                    }
                },
                None => {},
            };
        }
    }

    let pacman = alpm::Alpm::new().unwrap();
    for (pkg, cves) in infos {
        match pacman.query_package_version(pkg.clone()) {
            Ok(v) => {
                info!("Found installed version {} for package {}", v, pkg);
                for cve in cves {
                    match cve.version {
                        Some(version) => {
                            info!("Comparing with fixed version {}", version);
                            match pacman.vercmp(v.clone(), version.clone()).unwrap() {
                                Ordering::Less => { print_asa(&options, &pkg, cve.cve, Some(version) ) },
                                _ => {},
                            };
                        },
                        None => { print_asa(&options, &pkg, cve.cve, None) },
                    };
                };
            },
            Err(_) => { debug!("Package {} not installed", pkg) },
        }
    }
}

fn print_asa(options: &Options, pkgname: &String, cve: Vec<String>, version: Option<String>) {
    let msg = format!("Package {} is affected by {:?}", pkgname, cve);

    match version {
        Some(v) => {
            if options.quiet == 1 {
                println!("{}>={}", pkgname, v);
            } else if options.quiet >= 2 {
                println!("{}", pkgname);
            } else {
                match options.format {
                    Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                    None => { println!("{}. Update to {}!", msg, v) },
                }
            }
        }
        None => {
            if !options.upgradable_only {
                if options.quiet > 0 {
                    println!("{}", pkgname);
                } else {
                    match options.format {
                        Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                        None => { println!("{}. VULNERABLE!", msg) },
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate futures;
extern crate tokio_core;

// TCP or UDP?
// Can we get non-persistent TCP connections which don't have buffer stalls?
// Or should we work on UDP to make sure we have control over whether or not
// messages are sent / received?

// Note on the copy(reader, writer) function, it's very simple.
// The function takes data given to reader and copies it over to writer, writing back
// whatever was written. The 'copy' might as well be called 'echo'.

// Also, in this case, when an incoming socket happens, we cannot handle the split
// without a future, since the connection will persist far longer than the 'for_each'
// iteration will, therefore it must be run asynchronously, to avoid only being able
// to handle one client at a time.

use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use tokio_core::io::{copy, Io};
use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;

fn main() {
    let addr = "127.0.0.1:8080".to_string().parse::<SocketAddr>().unwrap();

    let mut core_loop = Core::new().unwrap();
    let handle = core_loop.handle();

    // initiate a tcp listener (server's role)
    let socket = TcpListener::bind(&addr, &handle).unwrap();

    println!("I'm listening on {}", addr);

    let done = socket.incoming().for_each(move |(socket, addr)| {

        // Copy's all bytes from 'reader' (from the client), to 'writer' (to the client).
        //let io_pair = futures::lazy(|| Ok(socket.split()));
        //let amt = io_pair.and_then(|(reader, writer)| { copy(reader, writer) });

        println!("I'm talking on {}", addr);

        //let msg = amt.map(move |amt| {
            //println!("Wrote {} bytes to {}", amt, addr);
        //}).map_err(|e| {
            //panic!("Error: {}", e);
        //});

        let msg = futures::lazy(|| Ok(socket.split()))
            .and_then(|(r, w)| copy(r, w))
            .map(move |amt| {
                println!("Wrote {} bytes to {}", amt, addr);
            }).map_err(|e| {
            panic!("Error: {}", e);
        });

        handle.spawn(msg);

        Ok(())
    });

    core_loop.run(done).unwrap();
}

<commit_msg>Preparing to read the JSONz<commit_after>//#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

//#[cfg(feature = "serde_derive")]
//#[macro_use]
//extern crate serde_derive;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
//extern crate serde;
//extern crate serde_json;

// TCP or UDP?
// Can we get non-persistent TCP connections which don't have buffer stalls?
// Or should we work on UDP to make sure we have control over whether or not
// messages are sent / received?

// Note on the copy(reader, writer) function, it's very simple.
// The function takes data given to reader and copies it over to writer, writing back
// whatever was written. The 'copy' might as well be called 'echo'.

// Also, in this case, when an incoming socket happens, we cannot handle the split
// without a future, since the connection will persist far longer than the 'for_each'
// iteration will, therefore it must be run asynchronously, to avoid only being able
// to handle one client at a time.

use std::net::SocketAddr;
use std::io::{Write, Read};
use std::str::{from_utf8};

use futures::Future;
use futures::stream::Stream;

use tokio_core::io::{copy, Io};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;

//use serde_json::*;

//mod server;
//mod client;
mod data;

use data::Data;

struct Writer;

impl Write for Writer {
    fn write(&mut self, buf : &[u8]) -> Result<usize, std::io::Error> {
        //println!("Recieved : {}", from_utf8(buf).unwrap().to_string());
        //let msg = from_utf8(buf).unwrap().to_string();
        //let val : Data = serde_json::from_slice(&buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> Result<(), std::io::Error> {
        Ok(())
    }
}

// We're gonna read some JSON
fn main() {
    let addr = "127.0.0.1:8080".to_string().parse::<SocketAddr>().unwrap();
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let socket = TcpListener::bind(&addr, &handle).unwrap();

    let core_loop = socket.incoming().for_each(|(stream, addr)| {
        let message =
            futures::lazy(move || {
                Ok(stream.split())
            }).and_then(|(r, _w)| {
                copy(r, Writer)
            }).map(move |amt| {
                println!("Said hello to client {} at {}!", amt, addr);
            }).map_err(|e| {
                panic!("Error: {}", e);
            });

        handle.spawn(message);

        Ok(())
    });

    core.run(core_loop).unwrap();
}

<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate hyper;

#[macro_use] extern crate log;

use std::io::BufferedReader;
use std::io::File;
use std::io::fs::PathExtensions;
use std::io::net::ip::Ipv4Addr;
use std::vec::Vec;

use hyper::Get;
use hyper::header::ContentLength;
use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { error!("Error: {}", e); return; }
        }
    }}
);

// Send a file as the response, but read it line by line instead of all at
// once to be easier on memory.
fn buffered_file_read(file: File, res: Response) {
    let mut response = try_return!(res.start());
    let mut reader = BufferedReader::new(file);

    for line in reader.lines() {
        try_return!(response.write_str(line.unwrap().as_slice()));
    }

    try_return!(response.end());
}

// Given a path extension, return back the proper MIME type.
// The default is text/plain.
fn get_content_type(extension: &str) -> Mime {
    let opts = Vec::new(); // This is empty as we don't use options.

    match extension {
        "html" => Mime(TopLevel::Text, SubLevel::Html, opts),
        "css" => Mime(TopLevel::Text, SubLevel::Css, opts),
        "js" => Mime(TopLevel::Application, SubLevel::Javascript, opts),
        "jpeg" | "jpg" => Mime(TopLevel::Image, SubLevel::Jpeg, opts),
        "png" => Mime(TopLevel::Image, SubLevel::Png, opts),
        "gif" => Mime(TopLevel::Image, SubLevel::Gif, opts),
        _ => Mime(TopLevel::Text, SubLevel::Plain, opts)
    }
}

// Write a static file as the response back in a GET request.
fn send_file(path: &str, mut res: Response) {
    let root = "/Users/gsquire/poly/senior_project/html";
    let file_path: Path;
    let file_to_send: File;

    // Let everyone know what cool server sent them this response.
    res.headers_mut().set(hyper::header::Server("swell".to_string()));

    // By default, try and send the index
    if path == "/" {
        file_path = Path::new(root.to_string() + "/index.html");
    } else {
        file_path = Path::new(root.to_string() + path);
    }

    // Get the file extension so we can set the MIME type.
    let ext = file_path.extension().unwrap();
    let ext_str = std::str::from_utf8(ext).unwrap();

    // We send a 404 response in the error case here, 203 is the size of
    // the file since it will not change.
    let file_stat = match file_path.stat() {
        Ok(stat) => stat,
        Err(e) => {
            println!("Could not perform stat on file: {}", e);
            *res.status_mut() = hyper::NotFound;
            let error_file = Path::new(root.to_string() + "/404.html");
            file_to_send = try_return!(File::open(&error_file));

            res.headers_mut().set(ContentLength(203)); // This is constant.
            res.headers_mut().set(ContentType(get_content_type("html".as_slice())));
            buffered_file_read(file_to_send, res);
            return;
        }
    };

    file_to_send = try_return!(File::open(&file_path));

    res.headers_mut().set(ContentType(get_content_type(ext_str)));
    res.headers_mut().set(ContentLength(file_stat.size));

    buffered_file_read(file_to_send, res);
}

fn base(req: Request, mut res: Response) {
    match req.uri {
        AbsolutePath(ref path) => match (&req.method, path.as_slice()) {
            (&Get, _) => {
                send_file(path.as_slice(), res);
                return;
            },
            _ => {
                *res.status_mut() = hyper::NotFound;
                try_return!(res.start().and_then(|res| res.end()));
                return;
            }
        },
        _ => {
            try_return!(res.start().and_then(|res| res.end()));
            return;
        }
    };
}

/// The main method that makes a new hyper Server on port 42007.
/// It starts listening and loops until we send the kill signal.
fn main() {
    const NUM_THREADS: usize = 64;
    let server = Server::http(Ipv4Addr(127, 0, 0, 1), 42007);
    let mut listener = server.listen_threads(base, NUM_THREADS).unwrap();
    println!("Listening on port 42007...");
    listener.await();
}

#[cfg(test)]
mod tests {
    use super::get_content_type;

    use hyper::mime::{Mime, TopLevel, SubLevel};

    #[test]
    fn testing_check() {
        assert!(true);
    }

    #[test]
    fn check_jpeg_content_type() {
        let jpeg_mime = Mime(TopLevel::Image, SubLevel::Jpeg, Vec::new());
        assert_eq!(jpeg_mime, get_content_type("jpeg".as_slice()));
        assert_eq!(jpeg_mime, get_content_type("jpg".as_slice()));
    }

    #[test]
    fn check_js_content_type() {
        let js_mime = Mime(TopLevel::Application, SubLevel::Javascript, Vec::new());
        assert_eq!(js_mime, get_content_type("js".as_slice()));
    }
}
<commit_msg>fixed error in writing files<commit_after>#![allow(unstable)]
extern crate hyper;

#[macro_use] extern crate log;

use std::io::BufferedReader;
use std::io::File;
use std::io::fs::PathExtensions;
use std::io::net::ip::Ipv4Addr;
use std::vec::Vec;

use hyper::Get;
use hyper::header::ContentLength;
use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { error!("Error: {}", e); return; }
        }
    }}
);

// Send a file as the response, reading all of the bytes into a buffer and
// then sending that back in the response.
fn buffered_file_read(file: File, res: Response) {
    let mut response = try_return!(res.start());
    let mut reader = BufferedReader::new(file);
    let bytes = reader.read_to_end().unwrap();

    try_return!(response.write(bytes.as_slice()));

    try_return!(response.end());
}

// Given a path extension, return back the proper MIME type.
// The default is text/plain.
fn get_content_type(extension: &str) -> Mime {
    let opts = Vec::new(); // This is empty as we don't use options.

    match extension {
        "html" => Mime(TopLevel::Text, SubLevel::Html, opts),
        "css" => Mime(TopLevel::Text, SubLevel::Css, opts),
        "js" => Mime(TopLevel::Application, SubLevel::Javascript, opts),
        "jpeg" | "jpg" => Mime(TopLevel::Image, SubLevel::Jpeg, opts),
        "png" => Mime(TopLevel::Image, SubLevel::Png, opts),
        "gif" => Mime(TopLevel::Image, SubLevel::Gif, opts),
        _ => Mime(TopLevel::Text, SubLevel::Plain, opts)
    }
}

// Write a static file as the response back in a GET request.
fn send_file(path: &str, mut res: Response) {
    let root = "/Users/gsquire/poly/senior_project/html";
    let file_path: Path;
    let file_to_send: File;

    // Let everyone know what cool server sent them this response.
    res.headers_mut().set(hyper::header::Server("swell".to_string()));

    // By default, try and send the index
    if path == "/" {
        file_path = Path::new(root.to_string() + "/index.html");
    } else {
        file_path = Path::new(root.to_string() + path);
    }

    // Get the file extension so we can set the MIME type.
    let ext = file_path.extension().unwrap();
    let ext_str = std::str::from_utf8(ext).unwrap();

    // We send a 404 response in the error case here, 203 is the size of
    // the file since it will not change.
    let file_stat = match file_path.stat() {
        Ok(stat) => stat,
        Err(e) => {
            println!("Could not perform stat on file: {}", e);
            *res.status_mut() = hyper::NotFound;
            let error_file = Path::new(root.to_string() + "/404.html");
            file_to_send = try_return!(File::open(&error_file));

            res.headers_mut().set(ContentLength(203)); // This is constant.
            res.headers_mut().set(ContentType(get_content_type("html".as_slice())));
            buffered_file_read(file_to_send, res);
            return;
        }
    };

    file_to_send = try_return!(File::open(&file_path));

    res.headers_mut().set(ContentType(get_content_type(ext_str)));
    res.headers_mut().set(ContentLength(file_stat.size));

    buffered_file_read(file_to_send, res);
}

fn base(req: Request, mut res: Response) {
    match req.uri {
        AbsolutePath(ref path) => match (&req.method, path.as_slice()) {
            (&Get, _) => {
                send_file(path.as_slice(), res);
                return;
            },
            _ => {
                *res.status_mut() = hyper::NotFound;
                try_return!(res.start().and_then(|res| res.end()));
                return;
            }
        },
        _ => {
            try_return!(res.start().and_then(|res| res.end()));
            return;
        }
    };
}

/// The main method that makes a new hyper Server on port 42007.
/// It starts listening and loops until we send the kill signal.
fn main() {
    const NUM_THREADS: usize = 64;
    let server = Server::http(Ipv4Addr(127, 0, 0, 1), 42007);
    let mut listener = server.listen_threads(base, NUM_THREADS).unwrap();
    println!("Listening on port 42007...");
    listener.await();
}

#[cfg(test)]
mod tests {
    use super::get_content_type;

    use hyper::mime::{Mime, TopLevel, SubLevel};

    #[test]
    fn testing_check() {
        assert!(true);
    }

    #[test]
    fn check_jpeg_content_type() {
        let jpeg_mime = Mime(TopLevel::Image, SubLevel::Jpeg, Vec::new());
        assert_eq!(jpeg_mime, get_content_type("jpeg".as_slice()));
        assert_eq!(jpeg_mime, get_content_type("jpg".as_slice()));
    }

    #[test]
    fn check_js_content_type() {
        let js_mime = Mime(TopLevel::Application, SubLevel::Javascript, Vec::new());
        assert_eq!(js_mime, get_content_type("js".as_slice()));
    }
}
<|endoftext|>


<commit_before>#![crate_type="bin"]
#![feature(slicing_syntax)]

extern crate "rust-crypto" as crypto;
extern crate getopts;

use std::os;
use std::from_str::FromStr;
use std::io;
use std::io::File;
use std::io::BufferedReader;
use getopts::{optopt,optflag,optmulti,getopts,OptGroup};
use util::random_pass;
use plause::Plause;

mod hash;
mod util;
mod item;
mod piece;
mod block;
mod settings;
mod plause;

static VERSION:                             f32 = 0.01;

static DEFAULT_ENCRYPTFILE:        &'static str = "output.enc";
static DEFAULT_DECRYPTFILE:        &'static str = "output.dec";
static DEFAULT_PASSWORDECRYPTFILE: &'static str = "pass.key";
static DEFAULT_SALT:               &'static str = "saltysaltsalt";
static DEFAULT_BLOCKSIZE:                   u32 = 1048576;

static CONT_ENCRYPT_FILE:     &'static str = "E";
static CONT_PASSWORD_FILE:    &'static str = "P";
static CONT_SET_BLOCKSIZE:    &'static str = "b";
static CONT_SET_SALT:         &'static str = "s";
static CONT_HELP_MODE:        &'static str = "h";
static CONT_VERSION_MODE:     &'static str = "v";
static CONT_DECRYPT_MODE:     &'static str = "d";
static CONT_ENCRYPT_MODE:     &'static str = "e";
static CONT_INTERACTIVE_MODE: &'static str = "i";

#[deriving(PartialEq, Eq)]
pub enum Mode {
    Help,
    Version,
    Interactive,
    Encrypt,
    Decrypt,
}

fn main() {
    let args: Vec<String> = os::args();
    let program = args[0].clone();
    let opts = [
        optopt(CONT_ENCRYPT_FILE,  "encrypt-file",  format!("set encryption output file (default: {})", DEFAULT_ENCRYPTFILE).as_slice(), "FILENAME"),
        optopt(CONT_PASSWORD_FILE, "password-file", format!("set password file (default: {})", DEFAULT_PASSWORDECRYPTFILE).as_slice(),   "FILENAME"),

        optopt(CONT_SET_BLOCKSIZE, "blocksize", format!("set block size (default: {})", DEFAULT_BLOCKSIZE).as_slice(), "SIZE"),
        optopt(CONT_SET_SALT,      "salt",      format!("set salt (default: {})", DEFAULT_SALT).as_slice(),            "SALT"),

        optflag(CONT_HELP_MODE,        "help",        "print this help menu"),
        optflag(CONT_VERSION_MODE,     "version",     "show version"),
        optflag(CONT_INTERACTIVE_MODE, "interactive", "interactively add text messages"),
        optmulti(CONT_ENCRYPT_MODE,    "encrypt",     "encrypt file(s)", "FILENAME"),
        optopt(CONT_DECRYPT_MODE,      "decrypt",     "decrypt file using password-file and filename prefix for output", "FILENAME"),
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m)  => { m },
        Err(f) => { fail!(f.to_string()) },
    };

    let blocksize     = fallback_match_fstr(CONT_SET_BLOCKSIZE, &matches, DEFAULT_BLOCKSIZE);
    let salt          = fallback_match(CONT_SET_SALT,           &matches, DEFAULT_SALT);
    let encrypt_file  = fallback_match(CONT_ENCRYPT_FILE,       &matches, DEFAULT_ENCRYPTFILE);
    let password_file = fallback_match(CONT_PASSWORD_FILE,      &matches, DEFAULT_PASSWORDECRYPTFILE);

    let mut plause = Plause::new(blocksize, salt.as_slice());

    match get_mode(&matches) {
        Help             => print_usage(program.as_slice(), opts),
        Version          => print_version(program.as_slice()),
        Interactive      => encrypt_interactive(&mut plause,
                                                &Path::new(encrypt_file.as_slice()),
                                                &Path::new(password_file.as_slice()),
                                                salt.as_slice()),
        Encrypt          => encrypt_files(&mut plause,
                                          &Path::new(encrypt_file.as_slice()),
                                          &Path::new(password_file.as_slice()),
                                          salt.as_slice(),
                                          &matches.opt_strs(CONT_ENCRYPT_MODE).iter().map(|x| Path::new(x.as_slice())).collect::<Vec<Path>>()),
        Decrypt          => decrypt(&mut plause,
                                    &Path::new(encrypt_file.as_slice()),
                                    &Path::new(matches.opt_str(CONT_DECRYPT_MODE).unwrap_or(String::from_str(DEFAULT_DECRYPTFILE))),
                                    &Path::new(password_file.as_slice())),
    }
}

fn print_usage(program: &str, opts: &[OptGroup]) {
    println!("{}", getopts::short_usage(program.as_slice(), opts));
    println!("plausible deniability for love and friendship");
    println!("{}", getopts::usage("", opts));
    println!("");
    println!("Examples:");
    println!("    ./plause -b 120000 -s secretsaltysalt -eFILE1 -eFILE2");
    println!("\t\t\tencrypt FILE1 and FILE2 into output.enc of 120kb size")
    println!("\t\t\tusing generated passwords secretsaltysalt as salt");
    println!("\t\t\tsaving them into pass.key");
    println!("    ./plause -d output_files");
    println!("\t\t\tDecrypt output.enc to output_files.# with salt/passwords");
    println!("\t\t\tfrom pass.key");
    println!("");
    println!("report all bugs to github.com/whackashoe/plause");
}

fn print_version(program: &str) {
    println!("{} {}", program, VERSION);
}

fn decrypt(plause: &mut Plause, encrypt_path: &Path, decrypt_path: &Path, password_path: &Path) {
    let mut passwords: Vec<Vec<u8>> = Vec::new();
    let mut enough_lines: bool = false;

    match File::open(password_path) {
        Ok(f)  => {
            let mut file = BufferedReader::new(f);
            for (i, line) in file.lines().enumerate() {
                if i == 0 {
                    plause.set_salt(line.unwrap().into_bytes().init().to_vec());
                } else {
                    enough_lines = true;
                    passwords.push(line.unwrap().into_bytes().init().to_vec());
                }
            }

            if !enough_lines {
                fail!("password file requires at least two lines (salt) and (password(s))");
            }
        },
        Err(e) => fail!("decrypt open password path: {}", e),
    }

    match File::open(encrypt_path).read_to_end() {
        Ok(f)  => plause.import(f),
        Err(e) => fail!("decrypt open encrypt path: {}", e),
    }

    for (i, password) in passwords.iter().enumerate() {
        let decpath = if passwords.len() == 1 {
            decrypt_path.clone()
        } else {
            Path::new(format!("{}.{}", decrypt_path.display(), i))
        };
        match File::create(&decpath).write(plause.extract(password).as_slice()) {
            Ok(f)  => f,
            Err(e) => fail!("decrypt create decrypt path: {}", e),
        };
    }
}

fn encrypt_interactive(plause: &mut Plause, encrypt_path: &Path, password_path: &Path, salt: &str) {
    for line in io::stdin().lines() {
        plause.add(&random_pass(24), &line.unwrap().into_bytes().init().to_vec());
    }

    plause.gen();
    write_results(plause, encrypt_path, password_path, salt);
}

fn encrypt_files(plause: &mut Plause, encrypt_path: &Path, password_path: &Path, salt: &str, files: &Vec<Path>) {
    for file in files.iter() {
        let contents = File::open(file).read_to_end();
        match contents {
            Ok(f)  => plause.add(&random_pass(24), &f),
            Err(e) => fail!("error reading file: {}", e),
        }
    }

    plause.gen();
    write_results(plause, encrypt_path, password_path, salt);
}
fn fallback_match(c: &str, matches: &getopts::Matches, default: &str) -> String {
    if matches.opt_present(c) {
        return matches.opt_str(c).unwrap_or(default.to_string());
    }

    default.to_string()
}

fn fallback_match_fstr<T: FromStr>(c: &str, matches: &getopts::Matches, default: T) -> T {
    if matches.opt_present(c) {
        match matches.opt_str(c) {
            Some(y) => {
                return match from_str(y.as_slice()) {
                    Some(x) => x,
                    None    => default,
                };
            },
            None    => { return default; }
        };
    }

    default
}

fn get_mode(matches: &getopts::Matches) -> Mode {
    if matches.opt_present(CONT_HELP_MODE) {
        return Help;
    }

    if matches.opt_present(CONT_VERSION_MODE) {
        return Version;
    }

    if matches.opt_present(CONT_INTERACTIVE_MODE) {
        return Interactive;
    }

    if matches.opt_present(CONT_ENCRYPT_MODE) {
        return Encrypt;
    }

    if matches.opt_present(CONT_DECRYPT_MODE) {
        return Decrypt;
    }

    Help
}

fn write_results(plause: &mut Plause, encrypt_file: &Path, password_file: &Path, salt: &str) {
    match File::create(encrypt_file).write(plause.content.as_slice()) {
        Ok(f)  => f,
        Err(e) => fail!("encrypt file error: {}", e),
    };

    let mut pfile = match File::create(password_file) {
        Ok(f)  => f,
        Err(e) => fail!("password file error: {}", e),
    };

    pfile.write_line(salt.as_slice()).unwrap();
    for i in plause.get_passwords().iter() {
        pfile.write(i.as_slice()).unwrap();
        pfile.write_line("").unwrap();
    }
}

<commit_msg>add disclaimer<commit_after>#![crate_type="bin"]
#![feature(slicing_syntax)]

extern crate "rust-crypto" as crypto;
extern crate getopts;

use std::os;
use std::from_str::FromStr;
use std::io;
use std::io::File;
use std::io::BufferedReader;
use getopts::{optopt,optflag,optmulti,getopts,OptGroup};
use util::random_pass;
use plause::Plause;

mod hash;
mod util;
mod item;
mod piece;
mod block;
mod settings;
mod plause;

static VERSION:                             f32 = 0.01;

static DEFAULT_ENCRYPTFILE:        &'static str = "output.enc";
static DEFAULT_DECRYPTFILE:        &'static str = "output.dec";
static DEFAULT_PASSWORDECRYPTFILE: &'static str = "pass.key";
static DEFAULT_SALT:               &'static str = "saltysaltsalt";
static DEFAULT_BLOCKSIZE:                   u32 = 1048576;

static CONT_ENCRYPT_FILE:     &'static str = "E";
static CONT_PASSWORD_FILE:    &'static str = "P";
static CONT_SET_BLOCKSIZE:    &'static str = "b";
static CONT_SET_SALT:         &'static str = "s";
static CONT_HELP_MODE:        &'static str = "h";
static CONT_VERSION_MODE:     &'static str = "v";
static CONT_DECRYPT_MODE:     &'static str = "d";
static CONT_ENCRYPT_MODE:     &'static str = "e";
static CONT_INTERACTIVE_MODE: &'static str = "i";

#[deriving(PartialEq, Eq)]
pub enum Mode {
    Help,
    Version,
    Interactive,
    Encrypt,
    Decrypt,
}

fn main() {
    let args: Vec<String> = os::args();
    let program = args[0].clone();
    println!("{} is a proof of concept and should not be considered trustworthy", program);
    let opts = [
        optopt(CONT_ENCRYPT_FILE,  "encrypt-file",  format!("set encryption output file (default: {})", DEFAULT_ENCRYPTFILE).as_slice(), "FILENAME"),
        optopt(CONT_PASSWORD_FILE, "password-file", format!("set password file (default: {})", DEFAULT_PASSWORDECRYPTFILE).as_slice(),   "FILENAME"),

        optopt(CONT_SET_BLOCKSIZE, "blocksize", format!("set block size (default: {})", DEFAULT_BLOCKSIZE).as_slice(), "SIZE"),
        optopt(CONT_SET_SALT,      "salt",      format!("set salt (default: {})", DEFAULT_SALT).as_slice(),            "SALT"),

        optflag(CONT_HELP_MODE,        "help",        "print this help menu"),
        optflag(CONT_VERSION_MODE,     "version",     "show version"),
        optflag(CONT_INTERACTIVE_MODE, "interactive", "interactively add text messages"),
        optmulti(CONT_ENCRYPT_MODE,    "encrypt",     "encrypt file(s)", "FILENAME"),
        optopt(CONT_DECRYPT_MODE,      "decrypt",     "decrypt file using password-file and filename prefix for output", "FILENAME"),
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m)  => { m },
        Err(f) => { fail!(f.to_string()) },
    };

    let blocksize     = fallback_match_fstr(CONT_SET_BLOCKSIZE, &matches, DEFAULT_BLOCKSIZE);
    let salt          = fallback_match(CONT_SET_SALT,           &matches, DEFAULT_SALT);
    let encrypt_file  = fallback_match(CONT_ENCRYPT_FILE,       &matches, DEFAULT_ENCRYPTFILE);
    let password_file = fallback_match(CONT_PASSWORD_FILE,      &matches, DEFAULT_PASSWORDECRYPTFILE);

    let mut plause = Plause::new(blocksize, salt.as_slice());

    match get_mode(&matches) {
        Help             => print_usage(program.as_slice(), opts),
        Version          => print_version(program.as_slice()),
        Interactive      => encrypt_interactive(&mut plause,
                                                &Path::new(encrypt_file.as_slice()),
                                                &Path::new(password_file.as_slice()),
                                                salt.as_slice()),
        Encrypt          => encrypt_files(&mut plause,
                                          &Path::new(encrypt_file.as_slice()),
                                          &Path::new(password_file.as_slice()),
                                          salt.as_slice(),
                                          &matches.opt_strs(CONT_ENCRYPT_MODE).iter().map(|x| Path::new(x.as_slice())).collect::<Vec<Path>>()),
        Decrypt          => decrypt(&mut plause,
                                    &Path::new(encrypt_file.as_slice()),
                                    &Path::new(matches.opt_str(CONT_DECRYPT_MODE).unwrap_or(String::from_str(DEFAULT_DECRYPTFILE))),
                                    &Path::new(password_file.as_slice())),
    }
}

fn print_usage(program: &str, opts: &[OptGroup]) {
    println!("{}", getopts::short_usage(program.as_slice(), opts));
    println!("plausible deniability for love and friendship");
    println!("{}", getopts::usage("", opts));
    println!("");
    println!("Examples:");
    println!("    ./plause -b 120000 -s secretsaltysalt -eFILE1 -eFILE2");
    println!("\t\t\tencrypt FILE1 and FILE2 into output.enc of 120kb size")
    println!("\t\t\tusing generated passwords secretsaltysalt as salt");
    println!("\t\t\tsaving them into pass.key");
    println!("    ./plause -d output_files");
    println!("\t\t\tDecrypt output.enc to output_files.# with salt/passwords");
    println!("\t\t\tfrom pass.key");
    println!("");
    println!("report all bugs to github.com/whackashoe/plause");
}

fn print_version(program: &str) {
    println!("{} {}", program, VERSION);
}

fn decrypt(plause: &mut Plause, encrypt_path: &Path, decrypt_path: &Path, password_path: &Path) {
    let mut passwords: Vec<Vec<u8>> = Vec::new();
    let mut enough_lines: bool = false;

    match File::open(password_path) {
        Ok(f)  => {
            let mut file = BufferedReader::new(f);
            for (i, line) in file.lines().enumerate() {
                if i == 0 {
                    plause.set_salt(line.unwrap().into_bytes().init().to_vec());
                } else {
                    enough_lines = true;
                    passwords.push(line.unwrap().into_bytes().init().to_vec());
                }
            }

            if !enough_lines {
                fail!("password file requires at least two lines (salt) and (password(s))");
            }
        },
        Err(e) => fail!("decrypt open password path: {}", e),
    }

    match File::open(encrypt_path).read_to_end() {
        Ok(f)  => plause.import(f),
        Err(e) => fail!("decrypt open encrypt path: {}", e),
    }

    for (i, password) in passwords.iter().enumerate() {
        let decpath = if passwords.len() == 1 {
            decrypt_path.clone()
        } else {
            Path::new(format!("{}.{}", decrypt_path.display(), i))
        };
        match File::create(&decpath).write(plause.extract(password).as_slice()) {
            Ok(f)  => f,
            Err(e) => fail!("decrypt create decrypt path: {}", e),
        };
    }
}

fn encrypt_interactive(plause: &mut Plause, encrypt_path: &Path, password_path: &Path, salt: &str) {
    for line in io::stdin().lines() {
        plause.add(&random_pass(24), &line.unwrap().into_bytes().init().to_vec());
    }

    plause.gen();
    write_results(plause, encrypt_path, password_path, salt);
}

fn encrypt_files(plause: &mut Plause, encrypt_path: &Path, password_path: &Path, salt: &str, files: &Vec<Path>) {
    for file in files.iter() {
        let contents = File::open(file).read_to_end();
        match contents {
            Ok(f)  => plause.add(&random_pass(24), &f),
            Err(e) => fail!("error reading file: {}", e),
        }
    }

    plause.gen();
    write_results(plause, encrypt_path, password_path, salt);
}
fn fallback_match(c: &str, matches: &getopts::Matches, default: &str) -> String {
    if matches.opt_present(c) {
        return matches.opt_str(c).unwrap_or(default.to_string());
    }

    default.to_string()
}

fn fallback_match_fstr<T: FromStr>(c: &str, matches: &getopts::Matches, default: T) -> T {
    if matches.opt_present(c) {
        match matches.opt_str(c) {
            Some(y) => {
                return match from_str(y.as_slice()) {
                    Some(x) => x,
                    None    => default,
                };
            },
            None    => { return default; }
        };
    }

    default
}

fn get_mode(matches: &getopts::Matches) -> Mode {
    if matches.opt_present(CONT_HELP_MODE) {
        return Help;
    }

    if matches.opt_present(CONT_VERSION_MODE) {
        return Version;
    }

    if matches.opt_present(CONT_INTERACTIVE_MODE) {
        return Interactive;
    }

    if matches.opt_present(CONT_ENCRYPT_MODE) {
        return Encrypt;
    }

    if matches.opt_present(CONT_DECRYPT_MODE) {
        return Decrypt;
    }

    Help
}

fn write_results(plause: &mut Plause, encrypt_file: &Path, password_file: &Path, salt: &str) {
    match File::create(encrypt_file).write(plause.content.as_slice()) {
        Ok(f)  => f,
        Err(e) => fail!("encrypt file error: {}", e),
    };

    let mut pfile = match File::create(password_file) {
        Ok(f)  => f,
        Err(e) => fail!("password file error: {}", e),
    };

    pfile.write_line(salt.as_slice()).unwrap();
    for i in plause.get_passwords().iter() {
        pfile.write(i.as_slice()).unwrap();
        pfile.write_line("").unwrap();
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;

extern crate clap;
extern crate qrcode;
extern crate termion;
extern crate image;
extern crate regex;

use clap::{App, Arg, SubCommand};
use qrcode::{QrCode, EcLevel};
use termion::color;

mod payloads;

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
- change strings into constants
*/
fn main() {
    let app = App::new("qrterm")
        .version("0.1")
        .author("Lukas R. <lukas@bootsmann-games.de>")
        .about("Generates and displays terminal friendly QR-Codes from input strings")
        .arg(Arg::with_name("safe_zone")
            .global(true)
            .short("s")
            .long("safe-zone")
            .value_name("BOOL")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(true)
            .default_value("true")
            .possible_values(&["true", "false"])
            .value_names(&["true", "false"])
        )

        .subcommand(SubCommand::with_name("wifi")
                                      .about("formats to a wifi access string")
                                      .arg(Arg::with_name("ssid").required(true))
                                      .arg(Arg::with_name("pwd").required(true))
                                      .arg(Arg::with_name("mode").required(true))
        )
        //.arg(Arg::with_name("type")
        //    .short("t")
        //    .long("type")
        //    .value_name("TYPE")
        //    .help("Sets if a special qr type should be used")
        //    .takes_value(true))
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required(true)
        );

    let matches = app.get_matches();
    //let subcommands = matches.subcommand_matches();

    let mut payload = String::new();
    if let Some(sub) = matches.subcommand_matches("wifi") {
        //TODO:prelimenary
        payload = payloads::wifi_string(sub.value_of("ssid").unwrap(),
                              &"".to_string(),
                              &payloads::Authentication::nopass,
                              false);
    }

    let input = matches.value_of("INPUT").unwrap();

    let safe: bool = matches.value_of("safe_zone").unwrap() == "true";

    let code = QrCode::with_error_correction_level(input, EcLevel::H).unwrap();

    let bit_array = code.to_vec();

    let w = code.width();
    let wide = w + 6;

    //Draw the first white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    for (i, item) in bit_array.iter().enumerate() {
        //left safe zone
        if safe && i % w == 0 {
            print!("{}      ", color::Bg(color::LightWhite));
        }

        if *item {
            print!("{}  ", color::Bg(color::Black)); //█ ▜
        } else {
            print!("{}  ", color::Bg(color::LightWhite));
        }

        if (i + 1) % w == 0 {
            if safe {
                //draw right safe zone
                println!("{}      {}",
                         color::Bg(color::LightWhite),
                         color::Bg(color::Reset));
            } else {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    //Draw the last white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }
}
<commit_msg>fixed wifi subcommand<commit_after>#[macro_use]
extern crate lazy_static;

extern crate clap;
extern crate qrcode;
extern crate termion;
extern crate image;
extern crate regex;

use clap::{App, Arg, SubCommand};
use qrcode::{QrCode, EcLevel};
use termion::color;

mod payloads;

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
- change strings into constants
*/
fn main() {
    let app = App::new("qrterm")
        .version("0.1")
        .author("Lukas R. <lukas@bootsmann-games.de>")
        .about("Generates and displays terminal friendly QR-Codes from input strings")
        .arg(Arg::with_name("safe_zone") //TODO: change this into an off switch
            .global(true)
            .short("s")
            .long("safe-zone")
            .value_name("BOOL")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(true)
            .default_value("true")
            .possible_values(&["true", "false"])
            .value_names(&["true", "false"]))
        .subcommand(SubCommand::with_name("wifi")
            .about("formats to a wifi access string")
            .arg(Arg::with_name("ssid").required(true))
            .arg(Arg::with_name("pwd").required(true))
            .arg(Arg::with_name("mode")
                .required(true)
                .possible_values(&["WEP", "WPA", "nopass"])
                .value_name("MODE"))
            .arg(Arg::with_name("hidden")
                .required(false)
                .default_value("false")
                .possible_values(&["true", "false"])
                .value_name("HIDDEN")))
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required(true));

    let matches = app.get_matches();

    let payload: String;
    if let Some(sub) = matches.subcommand_matches("wifi") {
        let auth = match sub.value_of("mode") {
            Some("WEP") => payloads::Authentication::WEP,
            Some("WPA") => payloads::Authentication::WPA,
            _ => payloads::Authentication::nopass,
        };
        payload = payloads::wifi_string(sub.value_of("ssid").unwrap(),
                                        sub.value_of("pwd").unwrap(),
                                        &auth,
                                        sub.value_of("hidden").unwrap() == "true");
    } else {
        payload = String::from(matches.value_of("INPUT").unwrap());
    }

    let safe: bool = matches.value_of("safe_zone").unwrap() == "true";

    let code = QrCode::with_error_correction_level(payload, EcLevel::H).unwrap();

    let bit_array = code.to_vec();

    let w = code.width();
    let wide = w + 6;

    //Draw the first white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    for (i, item) in bit_array.iter().enumerate() {
        //left safe zone
        if safe && i % w == 0 {
            print!("{}      ", color::Bg(color::LightWhite));
        }

        if *item {
            print!("{}  ", color::Bg(color::Black));
        } else {
            print!("{}  ", color::Bg(color::LightWhite));
        }

        if (i + 1) % w == 0 {
            if safe {
                //draw right safe zone
                println!("{}      {}",
                         color::Bg(color::LightWhite),
                         color::Bg(color::Reset));
            } else {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    //Draw the last white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }
}
<|endoftext|>


<commit_before>/// A genetic algorithm in Rust
/// Copyright (C) 2015  Andrew Schwartzmeyer

#[macro_use]
extern crate clap;
extern crate rand;
extern crate time;

use clap::App;
use rand::Rng;
use time::precise_time_s;
use std::thread;
use individual::Individual;

mod individual;
mod problem;

arg_enum!{
    #[derive(Debug, PartialEq, Eq, Copy, Clone)]
    pub enum Problem {
        Schwefel
    }
}

/// Tournament selection from 4 random individuals
fn select<R: Rng>(population: &[Individual], rng: &mut R) -> Individual {
    if let Some(selected) = (0..4).map(|_| rng.choose(population)).min() {
        selected.unwrap().clone()
    } else {
        unimplemented!();
    }
}

/// Setup and run algorithm to search for solution
fn main() {
    let matches = App::new("rust-genetic-algorithm")
        .version(&crate_version!()[..])
        .author("Andrew Schwartzmeyer <andrew@schwartzmeyer.com")
        .about("A genetic algorithm in Rust for Schwefel's function.")
        .args_from_usage(
            "[<problem>] 'The problem to solve'
             [-d --dimension <30>] 'Sets the dimension of the hypercube'
             [-p --population <256>] 'Sets the size of the population'
             [-i --iterations <5000>] 'Sets maximum number of generations'
             --verbose 'Print fitness every 10th generation'")
        .get_matches();
    let problem = value_t!(matches.value_of("problem"), Problem)
        .unwrap_or(Problem::Schwefel);
    let dimension = value_t!(matches.value_of("d"), usize).unwrap_or(30);
    let population_size = value_t!(matches.value_of("p"), usize).unwrap_or(256);
    let iterations = value_t!(matches.value_of("i"), usize).unwrap_or(5000);
    let verbose = matches.is_present("verbose");

    let mut rng = rand::thread_rng();

    // initialize population individuals
    let mut population: Vec<_> = (0..population_size).map(|_| {
        Individual::new(problem, dimension, &mut rng)
    }).collect();

    let start_time = precise_time_s();
    // search with generations
    for i in 0..iterations {
        // select, mutate, and recombine individuals for next generation
        let mut offspring: Vec<Individual> = Vec::with_capacity(population.len());
        for _ in 0..population.len()/2 {
            let (mut x, mut y) = (select(&population, &mut rng),
                                  select(&population, &mut rng));
            x.mutate(&mut rng);
            y.mutate(&mut rng);
            Individual::combine(&mut x, &mut y, &mut rng);
            offspring.push(x);
            offspring.push(y);
        }
        assert!(offspring.len() == population.len());

        // replace 2 random individuals with elite of prior generation
        for _ in 0..2 {
            if let Some(x) = population.iter().min() {
                offspring[rng.gen_range(0, population.len())] = x.clone();
            }
        }

        // replace population with next generation
        population = offspring;

        // examine best individual for convergence
        if let Some(x) = population.iter().min() {
            if verbose && i % 10 == 0 {
                let fitness = x.fitness;
                thread::spawn(move || {
                    println!("{}th fitness {}", i, fitness)
                });
            }
            if x.fitness < 0.05_f64 {
                let duration = precise_time_s() - start_time;
                println!("{}th solution converged at {} in {} seconds: {:?}",
                         i, x.fitness, duration, x.solution);
                return;
            }
        } else { unimplemented!() }
    }
    println!("Failed to converge.");
}
<commit_msg>Print solution only for --verbose<commit_after>/// A genetic algorithm in Rust
/// Copyright (C) 2015  Andrew Schwartzmeyer

#[macro_use]
extern crate clap;
extern crate rand;
extern crate time;

use clap::App;
use rand::Rng;
use time::precise_time_s;
use std::thread;
use individual::Individual;

mod individual;
mod problem;

arg_enum!{
    #[derive(Debug, PartialEq, Eq, Copy, Clone)]
    pub enum Problem {
        Schwefel
    }
}

/// Tournament selection from 4 random individuals
fn select<R: Rng>(population: &[Individual], rng: &mut R) -> Individual {
    if let Some(selected) = (0..4).map(|_| rng.choose(population)).min() {
        selected.unwrap().clone()
    } else {
        unimplemented!();
    }
}

/// Setup and run algorithm to search for solution
fn main() {
    let matches = App::new("rust-genetic-algorithm")
        .version(&crate_version!()[..])
        .author("Andrew Schwartzmeyer <andrew@schwartzmeyer.com")
        .about("A genetic algorithm in Rust for Schwefel's function.")
        .args_from_usage(
            "[<problem>] 'The problem to solve'
             [-d --dimension <30>] 'Sets the dimension of the hypercube'
             [-p --population <256>] 'Sets the size of the population'
             [-i --iterations <5000>] 'Sets maximum number of generations'
             --verbose 'Print fitness every 10th generation'")
        .get_matches();
    let problem = value_t!(matches.value_of("problem"), Problem)
        .unwrap_or(Problem::Schwefel);
    let dimension = value_t!(matches.value_of("d"), usize).unwrap_or(30);
    let population_size = value_t!(matches.value_of("p"), usize).unwrap_or(256);
    let iterations = value_t!(matches.value_of("i"), usize).unwrap_or(5000);
    let verbose = matches.is_present("verbose");

    let mut rng = rand::thread_rng();

    // initialize population individuals
    let mut population: Vec<_> = (0..population_size).map(|_| {
        Individual::new(problem, dimension, &mut rng)
    }).collect();

    let start_time = precise_time_s();
    // search with generations
    for i in 0..iterations {
        // select, mutate, and recombine individuals for next generation
        let mut offspring: Vec<Individual> = Vec::with_capacity(population.len());
        for _ in 0..population.len()/2 {
            let (mut x, mut y) = (select(&population, &mut rng),
                                  select(&population, &mut rng));
            x.mutate(&mut rng);
            y.mutate(&mut rng);
            Individual::combine(&mut x, &mut y, &mut rng);
            offspring.push(x);
            offspring.push(y);
        }
        assert!(offspring.len() == population.len());

        // replace 2 random individuals with elite of prior generation
        for _ in 0..2 {
            if let Some(x) = population.iter().min() {
                offspring[rng.gen_range(0, population.len())] = x.clone();
            }
        }

        // replace population with next generation
        population = offspring;

        // examine best individual for convergence
        if let Some(x) = population.iter().min() {
            if verbose && i % 10 == 0 {
                let fitness = x.fitness;
                thread::spawn(move || {
                    println!("{}th fitness {}", i, fitness)
                });
            }
            if x.fitness < 0.05_f64 {
                let duration = precise_time_s() - start_time;
                println!("{}th solution converged at {} in {} seconds",
                         i, x.fitness, duration);
                if verbose {
                    println!{"{:?}", x.solution};
                }
                return;
            }
        } else { unimplemented!() }
    }
    println!("Failed to converge.");
}
<|endoftext|>