URI: 
       dun dun dun - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
   DIR commit e74d9b6a4be8bdbcb582358098f62a3743e772ce
   DIR parent d05b856011c786fc8dee983a873228607ff7a9a0
  HTML Author: HD Moore <hd_moore@rapid7.com>
       Date:   Wed,  3 Aug 2011 22:42:01 +0000
       
       dun dun dun
       
       
       Diffstat:
         M Makefile                            |      13 +++----------
         M etc/warvox.conf                     |       2 +-
         M lib/warvox.rb                       |       2 +-
         D src/iaxrecord/Makefile              |       4 ----
         D src/iaxrecord/iaxrecord.c           |     310 -------------------------------
         M web/Gemfile                         |       3 +--
         M web/Gemfile.lock                    |       2 ++
         M web/app/controllers/analyze_contro… |      70 +++++++++++++++----------------
         M web/config/database.yml             |      30 +++++++++---------------------
         M web/config/environments/production… |       3 ++-
       
       10 files changed, 53 insertions(+), 386 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -3,16 +3,12 @@ all: test
        test: install
                bin/verify_install.rb
                
       -install: bundler iaxrecord dtmf2num ruby-kissfft db
       -        cp -a src/iaxrecord/iaxrecord bin/
       +install: bundler dtmf2num ruby-kissfft db
                cp -a src/dtmf2num/dtmf2num bin/
        
        ruby-kissfft-install: ruby-kissfft
                cp -a src/ruby-kissfft/kissfft.so lib/
        
       -iaxrecord:
       -        make -C src/iaxrecord/
       -
        dtmf2num:
                make -C src/dtmf2num/
                
       @@ -20,10 +16,8 @@ ruby-kissfft:
                ( cd src/ruby-kissfft/; ruby extconf.rb )
                make -C src/ruby-kissfft/
        
       -db: web/db/production.sqlite3
       +db:
                @echo "Checking the database.."
       -
       -web/db/production.sqlite3: ruby-kissfft-install
                (cd web; RAILS_ENV=production rake db:migrate )
        
        bundler:
       @@ -39,6 +33,5 @@ bundler:
        clean:
                ( cd src/ruby-kissfft/; ruby extconf.rb )
                make -C src/ruby-kissfft/ clean
       -        make -C src/iaxrecord/ clean
                make -C src/dtmf2num/ clean
       -        rm -f bin/iaxrecord lib/kissfft.so
       +        rm -f lib/kissfft.so
   DIR diff --git a/etc/warvox.conf b/etc/warvox.conf
       @@ -24,7 +24,7 @@ tools:
          gnuplot: gnuplot
          sox: sox
          lame: lame
       -  iaxrecord: %BASE%/bin/iaxrecord
       +  iaxrecord: %BASE%/bin/iaxrecord.rb
          dtmf2num: %BASE%/bin/dtmf2num
        
        #
   DIR diff --git a/lib/warvox.rb b/lib/warvox.rb
       @@ -11,7 +11,7 @@ require 'warvox/db'
        
        # Global configuration
        module WarVOX
       -        VERSION = '1.2.0'
       +        VERSION = '1.9.9-dev'
                Base = File.expand_path(File.join(File.dirname(__FILE__), '..'))
                Conf = File.expand_path(File.join(Base, 'etc', 'warvox.conf'))
                JobManager = WarVOX::JobQueue.new
   DIR diff --git a/src/iaxrecord/Makefile b/src/iaxrecord/Makefile
       @@ -1,4 +0,0 @@
       -all:
       -        gcc -Wall -o iaxrecord iaxrecord.c -liaxclient
       -clean:
       -        rm -f iaxrecord *.o
   DIR diff --git a/src/iaxrecord/iaxrecord.c b/src/iaxrecord/iaxrecord.c
       @@ -1,310 +0,0 @@
       -/*
       - * IAXRecord: a utility for recording audio on an outbound IAX call
       - *
       - * Copyright (C) 2009-2010 Rapid7 LLC - H D Moore <hdm[at]metasploit.com>
       - *
       - * Based on simpleclient from the IAXClient distribution
       - *
       - * Copyright (C) 1999, Linux Support Services, Inc.
       - *
       - * Mark Spencer <markster@linux-support.net>
       - *
       - * This program is free software, distributed under the terms of
       - * the GNU General Public License
       - */
       -
       -#define TEST_MODE 1
       -
       -#include <stdio.h>
       -#include <stdlib.h>
       -#include <unistd.h>
       -#include <sys/stat.h>
       -#include <fcntl.h>
       -#include <time.h>
       -#include <signal.h>
       -
       -#include <iaxclient.h>
       -
       -int initialized = 0;
       -int debug       = 0;
       -int audio       = 0;
       -int busy        = 0;
       -int fail        = 1;
       -int done        = 0;
       -
       -float silence_threshold = 0.0f;
       -int call_state  = 0;
       -int call_trace  = -1;
       -int call_done   = 0;
       -int call_bytes  = 0;
       -char *iax_out;
       -int reg_id;
       -
       -#ifdef TEST_MODE
       -int call_end = 0;
       -unsigned char empty_buf[200];
       -#endif
       -
       -void signal_handler(int signum) {
       -        if ( signum == SIGTERM || signum == SIGINT ) {
       -                done = 1;
       -        }
       -}
       -
       -void usage(char **argv) {
       -        fprintf(stdout, "Usage: %s -s [server] -u [user] -p <pass> -o [output] -n [number] -c <callerid> -l <seconds> [-D]\n", argv[0]);
       -        exit(1);
       -}
       - 
       -int state_event_callback(struct iaxc_ev_call_state call) {
       -        if(call.state & IAXC_CALL_STATE_BUSY) busy = 1;
       -        if(call.state & IAXC_CALL_STATE_COMPLETE) fail = 0;
       -
       -        call_state = call.state;
       -
       -        if(debug) {
       -                fprintf(stdout, "STATE: ");
       -                if(call.state & IAXC_CALL_STATE_FREE)
       -                        fprintf(stdout, "F");
       -                
       -                if(call.state & IAXC_CALL_STATE_ACTIVE)
       -                        fprintf(stdout, "A");
       -                
       -                if(call.state & IAXC_CALL_STATE_OUTGOING)
       -                        fprintf(stdout, "O");
       -                
       -                if(call.state & IAXC_CALL_STATE_RINGING)
       -                        fprintf(stdout, "R");        
       -        
       -                if(call.state & IAXC_CALL_STATE_COMPLETE)
       -                        fprintf(stdout, "C");        
       -        
       -                if(call.state & IAXC_CALL_STATE_SELECTED)
       -                        fprintf(stdout, "S");
       -                
       -                if(call.state & IAXC_CALL_STATE_BUSY)
       -                        fprintf(stdout, "B");                
       -        
       -                if(call.state & IAXC_CALL_STATE_TRANSFER)
       -                        fprintf(stdout, "T");                
       -                                
       -                fprintf(stdout, "\n");
       -                fflush(stdout);
       -        }
       -
       -    return 0;
       -}
       -
       -int audio_event_callback( struct iaxc_ev_audio audio) {
       -
       -        if(call_trace == -1 && !fail) {
       -                call_trace = open(iax_out, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
       -        }
       -                
       -        if(call_trace != -1) {
       -                if(debug) printf("audio data: format=%d encoded=%d size=%d state=%d\n", audio.format, audio.encoded, audio.size, call_state);
       -                write(call_trace, audio.data, audio.size);
       -                call_bytes += audio.size;
       -        }
       -        return 0;
       -}
       -
       -int iaxc_callback(iaxc_event e) {
       -    switch(e.type) {
       -                case IAXC_EVENT_TEXT:
       -                        // fprintf(stdout, "TEXT: %s\n", e.ev.text.message);
       -                        return ( debug ? 0 : 1 );
       -                        break;
       -        case IAXC_EVENT_STATE:
       -            return state_event_callback(e.ev.call);
       -                        break;
       -                case IAXC_EVENT_AUDIO:
       -                        return audio_event_callback(e.ev.audio);
       -                        break;
       -        default:
       -            return 0;
       -                        break;
       -    }
       -}
       -
       -                
       -int main(int argc, char **argv) {
       -
       -        char *iax_host = NULL;
       -        char *iax_user = NULL;
       -        char *iax_pass = "";
       -        char *iax_num = NULL;
       -        char *iax_cid = "15555555555";
       -        char *iax_name = "";
       -        int iax_sec = 20;
       -        int call_id = 0;
       -        char dest[1024];
       -        time_t stime, etime;
       -        
       -        int c;
       -        extern char *optarg;
       -        extern int optind, optopt;
       -
       -        while ((c = getopt(argc, argv, ":hs:u:p:c:o:n:l:N:DA")) != -1) {
       -                switch(c) {
       -                        case 'h':
       -                                usage(argv);
       -                                break;
       -                        case 's':
       -                                iax_host = optarg;
       -                                break;
       -                        case 'u':
       -                                iax_user = optarg;
       -                                break;
       -                        case 'p':
       -                                iax_pass = optarg;
       -                                break;
       -                        case 'c':
       -                                iax_cid = optarg;
       -                                break;
       -                        case 'o':
       -                                iax_out = optarg;
       -                                break;
       -                        case 'n':
       -                                iax_num = optarg;
       -                                break;
       -                        case 'l':
       -                                iax_sec = atoi(optarg);
       -                                break;
       -                        case 'N':
       -                                iax_name = optarg;
       -                                break;
       -                        case 'D':
       -                                debug = 1;
       -                                break;
       -                        case 'A':
       -                                audio = 1;
       -                                break;                        
       -                }
       -        }
       -        
       -        
       -/* 
       -  Version 2.2.x of iaxclient has a new function called iaxc_set_test_mode(1), which disables 
       -  audio processing for us. This will not be backported to 2.0.x however...
       -*/
       -        
       -        if(! (iax_host && iax_user && iax_num && iax_out)) usage(argv);
       -
       -        snprintf(dest, sizeof(dest), "%s:%s@%s/%s", iax_user, iax_pass, iax_host, iax_num);
       -        iaxc_set_video_prefs(IAXC_VIDEO_PREF_CAPTURE_DISABLE | IAXC_VIDEO_PREF_SEND_DISABLE);
       -        iaxc_set_audio_prefs(IAXC_AUDIO_PREF_SEND_DISABLE);
       -
       -        if(! debug) {
       -                fclose(stderr);
       -                stderr = fopen("/dev/null", "w");
       -        }
       -        
       -        fprintf(stdout, "STARTED %s BYTES=%d FILE=%s\n", iax_num, call_bytes, iax_out);
       -
       -        /* install signal handler to catch CRTL-Cs */
       -        signal(SIGINT, signal_handler);
       -        signal(SIGTERM, signal_handler);
       -
       -        /* enable test mode */
       -#ifdef TEST_MODE
       -        iaxc_set_test_mode(1);
       -#endif
       -        
       -        /* forcible disable pulse audio if the audio flag is not set (-A) */
       -        // if(! audio) setenv("PULSE_SERVER", "255.255.255.255", 1);
       -        
       -        setenv("ALSA_PCM_CARD", "pcm.null", 1);
       -        setenv("ALSA_CARD", "pcm.null", 1);
       -        setenv("ALSA_DEVICE", "pcm.null", 1);
       -                        
       -        if(debug) fprintf(stderr, ">> INITIALIZING\n");
       -        if ( iaxc_initialize(1) ) {
       -                fprintf(stdout, "error: Could not initialize iaxclient!\n");
       -                exit(0);
       -        }
       -        
       -        initialized = 1;
       -        if(debug) fprintf(stderr, ">> INITIALIZED\n");
       -        
       -        iaxc_set_audio_output(audio ? 0 : 1);
       -        iaxc_set_callerid (iax_name, iax_cid);
       -        iaxc_set_formats(IAXC_FORMAT_ULAW | IAXC_FORMAT_ALAW, IAXC_FORMAT_ULAW | IAXC_FORMAT_ALAW);
       -        
       -        // Causes problems for some asterix servers, not sure why yet
       -        // iaxc_set_silence_threshold(silence_threshold);
       -
       -        if(debug) fprintf(stderr, ">> STARTING PROCESSING THREAD\n");
       -        iaxc_set_event_callback(iaxc_callback);        
       -        iaxc_start_processing_thread();
       -        if(debug) fprintf(stderr, ">> STARTED PROCESSING THREAD\n");
       -
       -        iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_RAW);
       -
       -        if(debug) fprintf(stderr, ">> REGISTERING\n")        ;
       -        reg_id  = iaxc_register(iax_user, iax_pass, iax_host);
       -        if(debug) fprintf(stderr, ">> REGISTERED: %d\n", reg_id);
       -
       -        if(debug) fprintf(stderr, ">> CALLING\n");
       -        call_id = iaxc_call(dest);
       -        if(debug) fprintf(stderr, ">> CALLED: %d\n", call_id);
       -        
       -        stime = time(NULL);
       -        etime = 0;
       -        
       -        if(debug) fprintf(stderr, ">> WAITING\n");        
       -        if(call_id >= 0) {
       -                iaxc_select_call(call_id);
       -                while((unsigned int)(time(NULL))-(unsigned int)stime < iax_sec) {
       -                        if(done) break;
       -                        if(call_state & IAXC_CALL_STATE_COMPLETE && ! etime) etime = time(NULL);
       -                        if(call_state & IAXC_CALL_STATE_BUSY) break;
       -                        if(iaxc_first_free_call() == call_id) break;
       -                        iaxc_millisleep(250);
       -                        
       -#ifdef TEST_MODE
       -                        /* we need do send something to receive data... I don't know why... */
       -                        if( !call_end && call_state & IAXC_CALL_STATE_COMPLETE )
       -                                iaxc_push_audio(&empty_buf[0], 200, 200);
       -#endif
       -
       -                }
       -        } else {
       -                fail = 1;
       -        }
       -        
       -        if(debug) fprintf(stderr, ">> DONE\n");
       -        
       -        if(! etime) time(&etime);
       -        
       -        fprintf(stdout, "COMPLETED %s BYTES=%d FILE=%s FAIL=%d BUSY=%d RINGTIME=%d\n", 
       -                iax_num, 
       -                call_bytes,
       -                iax_out,
       -                fail,
       -                busy,
       -                (unsigned int)(etime) - (unsigned int)(stime)
       -        );
       -
       -
       -        iaxc_dump_call();
       -        iaxc_millisleep(500);
       -        iaxc_stop_processing_thread();
       -        iaxc_shutdown();
       -        return(0);
       -}
       -
       -/*
       -
       -Note about ring times vs ring counts: 
       -  http://en.wikipedia.org/wiki/Ringtone#Ringing_signal
       -        The ringing pattern is known as ring cadence. This only applies to POTS fixed phones, where 
       -        the high voltage ring signal is switched on and off to create the ringing pattern. In North
       -        America, the standard ring cadence is "2-4", or two seconds of ringing followed by four 
       -        seconds of silence. In Australia and the UK, the standard ring cadence is 400 ms on, 200 ms
       -        off, 400 ms on, 2000 ms off. These patterns may vary from region to region, and other 
       -        patterns are used in different countries around the world.
       -
       -ring count US = ringtime / 6.0 
       -ring count UK = ringtime / 3.0
       -*/
   DIR diff --git a/web/Gemfile b/web/Gemfile
       @@ -5,8 +5,7 @@ gem 'rails', '3.0.1'
        # Bundle edge Rails instead:
        # gem 'rails', :git => 'git://github.com/rails/rails.git'
        
       -gem 'sqlite3-ruby', :require => 'sqlite3'
       -
       +gem 'pg', '0.11'
        # Use unicorn as the web server
        # gem 'unicorn'
        
   DIR diff --git a/web/Gemfile.lock b/web/Gemfile.lock
       @@ -47,6 +47,7 @@ GEM
              mime-types (~> 1.16)
              treetop (~> 1.4.8)
            mime-types (1.16)
       +    pg (0.11.0)
            polyglot (0.3.1)
            rack (1.2.1)
            rack-mount (0.6.13)
       @@ -77,6 +78,7 @@ PLATFORMS
          ruby
        
        DEPENDENCIES
       +  pg (= 0.11)
          rails (= 3.0.1)
          sqlite3-ruby
          will_paginate!
   DIR diff --git a/web/app/controllers/analyze_controller.rb b/web/app/controllers/analyze_controller.rb
       @@ -1,9 +1,9 @@
        class AnalyzeController < ApplicationController
          layout 'warvox'
       -  
       +
          def index
                @jobs = DialJob.paginate(
       -                :page => params[:page], 
       +                :page => params[:page],
                        :order => 'id DESC',
                        :per_page => 30
                )
       @@ -13,7 +13,7 @@ class AnalyzeController < ApplicationController
                  @job_id   = params[:id]
                  @dial_job = DialJob.find(@job_id)
                @shown    = params[:show]
       -        
       +
                @g1 = Ezgraphix::Graphic.new(:c_type => 'col3d', :div_name => 'calls_pie1')
                @g1.render_options(:caption => 'Detected Lines by Type', :y_name => 'Lines', :w => 700, :h => 300)
        
       @@ -26,38 +26,38 @@ class AnalyzeController < ApplicationController
                                :conditions => ['dial_job_id = ? and line_type = ?', @job_id, k]
                        )
                end
       -        
       +
                @g1.data = res_types
        
                if(@shown and @shown != 'all')
                        @results = DialResult.where(:dial_job_id => @job_id).paginate(
       -                        :page => params[:page], 
       +                        :page => params[:page],
                                :order => 'number ASC',
                                :per_page => 10,
                                :conditions => [ 'completed = ? and processed = ? and busy = ? and line_type = ?', true, true, false, @shown ]
       -                )        
       +                )
                else
                        @results = DialResult.where(:dial_job_id => @job_id).paginate(
       -                        :page => params[:page], 
       +                        :page => params[:page],
                                :order => 'number ASC',
                                :per_page => 10,
                                :conditions => [ 'completed = ? and processed = ? and busy = ?', true, true, false ]
                        )
                end
       -        
       +
                @filters = []
                @filters << { :scope => "all", :label => "All" }
                res_types.keys.each do |t|
                        @filters << { :scope => t.to_s.downcase, :label => t.to_s }
                end
       -                
       +
          end
        
         def show
                  @job_id   = params[:id]
                  @dial_job = DialJob.find(@job_id)
                @shown    = params[:show]
       -        
       +
                @g1 = Ezgraphix::Graphic.new(:c_type => 'col3d', :div_name => 'calls_pie1')
                @g1.render_options(:caption => 'Detected Lines by Type', :y_name => 'Lines', :w => 700, :h => 300)
        
       @@ -70,31 +70,31 @@ class AnalyzeController < ApplicationController
                                :conditions => ['dial_job_id = ? and line_type = ?', @job_id, k]
                        )
                end
       -        
       +
                @g1.data = res_types
        
                if(@shown and @shown != 'all')
                        @results = DialJob.where(:id => @job_id).paginate(
       -                        :page => params[:page], 
       +                        :page => params[:page],
                                :order => 'number ASC',
                                :per_page => 20,
                                :conditions => [ 'completed = ? and processed = ? and busy = ? and line_type = ?', true, true, false, @shown ]
       -                )        
       +                )
                else
                        @results = DialJob.where(:id => @job_id).paginate(
       -                        :page => params[:page], 
       +                        :page => params[:page],
                                :order => 'number ASC',
                                :per_page => 20,
                                :conditions => [ 'completed = ? and processed = ? and busy = ?', true, true, false ]
                        )
                end
       -        
       +
                @filters = []
                @filters << { :scope => "all", :label => "All" }
                res_types.keys.each do |t|
                        @filters << { :scope => t.to_s.downcase, :label => t.to_s }
                end
       -                
       +
          end
        
        
       @@ -102,42 +102,40 @@ class AnalyzeController < ApplicationController
          def resource
                  ctype = 'text/html'
                cpath = nil
       -        
       +        cdata = "File not found"
       +
                res = DialResult.find(params[:result_id])
       -        if(res and res.processed and res.rawfile)
       +
       +        if res
                        case params[:type]
                        when 'big_sig'
                                ctype = 'image/png'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '_big.png'
       +                        cdata = res.png_sig_freq
                        when 'big_sig_dots'
                                ctype = 'image/png'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '_big_dots.png'        
       +                        cdata = res.png_big_dots
                        when 'small_sig'
                                ctype = 'image/png'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '.png'
       +                        cdata = res.png_sig
       +                when 'big_freq'
       +                        ctype = 'image/png'
       +                        cdata = res.png_big_freq
       +                when 'small_freq'
       +                        ctype = 'image/png'
       +                        cdata = res.png_sig_freq
                        when 'mp3'
                                ctype = 'audio/mpeg'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '.mp3'
       +                        cdata = res.mp3
                        when 'sig'
                                ctype = 'text/plain'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '.sig'
       +                        cdata = res.fprint
                        when 'raw'
                                ctype = 'octet/binary-stream'
       -                        cpath = res.rawfile
       -                when 'big_freq'
       -                        ctype = 'image/png'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '_freq_big.png'        
       -                when 'small_freq'
       -                        ctype = 'image/png'
       -                        cpath = res.rawfile.gsub(/\..*/, '') + '_freq.png'                        
       +                        cdata = res.audio
                        end
                end
       -        
       -        cdata = "File not found"
       -        if(cpath and File.readable?(cpath))
       -                cdata = File.read(cpath, File.size(cpath))
       -        end
       -        
       +
            send_data(cdata, :type => ctype, :disposition => 'inline')
          end
        end
       +
   DIR diff --git a/web/config/database.yml b/web/config/database.yml
       @@ -1,22 +1,10 @@
       -# SQLite version 3.x
       -#   gem install sqlite3-ruby (not necessary on OS X Leopard)
       -development:
       -  adapter: sqlite3
       -  database: db/development.sqlite3
       -  pool: 5
       -  timeout: 5000
       -
       -# Warning: The database defined as "test" will be erased and
       -# re-generated from your development database when you run "rake".
       -# Do not set this db to the same as development or production.
       -test:
       -  adapter: sqlite3
       -  database: db/test.sqlite3
       -  pool: 5
       -  timeout: 5000
       -
        production:
       -  adapter: sqlite3
       -  database: db/production.sqlite3
       -  pool: 5
       -  timeout: 5000
       +  adapter: postgresql
       +  database: warvox
       +  username: warvox
       +  password: "<yourpass>"
       +  host: 127.0.0.1
       +  port: 5433
       +  pool: 100
       +  timeout: 5
       +
   DIR diff --git a/web/config/environments/production.rb b/web/config/environments/production.rb
       @@ -6,7 +6,7 @@ Web::Application.configure do
          config.cache_classes = true
        
          # Full error reports are disabled and caching is turned on
       -  config.consider_all_requests_local       = true
       +  config.consider_all_requests_local       = false
          config.action_controller.perform_caching = true
        
          # Specifies the header that your server uses for sending files
       @@ -47,3 +47,4 @@ Web::Application.configure do
          # Send deprecation notices to registered listeners
          config.active_support.deprecation = :notify
        end
       +