Commit cf66c701 authored by Mathieu Valois's avatar Mathieu Valois
Browse files

merged GUI into cli, GUI working for now

parent c7933998
Loading
Loading
Loading
Loading

GUI/GUI.pro

deleted100644 → 0
+0 −21
Changes for GUI/GUI.pro: 0 added lines, 21 removed lines.
Original line number Diff line number Diff line

QT += core gui
QT += widgets
QT += charts

TARGET  = GUI
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp\
        statsgen.cpp

HEADERS  += mainwindow.h\
        statsgen.h\
        utils.h

FORMS    += mainwindow.ui


QMAKE_CXXFLAGS += -std=c++11 -lpthread -static

GUI/statsgen.cpp

deleted100644 → 0
+0 −558
Changes for GUI/statsgen.cpp: 0 added lines, 558 removed lines.
Original line number Diff line number Diff line
/**
 * @file statsgen.cpp
 * @brief Creation of all methods from Statsgen
 *
 * @author Jean-Baptiste Jorand
 * @author Yannick Bass
 * Copyright (c) 2018 Jorand Jean-baptiste Bass Yannick
 * All rights reserved.
 *
 * Please see the attached LICENSE file for additional licensing information.
 */



#include <fstream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <thread>
#include <pthread.h>

#include "statsgen.h"
#include "utils.h"

#include <QFile>
#include <QString>


using namespace std;





Statsgen::Statsgen() {}



void Statsgen::setFilename(QString name) {
    filename = name;
}


void Statsgen::setHiderare(int val) {
    hiderare = val;
}



void Statsgen::setTop(int val) {
    top = val;
}


void Statsgen::setRegex(string expr) {
    wstring tmp(expr.length(),L' ');
    copy(expr.begin(), expr.end(), tmp.begin());

    wregex tmp_reg(tmp);
    current_regex = tmp_reg;

    use_regex = true;
}


void Statsgen::setWithcount(bool val) {
    withcount = val;
}


void Statsgen::setLimitSimplemask(int val) {
    limitSimplemask = val;
}


void Statsgen::setLimitAdvancedmask(int val) {
    limitAdvancedmask = val;
}


void Statsgen::setNbThread(int nb) {
    int max = thread::hardware_concurrency();
    if (nb > max) {
        nbThread = max;
    } else {
        nbThread = nb;
    }
}


void Statsgen::setSecurityRules(int length,int special,int digit,int upper,int lower) {
    minLength=length;
    minSpecial=special;
    minDigit=digit;
    minUpper=upper;
    minLower=lower;
}



void Statsgen::generate_stats() {
    int nbline = nbline_file(filename);

    int rc;
    int i;
    pthread_t threads[nbThread];
    struct thread_data td[nbThread];

    pthread_attr_t attr;
    void *status;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for( i = 0; i < nbThread; i++ ) {
        td[i].filename = filename;
        td[i].thread_id = i + 1;
        td[i].current_regex = current_regex;
        td[i].use_regex = use_regex;
        td[i].withcount = withcount;

        td[i].lineBegin = i*(nbline/nbThread) + 1;
        td[i].lineEnd = (i+1)*nbline/nbThread;
        if (i > 0) {
            while (td[i].lineBegin <= td[i-1].lineEnd) {
                td[i].lineBegin++;
            }
        }
        

        td[i].sr.nbSecurePassword = 0;
        td[i].sr.minLength = minLength;
        td[i].sr.minSpecial = minSpecial;
        td[i].sr.minDigit = minDigit;
        td[i].sr.minLower = minLower;
        td[i].sr.minUpper = minUpper;

        wcout << "Thread " << td[i].thread_id << " analyse : " << td[i].lineBegin << " --> " << td[i].lineEnd << endl;
        rc = pthread_create(&threads[i], NULL, generate_stats_thread, (void *)&td[i] );
      
        if (rc) {
            cout << "Error:unable to create thread," << rc << endl;
            exit(-1);
        }
    }

    pthread_attr_destroy(&attr);
    for( i = 0; i < nbThread; i++ ) {
        rc = pthread_join(threads[i], &status);
        if (rc) {
            cout << "Error:unable to join," << rc << endl;
            exit(-1);
        }
    }


    Policy policyMin;
    Policy policyMax;

	for(i=0;i<nbThread;i++)	{
		total_counter+=td[i].total_counter;
		total_filter+=td[i].total_filter;

        policyMin.digit = td[i].minMaxValue.mindigit;
        policyMin.lower = td[i].minMaxValue.minlower;
        policyMin.upper = td[i].minMaxValue.minupper;
        policyMin.special = td[i].minMaxValue.minspecial;

        policyMax.digit = td[i].minMaxValue.maxdigit;
        policyMax.lower = td[i].minMaxValue.maxlower;
        policyMax.upper = td[i].minMaxValue.maxupper;
        policyMax.special = td[i].minMaxValue.maxspecial;

        nbSecurePassword += td[i].sr.nbSecurePassword;

        updateMinMax(minMaxValue, policyMin);
        updateMinMax(minMaxValue, policyMax);

		
		for(auto it=td[i].length.begin();it!=td[i].length.end();it++)
		{
			stats_length[it->first]+=it->second;
		}
		td[i].length.clear();
		for(auto it=td[i].charactersets.begin();it!=td[i].charactersets.end();it++)
		{
			stats_charactersets[it->first]+=it->second;
		}
		td[i].charactersets.clear();
		for(auto it=td[i].simplemasks.begin();it!=td[i].simplemasks.end();it++)
		{
			stats_simplemasks[it->first]+=it->second;
		}
		td[i].simplemasks.clear();
		for(auto it=td[i].advancedmasks.begin();it!=td[i].advancedmasks.end();it++)
		{
			stats_advancedmasks[it->first]+=it->second;
		}
		td[i].advancedmasks.clear();
	}



    if (!total_counter) {
        wcerr << "Empty file or not existing file" << endl;
    }
}




void Statsgen::print_stats() {
    int count;
    float perc = (float) 100 * (total_filter / total_counter);

    wofstream writeFile("result.txt");

    writeFile << "\n\tSelected " << total_filter << " on " << total_counter << " passwords\t("
        << perc << " %)" << endl;


    writeFile << "\nSecurity rules : " << endl;
    writeFile << "\tMinimal length of a password: " << minLength << endl;
    writeFile << "\tMinimum of special characters in a password: " << minSpecial << endl;
    writeFile << "\tMinimum of digits in a password: " << minDigit << endl;
    writeFile << "\tMinimum of lower characters in a password: " << minLower << endl;
    writeFile << "\tMinimum of upper characters in a password: " << minUpper << endl;

    float perce = (float) 100 * (nbSecurePassword / total_counter);
    writeFile << "\n\t\t--> " << nbSecurePassword << " passwords\t(" << perce << " %) respect the security rules\n" << endl;


    writeFile << "\nmin - max\n" << endl;
    writeFile << setw(43) << right << "digit:  "
            << setw(2) << right << minMaxValue.mindigit << " - " << minMaxValue.maxdigit << endl;
    writeFile << setw(43) << right << "lower:  "
            << setw(2) << right << minMaxValue.minlower << " - " << minMaxValue.maxlower << endl;
    writeFile << setw(43) << right << "upper:  "
            << setw(2) << right << minMaxValue.minupper << " - " << minMaxValue.maxupper << endl;
    writeFile << setw(43) << right << "special:  "
            << setw(2) << right << minMaxValue.minspecial << " - " << minMaxValue.maxspecial << endl;       



    writeFile << "\nStatistics relative to length: \n" << endl;
    showMap(writeFile, stats_length, top, total_counter, hiderare, count);

    writeFile << "\nStatistics relative to charsets: \n" << endl;
    showMap(writeFile, stats_charactersets, -1, total_counter, hiderare, count);


    writeFile << "\nStatistics relative to simplemasks: \n" << endl;
    showMap(writeFile, stats_simplemasks, top, total_counter, hiderare, count);

    if (limitSimplemask > 0) {
        wcout << endl;
        readResult(writeFile, stats_simplemasks[L"othermasks"], L"othermasks", count, total_counter, hiderare);
    }


    writeFile << "\nStatistics relative to advancedmask: \n" << endl;
    showMap(writeFile, stats_advancedmasks, top, total_counter, hiderare, count);
    
    if (limitAdvancedmask > 0) {
        wcout << endl;
        readResult(writeFile, stats_advancedmasks[L"othermasks"], L"othermasks", count, total_counter, hiderare);
    }
}




void Statsgen::initGraphicalStats(QBarSeries * barLength, QPieSeries * pieCharset, double & percentageTotal, double & percentageSecurity, double & total, double & filter) {
    total = total_counter;
    filter = total_filter;
    percentageTotal = (double) 100 * (total_filter / total_counter);
    percentageSecurity = (double) 100 * (nbSecurePassword / total_counter);

    /* LENGTH HISTOGRAM */
    multimap<double, int> reverseL = flip_map<int>(stats_length);
    double percentageL;
    double nbHideL = 0;

    MapIterator<double, int> itL;
    for(itL = reverseL.end(); itL != reverseL.begin(); itL--) {
        if (itL == reverseL.end()) continue;

        percentageL = (double) (100*itL->first) / total_counter;
        if (percentageL >= 2) {
            QBarSet *set = new QBarSet(QString::number(itL->second));
            *set << itL->first;
            barLength->append(set);
        } else {
            nbHideL += itL->first;
        }
    }

    QBarSet *set = new QBarSet("Other lengths");
    *set << nbHideL;
    barLength->append(set);


    /* CHARSET PIECHART */
    multimap<double, wstring> reverseC = flip_map<wstring>(stats_charactersets);
    int top = 0;
    double nbHideC = 0;

    MapIterator<double, wstring> itC;
    for(itC = reverseC.end(); itC != reverseC.begin(); itC--) {
        if (itC == reverseC.end()) continue;
        top++;
        if (top <= 5) {
            pieCharset->append(QString::fromStdWString(itC->second), itC->first);
        } else {
            nbHideC += itC->first;
        }
    }
    pieCharset->append("Other charsets", nbHideC);
}




void analyse_letter(const char & letter, char & last_simplemask, wstring & simplemask_string, wstring & advancedmask_string, Policy & policy, int & sizeAdvancedMask, int & sizeSimpleMask) {
    sizeAdvancedMask++;

    if (letter >= L'0' && letter <= L'9') {
        policy.digit++;
        advancedmask_string += L"?d";
        if (last_simplemask != 'd') {
            sizeSimpleMask++;
            simplemask_string += L"digit";
            last_simplemask = 'd';
        }
    }
    else if(letter >= L'a' && letter <= L'z') {
        policy.lower++;
        advancedmask_string += L"?l";
        if (last_simplemask != 'l') {
            sizeSimpleMask++;
            simplemask_string += L"lower";
            last_simplemask = 'l';
        }
    }
    else if(letter >= L'A' && letter <= L'Z') {
        policy.upper++;
        advancedmask_string += L"?u";
        if (last_simplemask != 'u') {
            sizeSimpleMask++;
            simplemask_string += L"upper";
            last_simplemask = 'u';
        }
    }
    else {
        policy.special++;
        advancedmask_string += L"?s";

        if (last_simplemask != 's') {
            sizeSimpleMask++;
            simplemask_string += L"special";
            last_simplemask = 's';
        }
    }
}


void analyse_charset(wstring & charset, const Policy & policy) {
    if (policy.digit && !policy.lower && !policy.upper && !policy.special) {
        charset = L"numeric";
    }
    else if (!policy.digit && policy.lower && !policy.upper && !policy.special) {
        charset = L"loweralpha";
    }
    else if (!policy.digit && !policy.lower && policy.upper && !policy.special) {
        charset = L"upperalpha";
    }
    else if (!policy.digit && !policy.lower && !policy.upper && policy.special) {
        charset = L"special";
    }
    else if (!policy.digit && policy.lower && policy.upper && !policy.special) {
        charset = L"mixedalpha";
    }
    else if (policy.digit && policy.lower && !policy.upper && !policy.special) {
        charset = L"loweralphanum";
    }
    else if (policy.digit && !policy.lower && policy.upper && !policy.special) {
        charset = L"upperalphanum";
    }
    else if (!policy.digit && policy.lower && !policy.upper && policy.special) {
        charset = L"loweralphaspecial";
    }
    else if (!policy.digit && !policy.lower && policy.upper && policy.special) {
        charset = L"upperalphaspecial";
    }
    else if (policy.digit && !policy.lower && !policy.upper && policy.special) {
        charset = L"specialnum";
    }

    else if (!policy.digit && policy.lower && policy.upper && policy.special) {
        charset = L"mixedalphaspecial";
    }
    else if (policy.digit && !policy.lower && policy.upper && policy.special) {
        charset = L"upperalphaspecialnum";
    }
    else if (policy.digit && policy.lower && !policy.upper && policy.special) {
        charset = L"loweralphaspecialnum";
    }
    else if (policy.digit && policy.lower && policy.upper && !policy.special) {
        charset = L"mixedalphanum";
    }

    else {
        charset = L"all";
    }
}


void analyze_password(const wstring & password, Container & c, SecurityRules & sr, const int & limitAdvancedmask, const int & limitSimplemask) {
    c.pass_length = password.size();

    char last_simplemask = 'a';
    int sizeAdvancedMask = 0;
    int sizeSimpleMask = 0;
    wchar_t letter;

    for (int i=0; i < c.pass_length; i++) {
        letter = password[i];
        analyse_letter(letter, last_simplemask, c.simplemask_string, c.advancedmask_string, c.pol, sizeAdvancedMask, sizeSimpleMask);
    }

    analyse_charset(c.characterset, c.pol);

    if ( (c.pass_length >= sr.minLength) &&
         (c.pol.digit >= sr.minDigit) &&
         (c.pol.lower >= sr.minLower) &&
         (c.pol.upper >= sr.minUpper) &&
         (c.pol.special >= sr.minSpecial) ) {
        sr.nbSecurePassword++;
    }

    if (sizeAdvancedMask > limitAdvancedmask) {
        c.advancedmask_string = L"othermasks";
    }

    if (sizeSimpleMask > limitSimplemask) {
        c.simplemask_string = L"othermasks";
    }
}



void updateMinMax(minMax & minMaxValue, const Policy & pol) {
    if (minMaxValue.mindigit == -1 || minMaxValue.mindigit > pol.digit) {
        minMaxValue.mindigit = pol.digit;
    }
    if (minMaxValue.maxdigit == -1 || minMaxValue.maxdigit < pol.digit) {
        minMaxValue.maxdigit = pol.digit;
    }

    if (minMaxValue.minlower == -1 || minMaxValue.minlower > pol.lower) {
        minMaxValue.minlower = pol.lower;
    }
    if (minMaxValue.maxlower == -1 || minMaxValue.maxlower < pol.lower) {
        minMaxValue.maxlower = pol.lower;
    }

    if (minMaxValue.minupper == -1 || minMaxValue.minupper > pol.upper) {
        minMaxValue.minupper = pol.upper;
    }
    if (minMaxValue.maxupper == -1 || minMaxValue.maxupper < pol.upper) {
        minMaxValue.maxupper = pol.upper;
    }

    if (minMaxValue.minspecial == -1 || minMaxValue.minspecial > pol.special) {
        minMaxValue.minspecial = pol.special;
    }
    if (minMaxValue.maxspecial == -1 || minMaxValue.maxspecial < pol.special) {
        minMaxValue.maxspecial = pol.special;
    }
}


void * generate_stats_thread(void * threadarg) {
    struct thread_data *my_data;
    my_data = (struct thread_data *) threadarg;

    QFile file(my_data->filename);
    file.open(QIODevice::ReadOnly | QIODevice::Text);
    QTextStream flux(&file);

    QString qline;
    wstring line;
    int nbline = 0;

    while(! flux.atEnd()) {
        ++nbline;
        qline = flux.readLine();

        if (nbline < my_data->lineBegin) {
            continue;
        }
        if (nbline > my_data->lineEnd) {
            break;
        }


        line = qline.toStdWString();
        if (line.size() == 0) {
            continue;
        }

        Container c;

        if (my_data->withcount) {
            uint i = 0;
            bool number=false;
            for(i=0; i < line.length(); i++) {
                if(iswdigit(line.at(i))) {
                    number=true;
                }
                else if (!iswdigit(line.at(i)) && number) {
                    break;
                }
            }
            wstring password = line.substr(i+1,line.length());
            int nbPasswords = stoi(line.substr(0,i));
            
            my_data->total_counter += nbPasswords;

            if ( !my_data->use_regex || (my_data->use_regex && regex_match(password,my_data->current_regex)) ) {
                my_data->total_filter += nbPasswords;
                analyze_password(password, c, my_data->sr, my_data->limitAdvancedmask, my_data->limitSimplemask);

                my_data->length[ c.pass_length ] += nbPasswords;
                my_data->charactersets[ c.characterset ] += nbPasswords;
                my_data->simplemasks[ c.simplemask_string ] += nbPasswords;
                my_data->advancedmasks[ c.advancedmask_string ] += nbPasswords;
            }
        }
        else {
            my_data->total_counter++;
            if ( !my_data->use_regex || (my_data->use_regex && regex_match(line,my_data->current_regex)) ) {
                analyze_password(line, c, my_data->sr, my_data->limitAdvancedmask, my_data->limitSimplemask);
                
                my_data->total_filter++;

                my_data->length[ c.pass_length ] += 1;
                my_data->charactersets[ c.characterset ] += 1;
                my_data->simplemasks[ c.simplemask_string ] += 1;
                my_data->advancedmasks[ c.advancedmask_string ] += 1;
            }
        }
        updateMinMax(my_data->minMaxValue, c.pol);
    }

    pthread_exit(NULL);
}

GUI/statsgen.h

deleted100644 → 0
+0 −294

File deleted.

Preview size limit exceeded, changes collapsed.

GUI/utils.h

deleted100644 → 0
+0 −139
Changes for GUI/utils.h: 0 added lines, 139 removed lines.
Original line number Diff line number Diff line
/**
 * @file utils.h
 * @brief useful functions
 *
 * @author Jean-Baptiste Jorand
 * @author Yannick Bass
 * Copyright (c) 2018 Jorand Jean-baptiste Bass Yannick
 * All rights reserved.
 *
 * Please see the attached LICENSE file for additional licensing information.
 */

#ifndef UTILS_STATSGEN_H
#define UTILS_STATSGEN_H


#include <map>
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QtCharts/QPieSeries>
using namespace std;



template<typename K, typename V>
using UnorderedMapIterator = typename unordered_map<K, V>::const_iterator;


template<typename K, typename V>
using MapIterator = typename map<K, V>::const_iterator;



/**
 * @brief Order an unoredered map whatever the key's type
 * @param src: unoredered map than needed to be ordered
 * @return ordered map
 */
template<typename A> 
multimap<double, A> flip_map(const std::unordered_map<A, double> & src) {
    multimap<double, A> dst;

    for(UnorderedMapIterator<A, double> it = src.begin(); it != src.end(); ++it)
        dst.insert(std::pair<double, A>(it->second, it->first));

    return dst;
}



/**
 * @brief Print a line of statistics
 * @param writeFile: output file
 * @param res: value of this statistic
 * @param crac: the statistic to display
 * @param count: the number of statistics already displayed
 * @param total_counter:total number of password analysed
 * @param hiderare: flag to hide statistics under 1%
 */
template<typename Type>
void readResult(wostream & writeFile, double res, Type carac, int & count, const double & total_counter, const int & hiderare) {
    float percentage;
    percentage = (float) (100*res) / total_counter;

    if (percentage >= hiderare) {
        wstring value = to_wstring(percentage);
        value = value.substr(0,5);

        writeFile << setw(40) << right << carac << ":  "
            << setw(5) << right << value << "%" 
            << setw(5) << right << "(" << res << ")" << endl;

        count++;
    }
}




/**
 * @brief Print an unordered map
 * @param writeFile: output file
 * @param stats: map to show
 * @param top: number of results to show
 * @param total_counter: number of finded passwords
 * @param hiderare: low statistics to hide
 * @param count: number of shown results
 */
template<typename Type>
void showMap(wofstream & writeFile, const unordered_map<Type, double> & stats, const int & top, const double & total_counter, const int & hiderare, int & count) {
	count = 0;
    multimap<double, Type> reverse = flip_map<Type>(stats);
    
    MapIterator<double, Type> it;
	for(it = reverse.end(); it != reverse.begin(); it--) {
        if (it == reverse.end()) continue;

        readResult<Type>(writeFile, it->first, it->second, count, total_counter, hiderare);
        if (top != -1 && count == top) break;
    }

    if (count != top) {
        readResult<Type>(writeFile, it->first, it->second, count, total_counter, hiderare);
    }
}




/**
 * @brief Calculate the number of line in a file
 * @param filename: name of the file
 * @return number of line
 */
int nbline_file(const QString & filename) {
    QFile file(filename);
    file.open(QIODevice::ReadOnly | QIODevice::Text);
    QTextStream flux(&file);
    int nb = 0;

    QString ligne;
    while(! flux.atEnd()) {
        ligne = flux.readLine();
        ++nb;
    }

    return nb;
}


#endif



Statsgen/GUI.pro

0 → 100644
+22 −0
Changes for Statsgen/GUI.pro: 22 added lines, 0 removed lines.
Original line number Diff line number Diff line
QT += core gui
QT += widgets
QT += charts

TARGET  = cstatsgen-gui
TEMPLATE = app

INCLUDEPATH += include


SOURCES += src/gui/main.cpp\
        src/gui/mainwindow.cpp\
        src/core/statsgen.cpp

HEADERS  += include/mainwindow.h\
        include/statsgen.h\
        include/utils.h

FORMS    += forms/mainwindow.ui


QMAKE_CXXFLAGS += -std=c++11 -lpthread
 No newline at end of file
Loading