pidgin2adium 2.0.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +9 -0
- data/History.txt +9 -0
- data/Manifest.txt +9 -1
- data/README.rdoc +8 -9
- data/Rakefile.rb +13 -2
- data/bin/pidgin2adium +1 -1
- data/ext/balance_tags_c/balance_tags_c.c +198 -0
- data/ext/balance_tags_c/extconf.rb +4 -0
- data/lib/pidgin2adium.rb +4 -2
- data/lib/pidgin2adium/log_file.rb +2 -2
- data/lib/pidgin2adium/log_parser.rb +17 -25
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/tasks/extconf.rake +13 -0
- data/tasks/extconf/balance_tags_c.rake +43 -0
- data/test/test_balance_tags_c_extn.rb +10 -0
- metadata +38 -10
- data/lib/pidgin2adium/balance_tags.rb +0 -118
data/.autotest
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 3.0.0 / 2010-01-31
|
2
|
+
* balance_tags.rb is now a C extension (Pidgin2Adium.balance_tags_c)
|
3
|
+
- the pure-ruby mixin balance_tags (without the trailing "_c") is gone
|
4
|
+
* Better handling of command-line arguments
|
5
|
+
* Format time zones offsets correctly (e.g. "+0500", not "+-0500")
|
6
|
+
* Write Yahoo! and Jabber logs to correct directories (#27710)
|
7
|
+
* Better matching of regexes against time strings
|
8
|
+
* Better documentation
|
9
|
+
|
1
10
|
=== 2.0.2 / 2009-12-18
|
2
11
|
* Much better documentation (more of it, and higher quality too!)
|
3
12
|
* Allow user-provided output dir at commandline
|
data/Manifest.txt
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
+
.autotest
|
1
2
|
History.txt
|
2
3
|
Manifest.txt
|
3
4
|
README.rdoc
|
4
5
|
Rakefile.rb
|
5
6
|
bin/pidgin2adium
|
7
|
+
ext/balance_tags_c/balance_tags_c.c
|
8
|
+
ext/balance_tags_c/extconf.rb
|
6
9
|
lib/pidgin2adium.rb
|
7
|
-
lib/pidgin2adium/balance_tags.rb
|
8
10
|
lib/pidgin2adium/log_converter.rb
|
9
11
|
lib/pidgin2adium/log_file.rb
|
10
12
|
lib/pidgin2adium/log_parser.rb
|
13
|
+
script/console
|
14
|
+
script/destroy
|
15
|
+
script/generate
|
16
|
+
tasks/extconf.rake
|
17
|
+
tasks/extconf/balance_tags_c.rake
|
18
|
+
test/test_balance_tags_c_extn.rb
|
data/README.rdoc
CHANGED
@@ -37,10 +37,7 @@ Or:
|
|
37
37
|
$ pidgin2adium -i pidgin-logs -a gabe,gabeb-w,gbw
|
38
38
|
|
39
39
|
===Example (using library)
|
40
|
-
The library style allows you to parse a log file and get back a
|
41
|
-
LogFile[link:classes/Pidgin2Adium/LogFile.html] instance for easy reading, manipulation, etc.
|
42
|
-
You can also create log files yourself using Pidgin2Adium.parse_and_generate[link:classes/Pidgin2Adium.html#M000006].
|
43
|
-
For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.html].
|
40
|
+
The library style allows you to parse a log file and get back a LogFile[link:classes/Pidgin2Adium/LogFile.html] instance for easy reading, manipulation, etc. If you don't need to do anything with the individual messages, use Pidgin2Adium.parse[link:classes/Pidgin2Adium.html#M000002].
|
44
41
|
|
45
42
|
require 'pidgin2adium'
|
46
43
|
logfile = Pidgin2Adium.parse("/path/to/log/file.html", "gabe,gbw,gabeb-w")
|
@@ -81,15 +78,17 @@ For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.ht
|
|
81
78
|
puts "Successfully wrote out log file!"
|
82
79
|
puts "Path to output file: #{success}"
|
83
80
|
end
|
84
|
-
# This deletes search indexes
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
81
|
+
# This deletes search indexes so Adium re-indexes the new chat logs.
|
82
|
+
# It is not automatically called after log_file.write_out()
|
83
|
+
# Call it after converting all the logs, since it takes up a bit of
|
84
|
+
# processing power.
|
88
85
|
Pidgin2Adium.delete_search_indexes()
|
89
86
|
end
|
90
87
|
|
91
88
|
===Example 2 (using library)
|
92
|
-
If you want to
|
89
|
+
If you want to parse the file and write it out instead of just parsing it, use Pidgin2Adium.parse_and_generate.
|
90
|
+
|
91
|
+
Note: For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.html].
|
93
92
|
|
94
93
|
require 'pidgin2adium'
|
95
94
|
# Both options are optional; without :output_dir, writes to Adium log dir
|
data/Rakefile.rb
CHANGED
@@ -18,12 +18,23 @@ $hoe = Hoe.spec 'pidgin2adium' do
|
|
18
18
|
#self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
19
19
|
self.rubyforge_name = self.name # this is default value
|
20
20
|
# self.extra_deps = [['activesupport','>= 2.0.2']]
|
21
|
+
|
22
|
+
self.spec_extras[:extensions] = "ext/balance_tags_c/extconf.rb"
|
23
|
+
end
|
24
|
+
|
25
|
+
$hoe.spec.rdoc_options = %w{--main README.rdoc}
|
26
|
+
|
27
|
+
# Use hanna RDoc template, if available
|
28
|
+
begin
|
29
|
+
gem "hanna"
|
30
|
+
$hoe.spec.rdoc_options << '-T hanna'
|
31
|
+
rescue GEM::LoadError
|
32
|
+
# hanna not installed, continue
|
21
33
|
end
|
22
|
-
# Use hanna RDoc template
|
23
|
-
$hoe.spec.rdoc_options = %w{--main README.rdoc -T hanna}
|
24
34
|
|
25
35
|
require 'newgem/tasks'
|
26
36
|
Dir['tasks/**/*.rake'].each { |t| load t }
|
37
|
+
task :postrelease => [:publish_docs, :announce]
|
27
38
|
|
28
39
|
# TODO - want other tests/tasks run by default? Add them to the list
|
29
40
|
# remove_task :default
|
data/bin/pidgin2adium
CHANGED
@@ -32,7 +32,7 @@ oparser = OptionParser.new do |opts|
|
|
32
32
|
"is you. Whitespace and case do not matter.") do |aliases|
|
33
33
|
options[:aliases] = aliases
|
34
34
|
end
|
35
|
-
opts.on('-o', '--out
|
35
|
+
opts.on('-o', '--out OUT_DIR',
|
36
36
|
'The top-level directory under which to',
|
37
37
|
'store the logs (each in its own folder',
|
38
38
|
'by screen name).',
|
@@ -0,0 +1,198 @@
|
|
1
|
+
/*
|
2
|
+
* Balances tags of string using a modified stack. Returns a balanced string.
|
3
|
+
*
|
4
|
+
* From Wordpress's formatting.php and rewritten in C by
|
5
|
+
* Gabe Berke-Williams, 2010.
|
6
|
+
*
|
7
|
+
* Original Author:: Leonard Lin <leonard@acm.org>
|
8
|
+
* License:: GPL v2.0
|
9
|
+
* Copyright:: November 4, 2001
|
10
|
+
*/
|
11
|
+
|
12
|
+
#include <ruby.h>
|
13
|
+
|
14
|
+
#ifndef RARRAY_PTR
|
15
|
+
#define RARRAY_PTR(arr) RARRAY(arr)->ptr
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#ifndef RSTRING_LEN
|
19
|
+
#define RSTRING_LEN(str) RSTRING(str)->len
|
20
|
+
#endif
|
21
|
+
|
22
|
+
VALUE balance_tags_c(VALUE, VALUE);
|
23
|
+
static VALUE mP2A;
|
24
|
+
|
25
|
+
/*
|
26
|
+
* call-seq: Pidgin2Adium.balance_tags_c(text) => text with balanced HTML tags
|
27
|
+
*
|
28
|
+
* Balances tags of _text_. Returns modified text.
|
29
|
+
*/
|
30
|
+
VALUE balance_tags_c(VALUE mod, VALUE text){
|
31
|
+
if( TYPE(text) != T_STRING ){
|
32
|
+
rb_raise(rb_eArgError, "bad argument to balance_tags_c, String only please.");
|
33
|
+
}
|
34
|
+
VALUE tagstack = rb_ary_new2(1);
|
35
|
+
int stacksize = 0;
|
36
|
+
VALUE tagqueue = rb_str_new2("");
|
37
|
+
VALUE ZERO = INT2FIX(0),
|
38
|
+
ONE = INT2FIX(1);
|
39
|
+
VALUE newtext = rb_str_new2("");
|
40
|
+
// Known single-entity/self-closing tags
|
41
|
+
VALUE single_tags = rb_ary_new3(5,
|
42
|
+
rb_str_new2("br"),
|
43
|
+
rb_str_new2("hr"),
|
44
|
+
rb_str_new2("img"),
|
45
|
+
rb_str_new2("input"),
|
46
|
+
rb_str_new2("meta"));
|
47
|
+
// Tags that can be immediately nested within themselves
|
48
|
+
VALUE nestable_tags = rb_ary_new3(4,
|
49
|
+
rb_str_new2("blockquote"),
|
50
|
+
rb_str_new2("div"),
|
51
|
+
rb_str_new2("span"),
|
52
|
+
rb_str_new2("font"));
|
53
|
+
// 1: tagname, with possible leading "/"
|
54
|
+
// 2: attributes
|
55
|
+
VALUE tag_regex = rb_reg_regcomp(rb_str_new2("<(\\/?\\w*)\\s*([^>]*)>"));
|
56
|
+
VALUE pos; // position in text
|
57
|
+
VALUE match;
|
58
|
+
VALUE tag;
|
59
|
+
VALUE attributes;
|
60
|
+
VALUE t; // loop variable when iterating over tagstack at end of while loop
|
61
|
+
int matchlen;
|
62
|
+
int done = 0;
|
63
|
+
int j, k, i; // loop counters
|
64
|
+
|
65
|
+
// WP bug fix for comments - in case you REALLY meant to type '< !--'
|
66
|
+
rb_funcall(text, rb_intern("gsub!"), 2,
|
67
|
+
rb_str_new2("< !--"),
|
68
|
+
rb_str_new2("< !--"));
|
69
|
+
|
70
|
+
// WP bug fix for LOVE <3 (and other situations with '<' before a number)
|
71
|
+
rb_funcall(text, rb_intern("gsub!"), 2,
|
72
|
+
rb_reg_regcomp(rb_str_new2("<([0-9]{1})")),
|
73
|
+
rb_str_new2("<\\1"));
|
74
|
+
|
75
|
+
pos = rb_funcall(text, rb_intern("=~"), 1, tag_regex);
|
76
|
+
done = (pos == Qnil);
|
77
|
+
while ( ! done ){
|
78
|
+
rb_str_concat(newtext, tagqueue);
|
79
|
+
match = rb_funcall(text, rb_intern("match"), 1, tag_regex);
|
80
|
+
tag = rb_funcall(rb_reg_nth_match(1, match), rb_intern("downcase"), 0);
|
81
|
+
attributes = rb_reg_nth_match(2, match);
|
82
|
+
|
83
|
+
matchlen = NUM2INT(rb_funcall(rb_reg_nth_match(0, match), rb_intern("size"), 0));
|
84
|
+
|
85
|
+
// clear the shifter
|
86
|
+
tagqueue = rb_str_new2("");
|
87
|
+
// Pop or Push
|
88
|
+
if (0 == rb_str_cmp(rb_str_substr(tag, 0, 1), rb_str_new2("/"))){ // End Tag
|
89
|
+
rb_funcall(tag, rb_intern("slice!"), 2, ZERO, ONE);
|
90
|
+
// if too many closing tags
|
91
|
+
if(stacksize <= 0){
|
92
|
+
tag = rb_str_new2("");
|
93
|
+
//or close to be safe: tag = '/' << tag
|
94
|
+
} else if (0 == rb_str_cmp(RARRAY_PTR(tagstack)[stacksize - 1], tag)){
|
95
|
+
// found closing tag
|
96
|
+
// if stacktop value == tag close value then pop
|
97
|
+
// Close Tag
|
98
|
+
tag = rb_str_append(rb_str_new2("</"), tag);
|
99
|
+
rb_str_concat(tag, rb_str_new2(">"));
|
100
|
+
// Pop
|
101
|
+
rb_ary_pop(tagstack);
|
102
|
+
stacksize--;
|
103
|
+
} else { // closing tag not at top, search for it
|
104
|
+
for(j=stacksize-1; j>=0; j--){
|
105
|
+
if(0 == rb_str_cmp(RARRAY_PTR(tagstack)[j], tag) ){
|
106
|
+
// add tag to tagqueue
|
107
|
+
for(k = stacksize-1;k>=j;k--){
|
108
|
+
rb_str_concat(tagqueue, rb_str_new2("</"));
|
109
|
+
rb_str_concat(tagqueue, rb_ary_pop(tagstack));
|
110
|
+
rb_str_concat(tagqueue, rb_str_new2(">"));
|
111
|
+
stacksize--;
|
112
|
+
}
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
tag = rb_str_new2("");
|
117
|
+
}
|
118
|
+
} else {
|
119
|
+
// Begin Tag
|
120
|
+
|
121
|
+
// Tag Cleaning
|
122
|
+
|
123
|
+
if( ( RSTRING_LEN(attributes) > 0 && // test length before rb_str_substr
|
124
|
+
(0 == rb_str_cmp(rb_str_substr(attributes, -1, 1), rb_str_new2("/"))) ) ||
|
125
|
+
(0 == rb_str_cmp(tag, rb_str_new2(""))) ){
|
126
|
+
// If: self-closing or '', don't do anything.
|
127
|
+
} else if ( rb_ary_includes(single_tags, tag) ) {
|
128
|
+
// ElseIf: it's a known single-entity tag but it doesn't close itself, do so
|
129
|
+
rb_str_concat(attributes, rb_str_new2("/"));
|
130
|
+
} else {
|
131
|
+
// Push the tag onto the stack
|
132
|
+
// If the top of the stack is the same as the tag we want
|
133
|
+
// to push, close previous tag
|
134
|
+
if ( (stacksize > 0) &&
|
135
|
+
(Qfalse == rb_ary_includes(nestable_tags, tag)) &&
|
136
|
+
(0 == rb_str_cmp(rb_ary_entry(tagstack, stacksize - 1), tag))){
|
137
|
+
tagqueue = rb_str_new2("</");
|
138
|
+
rb_str_concat(tagqueue, rb_ary_pop(tagstack));
|
139
|
+
rb_str_concat(tagqueue, rb_str_new2(">"));
|
140
|
+
stacksize--;
|
141
|
+
}
|
142
|
+
rb_ary_push(tagstack, tag);
|
143
|
+
stacksize++;
|
144
|
+
}
|
145
|
+
|
146
|
+
// Attributes
|
147
|
+
if( 0 != rb_str_cmp(attributes, rb_str_new2("")) ){
|
148
|
+
attributes = rb_str_plus(rb_str_new2(" "), attributes);
|
149
|
+
}
|
150
|
+
tag = rb_str_plus(rb_str_new2("<"), tag);
|
151
|
+
rb_str_concat(tag, attributes);
|
152
|
+
rb_str_concat(tag, rb_str_new2(">"));
|
153
|
+
//If already queuing a close tag, then put this tag on, too
|
154
|
+
if( RSTRING_LEN(tagqueue) > 0 ){
|
155
|
+
rb_str_concat(tagqueue, tag);
|
156
|
+
tag = rb_str_new2("");
|
157
|
+
}
|
158
|
+
}
|
159
|
+
rb_str_concat(newtext,
|
160
|
+
rb_str_plus(rb_str_substr(text, 0, pos-1), tag));
|
161
|
+
text = rb_str_substr(text,
|
162
|
+
NUM2INT(pos)+matchlen,
|
163
|
+
RSTRING_LEN(text) - (NUM2INT(pos)+matchlen));
|
164
|
+
pos = rb_funcall(text, rb_intern("=~"), 1, tag_regex);
|
165
|
+
done = (pos == Qnil);
|
166
|
+
}
|
167
|
+
|
168
|
+
// Clear Tag Queue
|
169
|
+
rb_str_concat(newtext, tagqueue);
|
170
|
+
|
171
|
+
// Add Remaining text
|
172
|
+
rb_str_concat(newtext, text);
|
173
|
+
|
174
|
+
i = NUM2INT(rb_funcall(tagstack, rb_intern("length"), 0)) - 1;
|
175
|
+
// Empty Stack
|
176
|
+
for(; i >= 0; i--){
|
177
|
+
// Add remaining tags to close
|
178
|
+
t = RARRAY_PTR(tagstack)[i];
|
179
|
+
rb_str_concat(newtext, rb_str_new2("</"));
|
180
|
+
rb_str_concat(newtext, t);
|
181
|
+
rb_str_concat(newtext, rb_str_new2(">"));
|
182
|
+
}
|
183
|
+
|
184
|
+
// WP fix for the bug with HTML comments
|
185
|
+
rb_funcall(newtext, rb_intern("gsub!"), 2,
|
186
|
+
rb_str_new2("< !--"),
|
187
|
+
rb_str_new2("<!--"));
|
188
|
+
rb_funcall(newtext, rb_intern("gsub!"), 2,
|
189
|
+
rb_str_new2("< !--"),
|
190
|
+
rb_str_new2("< !--"));
|
191
|
+
|
192
|
+
return newtext;
|
193
|
+
}
|
194
|
+
|
195
|
+
void Init_balance_tags_c(){
|
196
|
+
mP2A = rb_define_module("Pidgin2Adium");
|
197
|
+
rb_define_module_function(mP2A, "balance_tags_c", balance_tags_c, 1);
|
198
|
+
}
|
data/lib/pidgin2adium.rb
CHANGED
@@ -14,7 +14,7 @@ module Pidgin2Adium
|
|
14
14
|
ADIUM_LOG_DIR = File.expand_path('~/Library/Application Support/Adium 2.0/Users/Default/Logs/') << '/'
|
15
15
|
# These files/directories show up in Dir.entries()
|
16
16
|
BAD_DIRS = %w{. .. .DS_Store Thumbs.db .system}
|
17
|
-
VERSION = "
|
17
|
+
VERSION = "3.0.0"
|
18
18
|
# For displaying after we finish converting
|
19
19
|
@@oops_messages = []
|
20
20
|
@@error_messages = []
|
@@ -38,6 +38,7 @@ module Pidgin2Adium
|
|
38
38
|
module_function :log_msg, :oops, :error
|
39
39
|
#######################
|
40
40
|
|
41
|
+
# Parses the provided log.
|
41
42
|
# Returns a LogFile instance or false if an error occurred.
|
42
43
|
def parse(logfile_path, my_aliases)
|
43
44
|
logfile_path = File.expand_path(logfile_path)
|
@@ -54,7 +55,8 @@ module Pidgin2Adium
|
|
54
55
|
|
55
56
|
return parser.parse()
|
56
57
|
end
|
57
|
-
|
58
|
+
|
59
|
+
# Parses the provided log and writes out the log in Adium format.
|
58
60
|
# Returns the path to the converted log, false if an error occurred, or
|
59
61
|
# Pidgin2Adium::FILE_EXISTS if file already exists AND opts[:overwrite] =
|
60
62
|
# false.
|
@@ -26,12 +26,12 @@ module Pidgin2Adium
|
|
26
26
|
# key is for Pidgin, value is for Adium
|
27
27
|
# Just used for <service>.<screenname> in directory structure
|
28
28
|
service_name_map = {'aim' => 'AIM',
|
29
|
-
'jabber' =>'
|
29
|
+
'jabber' =>'Jabber',
|
30
30
|
'gtalk'=> 'GTalk',
|
31
31
|
'icq' => 'ICQ',
|
32
32
|
'qq' => 'QQ',
|
33
33
|
'msn' => 'MSN',
|
34
|
-
'yahoo' => 'Yahoo'}
|
34
|
+
'yahoo' => 'Yahoo!'}
|
35
35
|
|
36
36
|
@service = service_name_map[service.downcase]
|
37
37
|
end
|
@@ -7,7 +7,7 @@
|
|
7
7
|
require 'parsedate'
|
8
8
|
require 'time' # for Time.zone_offset
|
9
9
|
|
10
|
-
require '
|
10
|
+
require 'balance_tags_c'
|
11
11
|
require 'pidgin2adium/log_file'
|
12
12
|
|
13
13
|
module Pidgin2Adium
|
@@ -42,12 +42,12 @@ module Pidgin2Adium
|
|
42
42
|
# Time regexes must be set before pre_parse().
|
43
43
|
# "4/18/2007 11:02:00 AM" => %w{4, 18, 2007, 11, 02, 00, AM}
|
44
44
|
# ONLY used (if at all) in first line of chat ("Conversation with...at...")
|
45
|
-
@time_regex_first_line = %r{(\d{1,2})/(\d{1,2})/(\d{4}) (\d{1,2}):(\d{2}):(\d{2}) ([AP]M)}
|
45
|
+
@time_regex_first_line = %r{^(\d{1,2})/(\d{1,2})/(\d{4}) (\d{1,2}):(\d{2}):(\d{2}) ([AP]M)$}
|
46
46
|
# "2007-04-17 12:33:13" => %w{2007, 04, 17, 12, 33, 13}
|
47
|
-
@time_regex =
|
47
|
+
@time_regex = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/
|
48
48
|
# sometimes a line in a chat doesn't have a full timestamp
|
49
49
|
# "04:22:05 AM" => %w{04 22 05 AM}
|
50
|
-
@minimal_time_regex =
|
50
|
+
@minimal_time_regex = /^(\d{1,2}):(\d{2}):(\d{2})( [AP]M)?$/
|
51
51
|
|
52
52
|
# Whether or not the first line is parseable.
|
53
53
|
@first_line_is_valid = true
|
@@ -90,10 +90,10 @@ module Pidgin2Adium
|
|
90
90
|
/(.+) is offering to send file/,
|
91
91
|
/^Transfer of file .+ complete$/,
|
92
92
|
/Error reading|writing|accessing .+: .+/,
|
93
|
-
/You
|
93
|
+
/You cancell?ed the transfer of/,
|
94
94
|
/File transfer cancelled/,
|
95
|
-
/(
|
96
|
-
/(
|
95
|
+
/(.+?) cancell?ed the transfer of/,
|
96
|
+
/(.+?) cancelled the file transfer/,
|
97
97
|
# Direct IM - actual (dis)connect events are their own types
|
98
98
|
/^Attempting to connect to (.+) at .+ for Direct IM\./,
|
99
99
|
/^Asking (.+) to connect to us at .+ for Direct IM\./,
|
@@ -106,9 +106,6 @@ module Pidgin2Adium
|
|
106
106
|
/^Conflicting Key Received!$/,
|
107
107
|
/^Error in decryption- asking for resend\.\.\.$/,
|
108
108
|
/^Making new key pair\.\.\.$/,
|
109
|
-
# file transfer
|
110
|
-
/You canceled the transfer of/,
|
111
|
-
/(.+?) canceled the transfer of/,
|
112
109
|
# sending errors
|
113
110
|
/^Last outgoing message not received properly- resetting$/,
|
114
111
|
/Resending\.\.\./,
|
@@ -178,9 +175,8 @@ module Pidgin2Adium
|
|
178
175
|
if tz_match and tz_match[1]
|
179
176
|
tz_offset = tz_match[1]
|
180
177
|
else
|
181
|
-
zone = Time.local(Time.new.year).zone
|
182
178
|
# "-0500" (3d rather than 2d to allow for "+")
|
183
|
-
tz_offset = sprintf('
|
179
|
+
tz_offset = sprintf('%+03d00', Time.zone_offset(Time.now.zone) / 3600)
|
184
180
|
end
|
185
181
|
return tz_offset
|
186
182
|
end
|
@@ -255,7 +251,7 @@ module Pidgin2Adium
|
|
255
251
|
user_SN = first_line_match[3].downcase.tr(' ', '')
|
256
252
|
partner_SN = first_line_match[1]
|
257
253
|
pidgin_chat_time_start = first_line_match[2]
|
258
|
-
basic_time_info = case
|
254
|
+
basic_time_info = case pidgin_chat_time_start
|
259
255
|
when @time_regex: [$1.to_i, $2.to_i, $3.to_i]
|
260
256
|
when @time_regex_first_line: [$3.to_i, $1.to_i, $2.to_i]
|
261
257
|
end
|
@@ -488,18 +484,15 @@ module Pidgin2Adium
|
|
488
484
|
|
489
485
|
styleparts = style.split(/; ?/)
|
490
486
|
styleparts.map! do |p|
|
491
|
-
if p
|
492
|
-
|
493
|
-
# <span style="color: #000000>today;">today was busy</span>
|
494
|
-
# Then p = "color: #000000>today"
|
495
|
-
# Or it can end in ">;", with no text before the semicolon.
|
496
|
-
# So remove the ">" and anything following it.
|
497
|
-
|
498
|
-
# Use regex instead of string, to account for funky ">" stuff
|
499
|
-
if p =~ /color: #000000/
|
487
|
+
if p[0,5] == 'color'
|
488
|
+
if p.include?('color: #000000')
|
500
489
|
next
|
501
490
|
elsif p =~ /(color: #[0-9a-fA-F]{6})(>.*)?/
|
502
|
-
#
|
491
|
+
# Regarding the bit with the ">", sometimes this happens:
|
492
|
+
# <span style="color: #000000>today;">today was busy</span>
|
493
|
+
# Then p = "color: #000000>today"
|
494
|
+
# Or it can end in ">;", with no text before the semicolon.
|
495
|
+
# So keep the color but remove the ">" and anything following it.
|
503
496
|
next($1)
|
504
497
|
end
|
505
498
|
else
|
@@ -546,7 +539,6 @@ module Pidgin2Adium
|
|
546
539
|
# Basic message with body text (as opposed to pure status messages, which
|
547
540
|
# have no body).
|
548
541
|
class XMLMessage < Message
|
549
|
-
include Pidgin2Adium
|
550
542
|
def initialize(sender, time, buddy_alias, body)
|
551
543
|
super(sender, time, buddy_alias)
|
552
544
|
@body = body
|
@@ -571,7 +563,7 @@ module Pidgin2Adium
|
|
571
563
|
normalize_body_entities!()
|
572
564
|
# Fix mismatched tags. Yes, it's faster to do it per-message
|
573
565
|
# than all at once.
|
574
|
-
@body =
|
566
|
+
@body = Pidgin2Adium.balance_tags_c(@body)
|
575
567
|
if @buddy_alias[0,3] == '***'
|
576
568
|
# "***<alias>" is what pidgin sets as the alias for a /me action
|
577
569
|
@buddy_alias.slice!(0,3)
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/p2a.rb'}"
|
9
|
+
puts "Loading p2a gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/tasks/extconf.rake
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :extconf do
|
2
|
+
desc "Compiles the Ruby extension"
|
3
|
+
task :compile
|
4
|
+
end
|
5
|
+
|
6
|
+
task :compile => "extconf:compile"
|
7
|
+
|
8
|
+
task :test => :compile
|
9
|
+
|
10
|
+
BIN = "*.{bundle,jar,so,obj,pdb,lib,def,exp}"
|
11
|
+
$hoe.clean_globs |= ["ext/**/#{BIN}", "lib/**/#{BIN}", 'ext/**/Makefile']
|
12
|
+
$hoe.spec.require_paths = Dir['{lib,ext/*}']
|
13
|
+
$hoe.spec.extensions = FileList["ext/**/extconf.rb"].to_a
|
@@ -0,0 +1,43 @@
|
|
1
|
+
namespace :extconf do
|
2
|
+
extension = File.basename(__FILE__, '.rake')
|
3
|
+
|
4
|
+
ext = "ext/#{extension}"
|
5
|
+
ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
|
6
|
+
ext_files = FileList[
|
7
|
+
"#{ext}/*.c",
|
8
|
+
"#{ext}/*.h",
|
9
|
+
"#{ext}/*.rl",
|
10
|
+
"#{ext}/extconf.rb",
|
11
|
+
"#{ext}/Makefile",
|
12
|
+
# "lib"
|
13
|
+
]
|
14
|
+
|
15
|
+
|
16
|
+
task :compile => extension do
|
17
|
+
if Dir.glob("**/#{extension}.{o,so,dll}").length == 0
|
18
|
+
STDERR.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
19
|
+
STDERR.puts "Gem actually failed to build. Your system is"
|
20
|
+
STDERR.puts "NOT configured properly to build #{GEM_NAME}."
|
21
|
+
STDERR.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
22
|
+
exit(1)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Builds just the #{extension} extension"
|
27
|
+
task extension.to_sym => ["#{ext}/Makefile", ext_so ]
|
28
|
+
|
29
|
+
file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
|
30
|
+
Dir.chdir(ext) do ruby "extconf.rb" end
|
31
|
+
end
|
32
|
+
|
33
|
+
file ext_so => ext_files do
|
34
|
+
Dir.chdir(ext) do
|
35
|
+
sh(PLATFORM =~ /win32/ ? 'nmake' : 'make') do |ok, res|
|
36
|
+
if !ok
|
37
|
+
require "fileutils"
|
38
|
+
FileUtils.rm Dir.glob('*.{so,o,dll,bundle}')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pidgin2adium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabe B-W
|
@@ -9,9 +9,29 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-31 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rubyforge
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.3
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: gemcutter
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.0
|
34
|
+
version:
|
15
35
|
- !ruby/object:Gem::Dependency
|
16
36
|
name: hoe
|
17
37
|
type: :development
|
@@ -20,7 +40,7 @@ dependencies:
|
|
20
40
|
requirements:
|
21
41
|
- - ">="
|
22
42
|
- !ruby/object:Gem::Version
|
23
|
-
version: 2.
|
43
|
+
version: 2.5.0
|
24
44
|
version:
|
25
45
|
description: |-
|
26
46
|
Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the
|
@@ -30,23 +50,31 @@ email:
|
|
30
50
|
- pidgin2adium@brandeis.edu
|
31
51
|
executables:
|
32
52
|
- pidgin2adium
|
33
|
-
extensions:
|
34
|
-
|
53
|
+
extensions:
|
54
|
+
- ext/balance_tags_c/extconf.rb
|
35
55
|
extra_rdoc_files:
|
36
56
|
- History.txt
|
37
57
|
- Manifest.txt
|
38
58
|
- README.rdoc
|
39
59
|
files:
|
60
|
+
- .autotest
|
40
61
|
- History.txt
|
41
62
|
- Manifest.txt
|
42
63
|
- README.rdoc
|
43
64
|
- Rakefile.rb
|
44
65
|
- bin/pidgin2adium
|
66
|
+
- ext/balance_tags_c/balance_tags_c.c
|
67
|
+
- ext/balance_tags_c/extconf.rb
|
45
68
|
- lib/pidgin2adium.rb
|
46
|
-
- lib/pidgin2adium/balance_tags.rb
|
47
69
|
- lib/pidgin2adium/log_converter.rb
|
48
70
|
- lib/pidgin2adium/log_file.rb
|
49
71
|
- lib/pidgin2adium/log_parser.rb
|
72
|
+
- script/console
|
73
|
+
- script/destroy
|
74
|
+
- script/generate
|
75
|
+
- tasks/extconf.rake
|
76
|
+
- tasks/extconf/balance_tags_c.rake
|
77
|
+
- test/test_balance_tags_c_extn.rb
|
50
78
|
has_rdoc: true
|
51
79
|
homepage: http://rubyforge.org/projects/pidgin2adium/
|
52
80
|
licenses: []
|
@@ -55,10 +83,10 @@ post_install_message:
|
|
55
83
|
rdoc_options:
|
56
84
|
- --main
|
57
85
|
- README.rdoc
|
58
|
-
- -T
|
59
|
-
- hanna
|
86
|
+
- -T hanna
|
60
87
|
require_paths:
|
61
88
|
- lib
|
89
|
+
- ext/balance_tags_c
|
62
90
|
required_ruby_version: !ruby/object:Gem::Requirement
|
63
91
|
requirements:
|
64
92
|
- - ">="
|
@@ -78,5 +106,5 @@ rubygems_version: 1.3.5
|
|
78
106
|
signing_key:
|
79
107
|
specification_version: 3
|
80
108
|
summary: Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the Adium format
|
81
|
-
test_files:
|
82
|
-
|
109
|
+
test_files:
|
110
|
+
- test/test_balance_tags_c_extn.rb
|
@@ -1,118 +0,0 @@
|
|
1
|
-
module Pidgin2Adium
|
2
|
-
# Balances tags of string using a modified stack. Returns a balanced
|
3
|
-
# string, but also affects the text passed into it!
|
4
|
-
# Use text = balance_tags(text).
|
5
|
-
|
6
|
-
# From Wordpress's formatting.php; rewritten in Ruby by Gabe
|
7
|
-
# Berke-Williams, 2009.
|
8
|
-
# Author:: Leonard Lin <leonard@acm.org>
|
9
|
-
# License:: GPL v2.0
|
10
|
-
# Copyright:: November 4, 2001
|
11
|
-
def balance_tags( text )
|
12
|
-
tagstack = []
|
13
|
-
stacksize = 0
|
14
|
-
tagqueue = ''
|
15
|
-
newtext = ''
|
16
|
-
single_tags = %w{br hr img input meta} # Known single-entity/self-closing tags
|
17
|
-
#nestable_tags = %w{blockquote div span} # Tags that can be immediately nested within themselves
|
18
|
-
nestable_tags = %w{blockquote div span font} # Tags that can be immediately nested within themselves
|
19
|
-
# 1: tagname, with possible leading "/"
|
20
|
-
# 2: attributes
|
21
|
-
tag_regex = /<(\/?\w*)\s*([^>]*)>/
|
22
|
-
|
23
|
-
# WP bug fix for comments - in case you REALLY meant to type '< !--'
|
24
|
-
text.gsub!('< !--', '< !--')
|
25
|
-
|
26
|
-
# WP bug fix for LOVE <3 (and other situations with '<' before a number)
|
27
|
-
text.gsub!(/<([0-9]{1})/, '<\1')
|
28
|
-
|
29
|
-
while ( pos = (text =~ tag_regex) )
|
30
|
-
newtext << tagqueue
|
31
|
-
tag = $1.downcase
|
32
|
-
attributes = $2
|
33
|
-
matchlen = $~[0].size
|
34
|
-
|
35
|
-
# clear the shifter
|
36
|
-
tagqueue = ''
|
37
|
-
# Pop or Push
|
38
|
-
if (tag[0,1] == "/") # End Tag
|
39
|
-
tag.slice!(0,1)
|
40
|
-
# if too many closing tags
|
41
|
-
if(stacksize <= 0)
|
42
|
-
tag = ''
|
43
|
-
#or close to be safe: tag = '/' << tag
|
44
|
-
elsif (tagstack[stacksize - 1] == tag) # found closing tag
|
45
|
-
# if stacktop value == tag close value then pop
|
46
|
-
tag = '</' << tag << '>' # Close Tag
|
47
|
-
# Pop
|
48
|
-
tagstack.pop
|
49
|
-
stacksize -= 1
|
50
|
-
else # closing tag not at top, search for it
|
51
|
-
(stacksize-1).downto(0) do |j|
|
52
|
-
if (tagstack[j] == tag)
|
53
|
-
# add tag to tagqueue
|
54
|
-
ss = stacksize - 1
|
55
|
-
ss.downto(j) do |k|
|
56
|
-
tagqueue << '</' << tagstack.pop << '>'
|
57
|
-
stacksize -= 1
|
58
|
-
end
|
59
|
-
break
|
60
|
-
end
|
61
|
-
end
|
62
|
-
tag = ''
|
63
|
-
end
|
64
|
-
else
|
65
|
-
# Begin Tag
|
66
|
-
|
67
|
-
# Tag Cleaning
|
68
|
-
if( (attributes[-1,1] == '/') || (tag == '') )
|
69
|
-
# If: self-closing or '', don't do anything.
|
70
|
-
elsif ( single_tags.include?(tag) )
|
71
|
-
# ElseIf: it's a known single-entity tag but it doesn't close itself, do so
|
72
|
-
attributes << '/'
|
73
|
-
else
|
74
|
-
# Push the tag onto the stack
|
75
|
-
# If the top of the stack is the same as the tag we want to push, close previous tag
|
76
|
-
if ((stacksize > 0) &&
|
77
|
-
! nestable_tags.include?(tag) &&
|
78
|
-
(tagstack[stacksize - 1] == tag))
|
79
|
-
tagqueue = '</' << tagstack.pop << '>'
|
80
|
-
stacksize -= 1
|
81
|
-
end
|
82
|
-
tagstack.push(tag)
|
83
|
-
stacksize += 1
|
84
|
-
end
|
85
|
-
|
86
|
-
# Attributes
|
87
|
-
if(attributes != '')
|
88
|
-
attributes = ' ' << attributes
|
89
|
-
end
|
90
|
-
tag = '<' << tag << attributes << '>'
|
91
|
-
#If already queuing a close tag, then put this tag on, too
|
92
|
-
if (tagqueue)
|
93
|
-
tagqueue << tag
|
94
|
-
tag = ''
|
95
|
-
end
|
96
|
-
end
|
97
|
-
newtext << text[0,pos] << tag
|
98
|
-
text = text[pos+matchlen, text.length - (pos+matchlen)]
|
99
|
-
end
|
100
|
-
|
101
|
-
# Clear Tag Queue
|
102
|
-
newtext << tagqueue
|
103
|
-
|
104
|
-
# Add Remaining text
|
105
|
-
newtext << text
|
106
|
-
|
107
|
-
# Empty Stack
|
108
|
-
tagstack.reverse_each do |t|
|
109
|
-
newtext << '</' << t << '>' # Add remaining tags to close
|
110
|
-
end
|
111
|
-
|
112
|
-
# WP fix for the bug with HTML comments
|
113
|
-
newtext.gsub!("< !--", "<!--")
|
114
|
-
newtext.gsub!("< !--", "< !--")
|
115
|
-
|
116
|
-
return newtext
|
117
|
-
end
|
118
|
-
end
|