2016-10-19 12 views
-1

У меня есть ситуация, когда я хочу иметь возможность minify (не скомпилировать) скрипт Ruby. Цели состоят в следующем:Как я могу минимизировать исходный файл Ruby?

  1. Уменьшить общее количество символов в скрипте;
  2. Выполните определенную степень обфускации, чтобы другие могли изменить код.

Мы можем предположить, что:

  1. Да, я знаю, что я делаю, и я действительно хочу преуменьшать и запутывание кода.
  2. Исходный код Ruby имеет простой синтаксис и не использует какие-либо передовые методы метапрограммирования или тому подобное.

Есть ли какая-либо существующая библиотека или инструмент? Если нет, то каков был бы лучший способ начать разработку простого минификатора (в идеале, также написанного на Ruby)?

ответ

0

Я создал simple script that reads a Ruby file, generates a minified and obfuscated version, and then interprets the output to regenerate it again. Я создал файл Ruby, и используется расширение команды, чтобы запустить сценарий оболочки, который может быть выполнен с ruby main.rb:

main.rb

class MinifyAndObfuscateRuby 
    def initialize(shell_script="./main.sh") 
    @shell_script = shell_script 
    run_shell_script 
    end 

    private 

    def run_shell_script 
    %x[sh #{@shell_script}] 
    end 
end 

Я написал сценарий оболочки, который принимает входной Рубиновый исходный файл и генерирует выходной файл на основе ввода. При желании вы можете просто запустить его напрямую с помощью sh main.sh (вместо использования обертки main.rb, которую я добавил для тестирования с помощью RSpec). Обратите внимание, что большая часть кода main.sh, разделяемого в репозитории, показана ниже, но для краткости я пропустил подробности функции recover_source, которая пытается повторно сгенерировать исходный исходный файл Ruby во втором выходном файле.

main.sh

#!/bin/bash 

# Purpose: Simple script that reads a Ruby file, generates a minified and 
# obfuscated version, and then interprets the output to regenerate it again. 
# Execute either by running `main.rb` Ruby file (uses command expansion to run this Shell script) 
# with `ruby main.rb` or with directly with `sh main.sh`. Outputs are automatically 
# generated in an ./outputs subdirectory. 

# declare and instantiate variables 
MINLEN=0 # optionally exclude iteration of blank lines when MINLENGTH is 1 
input_file="./source.rb" 
reverse="" 
output_file="./outputs/output_minified_and_obfuscated.min.rb" 
output_file_recovered="./outputs/output_unminified_and_unobfuscated.rb" 

# obfuscate: by reversing each line 
function obfuscate { 
    for ((i=$len-1; i>=0; i--)); do 
     reverse="$reverse${line:$i:1}" 
    done 
    reverse+="\n" 
} 

# minify: find instances of the tuple keys in the variable containing the 
# reversed input file string and replace with respective tuple values 
function minify { 
    find_data='eriuqer;*r* fed;*d* dne;*e* edulcni;*i* ssalc;*c* redaer_rtta;*ar*'; 
    for tuple in $find_data; do 
     key=$(echo $tuple | cut -d ';' -f 1); 
     value=$(echo $tuple | cut -d ';' -f 2); 
     reverse=${reverse/$key/$value} 
    done 
} 

function process_source { 
    # read lines from input file 
    while IFS= read -r line || [ -n "$line" ]; do 
     len=${#line} 
     if [ "$len" -ge "$MINLEN" ]; then 
      obfuscate 
      minify 
     fi 
    done < "$input_file" 

    echo "$output_file not found. Creating $output_file and adding minified and obfuscated contents" 
    ! [[ -d "outputs" ]] && mkdir outputs 
    touch $output_file 
    echo $reverse >> $output_file 
} 

# check if output Ruby file already exists and if so regenerate source, otherwise create it 
if [ -f "$output_file" ] && ! [ -f "$output_file_recovered" ]; then 
    echo "$output_file already exists." 
    recover_source # see source code for details of this method 
    exit 0 
elif [ -f "$input_file" ] && ! [ -f "$output_file_recovered" ]; then 
    process_source 
    exit 0 
else 
    echo "$output_file and $output_file_recovered have both already been generated." 
    echo "Deleted temporary files and restarting process..." 
    [ -f "$output_file" ] && rm -f "$output_file" 
    [ -f "$output_file_recovered" ] && rm -f "$output_file_recovered" 
    [ -d "outputs" ] && rmdir outputs 
    exit 0 
fi 

Файл пример исходного кода я использовал показано ниже:

source.rb
require 'bigdecimal' 

class Obfiscate 
    include Comparable 

    attr_reader :name 

    def initialize(name) 
    @name = name 
    end 
end 

Это относится степень запутывания путем изменения каждой строки в исходный файл и использует регулярные выражения, замените синтаксис Ruby моими собственными аббревиатурами (т.е. замените require на *r*, class с *c*, attr_accessor с *ar*, def с *d* и end с *e*), чтобы уменьшить общее количество символов и, возможно, удалить пустые строки, как показано на примере вывода ниже:

./outputs/output_minified_and_obfuscated.min.rb
'lamicedgib' *r* 
etacsifbO *c* 
elbarapmoC 
eman: *ar* 
)eman(ezilaitini *d* 
eman = [email protected] 
*e* 
*e* 
+1

Привет, Лука, спасибо за очень подробный ответ и уровень усилий, в которые вы пошли! К сожалению, я за что-то, что все еще исполняемый код Ruby, когда его минимизируют - извините, если это не было ясно в вопросе. Подобно тому, как работает minification для файлов Javascript или CSS. –