flat2sql.pl 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #!/usr/bin/perl
  2. #
  3. # Converts file based preferences into SQL statements.
  4. #
  5. # WARNING: this script is experimental. Don't use it as
  6. # privileged user or backup your data directory before using it.
  7. #
  8. # Copyright (c) 2002, Michael Blandford and Tal Yardeni
  9. # Copyright (c) 2005-2006 The SquirrelMail Project Team
  10. #
  11. # This script is licensed under GPL.
  12. # $Id$
  13. #
  14. ##### Default values #####
  15. $db = "squirrelmail";
  16. $abook_table = "address";
  17. $pref_table = "userprefs";
  18. $dbtype = 'mysql';
  19. ##### ##### #####
  20. use Getopt::Long;
  21. &GetOptions( \%opts, qw( abook data_dir:s delete h help pref sig user:s db:s pref_table:s abook_table:s) );
  22. &Usage if ( defined $opts{h} or defined $opts{help} );
  23. unless ( defined $opts{abook} or defined $opts{pref} or defined $opts{sig}) {
  24. $opts{abook}=TRUE;
  25. $opts{pref}=TRUE;
  26. $opts{sig}=TRUE;
  27. }
  28. if ( defined $opts{db} and $opts{db} ) {
  29. $db = $opts{db};
  30. }
  31. if ( defined $opts{pref_table} and $opts{pref_table} ) {
  32. $pref_table = $opts{pref_table};
  33. }
  34. if ( defined $opts{abook_table} and $opts{abook_table}) {
  35. $abook_table = $opts{abook_table};
  36. }
  37. # Get data directory option and display help if it is not defined
  38. if ( defined $opts{data_dir} and $opts{data_dir} ) {
  39. $data_dir = $opts{data_dir};
  40. } else {
  41. &Usage;
  42. }
  43. # Are we looking for specific users or all users?
  44. # There has to be a better way to do this - Below
  45. @user_list = split ( /,/, $opts{user} ) if defined $opts{user};
  46. # Here we go
  47. # If no arguments are passed, and we cant open the dir, we should
  48. # get a usage.
  49. opendir(DIR, $data_dir) or
  50. die "DIRECTORY READ ERROR: Could not open $data_dir!!\n";
  51. while ( $filename = readdir DIR ) {
  52. next if ( $filename eq "." or $filename eq ".." );
  53. $filename =~ /(.*)\.(.*)/;
  54. $username = $1;
  55. # Deal with the people
  56. # There has to be a better way to do this - Above
  57. next if ( defined $opts{user} and grep(!/$username/, @user_list));
  58. # Deal with the extension files
  59. $ext = $2;
  60. next unless $ext;
  61. &abook if ( $ext eq "abook" and defined $opts{abook} );
  62. &pref if ( $ext eq "pref" and defined $opts{pref} );
  63. &sig if ( $ext =~ /si([g\d])$/ and defined $opts{sig});
  64. }
  65. closedir ( DIR );
  66. # All done. Below are functions
  67. # Process a user address file
  68. sub abook {
  69. print "DELETE FROM $db.$abook_table WHERE owner = '".escape_sql_string($username,true)."';\n"
  70. if ( defined $opts{delete} );
  71. open(ABOOK, "<$data_dir/$filename") or
  72. die "FILE READ ERROR: Could not open $filename!!\n";
  73. while (my $line = <ABOOK> ) {
  74. chomp $line;
  75. my ( $nickname,$firstname,$lastname,$email,$label ) = split(/\|/, $line);
  76. print "INSERT INTO $db.$abook_table "
  77. . "(owner,nickname,firstname,lastname,email,label) "
  78. . "VALUES ('"
  79. .escape_sql_string($username)."','"
  80. .escape_sql_string($nickname)."','"
  81. .escape_sql_string($firstname)."','"
  82. .escape_sql_string($lastname)."','"
  83. .escape_sql_string($email)."','"
  84. .escape_sql_string($label)."');\n";
  85. }
  86. close(ABOOK);
  87. }
  88. # Process a user preference file
  89. sub pref {
  90. print "DELETE FROM $db.$pref_table "
  91. . "WHERE user = '".escape_sql_string($username,true)."' and prefkey not like '___sig\%___';\n"
  92. if ( defined $opts{delete} );
  93. open(PREFS, "<$data_dir/$filename") or
  94. die "FILE READ ERROR: Could not open $filename!!\n";
  95. while (my $line = <PREFS> ) {
  96. chomp $line;
  97. my ( $prefkey, $prefval ) = split(/=/, $line);
  98. print "INSERT INTO $db.$pref_table "
  99. . "(user,prefkey,prefval) "
  100. . "VALUES ('"
  101. .escape_sql_string($username)."','"
  102. .escape_sql_string($prefkey)."','"
  103. .escape_sql_string($prefval)."');\n";
  104. }
  105. close(PREFS);
  106. }
  107. # Process a user signature file
  108. sub sig {
  109. $del_ext = $1;
  110. $del_ext = "nature" if ( $del_ext eq "g" );
  111. print "DELETE FROM $db.$pref_table "
  112. . "WHERE user = '".escape_sql_string($username,true)."' and prefkey like '___sig" . escape_sql_string($del_ext,true) . "___';\n"
  113. if ( defined $opts{delete} );
  114. open(SIG, "<$data_dir/$filename") or
  115. die "FILE READ ERROR: Could not open $filename!!\n";
  116. my @lines = <SIG>;
  117. close(SIG);
  118. $filename =~ /.*\.si([g,\d]$)/;
  119. $prefkey = "___sig";
  120. if ( $1 eq "g" ) {
  121. $prefkey .= "nature___";
  122. } else {
  123. $prefkey .= "$1___";
  124. }
  125. print "INSERT INTO $db.$pref_table (user,prefkey,prefval) "
  126. . "VALUES ('".escape_sql_string($username)."','"
  127. .escape_sql_string($prefkey)."','"
  128. .escape_sql_string(join("", @lines))."');\n";
  129. }
  130. # Escapes sql strings
  131. # MySQL escaping:
  132. # http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
  133. # full - \x00 (null), \n, \r, \, ', " and \x1a (Control-Z)
  134. # add % and _ in pattern matching expressions.
  135. # short - only character used for quoting and backslash should be escaped
  136. # PostgreSQL
  137. # Oracle
  138. # Sybase - different quoting of '
  139. sub escape_sql_string() {
  140. my ($str,$isPattern) = @_;
  141. if ($dbtype eq 'mysql'){
  142. # escape \, ' and "
  143. $str =~ s/(['"\\])/\\$1/g;
  144. # escape \x1a
  145. $str =~ s/([\x1a])/\\Z/g;
  146. # escape ascii null
  147. $str =~ s/([\x0])/\\0/g;
  148. # escape line feed
  149. $str =~ s/([\n])/\\n/g;
  150. # escape cr
  151. $str =~ s/([\r])/\\r/g;
  152. if ($isPattern) {
  153. $str =~ s/([%_])/\\$1/g;
  154. }
  155. } else {
  156. die "ERROR: Unsupported database type";
  157. }
  158. return $str;
  159. }
  160. # Print out the usage screen
  161. sub Usage {
  162. $0 =~ /.*\/(.*)/;
  163. $prog = $1;
  164. print <<EOL;
  165. This program generates SQL statements to aid importing SquirrelMail
  166. user config into a database.
  167. WARNING: this script is experimental. Don't use it as
  168. privileged user or backup your data directory before using it.
  169. Usage: $prog --data_dir=<data_dir> [--delete] [--abook] [--pref] [--sig]
  170. [--user=<username0[,username1[,username2]...]]
  171. [--db=<database>] [--pref_table=<userprefs>] [--abook_table=<address>]
  172. --data_dir option must define path to SquirrelMail data directory. If
  173. option is not defined, script displays this help message.
  174. --abook option is used to generate SQL with address books.
  175. --pref option is used to generate SQL with user preferences.
  176. --sig option is used to generate SQL with signatures.
  177. --db option can be used to set database name. Script defaults to
  178. 'squirrelmail'.
  179. --pref_table option can be used to set preference table name. Script
  180. defaults to 'userprefs'.
  181. --abook_table option can be used to set address book table name. Script
  182. defaults to 'address'.
  183. Prefs --abook, --pref, and --sig are assumed if none of them as passed
  184. --delete removes all previous values for users ( --users=<> ) already in
  185. the database. This is useful to reimport users.
  186. It respects --abook, --pref, and --sig.
  187. If --user is not specified, script extracts all user data.
  188. EOL
  189. exit 1;
  190. }