text:
<file_sep>use {
    super::Sort,
    crate::pattern::*,
    clap::ArgMatches,
};

/// Options defining how the tree should be build and|or displayed
#[derive(Debug, Clone)]
pub struct TreeOptions {
    pub show_hidden: bool, // whether files whose name starts with a dot should be shown
    pub only_folders: bool, // whether to hide normal files and links
    pub show_counts: bool,  // whether to show the number of files (> 1 only for dirs)
    pub show_dates: bool,  // whether to show the last modified date
    pub show_sizes: bool,  // whether to show sizes of files and dirs
    pub show_git_file_info: bool,
    pub show_root_fs: bool, // show information relative to the fs of the root
    pub trim_root: bool,            // whether to cut out direct children of root
    pub show_permissions: bool,     // show classic rwx unix permissions (only on unix)
    pub respect_git_ignore: bool,   // hide files as requested by .gitignore ?
    pub filter_by_git_status: bool, // only show files whose git status is not nul
    pub pattern: InputPattern,           // an optional filtering/scoring pattern
    pub date_time_format: &'static str,
    pub sort: Sort,
}

impl TreeOptions {
    /// clone self but without the pattern (if any)
    pub fn without_pattern(&self) -> Self {
        TreeOptions {
            show_hidden: self.show_hidden,
            only_folders: self.only_folders,
            show_counts: self.show_counts,
            show_dates: self.show_dates,
            show_sizes: self.show_sizes,
            show_permissions: self.show_permissions,
            respect_git_ignore: self.respect_git_ignore,
            filter_by_git_status: self.filter_by_git_status,
            show_git_file_info: self.show_git_file_info,
            show_root_fs: self.show_root_fs,
            trim_root: self.trim_root,
            pattern: InputPattern::none(),
            date_time_format: self.date_time_format,
            sort: self.sort,
        }
    }
    /// counts must be computed, either for sorting or just for display
    pub fn needs_counts(&self) -> bool {
        self.show_counts || self.sort == Sort::Count
    }
    /// dates must be computed, either for sorting or just for display
    pub fn needs_dates(&self) -> bool {
        self.show_dates || self.sort == Sort::Date
    }
    /// sizes must be computed, either for sorting or just for display
    pub fn needs_sizes(&self) -> bool {
        self.show_sizes || self.sort == Sort::Size
    }
    pub fn needs_sum(&self) -> bool {
        self.needs_counts() || self.needs_dates() || self.needs_sizes()
    }
    /// this method does not exist, you saw nothing
    /// (at least don't call it other than with the config, once)
    pub fn set_date_time_format(&mut self, format: String) {
        self.date_time_format = Box::leak(format.into_boxed_str());
    }
    /// change tree options according to broot launch arguments
    pub fn apply(&mut self, cli_args: &ArgMatches<'_>) {
        if cli_args.is_present("sizes") {
            self.show_sizes = true;
            self.show_root_fs = true;
        } else if cli_args.is_present("no-sizes") {
            self.show_sizes = false;
        }
        if cli_args.is_present("whale-spotting") {
            self.show_hidden = true;
            self.respect_git_ignore = false;
            self.sort = Sort::Size;
            self.show_sizes = true;
            self.show_root_fs = true;
        }
        if cli_args.is_present("only-folders") {
            self.only_folders = true;
        } else if cli_args.is_present("no-only-folders") {
            self.only_folders = false;
        }
        if cli_args.is_present("git-status") {
            self.filter_by_git_status = true;
            self.show_hidden = true;
        }
        if cli_args.is_present("hidden") {
            self.show_hidden = true;
        } else if cli_args.is_present("no-hidden") {
            self.show_hidden = false;
        }
        if cli_args.is_present("dates") {
            self.show_dates = true;
        } else if cli_args.is_present("no-dates") {
            self.show_dates = false;
        }
        if cli_args.is_present("permissions") {
            self.show_permissions = true;
        } else if cli_args.is_present("no-permissions") {
            self.show_permissions = false;
        }
        if cli_args.is_present("show-root-fs") {
            self.show_root_fs = true;
        }
        if cli_args.is_present("show-gitignored") {
            self.respect_git_ignore = false;
        } else if cli_args.is_present("no-show-gitignored") {
            self.respect_git_ignore = true;
        }
        if cli_args.is_present("show-git-info") {
            self.show_git_file_info = true;
        } else if cli_args.is_present("no-show-git-info") {
            self.show_git_file_info = false;
        }
        if cli_args.is_present("sort-by-count") {
            self.sort = Sort::Count;
            self.show_counts = true;
        }
        if cli_args.is_present("sort-by-date") {
            self.sort = Sort::Date;
            self.show_dates = true;
        }
        if cli_args.is_present("sort-by-size") {
            self.sort = Sort::Size;
            self.show_sizes = true;
        }
        if cli_args.is_present("no-sort") {
            self.sort = Sort::None;
        }
        if cli_args.is_present("trim-root") {
            self.trim_root = true;
        } else if cli_args.is_present("no-trim-root") {
            self.trim_root = false;
        }
    }
}

impl Default for TreeOptions {
    fn default() -> Self {
        Self {
            show_hidden: false,
            only_folders: false,
            show_counts: false,
            show_dates: false,
            show_sizes: false,
            show_git_file_info: false,
            show_root_fs: false,
            trim_root: false,
            show_permissions: false,
            respect_git_ignore: true,
            filter_by_git_status: false,
            pattern: InputPattern::none(),
            date_time_format: "%Y/%m/%d %R",
            sort: Sort::None,
        }
    }
}
<file_sep>

mod byte;
mod hex_view;

pub use {
    hex_view::HexView,
};

<file_sep>use {
    crate::{
        errors::ConfError,
    },
    std::str::FromStr,
};

// number of columns in enum
const COLS_COUNT: usize = 8;

/// One of the "columns" of the tree view
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Col {
    /// selection mark, typically a triangle on the selected line
    Mark,

    /// Git file status
    Git,

    /// the branch showing filliation
    Branch,

    /// file mode and ownership
    Permission,

    /// last modified date
    Date,

    /// file size, including size bar in sort_by_size mode
    Size,

    /// number of files in the directory
    Count,

    /// name of the file, or subpath if relevant due to filtering mode
    Name,
}

impl FromStr for Col {
    type Err = ConfError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = s.to_lowercase();
        match s.as_ref() {
            "m" | "mark" => Ok(Self::Mark),
            "g" | "git"  => Ok(Self::Git),
            "b" | "branch" =>  Ok(Self::Branch),
            "p" | "permission" => Ok(Self::Permission),
            "d" | "date" => Ok(Self::Date),
            "s" | "size" => Ok(Self::Size),
            "c" | "count" => Ok(Self::Count),
            "n" | "name" => Ok(Self::Name),
            _ => Err(ConfError::InvalidCols {
                details: format!("column not recognized : {}", s),
            })
        }
    }
}

impl Col {
    pub fn index_in(self, cols: &Cols) -> Option<usize> {
        for (idx, col) in cols.iter().enumerate() {
            if *col==self {
                return Some(idx);
            }
        }
        None
    }
    // warning: don't change the type of argument of this function or
    // it won't compile on some platforms
    /// return a Cols which tries to take the s setting into account
    /// but is guaranteed to have every Col exactly once.
    pub fn parse_cols(arr: &Vec<String>) -> Result<Cols, ConfError> {
        let mut cols = DEFAULT_COLS;
        for (idx, s) in arr.iter().enumerate() {
            if idx >= COLS_COUNT {
                return Err(ConfError::InvalidCols {
                    details: format!("too long: {:?}", arr),
                });
            }
            // we swap the cols, to ensure both keeps being present
            let col = Col::from_str(s)?;
            let dest_idx = col.index_in(&cols).unwrap(); // can't be none by construct
            cols[dest_idx] = cols[idx];
            cols[idx] = col;
        }
        debug!("cols from conf = {:?}", cols);
        Ok(cols)
    }
    /// return a Cols which tries to take the s setting into account
    /// but is guaranteed to have every Col exactly once.
    pub fn parse_cols_single_str(s: &str) -> Result<Cols, ConfError> {
        Self::parse_cols(&s.chars().map(String::from).collect())
    }
}

pub type Cols = [Col;COLS_COUNT];

/// Default column order
pub static DEFAULT_COLS: Cols = [
    Col::Mark,
    Col::Git,
    Col::Date,
    Col::Permission,
    Col::Size,
    Col::Count,
    Col::Branch,
    Col::Name,
];

<file_sep>use {
    toml::{
        value::Table,
        Value,
    },
};

/// try to read the field_name property of the given value, as a string
pub fn string_field(tbl: &Table, field_name: &str) -> Option<String> {
    tbl.get(field_name)
        .and_then(|fv| fv.as_str())
        .map(|s| s.to_string())
}

/// try to read the field_name property of the given value, as an array of strings.
/// Return None if the type isn't compatible
pub fn string_array_field(tbl: &Table, field_name: &str) -> Option<Vec<String>> {
    if let Some(fv) = tbl.get(field_name) {
        if let Value::Array(arr_val) = fv {
            let mut arr = Vec::new();
            for v in arr_val {
                match v.as_str() {
                    Some(s) => {
                        arr.push(s.to_string());
                    }
                    None => {
                        return None; // non matching value
                    }
                }
            }
            return Some(arr);
        }
    }
    None

}

/// try to read the field_name property of the given value, as a boolean
/// (only read it if it's a proper toml boolean, doesn't try to do hazardous
/// string to bool conversions)
pub fn bool_field(tbl: &Table, field_name: &str) -> Option<bool> {
    match tbl.get(field_name) {
        Some(Value::Boolean(b)) => Some(*b),
        _ => None,
    }
}
<file_sep>//! manage reading the verb shortcuts from the configuration file,
//! initializing if if it doesn't yet exist

use {
    super::{
        default_conf::DEFAULT_CONF_FILE,
        toml::*,
    },
    crate::{
        verb::Verb,
        display::{Col, Cols},
        errors::ConfError,
        pattern::{SearchModeMap, SearchModeMapEntry},
        skin::{ExtColorMap, SkinEntry},
        tree::*,
    },
    crossterm::style::Attribute,
    fnv::FnvHashMap,
    std::{
        convert::TryFrom,
        fs, io,
        path::{Path, PathBuf},
    },
    toml::{self, Value},
};

/// The configuration read from conf.toml file(s)
#[derive(Default)]
pub struct Conf {
    pub default_flags: String, // the flags to apply before cli ones
    pub date_time_format: Option<String>,
    pub verbs: Vec<Verb>,
    pub skin: FnvHashMap<String, SkinEntry>,
    pub special_paths: Vec<SpecialPath>,
    pub search_modes: SearchModeMap,
    pub disable_mouse_capture: bool,
    pub cols_order: Option<Cols>,
    pub show_selection_mark: Option<bool>,
    pub ext_colors: ExtColorMap,
    pub syntax_theme: Option<String>,
    pub true_colors: Option<bool>,
    pub icon_theme: Option<String>,
}

impl Conf {

    pub fn default_location() -> &'static Path {
        lazy_static! {
            static ref CONF_PATH: PathBuf = super::dir().join("conf.toml");
        }
        &*CONF_PATH
    }

    /// read the configuration file from the default OS specific location.
    /// Create it if it doesn't exist
    pub fn from_default_location() -> Result<Conf, ConfError> {
        let conf_filepath = Conf::default_location();
        if !conf_filepath.exists() {
            Conf::write_sample(&conf_filepath)?;
            println!(
                "New Configuration file written in {}{:?}{}.",
                Attribute::Bold,
                &conf_filepath,
                Attribute::Reset,
            );
            println!("You should have a look at it.");
        }
        let mut conf = Conf::default();
        match conf.read_file(&conf_filepath) {
            Err(e) => {
                println!("Failed to read configuration in {:?}.", &conf_filepath);
                println!("Please delete or fix this file.");
                Err(e)
            }
            _ => Ok(conf),
        }
    }

    /// assume the file doesn't yet exist
    pub fn write_sample(filepath: &Path) -> Result<(), io::Error> {
        fs::create_dir_all(filepath.parent().unwrap())?;
        fs::write(filepath, DEFAULT_CONF_FILE)?;
        Ok(())
    }

    /// read the configuration from a given path. Assume it exists.
    /// stderr is supposed to be a valid solution for displaying errors
    /// (i.e. this function is called before or after the terminal alternation)
    pub fn read_file(&mut self, filepath: &Path) -> Result<(), ConfError> {
        let data = fs::read_to_string(filepath)?;
        let root: toml::value::Table = match data.parse::<Value>()? {
            Value::Table(tbl) => tbl,
            _ => {
                return Err(ConfError::Invalid {});
            }
        };
        // reading default flags
        if let Some(s) = string_field(&root, "default_flags") {
            // it's additive because another config file may have
            // been read before and we usually want all the flags
            // (the last ones may reverse the first ones)
            self.default_flags.push_str(&s);
        }
        // date/time format
        self.date_time_format = string_field(&root, "date_time_format");
        // Icon theme
        self.icon_theme = string_field(&root, "icon_theme");
        // reading the optional theme for syntect
        self.syntax_theme = string_field(&root, "syntax_theme");
        // mouse capture
        if let Some(mouse_capture) = bool_field(&root, "capture_mouse") {
            self.disable_mouse_capture = !mouse_capture;
        }
        // cols order
        if let Some(s) = string_field(&root, "cols_order") {
            // old format, with each char being a col, for example
            // `cols_order = "gbpdscn"`
            self.cols_order = Some(Col::parse_cols_single_str(&s)?);
        } else if let Some(arr) = string_array_field(&root, "cols_order") {
            // new format, where each col is a string, for example
            // `cols_order = ["branch", "size" ..., "name"]`
            self.cols_order = Some(Col::parse_cols(&arr)?);
        }
        // reading verbs
        if let Some(Value::Array(verbs_value)) = &root.get("verbs") {
            for verb_value in verbs_value.iter() {
                match Verb::try_from(verb_value) {
                    Ok(verb) => {
                        self.verbs.push(verb);
                    }
                    Err(e) => {
                        eprintln!("Invalid [[verbs]] entry in configuration: {}", e);
                    }
                }
            }
        }
        // reading the skin
        if let Some(Value::Table(entries_tbl)) = &root.get("skin") {
            for (k, v) in entries_tbl.iter() {
                if let Some(s) = v.as_str() {
                    match SkinEntry::parse(s) {
                        Ok(sec) => {
                            self.skin.insert(k.to_string(), sec);
                        }
                        Err(e) => {
                            eprintln!("{}", e);
                        }
                    }
                }
            }
        }
        // reading special paths
        if let Some(Value::Table(paths_tbl)) = &root.get("special-paths") {
            for (k, v) in paths_tbl.iter() {
                if let Some(v) = v.as_str() {
                    match SpecialPath::parse(k, v) {
                        Ok(sp) => {
                            debug!("Adding special path: {:?}", &sp);
                            self.special_paths.push(sp);
                        }
                        Err(e) => {
                            eprintln!("{}", e);
                        }
                    }
                }
            }
        }
        // reading serch modes
        if let Some(Value::Table(search_modes_tbl)) = &root.get("search-modes") {
            for (k, v) in search_modes_tbl.iter() {
                if let Some(v) = v.as_str() {
                    match SearchModeMapEntry::parse(k, v) {
                        Ok(entry) => {
                            debug!("Adding search mode map entry: {:?}", &entry);
                            self.search_modes.set(entry);
                        }
                        Err(e) => {
                            eprintln!("{}", e);
                        }
                    }
                }
            }
        }
        // reading the ext_colors map
        if let Some(Value::Table(ext_colors_tbl)) = &root.get("ext-colors") {
            for (k, v) in ext_colors_tbl.iter() {
                if let Some(v) = v.as_str() {
                    if let Err(e) = self.ext_colors.set(k.to_string(), v) {
                        eprintln!("{}", e);
                    }
                }
            }
        }
        // true_colors ?
        if let Some(b) = bool_field(&root, "true_colors") {
            self.true_colors = Some(b);
        }
        // show selection mark
        if let Some(b) = bool_field(&root, "show_selection_mark") {
            self.show_selection_mark = Some(b);
        }

        Ok(())
    }
}

<file_sep>use {
    super::*,
    crate::{
        app::SelectionType,
        conf::toml::*,
        keys,
        command::Sequence,
        errors::ConfError,
    },
    std::convert::TryFrom,
    toml::Value,
};

/// read a TOML parsed value into a verb,
/// checking a few basic things in the process
impl TryFrom<&Value> for Verb {
    type Error = ConfError;
    fn try_from(verb_value: &Value) -> Result<Self, Self::Error> {
        let verb_value = match verb_value {
            Value::Table(tbl) => tbl,
            _ => {
                return Err(ConfError::InvalidVerbConf {
                    details: "unexpected verb conf structure".to_string(),
                });
            }
        };
        let invocation = string_field(verb_value, "invocation");
        let key = string_field(verb_value, "key")
            .map(|s| keys::parse_key(&s))
            .transpose()?;
        let execution = string_field(verb_value, "execution");
        let internal = string_field(verb_value, "internal");
        let external = string_field(verb_value, "external");
        let cmd = string_field(verb_value, "cmd");
        let cmd_separator = string_field(verb_value, "cmd_separator");
        let from_shell = bool_field(verb_value, "from_shell");
        let leave_broot = bool_field(verb_value, "leave_broot");
        if leave_broot == Some(false) && from_shell == Some(true) {
            return Err(ConfError::InvalidVerbConf {
                details: "You can't simultaneously have leave_broot=false and from_shell=true".to_string(),
            });
        }
        let make_external_execution = |s| ExternalExecution::new(
            s,
            ExternalExecutionMode::from_conf(from_shell, leave_broot),
        ).with_set_working_dir(bool_field(verb_value, "set_working_dir"));
        let execution = match (execution, internal, external, cmd) {
            // old definition with "execution": we guess whether it's an internal or
            // an external
            (Some(s), None, None, None) => if s.starts_with(':') || s.starts_with(' ') {
                VerbExecution::Internal(InternalExecution::try_from(&s[1..])?)
            } else {
                VerbExecution::External(make_external_execution(s))
            }
            // "internal": the leading `:` or ` ` is optional
            (None, Some(s), None, None) => VerbExecution::Internal(
                if s.starts_with(':') || s.starts_with(' ') {
                    InternalExecution::try_from(&s[1..])?
                } else {
                    InternalExecution::try_from(&s)?
                }
            ),
            // "external": it can be about any form
            (None, None, Some(s), None) => VerbExecution::External(make_external_execution(s)),
            // "cmd": it's a sequence
            (None, None, None, Some(s)) => VerbExecution::Sequence(
                SequenceExecution {
                    sequence: Sequence::new(s, cmd_separator),
                }
            ),
            _ => {
                return Err(ConfError::InvalidVerbConf {
                    details: "You must define either internal, external or cmd".to_string(),
                });
            }
        };
        let description = string_field(verb_value, "description")
            .map(VerbDescription::from_text)
            .unwrap_or_else(|| VerbDescription::from_code(execution.to_string()));
        let mut verb = Verb::new(
            invocation.as_deref(),
            execution,
            description,
        )?;
        if let Some(key) = key {
            if keys::is_reserved(key) {
                return Err(ConfError::ReservedKey { key: keys::key_event_desc(key) });
            }
            verb = verb.with_key(key);
        }
        if let Some(shortcut) = string_field(verb_value, "shortcut") {
            verb.names.push(shortcut);
        }
        verb.selection_condition = match string_field(verb_value, "apply_to").as_deref() {
            Some("file") => SelectionType::File,
            Some("directory") => SelectionType::Directory,
            Some("any") => SelectionType::Any,
            None => SelectionType::Any,
            Some(s) => {
                return Err(ConfError::InvalidVerbConf {
                    details: format!("{:?} isn't a valid value of apply_to", s),
                });
            }
        };
        Ok(verb)
    }
}

repo_language: Rust

repo_name: yaoshuyin/broot


text:
<repo_name>DiDouble/logpipe<file_sep>/plugin/input.go
package plugin

import (
	"github.com/logpipe/logpipe/config"
	"github.com/logpipe/logpipe/core"
	"github.com/logpipe/logpipe/log"
)

type InputBuilder interface {
	Kind() string
	Build(name string, spec config.Value) core.Input
}

type inputBuilderWrapper struct {
	kind    string
	builder func(name string, spec config.Value) core.Input
}

func (i *inputBuilderWrapper) Kind() string {
	return i.kind
}

func (i *inputBuilderWrapper) Build(name string, spec config.Value) core.Input {
	return i.builder(name, spec)
}

func RegisterInputBuilder(builder InputBuilder) bool {
	inputLock.Lock()
	defer inputLock.Unlock()
	kind := builder.Kind()
	log.Info("register input plugin [%v]", kind)
	if _, ok := inputBuilders[kind]; ok {
		log.Error("register input plugin [%v] error: plugin already exist", kind)
		return false
	}
	inputBuilders[kind] = builder
	return true
}

func RegisterInput(kind string, builder func(name string, spec config.Value) core.Input) bool {
	return RegisterInputBuilder(&inputBuilderWrapper{kind: kind, builder: builder})
}

func BuildInput(conf config.InputConf) core.Input {
	inputLock.RLock()
	defer inputLock.RUnlock()
	if builder, ok := inputBuilders[conf.Kind()]; ok {
		codec := BuildCodec(conf.Codec())
		input := builder.Build(conf.Name(), conf.Spec())
		if container, ok := input.(core.CodecContainer); ok {
			container.SetCodec(codec)
		}
	}
	return nil
}
<file_sep>/plugin/filter.go
package plugin

import (
	"github.com/logpipe/logpipe/config"
	"github.com/logpipe/logpipe/core"
	"github.com/logpipe/logpipe/log"
)

type FilterBuilder interface {
	Kind() string
	Build(name string, spec config.Value) core.Filter
}

type filterBuilderWrapper struct {
	kind    string
	builder func(name string, spec config.Value) core.Filter
}

func (f *filterBuilderWrapper) Kind() string {
	return f.kind
}

func (f *filterBuilderWrapper) Build(name string, spec config.Value) core.Filter {
	return f.builder(name, spec)
}

func RegisterFilterBuilder(builder FilterBuilder) bool {
	filterLock.Lock()
	defer filterLock.Unlock()
	kind := builder.Kind()
	log.Info("register filter plugin [%v]", kind)
	if _, ok := filterBuilders[kind]; ok {
		log.Error("register filter plugin [%v] error: plugin already exist", kind)
		return false
	}
	filterBuilders[kind] = builder
	return true
}

func RegisterFilter(kind string, builder func(name string, spec config.Value) core.Filter) {
	RegisterFilterBuilder(&filterBuilderWrapper{kind: kind, builder: builder})
}

func BuildFilter(conf config.FilterConf) core.Filter {
	filterLock.RLock()
	defer filterLock.RUnlock()
	if builder, ok := filterBuilders[conf.Kind()]; ok {
		return builder.Build(conf.Name(), conf.Spec())
	}
	return nil
}
<file_sep>/plugin/plugin.go
package plugin

import (
	"sync"
)

var (
	inputLock      sync.RWMutex
	filterLock     sync.RWMutex
	outputLock     sync.RWMutex
	codecLock      sync.RWMutex
	inputBuilders  = make(map[string]InputBuilder)
	filterBuilders = make(map[string]FilterBuilder)
	outputBuilders = make(map[string]OutputBuilder)
	codecBuilders  = make(map[string]CodecBuilder)
)
<file_sep>/engine/node.go
package engine

import (
	"github.com/logpipe/logpipe/core"
)

type inputNode struct {
	name   string
	ctx    *core.Context
	input  core.Input
	action core.Actions
}

type filterNode struct {
	name   string
	ctx    *core.Context
	cond   core.Conds
	filter core.Filter
	action core.Actions
}

type outputNode struct {
	name   string
	ctx    *core.Context
	cond   core.Conds
	output core.Output
}
<file_sep>/log/log.go
package log

import (
	"sync"
)

var levelMap = make(map[string]int)
var appLogger *Logger
var once = sync.Once{}

func init() {
	levelMap["DEBUG"] = 1
	levelMap["INFO"] = 2
	levelMap["WARN"] = 3
	levelMap["ERROR"] = 4

	appLogger = newStdoutLogger("DEBUG")
}

func InitAppLogger(path string, level string) {
	once.Do(func() {
		appLogger = NewLogger(path, level)
	})
}

func Debug(format string, values ...interface{}) {
	appLogger.Debug(format, values...)
}

func Info(format string, values ...interface{}) {
	appLogger.Info(format, values...)
}

func Warn(format string, values ...interface{}) {
	appLogger.Warn(format, values...)
}

func Error(format string, values ...interface{}) {
	appLogger.Error(format, values...)
}

func Fatal(format string, values ...interface{}) {
	appLogger.Fatal(format, values...)
}
<file_sep>/plugin/codec.go
package plugin

import (
	"github.com/logpipe/logpipe/config"
	"github.com/logpipe/logpipe/core"
	"github.com/logpipe/logpipe/log"
)

type CodecBuilder interface {
	Kind() string
	Build(spec config.Value) core.Codec
}

type codecBuilderWrapper struct {
	kind    string
	builder func(spec config.Value) core.Codec
}

func (c *codecBuilderWrapper) Kind() string {
	return c.kind
}

func (c *codecBuilderWrapper) Build(spec config.Value) core.Codec {
	return c.builder(spec)
}

func RegisterCodecBuilder(builder CodecBuilder) bool {
	codecLock.Lock()
	defer codecLock.Unlock()
	kind := builder.Kind()
	log.Info("register codec plugin [%v]", kind)
	if _, ok := codecBuilders[kind]; ok {
		log.Error("register codec plugin [%v] error: plugin already exist", kind)
		return false
	}
	codecBuilders[kind] = builder
	return true
}

func RegisterCodec(kind string, builder func(spec config.Value) core.Codec) bool {
	return RegisterCodecBuilder(&codecBuilderWrapper{kind: kind, builder: builder})
}

func BuildCodec(conf config.CodecConf) core.Codec {
	codecLock.RLock()
	defer codecLock.RUnlock()
	if builder, ok := codecBuilders[conf.Kind()]; ok {
		return builder.Build(conf.Spec())
	}
	return nil
}
<file_sep>/config/config.go
package config

import (
	"github.com/logpipe/logpipe/log"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var appConf = AppConf{}

func init() {
	appConf.Pipes = make(map[string]PipeConf)
}

type AppConf struct {
	Plugins string
	Pipe    struct {
		Path string
	}
	Pipes map[string]PipeConf
	Log   LogConf
}

func LoadConf() error {

	if err := loadAppConf(); err != nil {
		return err
	}
	if err := loadPipeConf(); err != nil {
		return err
	}
	log.Info("config file load finished")
	return nil
}
func loadAppConf() error {
	appConfPath := "conf/logpipe.yaml"

	stat, err := os.Stat(appConfPath)
	if err != nil {
		return err
	}
	if stat.IsDir() {
		appConfPath = filepath.Join(appConfPath, "logpipe.yaml")
	}
	appConfPath, err = filepath.Abs(appConfPath)
	if err != nil {
		return err
	}
	value, err := readValue(appConfPath)
	if err != nil {
		return err
	}
	err = value.Parse(&appConf)
	if err != nil {
		return err
	}
	if !filepath.IsAbs(appConf.Pipe.Path) {
		appConf.Pipe.Path = filepath.Join(filepath.Dir(appConfPath), appConf.Pipe.Path)
	}
	err = initLog()
	if err != nil {
		return err
	}
	return nil
}

func initLog() error {
	if appConf.Log.Level == "" {
		appConf.Log.Level = DEFAULT_LOG_LEVEL
	}
	if appConf.Log.Path == "" {
		appConf.Log.Path = DEFAULT_LOG_PATH
	}
	stat, err := os.Stat(appConf.Log.Path)
	if err != nil {
		return err
	}
	if stat.IsDir() {
		appConf.Log.Path = filepath.Join(appConf.Log.Path, DEFAULT_LOG_NAME)
	}
	if !filepath.IsAbs(appConf.Log.Path) {
		appConf.Log.Path, err = filepath.Abs(appConf.Log.Path)
	}

	log.InitAppLogger(appConf.Log.Path, appConf.Log.Level)
	log.Info("logging [%v] into %v", appConf.Log.Level, appConf.Log.Path)
	return nil
}

func loadPipeConf() error {
	path := appConf.Pipe.Path
	log.Info("scanning pipe conf file in %v", appConf.Pipe.Path)
	dir, err := ioutil.ReadDir(path)
	if err != nil {
		return err
	}
	for _, fi := range dir {
		name := fi.Name()
		if !fi.IsDir() && (strings.HasSuffix(name, ".yaml")) {
			absPath := filepath.Join(path, name)
			log.Info("loading pipe conf: %v", absPath)

			err := readPipeConf(absPath)
			if err != nil {
				log.Error("loading %v error: %v", absPath, err.Error())
			}
		}
	}
	return nil
}

func readPipeConf(path string) error {
	value, err := readValue(path)
	if err != nil {
		return err
	}
	conf := PipeConf{file: path}
	err = value.Parse(&conf)
	if err != nil {
		return err
	}
	appConf.Pipes[path] = conf
	return nil
}

func GetAppConf() AppConf {
	return appConf
}
<file_sep>/plugin/output.go
package plugin

import (
	"github.com/logpipe/logpipe/config"
	"github.com/logpipe/logpipe/core"
	"github.com/logpipe/logpipe/log"
)

type OutputBuilder interface {
	Kind() string
	Build(name string, spec config.Value) core.Output
}

type outputBuilderWrapper struct {
	kind    string
	builder func(name string, spec config.Value) core.Output
}

func (o *outputBuilderWrapper) Kind() string {
	return o.kind
}

func (o *outputBuilderWrapper) Build(name string, spec config.Value) core.Output {
	return o.builder(name, spec)
}

func RegisterOutputBuilder(builder OutputBuilder) bool {
	outputLock.Lock()
	defer outputLock.Unlock()
	kind := builder.Kind()
	log.Info("register output plugin [%v]", kind)
	if _, ok := outputBuilders[kind]; ok {
		log.Error("register output plugin [%v] error: plugin already exist", kind)
		return false
	}
	outputBuilders[kind] = builder
	return true
}

func RegisterOutput(kind string, builder func(name string, spec config.Value) core.Output) bool {
	return RegisterOutputBuilder(&outputBuilderWrapper{kind: kind, builder: builder})
}

func BuildOutput(conf config.OutputConf) core.Output {
	outputLock.RLock()
	defer outputLock.RUnlock()
	if builder, ok := outputBuilders[conf.Kind()]; ok {
		codec := BuildCodec(conf.Codec())
		output := builder.Build(conf.Name(), conf.Spec())
		if container, ok := output.(core.CodecContainer); ok {
			container.SetCodec(codec)
		}
	}
	return nil
}
<file_sep>/README.md
# logpipe
A log processing engine.
<file_sep>/plugin/loader.go
// +build linux
package plugin

import (
	"github.com/logpipe/logpipe/config"
	"github.com/logpipe/logpipe/log"
	"io/ioutil"
	"os"
	"path/filepath"
	"plugin"
	"strings"
)

const plugin_dir = "plugins/"
const plugin_ext = ".so"
const plugin_register = "Register"

func LoadPlugins() error {
	appConf := config.GetAppConf()
	if appConf.Plugins == "" {
		appConf.Plugins = plugin_dir
	}
	stat, err := os.Stat(appConf.Plugins)
	if err == os.ErrNotExist {
		log.Error("plugins dir not exist: %v", appConf.Plugins)
		return err
	} else if err != nil {
		log.Error("scan plugins dir [%v] error: %v", appConf.Plugins, err.Error())
	}
	if !filepath.IsAbs(appConf.Plugins) {
		appConf.Plugins, err = filepath.Abs(appConf.Plugins)
		if err != nil {
			return err
		}
	}
	if stat.IsDir() {
		dir, err := ioutil.ReadDir(appConf.Plugins)
		if err != nil {
			return err
		}
		for _, f := range dir {
			if strings.HasSuffix(f.Name(), plugin_ext) {
				load(filepath.Join(stat.Name(), f.Name()))
			}
		}
	} else {
		load(appConf.Plugins)
	}
	return nil
}

func load(path string) {
	p, err := plugin.Open(path)
	if err != nil {
		log.Error("loading plugin [%v] error: %v", path, err.Error())
	}
	symbol, err := p.Lookup(plugin_register)
	if err != nil {
		log.Error("lookup Register func in [%v] error: %v", path, err.Error())
	}
	if register, ok := symbol.(func()); ok {
		func() {
			defer func() {
				err := recover()
				log.Error("call Register func error: %v", err)
			}()
			register()
		}()
	}
}
<file_sep>/engine/debug.go
package engine

import (
	"github.com/logpipe/logpipe/config"
	"github.com/logpipe/logpipe/core"
	"github.com/logpipe/logpipe/plugin/buildin"
)

func DebugPipe(conf config.PipeConf) {
	p := pipe{}
	p.Init(conf)
	if len(p.inputs) == 0 {
		p.inputs = make([]inputNode, 1)
		p.inputs[0] = inputNode{input: &buildin.StdinInput{}}
	}
	if len(p.outputs) == 0 {
		p.outputs = make([]outputNode, 1)
		p.outputs[0] = outputNode{output: &buildin.StdoutOutput{}}
	}
	p.Start()
}

func DebugInput(input core.Input) {
	debug(input, nil, nil)
}

func DebugFilter(filter core.Filter) {
	debug(nil, filter, nil)
}
func DebugOutput(output core.Output) {
	debug(nil, nil, output)
}
func debug(input core.Input, filter core.Filter, output core.Output) {
	p := pipe{}
	p.Init(config.PipeConf{})
	p.inputs = make([]inputNode, 1)
	if input == nil {
		input = &buildin.StdinInput{}
	}
	p.inputs[0] = inputNode{input: input}
	if filter != nil {
		p.filters = make([]filterNode, 1)
		p.filters[0] = filterNode{filter: filter}
	}
	p.outputs = make([]outputNode, 1)
	if output == nil {
		output = &buildin.StdoutOutput{}
	}
	p.outputs[0] = outputNode{output: output}
	p.Start()
}
<file_sep>/core/context.go
package core

import (
	"fmt"
	"github.com/logpipe/logpipe/log"
)

type ContextContainer interface {
	Context() *Context
	SetContext(ctx *Context)
}

type Context struct {
	pipe   string
	name   string
	kind   string
	plugin string
	logger *log.Logger
	vars   map[string]interface{}
}

func NewContext(pipe string, name string, kind string, logger *log.Logger, vars map[string]interface{}) *Context {
	plugin := fmt.Sprintf(" [%s-%s-%s] ", pipe, kind, name)
	return &Context{pipe: pipe, name: name, kind: kind, plugin: plugin, logger: logger, vars: vars}
}

func (c *Context) GetVar(name string) interface{} {
	return c.vars[name]
}

func (c *Context) SetVar(name string, value interface{}) {
	c.vars[name] = value
}

func (c *Context) HasVar(name string) bool {
	_, ok := c.vars[name]
	return ok
}

func (c *Context) Debug(format string, values ...interface{}) {
	c.logger.Debug(c.plugin+format, values...)
}

func (c *Context) Info(format string, values ...interface{}) {
	c.logger.Info(c.plugin+format, values...)
}

func (c *Context) Warn(format string, values ...interface{}) {
	c.logger.Warn(c.plugin+format, values...)
}

func (c *Context) Error(format string, values ...interface{}) {
	c.logger.Error(c.plugin+format, values...)
}
<file_sep>/log/logger.go
package log

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
)

type Logger struct {
	logLevel zap.AtomicLevel
	logger   *zap.SugaredLogger
}

func NewLogger(path string, level string) *Logger {
	return newFileLogger(path, level)
}

func (l *Logger) Debug(format string, values ...interface{}) {
	l.logger.Debugf(format, values...)
}

func (l *Logger) Info(format string, values ...interface{}) {
	l.logger.Infof(format, values...)
}

func (l *Logger) Warn(format string, values ...interface{}) {
	l.logger.Warnf(format, values...)
}

func (l *Logger) Error(format string, values ...interface{}) {
	l.logger.Errorf(format, values...)
}

func (l *Logger) Fatal(format string, values ...interface{}) {
	l.logger.Fatalf(format, values...)
}

func (l *Logger) setLevel(level string) {
	switch level {
	case "DEBUG":
		l.logLevel.SetLevel(zapcore.DebugLevel)
	case "INFO":
		l.logLevel.SetLevel(zapcore.InfoLevel)
	case "WARN":
		l.logLevel.SetLevel(zapcore.WarnLevel)
	case "ERROR":
		l.logLevel.SetLevel(zapcore.ErrorLevel)
	case "FATAL":
		l.logLevel.SetLevel(zapcore.FatalLevel)
	default:
		l.logLevel.SetLevel(zapcore.ErrorLevel)
	}
}

func newFileLogger(path string, level string) *Logger {
	var logLevel = zap.NewAtomicLevel()
	writer := zapcore.AddSync(&lumberjack.Logger{
		Filename:  path,
		MaxSize:   1024, //MB
		LocalTime: true,
		Compress:  true,
	})

	core := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, logLevel)
	l := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(2))
	logger := &Logger{logger: l.Sugar(), logLevel: logLevel}
	logger.setLevel(level)
	return logger
}

func newStdoutLogger(level string) *Logger {
	var logLevel = zap.NewAtomicLevel()
	writer := zapcore.AddSync(os.Stdout)
	core := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, logLevel)
	l := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(2))
	logger := &Logger{logger: l.Sugar(), logLevel: logLevel}
	logger.setLevel(level)
	return logger
}

branch_name: refs/heads/master

languages: Markdown Go

repo_language: Markdown

repo_name: DiDouble/logpipe


text:
<repo_name>emli/go-web<file_sep>/.travis.yml
language: go
go:
- '1.10'
before_install:
- openssl aes-256-cbc -K $encrypted_81278a220d01_key -iv $encrypted_81278a220d01_iv
  -in deploy_rsa.enc -out deploy_rsa -d
- eval "$(ssh-agent -s)"
- chmod 600 deploy_rsa
- ssh-add deploy_rsa
script:
- ssh -o StrictHostKeyChecking=no -f <EMAIL>@deploy-<EMAIL> -p8888
    "systemctl stop go-web.service"
    "go get https://github.com/emli/go-web"
    "go build"
    "systemctl start go-web.service"
<file_sep>/main.go
package main

import (
	"net/http"
	"log"
)

var (
	srv *http.Server
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
		http.ServeFile(w, r, "static/go-web.html")
	})

	srv = &http.Server{
		Addr:    ":" + "8080",
		Handler: nil,
	}
	log.Println("App listening on port 8080")
	srv.ListenAndServe()

}
<file_sep>/README.md
[Click me](http://golang-server.envs.subutai.cloud/)

languages: Markdown YAML Go

repo_name: emli/go-web


text:
<repo_name>sehahare/testYii<file_sep>/backend/views/layouts/main.php
<?php
/* @var $this \yii\web\View */
/* @var $content string */

use backend\assets\LibraryAsset;
use yii\helpers\Html;
use yii\widgets\Breadcrumbs;
use yii\bootstrap\NavBar;
use yii\helpers\Url;
use common\widgets\Alert;

LibraryAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">

        <meta charset="<?= Yii::$app->charset ?>">
        <meta name="viewport" content="width=device-width, initial-scale=1">
<?= Html::csrfMetaTags() ?>
        <title><?= Html::encode($this->title) ?></title>
        <?php $this->head() ?>

<?php $this->beginBody() ?>
 <link href="font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <link href="http://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel="stylesheet" type="text/css">
    <link href="http://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css">

      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">

      </button>

                      Home

                        About

                        Books

                        Contact

<a href="<?= Url::to(['/site/signup'])?>" data-method="post""> Sign Up

<a href="<?= Url::to(['/site/logout'])?>" data-method="post" class="btn btn-default btn-flat"> Logout

Library

Books for everyone
Historical, Crime, Romance,Fantasy, Thrillers

About Grayscale

Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.

This theme features stock photos by Gratisography along with a custom Google Maps skin courtesy of Snazzy Maps.

Grayscale includes full HTML, CSS, and custom JavaScript files along with LESS files for easy customization.

Download Grayscale

You can download Grayscale for free on the preview page at Start Bootstrap.

                    Visit Download Page

Contact Start Bootstrap

Feel free to email us to provide some feedback on our templates, give us suggestions for new templates and themes, or to just say hello!

<a href="mailto:<EMAIL>"><EMAIL>

                         Twitter

                         Github

                         Google+

        <?= Breadcrumbs::widget([
            'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
        ]) ?>
        <?= Alert::widget() ?>
        <?= $content ?>

Copyright © Your Website <?php echo date("Y") ?>

        <?php $this->endBody() ?>

<?php $this->endPage() ?>
<file_sep>/backend/assets/LibraryAsset.php
<?php
namespace backend\assets;
use yii\web\AssetBundle;
class LibraryAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'library/css/bootstrap.min.css',
        'library/css/grayscale.css',
        'library/css/bootstrap.css',
    ];
    public $js = [
        'library/js/jquery.js',
        'library/js/grayscale.js',
        'library/js/bootstrap.js',
        'library/js/bootstrap.min.js',
        'library/js/jquery.easing.min.js',
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}

<file_sep>/frontend/views/site/index.php
<?php

/* @var $this yii\web\View */

$this->title = 'My Yii Application';
?>

My Company

Company, Business, Education

                                 Twitter

                                 Facebook

                                 Linkedin

Lorem ipsum dolor sit amet
Lorem ipsum

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut bibendum bibendum eros, in efficitur lacus posuere eu. Sed diam enim, aliquet ut volutpat ac, aliquet sed orci. Aenean felis sapien, consequat et iaculis quis, molestie ut elit. Nullam at quam congue, imperdiet lectus sit amet, iaculis nunc. Etiam mollis et nibh quis efficitur. Nullam eget enim augue. Fusce quis nulla vel diam varius lobortis in nec nulla. Sed ultrices

Lorem ipsum dolor sit amet
by PSDCovers

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut bibendum bibendum eros, in efficitur lacus posuere eu. Sed diam enim, alique Google! Visit ros, in efficitur lacus posuere eu. Sed di!

Google Web Fonts and
Font Awesome Icons

Aenean interdum sollicitudin auctor.  Lorem ipsum, Nunc vulputate iaculis eros, non maximus arcu facilisis luctus. Curabitur ut vestibulum sapien. Sed eget nunc sit amet diam accumsan finibus. Curabitur pretium ante neque, sit amet consectetur ligula viverra non. Praesent condimentum tellus sed porta varius. .

Follow us on social network:

                             Twitter

                             Facebook

                             Linkedin

<file_sep>/backend/config/params.php
<?php
return [
    'adminEmail' => '<EMAIL>',
    'languages' => [
        'bs' =>'bosnian',
        'fr' =>'france',
        'en' =>'english'
    ]
];
<file_sep>/backend/components/MyComponent.php
<?php

namespace backend\components;

use Yii;
use yii\base\Component;

class MyComponent extends Component{
    public function hello(){
        echo "Welcome To The Components";
    }
}

?>
<file_sep>/backend/models/Books.php
<?php

namespace backend\models;

use Yii;

/**
 * This is the model class for table "books".
 *
 * @property integer $id
 * @property string $title
 * @property string $author
 * @property string $summary
 * @property string $published_in
 */
class Books extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'books';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['summary'], 'string'],
            [['title', 'author'], 'string', 'max' => 50],
            [['published_in'], 'string', 'max' => 124],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'title' => 'Title',
            'author' => 'Author',
            'summary' => 'Summary',
            'published_in' => 'Published In',
        ];
    }
}
<file_sep>/frontend/views/site/products.php
<?php

use yii\helpers\Html;
use yii\grid\GridView;
use yii\bootstrap\ActiveForm;

/* @var $this yii\web\View */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Products';
$this->params['breadcrumbs'][] = $this->title;
?>

<?= Html::encode($this->title) ?>

  <?php $imgFiles = \yii\helpers\FileHelper::findFiles(Yii::getAlias('@webroot'),['only'=>['*.png']]);

 foreach($imgFiles as $files)
{
        echo "
";
        echo "
";

        $explodeImg = explode('\\', $files);
        $imgName = end($explodeImg);
        echo ".$imgName	";
        echo Html::img(Yii::getAlias('@web').'/img/'.$imgName, ['class' => 'img-responsive img_list_products']);
        echo "
";
        echo "
";
}

?>

repo_language: PHP

repo_name: sehahare/testYii


text:
<file_sep>#! /usr/bin/python
#-*-coding: utf-8 -*-

import random
import sys
import math
NB_BIT = 5
dictionnaire = {'A': 0,'B':1,'C':2,'D':3,'E':4,
'F':5,'G':6,'H':7,'I':8,'J':9,
'K':10,'L':11,'M':12,'N':13,'O':14,
'P':15,'Q':16,'R':17,'S':18,'T':19,
'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,' ':26,'.':27,',':28,'\'':29,'!':30,'?':31}

dic_bin = {dictionnaire[k]:k for k in dictionnaire.keys()}

def __pgcd(m,n):
	while m%n:
		r=m%n
		m=n
		n=r
	return n

def __search_s_and_d(n):
	s=1
	t = (n-1)/2
	while t%2 == 0:
		t = t/2
		s +=1

#liste des primitifs de n
def __primes(n):
    prime = []
    d = 2
    while d*d <= n:
        while (n % d) == 0:
            prime.append(d)
            n //= d
        d += 1
    if n > 1:
       prime.append(n)
    return prime

#Test de primatlité
def __lucas_lehmer(n,k = 7):
	# n>2
	if n<2:
		return False
	# le test de primalité de Lucas Lehmer ne marche que pour les nombre impairs
	if n==2:
		return True
	for _ in range(k):
		a = random.randint(3,n-2)
		if __exponentiation_modulaire_rapide(a,n-1,n) != 1:
			return False
		for q in __primes(n-1):
			if __exponentiation_modulaire_rapide(a,(n-1)/q,n) == 1:
				return False

	return True

def __exponentiation_modulaire_rapide(g,d,n):
	d = bin(d)
	# supprime les caractères "0b"
	d = d[2:]
	# renverse la chaine
	d = d[::-1]

	R0 = 1
	R1 = g
	for i in range(len(d)):
		if d[i]=="1":
			R0 = (R1*R0) % n
		R1 = (R1**2) % n
	return R0

def __inverse_modulaire(a,b):
	r = a
	r1 = b
	u = 1
	v = 0
	u1 = 0
	v1 = 1

	r = (a*u) + (b*v)
	r1 = (a*u1) + (b*v1)

	while r1 != 0:
		q = r/r1

		rs = r
		us = u
		vs = v

		r = r1
		u = u1
		v = v1

		r1 = rs - (q * r1)
		u1 = us - (q * u1)
		v1 = vs - (q * v1)

	while u <= 0:
		u = b + u
	#print a,b
	#print r,u,v
	return u

def __n_et_phi_de_n(p,q):
	n = p*q
	phi = (p-1)*(q-1)

	return [n,phi]

def __e_aleatoire(phi):
	d = random.randint(2,phi-1)
	while __pgcd(d,phi) != 1:
		d = random.randint(1,phi)
	return d

def __get_random():
	rand = random.randint(1000,10000)
	while not __lucas_lehmer(rand):
		rand = random.randint(1000,10000)

	return rand

def generation():

	p = __get_random()
	q = __get_random()

	n = p*q
	phi = (p-1)*(q-1)

	#e premier avec phi
	e = __e_aleatoire(phi)

	#print __pgcd(e,phi)

	d = __inverse_modulaire(e, phi)
	#d = 2753
	#print d
	x = d*e
	#print (d*phi)%n==1
	#test d correct
	#print __exponentiation_modulaire_rapide(x,1,n)==1

	return e,d,n

#-----------------Importation des fonctions du TP1-----------------#

def toilettage_binaire(binaire):
	#jean_nono
	taille = len(binaire) - 2
	cypherText=''
	if(taille < NB_BIT):
		for j in range(NB_BIT-taille):
			cypherText+='0'

	for i in range(2,taille+2):
		cypherText+= binaire[i]

	return cypherText

def encrypt_binaire(lettre):
	return toilettage_binaire(bin(dictionnaire[lettre]))
def encrypt_mot_binaire(mot):
	mot_bin = ''
	for i in mot:
		mot_bin += encrypt_binaire(i)
	return mot_bin
def decrypt_binaire(binaire):
	#return dictionnaire[int(binaire,2)]
	dic_bin[(int(binaire,2))]
	return dic_bin[(int(binaire,2))]

def decrypt_mot_binaire(mot_bin):
	mot=''
	for i in range(0,len(mot_bin),5):
		mot+=decrypt_binaire(mot_bin[:5])
		mot_bin=mot_bin[5:]

	return mot

def function(msg,Key):
	#Decalage binaire
	msg_bin = encrypt_mot_binaire(msg)
	#print msg_bin
	msg_fin=''
	for i in range(1,len(msg_bin)):
		msg_fin+= msg_bin[i]
	msg_fin+=msg_bin[0]
	#print msg_fin
	#ou exclusif
	return ouExclusif(msg_fin,Key)

def ouExclusif(A,B):
	resultat = ''
	for i in range(0,len(A)):
		if (A[i] == B[i] and B[i]=='1'):
			resultat += '0'
		elif A[i] == '1' or B[i]=='1':
			resultat += '1'
		else:
			resultat += '0'
	return resultat

def encrypt_feistel(bloc,Key):
	G = bloc[:2]
	D = bloc[2:]
	#print "encrypt"
	for i in range(4):
		#copie du bloc de droite
		D2 = D
		#la cle prend les deux premiers caracteres
		Key_feistel = Key[:2]
		#La cle globale est décalée de 1 caractere
		Key = Key[1:]+Key[:1]
		#On chiffre la partie droite
		#print "key:"+Key_feistel
		print G+" : "+D +" ////////// "+Key_feistel

		D = function(D,encrypt_mot_binaire(Key_feistel))

		#Maintenant, il faut réaliser le ou exclusif
		D = decrypt_mot_binaire(ouExclusif(D,encrypt_mot_binaire(G)))
		G = D2

		print G+" : "+D
		print Key_feistel

	return G+D
def encrypt_feistel_2(bloc,key):
	key_blocs = []
	for i in range(0,len(key)):
		if(i<len(key)-1):
			if(i<len(key)-2):
				key_blocs.append(str(key[i])+str(key[i+1])+str(key[i+2]))
			else:
				key_blocs.append(str(key[i])+str(key[i+1])+str(key[0]))
		else:
			key_blocs.append(str(key[i])+str(key[0])+str(key[1]))

	while len(bloc) % (len(key_blocs[0])) > 0:
		tmp  = "A"
		tmp += bloc
		bloc = tmp

	print bloc
	G = bloc[:len(key_blocs[0])]
	D = bloc[len(key_blocs[0]):]
	for i in range(len(key_blocs)):
		print key_blocs[i]
		D2 = D
		D = function(D,encrypt_mot_binaire(key_blocs[i]))
		D = decrypt_mot_binaire(ouExclusif(D,encrypt_mot_binaire(G)))
		G = D2
	return D+G

def decrypt_feistel_2(bloc,key):
	key_blocs = []
	for i in range(0,len(key)):
		if(i<len(key)-1):
			if(i<len(key)-2):
				key_blocs.append(str(key[i])+str(key[i+1])+str(key[i+2]))
			else:
				key_blocs.append(str(key[i])+str(key[i+1])+str(key[0]))
		else:
			key_blocs.append(str(key[i])+str(key[0])+str(key[1]))

	while len(bloc) % (len(key_blocs[0])) > 0:
		tmp  = "A"
		tmp += bloc
		bloc = tmp

	G = bloc[:len(key_blocs[0])]
	D = bloc[len(key_blocs[0]):]
	for i in range(len(key_blocs)-1,-1,-1):
		D2 = D
		D = function(D,encrypt_mot_binaire(key_blocs[i]))
		D = decrypt_mot_binaire(ouExclusif(D,encrypt_mot_binaire(G)))
		G = D2
	while (D[0]=='A'):
		tmp = D[len(D)-1:]
		D = tmp
	return D+G
def decrypt_feistel(bloc,Key):
	D = bloc[:2]
	G = bloc[2:]
	Key = Key[3:]+Key[:3]
	#print Key
	#print "Decrypt"
	for i in range(4):
		#copie du bloc de droite
		D2 = D
		#la cle prend les deux premiers caracteres
		Key_feistel = Key[:2]
		#La cle globale est décalée de 1 caractere
		Key = Key[3:]+Key[:3]
		#print Key
		#On chiffre la partie droite
		#print "key:"+Key_feistel
		D = function(D,encrypt_mot_binaire(Key_feistel))

		#Maintenant, il faut réaliser le ou exclusif
		D = decrypt_mot_binaire(ouExclusif(D,encrypt_mot_binaire(G)))
		G = D2

	return D+G

def tailleTexteMod4(mot):
	space=''
	if len(mot)%4 != 0:
		nb_space =4-len(mot)%4
		for i in range(nb_space):
			space+=' '
	return mot+space

def verif_texte(mot):
	resultat = 0
	# liste des caractères interdits
	if re.search("['\"²&é~#{}()\[\]\-|è`_\ç^à@°=+0-9]",mot):
		resultat = 1
		print "\n# Texte non valide : "+mot+"\n"

	return resultat

# excecute seulement si on lance C.py
if __name__ == '__main__':

	cle = generation()
	print "e : "+str(cle[0])
	print "d : "+str(cle[1])
	p = __get_random()
	q = __get_random()
	n = p*q
	phi = (p-1)*(q-1)
	print "---------"
<file_sep>#!/usr/bin/python
#-*-coding:utf8-*-

# fonction random
import random
# librairie permettant d'utiliser des pattern sur une chaine de texte
import re

NB_BIT = 5

dictionnaire = {'A': 0,'B':1,'C':2,'D':3,'E':4,
'F':5,'G':6,'H':7,'I':8,'J':9,
'K':10,'L':11,'M':12,'N':13,'O':14,
'P':15,'Q':16,'R':17,'S':18,'T':19,
'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,' ':26,'.':27,',':28,'\'':29,'!':30,'?':31}

dic_bin = {dictionnaire[k]:k for k in dictionnaire.keys()}

def toilettage_binaire(binaire):
	taille = len(binaire) - 2
	cypherText=''
	if(taille < NB_BIT):
		for j in range(NB_BIT-taille):
			cypherText+='0'

	for i in range(2,taille+2):
		cypherText+= binaire[i]

	return cypherText

def encrypt_binaire(lettre):
	return toilettage_binaire(bin(dictionnaire[lettre]))
def encrypt_mot_binaire(mot):
	mot_bin = ''
	for i in mot:
		mot_bin += encrypt_binaire(i)
	return mot_bin
def decrypt_binaire(binaire):
	#return dictionnaire[int(binaire,2)]
	dic_bin[(int(binaire,2))]
	return dic_bin[(int(binaire,2))]

def decrypt_mot_binaire(mot_bin):
	mot=''
	for i in range(0,len(mot_bin),5):
		mot+=decrypt_binaire(mot_bin[:5])
		mot_bin=mot_bin[5:]

	return mot

def function(msg,Key):
	#Decalage binaire
	msg_bin = encrypt_binaire(msg[0]) + encrypt_binaire(msg[1])
	#print msg_bin
	msg_fin=''
	for i in range(1,len(msg_bin)):
		msg_fin+= msg_bin[i]
	msg_fin+=msg_bin[0]
	#print msg_fin
	#ou exclusif
	return ouExclusif(msg_fin,Key)

def ouExclusif(A,B):
	resultat = ''
	for i in range(0,len(A)):
		if (A[i] == B[i] and B[i]=='1'):
			resultat += '0'
		elif A[i] == '1' or B[i]=='1':
			resultat += '1'
		else:
			resultat += '0'
	return resultat

def encrypt_feistel(bloc,Key):
	G = bloc[:2]
	D = bloc[2:]
	#print "encrypt"
	for i in range(4):
		#copie du bloc de droite
		D2 = D
		#la cle prend les deux premiers caracteres
		Key_feistel = Key[:2]
		#La cle globale est décalée de 1 caractere
		Key = Key[1:]+Key[:1]
		#On chiffre la partie droite
		#print "key:"+Key_feistel
		print G+" : "+D +" ////////// "+Key_feistel

		D = function(D,encrypt_mot_binaire(Key_feistel))

		#Maintenant, il faut réaliser le ou exclusif
		D = decrypt_mot_binaire(ouExclusif(D,encrypt_mot_binaire(G)))
		G = D2

		print G+" : "+D
		print Key_feistel

	return G+D

def decrypt_feistel(bloc,Key):
	D = bloc[:2]
	G = bloc[2:]
	Key = Key[3:]+Key[:3]
	#print Key
	#print "Decrypt"
	for i in range(4):
		#copie du bloc de droite
		D2 = D
		#la cle prend les deux premiers caracteres
		Key_feistel = Key[:2]
		#La cle globale est décalée de 1 caractere
		Key = Key[3:]+Key[:3]
		#print Key
		#On chiffre la partie droite
		#print "key:"+Key_feistel
		D = function(D,encrypt_mot_binaire(Key_feistel))

		#Maintenant, il faut réaliser le ou exclusif
		D = decrypt_mot_binaire(ouExclusif(D,encrypt_mot_binaire(G)))
		G = D2

	return D+G

def tailleTexteMod4(mot):
	space=''
	if len(mot)%4 != 0:
		nb_space =4-len(mot)%4
		for i in range(nb_space):
			space+=' '
	return mot+space

def verif_texte(mot):
	resultat = 0
	# liste des caractères interdit
	if re.search("['\"²&é~#{}()\[\]\-|è`_\ç^à@°=+0-9]",mot):
		resultat = 1
		print "\n# Texte non valide : "+mot+"\n"

	return resultat

#******************************** EBC *********************************
print "\n# ECB encryption #\n"

mot='AAAA??BB'
mot = mot.upper()
mot=tailleTexteMod4(mot)
if verif_texte(mot)==1:
	exit(0)

print " Message   : "+mot

key='KXCX'
cypher_text=''
resultat =''
#save_mot = mot

#Encryption
for i in range (0,len(mot),4):
	cypher_text += encrypt_feistel(mot[:4],key);
	mot = mot[4:]

print "\n Chiffré : "+cypher_text

#Decryption
for i in range (0,len(cypher_text),4):
	resultat += decrypt_feistel(cypher_text[:4],key)
	cypher_text = cypher_text[4:]

print "\n Déchiffré : "+resultat+"\n"

#******************************** CBC *********************************

def vecteur_initialisation():
	length = len(dictionnaire) -1
	# 4 lettre random
	return dic_bin[random.randint(0,length)]+dic_bin[random.randint(0,length)]+dic_bin[random.randint(0,length)]+dic_bin[random.randint(0,length)]

def encrypt_CBC(mot,Key,VI):
	key = encrypt_mot_binaire(Key)
	res=''
	#print "encrypt"
	VI = encrypt_mot_binaire(VI)

	for i in range (0,len(mot),4):
		#passage des 4 premiers caractères en binaire
		plain_bin = encrypt_mot_binaire(mot[:4])
		#plain text XOR Vecteur d'initialisation
		cypher_text = ouExclusif(plain_bin[:20],VI)
		#passage en caractère
		cypher_text = decrypt_mot_binaire(cypher_text)
		#print cypher_text
		cypher_text = encrypt_feistel(cypher_text,Key)

		res += cypher_text

		VI = encrypt_mot_binaire(cypher_text)

		#supression des 4 premier caractères déjà chiffrés
		mot = mot[4:]

	return res

def decrypt_CBC(mot,Key,VI):
	res=''
	VI = encrypt_mot_binaire(VI)

	for i in range (0,len(mot),4):
		#passage des 4 premier caractère en binaire
		cipher_text = decrypt_feistel(mot[:4],Key)

		cipher_text = ouExclusif(encrypt_mot_binaire(cipher_text),VI)

		res += decrypt_mot_binaire(cipher_text)

		VI = encrypt_mot_binaire(mot[:4])

		#supression des 4 premier caractère déjà crypter
		mot = mot[4:]

	return res

print "\n# CBC encryption #\n"

crypt=''
decrypt=''

mot='Je suis une phrase'
mot = mot.upper()
mot=tailleTexteMod4(mot)
if verif_texte(mot)==1:
	exit(0)

key='KXCX'

#VI = vecteur_initialisation()
VI="PROU"

print " Vect Init : "+VI

print "\n Message   : "+mot

crypt = encrypt_CBC(mot,key,VI)

print "\n Encrypter : "+crypt

decrypt = decrypt_CBC(crypt,key,VI)

print "\n Decrypter : "+decrypt+"\n"

<file_sep>#! /usr/bin/python
#-*-coding: utf-8 -*-

import random
import sys
import math

def Bezout(c,phiN):
    r1=c
    r2=phiN
    u1=1
    v1=0
    u2=0
    v2=1
    while r2!=0 :
        q=r1/r2
        rs=r1
        us=u1
        vs=v1
        r1=r2
        u1=u2
        v1=v2
        r2=rs-q*r2
        u2=us-q*u2
        v2=vs-q*v2
    return r1,u1,v1

# expension modulaire
def puissance(a,e,n):
    p=1
    while(e>0):
        if e%2!=0:
            #print type(p),type(a),type(n)
            p=(p*a)%n
        a=(a*a)%n
        e=e/2
    return p

def temoin(a,n):
    m = n-1
    y = 1
    while m!=0 :
        if m%2 == 1 :
            y = (a*y) % n
            m = m-1
        else :
            b = a
            a = (a*a) % n
            if a==1 and b!=1 and b!=(n-1) :
                return True
            m=m/2
    if y != 1 :
        return True
    else :
        return False

def millerRabin(n,t=40):
    for i in range(t):
        a = random.randint(2, n-1)
        if temoin(a,n) :
            return False
    return True

def randomNombrePremier(d=1000,f=10000):
    nbrePremier = random.randint(d,f)
    while not millerRabin(nbrePremier):
        nbrePremier = random.randint(d,f)
    return nbrePremier

def sizeInt(i):
    return len(map(int,str(i)))

def lstToStr(lst):
    msg=""
    for elt in lst:
        if(sizeInt(elt)==3):
            msg+=str(elt)
        elif(sizeInt(elt)==2):
            msg+="0"
            msg+=str(elt)
        elif(sizeInt(elt)==1):
            msg+="00"
            msg+=str(elt)
        else: # cas impossible
            msg+="000"
    return msg

def strToLst(msg):
    lst=[]
    for i in range(len(msg)):
        if(i%3==0):
            tmp=str(msg[i])
        elif(i%3==1):
            tmp+=str(msg[i])
        else:
            tmp+=str(msg[i])
            lst.append(int(tmp))
    return lst

def strInAscii(msg):
    lst=[]
    for i in range(len(msg)):
        lst.append(ord(msg[i]))
    return lst

def asciiInStr(msg):
    lst=""
    for i in range(len(msg)):
        lst+=chr(msg[i])
    return lst

def crypter(msg,clefs):
    msg = strInAscii(msg)
    msg = lstToStr(msg)
    msg = puissance(int(msg),clefs[0],clefs[1])
    return msg

def decrypter(msg,clefs):
    msg = puissance(msg,clefs[0],clefs[1])
    if(sizeInt(msg)%3==2):
        msg = "0"+str(msg)
    elif(sizeInt(msg)%3==1):
        msg = "00"+str(msg)
    else:
        msg = str(msg)
    msg = strToLst(str(msg))
    msg = asciiInStr(msg)

    return msg

def genererClefs(a,b):
    p=randomNombrePremier(a,b)
    q=randomNombrePremier(a,b)
    #p=3
    #q=11
    n=p*q
    phiN=(p-1)*(q-1)
    #c=7
    c = random.randint(99999,999999)
    r=0
    u=v=-1
    while not (r==1 and u>=0):
        c+=1
        (r,u,v) = Bezout(c,phiN)
    d=abs(u)
    return (c,n),(d,n)

a=9999999999999999999999999999999999999999999999999999999999999999999999999999999
b=9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

clefPublic,clefPrivee = genererClefs(a,b)
print "\nCle public :",clefPublic
print "\nCle privée :",clefPrivee

msgACrypter = "Hello world !!"
print "\nMessage :",msgACrypter
msgCrypter = crypter(msgACrypter, clefPublic)
print "\nMessage crypté :",msgCrypter
msgDecrypter = decrypter(msgCrypter, clefPrivee)
print "\nMessage decrypté :",msgDecrypter
<file_sep>#! /usr/bin/python
#-*-coding: utf-8 -*-

import random
import sys
import math
import C as c
import A as a

dictionnaire = {'A': 0,'B':1,'C':2,'D':3,'E':4,
'F':5,'G':6,'H':7,'I':8,'J':9,
'K':10,'L':11,'M':12,'N':13,'O':14,
'P':15,'Q':16,'R':17,'S':18,'T':19,
'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,' ':26,'.':27,',':28,'\'':29,'!':30,'?':31}

dic_bin = {dictionnaire[k]:k for k in dictionnaire.keys()}

e = ""
d = ""
n = ""
rand=""
mdp=""

def generation():
	global e
	global d
	global n
	cle = c.generation()
	e= cle[0]
	d = cle[1]
	n = cle[2]

def toInt(lettre):
	return dictionnaire[lettre]

def toLetter(num):
	return dic_bin[num]

def __exponentiation_modulaire_rapide(g,d,n):
	d = bin(d)
	# supprime les caractère "0b"
	d = d[2:]
	# reverse la chaine
	d = d[::-1]

	R0 = 1
	R1 = g
	for i in range(len(d)):
		if d[i]=="1":
			R0 = (R1*R0) % n
		R1 = (R1**2) % n
	return R0

def get_cle_publique():
	return e,n

def envoie_message_to_A(msg):
	print "\n  $$ Message à chiffrer : "+msg
	# Demande a A ça clé public
	cle_A = a.get_cle_publique()
	msg_crypter = []
	for caract in msg:
		msg_crypter.append(__exponentiation_modulaire_rapide(toInt(caract),int(cle_A[0]),int(cle_A[1])))
	print "\n  $$ Envoie du message chiffré à A : "+str(msg_crypter)
	return msg_crypter

def decrypt_message_from_A(msg_crypt):
	global d
	global n
	msg = ''
	for caract in msg_crypt:
		msg += toLetter(__exponentiation_modulaire_rapide(caract, d, n))

	print "\n  $$ Message déchiffré par B : "+msg
	return msg

def etape_1(msg_crypt):
	msg_decrypt = decrypt_message_from_A(msg_crypt)
	etape_2(msg_decrypt)

def etape_2(msg):
	print "\n  ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 2 ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
	if msg == "AB ?!":
		msg_ok = "AB OK"
		msg_crypt = envoie_message_to_A(msg_ok)
		a.etape_2(msg_crypt)

def etape_3(msg_crypt):
	global rand
	rand = decrypt_message_from_A(msg_crypt)
	msg_crypt = envoie_message_to_A(rand)
	a.etape_3_suite(msg_crypt)
def etape4(msg_decrypt):
	if msg_decrypt == rand:
		msg = "AB OK"
		msg_droite = msg[-len(rand):]
		msg_droite_bin = c.encrypt_mot_binaire(msg_droite)
		global mdp
		mdp += c.encrypt_binaire(msg[:len(msg)-len(rand)])
		mdp += c.ouExclusif(msg_droite_bin,c.encrypt_mot_binaire(rand))
		mdp = c.decrypt_mot_binaire(mdp)
		print "\n$$ Mot de passe " +mdp
		a.etape_5()

def etape_6(msg_chiffre):
	print "\n  ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 6 ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
	print "\n$$Dechiffrage de " + msg_chiffre

	code = c.decrypt_feistel_2(msg_chiffre,mdp)
	print "\n$$ Message lu : " + code

# petit tour pour régler le problème d'import circulaire de python
def main():
	a.etape_1()

# excecute seulement si on lance B.py
if __name__ == '__main__':
	#a.generation()
	#generation()
	#print "\n Clés de B : "
	#print "  # e : "+str(e)
	#print "  # d : "+str(d)
	#print "  # n : "+str(n)
	#a.decrypt_message_from_B(envoie_message_to_A(['A','C']))
	print "$$$ A commence la communication $$$"
	a.main()

<file_sep>On carry la game
<file_sep>#ce programme n est pas en open source

def inverse_modulaire(a,b): #inverse de a modulo b

	#on cherche la forme r0 = r1 * a1 + r2
	r0 = a
	r1 = b
	r2 = 0
	a1 = 0
	start = 1
	cpt = 0
	a = []

	while r2 != 0 or start:
		if not start:
			r0 = r1
			r1 = r2
		else:
			start = 0

		cpt +=1
		a1 = int(r0 / r1)
		r2 = r0 % r1
		a.insert(cpt,a1)
		#print r0,"=",r1,"x",a1,"+",r2
	#print "M=",cpt
	#print a

	#Valeurs arbitraires
	u0 = v1 = 1
	u1 = v0 = 0

	u = []
	u.insert(0,u0)
	u.insert(1,u1)

	v= []
	v.insert(0,v0)
	v.insert(1,v1)

	M = cpt
	cpt = 2
	while cpt <=M:
		u.insert(cpt, u[cpt - 2] - a[cpt-2]* u[cpt-1])
		cpt+=1

	#print u[M]
	return u[M]

print inverse_modulaire(75,28)	  <file_sep>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The Legrand Orange Book
% LaTeX Template
% Version 2.0 (9/2/15)
%
% This template has been downloaded from:
% http://www.LaTeXTemplates.com
%
% <NAME> (<EMAIL>) with modifications by:
% Vel (<EMAIL>)
%
% License:
% CC BY-NC-SA 3.0 (http://creativecommons.org/licenses/by-nc-sa/3.0/)
%
% Compiling this template:
% This template uses biber for its bibliography and makeindex for its index.
% When you first open the template, compile it from the command line with the
% commands below to make sure your LaTeX distribution is configured correctly:
%
% 1) pdflatex main
% 2) makeindex main.idx -s StyleInd.ist
% 3) biber main
% 4) pdflatex main x 2
%
% After this, when you wish to update the bibliography/index use the appropriate
% command above and make sure to compile with pdflatex several times
% afterwards to propagate your changes to the document.
%
% This template also uses a number of packages which may need to be
% updated to the newest versions for the template to compile. It is strongly
% recommended you update your LaTeX distribution if you have any
% compilation errors.
%
% Important note:
% Chapter heading images should have a 2:1 width:height ratio,
% e.g. 920px width and 460px height.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%----------------------------------------------------------------------------------------
%	PACKAGES AND OTHER DOCUMENT CONFIGURATIONS
%----------------------------------------------------------------------------------------

\documentclass[11pt,fleqn]{book} % Default font size and left-justified equations

%----------------------------------------------------------------------------------------

\input{structure} % Insert the commands.tex file which contains the majority of the structure behind the template
\begin{document}

%----------------------------------------------------------------------------------------
%	TITLE PAGE
%----------------------------------------------------------------------------------------

\begingroup
\thispagestyle{empty}
\begin{tikzpicture}[remember picture,overlay]
\coordinate [below=12cm] (midpoint) at (current page.north);
\node at (current page.north west)
{\begin{tikzpicture}[remember picture,overlay]
\node[anchor=north west,inner sep=0pt] at (0,0) {\includegraphics[width=\paperwidth]{crypto}}; % Background image
\draw[anchor=north] (midpoint) node [fill=ocre!30!white,fill opacity=0.6,text opacity=1,inner sep=1cm]{\Huge\centering\bfseries\sffamily\parbox[c][][t]{\paperwidth}{\centering Projet MI44\\[15pt] % Book title
{\huge DAUDAN Florian / GUIMARAES Patrick}}}; % Author name
\end{tikzpicture}};
\end{tikzpicture}
\vfill
\endgroup

%----------------------------------------------------------------------------------------
%	TABLE OF CONTENTS
%----------------------------------------------------------------------------------------

\renewcommand*\contentsname{Sommaire}

\chapterimage{crypto_chapter} % Table of contents heading image

\pagestyle{empty} % No headers

\tableofcontents % Print the table of contents itself

%\cleardoublepage % Forces the first chapter to start on an odd page so it's on the right

%\pagestyle{fancy} % Print headers again

%----------------------------------------------------------------------------------------
%	PART
%----------------------------------------------------------------------------------------

%\part{Part One}

%----------------------------------------------------------------------------------------
%	CHAPTER 1
%----------------------------------------------------------------------------------------
\cleardoublepage
\chapterimage{crypto_chapter} % Chapter heading image

\chapter{TP1 : Cryptographie par bloc}

%\section{Paragraphs of Text}\index{Paragraphs of Text}

%\lipsum[1-7] % Dummy text
%------------------------------------------------

\section{Introduction}

\paragraph{}Afin de gérer la conversion d'un caractère en un nombre binaire, nous avons mis au point un dictionnaire. En effet, chaque caractère (A,B,C…) correspond à un nombre (A=0, B=1,C=2,…) et le dictionnaire va donc permettre d'attribuer plus rapidement un nombre à un caractère. Et dans le cadre inverse, un second dictionnaire va permettre de passer d'un nombre au caractère correspondant.
\\\\ Nous avons 32 caractères à gérer ; toutes les lettres de l'alphabet latin ainsi que les caractères espace, point, virgule, apostrophe, point d'exclamation et point d'interrogation. Ce qui nous fait un total de 32 caractère codable sur 5 bits en binaire. Notons la constante NB\_BIT permettant d'ajuster le codage des caractères. En outre, elle permet d’égaliser l'écriture de tous les nombres binaires qui auront, de surcroît, le même nombre de bit. Par exemple, B (=1) sera écrit 00001.
%------------------------------------------------

\section{Binaire}\index{Binaire}

\subsection{Chiffrer}\index{Crypter}
%Texte encrypt \cite{image_crypt}.
\paragraph{}La fonction \textbf{encrypt\_binaire(lettre)} reçoit en paramètre un caractère et retourne directement le nombre binaire associé. En prime abord, elle demande au dictionnaire de lui retourner la valeur numérique en base 10 du caractère . Puis ensuite elle convertit cette valeur en binaire qui sera elle-même envoyée à la fonction \textbf{toilettage\_binaire(binaire)} qui, comme son nom l'indique, va se charger d'écrire le binaire sous le bon nombre de bit(cf. constante NB\_BIT).
Une fois ces opérations terminées, le caractère en binaire sera renvoyé.
\\\\Dans la même optique, nous avons conçu la fonction \textbf{encrypt\_mot\_binaire(mot)}  qui va recevoir un mot, ou une phrase, et renvoyer directement le mot/phrase converti(e).

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{encrypt_bin}
\caption{Fonctions de conversion en binaire}

\end{figure}

%------------------------------------------------
\subsection{Déchiffrer}\index{Decrypter}

\paragraph{}Finalement, pour réaliser l'opération inverse, c'est à dire de convertir un binaire en caractère, nous avons écrit la fonction \textbf{decrypt\_binaire()} qui reçoit un nombre binaire. Cette méthode va en premier lieu convertir le nombre en décimal. Puis appeler le second dictionnaire pour lui demander quel caractère est associé au nombre. Enfin, elle va retourner le caractère trouvé. De façon similaire à encryp\_mot\_binaire(), nous avons écrit \textbf{decrypt\_mot\_binaire(}) qui à partir d'une phrase ou un mot binaire de taille \% NB\_BIT, va retourner les caractères correspondant.

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{decrypt_binaire}
\caption{Fonctions de conversion en caractère}
\label{fig:nonfloat}
\end{figure}

%------------------------------------------------

\subsection{Ou Exclusif}\index{Ou Exclusif}

\paragraph{}La fonction \textbf{ouExclusif(A,B)} réalise le ou exclusif en binaire, elle prend en compte deux binaires.
\\\\On parcourt le premier binaire bit à bit, on compare le bit avec le bit de l'autre binaire. S'ils sont égals et que l'un d'eux est égal à 1, on retourne 0. Sinon si l'un deux est égal à 1 on retourne 1. Dans les autres cas on retourne 0. Une fois terminé, nous avons le résultat de l'addition binaire.

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{ouExclusif}
\caption{ou exclusif(XOR)}
\end{figure}

%------------------------------------------------

\section{Function}\index{Function}

\paragraph{}La fonction \textbf{function()} prend en paramètre un message msg de 2 caractères ainsi qu'une clé Key de 2 caractères convertie en binaire. On converti le message en binaire puis on réalise le décalage binaire. Ce dernier se réalise de cette manière : on crée une nouvelle variable, on lui ajoute tous les bits du message binaire en commençant par le second bit. Une fois arrivé à la fin, on lui ajoute le premier bit du message réalisant ainsi le décalage binaire gauche.

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{function}
\caption{Fonction de Feistel}
\end{figure}

%------------------------------------------------

\section{Réseau de Feistel}\index{Feistel}

\subsection{Chiffrer}

\paragraph{}Le réseau de Feistel est symbolisé par la fonction \textbf{encrypt\_feistel()} qui à partir d'un bloc et d'une clé, va chiffrer un texte. Tout d'abord, nous divisons le bloc en deux, le bloc gauche et le bloc droit. Pour chaque caractère de la clé (i.e. 4 boucles), nous effectuons les opérations suivantes. On réalise la copie du bloc droit, on prend les deux premiers caractères de la clé et on les stocke, on décale la clé de 1 caractère, on transforme le bloc droit à travers la fonction function() à laquelle on lui envoie le bloc droit lui-même ainsi que la clé convertie en binaire. Une fois cela réalisé, on effectue le ou exclusif avec le nouveau bloc droit (résultat de la fonction function()) et la partie gauche. Le résultat obtenu est ainsi converti en caractère, on stocke la copie du bloc droit dans le bloc gauche, et on réitère ce traitement. Nous obtenons finalement notre bloc chiffré à partir de la clé.
\clearpage
\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{feistel}
\caption{Réseau de Feistel pour chiffrer}
\end{figure}

%------------------------------------------------

\subsection{Déchiffrer}

\paragraph{}Dans l'optique inverse, nous avons conçu \textbf{decrypt\_Feistel()}, qui à partir d'un bloc chiffré et d'une clé va déchiffrer le message. L'opération est similaire à encrypt\_Feistel(), nous divisons notre bloc de 4 caractères en deux blocs : gauche et droite. À la différence de encrypt\_Feistel(), nous parcourons la clé à l'envers (i.e. « XK » → « CX » → « XC » → « KX ») mais nous effectuons les mêmes opérations : le bloc droit passe par function(), puis le résultat obtenu subit un ou exclusif avec le bloc gauche, et finalement on inverse le bloc gauche avec le bloc droit.

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{dechiffrement_feistel}
\caption{Déchiffrement par Feistel}
\end{figure}

%------------------------------------------------

\subsection{Exemple}

\paragraph{}Afin d'illustrer un exemple concret de fonctionnement du réseau de Feistel, nous avons procédé à une fonction main() permettant de simuler l'échange d'un texte chiffré.
\\\\Nous choisissons un mot arbitraire « AAAA??BB » et une clé « KXCX ». Nous nous assurons que les lettres soient en lettres majuscules (mot.upper()). Nous « préparons » le texte de sorte que sa taille soit un multiple de 4 par le fonction tailleTexteMod4() qui va ajouter des espaces à la fin du mot. Par la suite, nous chiffrons bloc par bloc le texte (taille de 4 caractères). Nous obtenons ainsi « MYMWEQG, ». Et en effectuant l'opération inverse par la fonction decrypt\_feistel() nous ré-obtenons « AAAA??BB ».

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{exemple}
\caption{Exemple de chiffrement}
\end{figure}

%------------------------------------------------

\section{Cipher-bloc Chaining}

\paragraph{}Maintenant intéressons nous au chiffrement et déchiffrement en mode CBC. Tout d'abord, nous avons la fonction \textbf{vecteur\_initialisation()} qui va prendre au hasard 4 caractères dans le dictionnaire pour former la clé. Une fois cette clé formée, nous effectuons un ou exclusif avec le texte en clair. Avec le resultat, nous opérons avec la fonction du réseau de feistel. Une fois l'opération terminée, nous recommençons mais en prenant cette fois-ci le résultat de la fonction et le texte en clair.

\begin{figure}[!h]
\centering\includegraphics[scale=0.5]{cbc}
\caption{CBC}
\end{figure}

%----------------------------------------------------------------------------------------
%	CHAPTER 2
%----------------------------------------------------------------------------------------

\chapter{TP2 : Cryptographie RSA}

%------------------------------------------------

\section{Introduction}

\paragraph{}Nous avons simulé un échange de messages avec le protocole RSA entre deux identités à l'aide de 3 programmes. Les programmes A et B simulent Alice et Bob, deux personnes souhaitant communiquer de manière secrète, et finalement le programme C représentant l'autorité décernant les clés aux différentes personnes. Nous allons nous intéresser dans un premier temps au programme C qui génère les différentes clés, puis nous étudierons le fonctionnement de l'échange de messages.

%------------------------------------------------

\section{Le programme C}

\paragraph{}La fonction centrale de ce programme est la fonction \textbf{generation()} permettant d'éditer l'ensemble des clés.
\\Tout d'abord, nous choisissons 2 nombres premiers aléatoires à l'aide de la fonction \textbf{get\_random()} qui va tirer au hasard un nombre puis va vérifier s'il est premier grâce à la méthode \textbf{lucas\_lehmer()}.
Cette dernière fonctionne ainsi : elle reçoit en paramètre un nombre à tester ainsi qu'un nombre de test qui par défaut est 7. Ce nombre correspond aux nombres de boucles de test que nous réalisons pour tester la primalité du nombre. Tout d'abord si le nombre à tester, que nous appellerons n, est inférieur à 1 le test retourne faux. Ainsi que si n est égal à 2 le test retourne vrai. Nous arrivons dans la boucle principale où le traitement sera réitéré plusieurs fois. En premier lieu nous choisissons un nombre aléatoire entre 3 (car nous excluons 1 et 2) et n-2 . Nous réalisons l’exponentiation modulaire de a\^n-1 mod n. Si le résultat est différent de 1,  on retourne faux. Sinon nous établissons la liste des primitifs de n(cf plus bas la description de la fonction \textbf{primes()}). Nous parcourons cette liste et à chaque primitif nous réalisons a\^(n-1)/q mod n. Si le résultat est égal à 1, nous retournons faux. A la fin de la boucle, si le test n'a retourné aucune valeur, nous finissons par le retour de vrai, car nous avons trouvé que n est un nombre entier.
\\\\\\Fonction \textbf{primes()}. Cette fonction permet de trouver la liste des entiers primifs d'un nombre entier. Tout d'abord, nous allouons un tableau, et un indice de départ d égal à 2 (premier nombre premier). Nous entrons ensuite dans la boucle while principale où la condition est tant que d² ≤ n , avec n le nombre premier. Dans cette boucle, nous entrons dans une sous-boucle while  où la condition est (n \% d) == 0. Si la condition est respectée, on ajoute d à la liste. Puis on divise n par d, en gardant la partie entière. On sort de la sous-boucle while , on incrémente d et on recommence. Lors de la sortie de la boucle principale while, si n>1 on ajoute n à la liste des entiers primitifs, dans tous les cas on retourne la liste.
\\\\Retournons à la génération des clés, nous avons grâce aux fonctions précédentes, 2 nombres entiers que nous nommerons p et q. Nous calculons n = p*q puis phi(n) = (p-1)*(q-1). Maintenant nous cherchons e, qui est un nombre premier aléatoire entre 1 et phi(n). Intéressons nous à la fonction e\_aleatoire(phi). Cette fonction tire un nombre premier aléatoire entre 2 et phi-1 uniquement si ce nombre ne possède aucun diviseur commun avec phi.
\\Maintenant que nous possédons la clé privée (i.e. e), nous pouvons éditer la clé publique	.
\\Pour cela nous devons chercher d, l'inverse modulaire de phi modulo n. Nous faisons appel à la fonction \textbf{inverse\_modulaire(e,phi)}. Cette fonction utilise l’algorithme suivant :
\begin{itemize}
\item les constantes u0 = 1, u1 = 0, v0=0 et v1 = 1
\item r0 = (e * u0) + (phi * v0)
\item r1 = (e * u1) + (phi * v1)
\item Tant que r1 est différent de 0 nous faisons
	\begin{itemize}
	\item q = r0 / r1
	\item r = r0
	\item u = u0
	\item v = v0
	\item on affecte à r0 la valeur de r1, ainsi que u0 reçoit u1 et v0 vaut v1.
	\item r1 = r – (q * r1)
	\item u1 = u – (q * u1)
	\item v1 = v – (q*v1)
	\end{itemize}

\item Une fois terminé,  nous incrémentons b à u0 afin qu'il devienne positif
\item On retourne u, l'inverse modulaire de phi.
\end{itemize}
\vspace{0.5cm}La fonction génération retourne le couple e,d,n qui comporte clé publique/privée pour le futur utilisateur.

%------------------------------------------------

\section{Le programme A et B}
\paragraph{}Maintenons nous allons étudier le fonctionnement des différents opérateurs dans l'échange de leur message. Nommons les A et B.
\subsection{Etape 1}
\paragraph{}A souhaite envoyer le message suivant : « AB ?! » vers B. Pour cela il fait appel à la fonction \textbf{envoie\_message\_to\_B(message)} qui va encoder le message selon le protocole RSA. C'est à dire que nous allons convertir chaque caractère en nombre. Pour cela nous réutilisons le dictionnaire du TP précédent. Maintenant que nous avons un nombre, nous effectuons le calcul suivant :
\\soit M le nombre à chiffrer et (d,n) la clé publique de B
\\C = $M^d$ mod n
\\\\\textbf{Nota Bene} : à des fins pratiques, nous utilisons la fonction d'exponentiation modulaire rapide pour limiter l'utilisation du processeur et pour une résultat plus rapide.
\\\\Une fois notre nombre chiffré, nous recommençons avec les autres caractères du message. Ce qui nous donne une liste de nombres. Nous envoyons cette liste à B qui va commencer le déchiffrement.
\\Pour cela, B utilise \textbf{decrypt\_message\_from\_A(msg\_crypt)} . Cette fonction va prendre chaque nombre dans la liste reçue et le déchiffrer en utilisant la formule suivante :
\begin{itemize}
 \item soit C le message chiffré, (e,n) la clé privée de B
 \item M = $C^e$ mod n
\end{itemize}

\subsection{Etape 2}
\paragraph{}Une fois le message lu, B compare si le message reçu est égal à « AB?! ». Si tel est le cas, B prépare le message « AB OK » pour A. Il le chiffre de la même manière que A en faisant C = M\^d mod n avec ( d,n) la clé publique de A.
\\\\A reçoit le message, le déchiffre et le compare à « AB OK ». S'ils sont similaires, on passe à l'étape 3.

\subsection{Etape 3}
\paragraph{}A génère 4 caractères aléatoires à partir de son dictionnaire. Puis il les envoie à B en utilisant le protocole RSA.  B les déchiffre, puis les chiffre pour les renvoyer à A. A son tour, A déchiffre pour vérifier que le message a bien été reçu.

\subsection{Etape 4}
\paragraph{}Puisque A et B possède le même mot de passe, on va pouvoir effectuer les opérations suivantes. On effectue le ou exclusif de « AB OK » et du mot de passe. Puisque que le message possède une taille plus grande que le mot de passe ( 4 caractères contre 5), nous nous sommes adaptés à la fonction ouExclusif(). En effet nous effectuons un ou exclusif uniquement avec les caractères nécessaires en partant de la droite du message. \\Exemple :
\\\\}AB OK → message
\\ABCD → mot de passe
\\Nous alignons à droite le mot de passe
\\\\AB OK
\\-ABCD
\\puis nous découpons le message
\\B OK
\\ABCD
\\Maintenant nous effectuons un ou exclusif de B OK et ABCD.
\\Puisque le XOR de A et 0 donne A, nous prenons A et ajoutons le résultat du XOR à la suite.

\subsection{Etape 5}
\paragraph{}Avec notre mot de passe ainsi généré ( la clé pour le réseau de Feitel), nous pouvons commencer le chiffrement. Nous avons adapté la fonction \textbf{encrypt\_feistel} en \textbf{encrypt\_feistel\_2}  , elle permet de réaliser le chiffrement avec des tailles différentes de 4 caractères. A chiffre son message puis l'envoie à B qui va le déchiffrer avec le même mot de passe(clé).

\begin{figure}[h]
\centering\includegraphics[scale=0.5]{encrypt_feistel2}
\caption{Nouvelle version du réseau de Feistel}
\end{figure}

\end{document}<file_sep>import array
from math import floor
import sys

# 2^32 en HEXA
N = 0x100000000;

# 2^32 - 1
MASK = 	0xFFFFFFFF;

#  Fonction :  Decallage a gauche de n bit , d'un mot de 32 bit word
def leftRotate(word, n):
	return ((word<<n)&MASK)|(word>>32 - n)

# Fonction : addition mod 2^32 des entiers qui correspondent aux mot de 32 bits.
def add(A,B):
	return (A + B) % N

def sha1Hash(stringArray):

    # on souhaite savoir le nombre de bit que contient le mot, chaque caractere etant sur 8 bits
	l = len(stringArray)*8

	# Ajout d'un bit a 1 a la fin du message
	stringArray.append(0x80);

	# calculs du nombre de zero a rajouter de facon a ce que le message soit divisible par 512 bits
	nZeros = ( 448 - (len(stringArray))*8) % 0x200
	boxes = int(floor(nZeros/8));

	print ("Rajout de %i zeros en (boxes=%i) blocs") % (nZeros,boxes)

    # ici on ajoute les zero calculer precedement.
	for i in range(boxes): stringArray.append(0);

	# On verifie que la taille est < 2^32
	stringArray.append(0)
	stringArray.append(0)
	stringArray.append(0)
	stringArray.append(0)

	stringArray.append(0)
	stringArray.append(0)
	stringArray.append(0)
	stringArray.append(l)

	n = len(stringArray)/ 64

# initialisation
	h0 = 0x67452301
	h1 = 0xEFCDAB89
	h2 = 0x98BADCFE
	h3 = 0x10325476
	h4 = 0xC3D2E1F0

	for i in range(n):

		startOfChunk = i*64
		w = [0]*80

		# Diviser le mot en 16
		for i in range(16):

			val = 0;

			for x in range(4):
				cell = stringArray[startOfChunk + 4*i + x]
				val = val << 8
				val |=cell

			w[i] = val

		for t in range(16,80):
			w[t] = leftRotate((w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]),1)

		A = h0
		B = h1
		C = h2
		D = h3
		E = h4

        # on applique les 80 rotations, en appliquant des constantes differentes celon t.
		for t in range(80):

			if t < 20:
				K = 0x5a827999
				f = (B & C) | ((B ^ 0xFFFFFFFF) & D)
			elif t < 40:
				K = 0x6ed9eba1
				f = B ^ C ^ D
			elif t < 60:
				K = 0x8f1bbcdc
				f = (B & C) | (B & D) | (C & D)
			else:
				K = 0xca62c1d6
				f = B ^ C ^ D

			temp = (leftRotate(A,5) + f + E + w[t] + K) & 0xFFFFFFFF;

			E = D
			D = C
			C = leftRotate(B,30)
			B = A
			A = temp

		h0 = add(h0,A)
		h1 = add(h1,B)
		h2 = add(h2,C)
		h3 = add(h3,D)
		h4 = add(h4,E)

        print "Usual :" , convert_lisible(h0),convert_lisible(h1),convert_lisible(h2),convert_lisible(h3),convert_lisible(h4)
    #    print "Hexadecimal :", hex(h0),hex(h1),hex(h2),hex(h3),hex(h4)

def convert_lisible(h):
    return str(hex(h))[2:10]

def main():

	if(len(sys.argv) < 2):
		print "usage: sha1 <Text Message>"
	else:
		stringMsg = sys.argv[1]
		stringArray = []
        # on  remplace chaque caractere par son equivalent dans la table ASCII
		for byte in array.array('B', stringMsg): stringArray.append(byte)
        # print stringArray
        sha1Hash(stringArray)

main()
<file_sep>#!/usr/bin/python
#-*-coding:utf8-*-

dictionnaire = {'A': 0,'B':1,'C':2,'D':3,'E':4,
'F':5,'G':6,'H':7,'I':8,'J':9,
'K':10,'L':11,'M':12,'N':13,'O':14,
'P':15,'Q':16,'R':17,'S':18,'T':19,
'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,' ':26,'.':27,',':28,'\'':29,'!':30,'?':31}

def encrypt_binaire(lettre):
	return bin(dictionnaire[lettre])

print encrypt_binaire('A')

<file_sep>#! /usr/bin/python
#-*-coding: utf-8 -*-

import random
import sys
import math
import C as c
import B as b

dictionnaire = {'A': 0,'B':1,'C':2,'D':3,'E':4,
'F':5,'G':6,'H':7,'I':8,'J':9,
'K':10,'L':11,'M':12,'N':13,'O':14,
'P':15,'Q':16,'R':17,'S':18,'T':19,
'U':20,'V':21,'W':22,'X':23,'Y':24,'Z':25,' ':26,'.':27,',':28,'\'':29,'!':30,'?':31}

dic_bin = {dictionnaire[k]:k for k in dictionnaire.keys()}

e = ""
d = ""
n = ""
rand = ""
mdp = ""

def generation():
	global e
	global d
	global n
	cle = c.generation()
	e= cle[0]
	d = cle[1]
	n = cle[2]

def toInt(lettre):
	return dictionnaire[lettre]

def toLetter(num):
	return dic_bin[num]

def toASCII(nombre):
	return int(dic_bin[nombre])

def __exponentiation_modulaire_rapide(g,d,n):
	d = bin(d)
	# supprime les caractère "0b"
	d = d[2:]
	# reverse la chaine
	d = d[::-1]

	R0 = 1
	R1 = g
	for i in range(len(d)):
		if d[i]=="1":
			R0 = (R1*R0) % n
		R1 = (R1**2) % n
	return R0

def get_cle_publique():
	return e,n

def envoie_message_to_B(msg):
	print "\n  ## Message a encrypter : "+msg
	# Demande a B ça clé public
	cle_B = b.get_cle_publique()
	msg_crypter = []
	for caract in msg:
		msg_crypter.append(__exponentiation_modulaire_rapide(toInt(caract),int(cle_B[0]),int(cle_B[1])))

	print "\n  ## Envoie du message crypter à B : "+str(msg_crypter)
	return msg_crypter

def decrypt_message_from_B(msg_crypt):
	global d
	global n
	msg = ''
	for caract in msg_crypt:
		msg += toLetter(__exponentiation_modulaire_rapide(caract, d, n))

	print "\n  ## Message décrypter par A : "+msg
	return msg

def etape_1():
	b.generation()
	generation()
	msg = "AB ?!"

	print "\n  # A"
	print "  $ B"
	#print "\n  Clés de A : "
	#print "  # e : "+str(e)
	#print "  # d : "+str(d)
	#print "  # n : "+str(n)

	print "\n  ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 1 ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"

	msg_crypt = envoie_message_to_B(msg)

	b.etape_1(msg_crypt)

def etape_2(msg_crypt):
	msg_decrypt = decrypt_message_from_B(msg_crypt)
	etape_3(msg_decrypt)

def etape_3(msg_decrypt):
	global rand

	print "\n  ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 3 ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
	if msg_decrypt == "AB OK":
		rand = ''
		for _ in range(4):
			rand += toLetter(random.randint(0,31))
		print "\n  ## 4 caractères aléatoire : "+rand

		msg_crypt = envoie_message_to_B(rand)
		b.etape_3(msg_crypt)

def etape_3_suite(msg_crypt):
	msg_decrypt = decrypt_message_from_B(msg_crypt)
	etape_4(msg_decrypt)

def etape_4(msg_decrypt):
	print "\n  ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 4 ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
	if msg_decrypt == rand:
		msg = "AB OK"
		msg_droite = msg[-len(rand):]
		msg_droite_bin = c.encrypt_mot_binaire(msg_droite)
		global mdp
		mdp += c.encrypt_binaire(msg[:len(msg)-len(rand)])
		mdp += c.ouExclusif(msg_droite_bin,c.encrypt_mot_binaire(rand))
		mdp = c.decrypt_mot_binaire(mdp)
		print "\n## Mot de passe " +mdp
		b.etape4(msg_decrypt)

def etape_5():
	msg_chiffre = c.encrypt_feistel_2(rand,mdp)
	print "\n  ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 5 ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
	print "\n##Message clair : "+rand
	print "\n## Envoi du message chiffré :"+msg_chiffre
	b.etape_6(msg_chiffre)

def main():
	msg_crypt = etape_1()

# excecute seulement si on lance A.py
if __name__ == '__main__':
	# petit tour part B pour régler le problème d'import circulaire de python
	# b.main appelle a.etape_1()
	b.main()

languages: Markdown TeX Python