import of rt 3.0.9
[freeside.git] / rt / lib / RT.pm
1 # BEGIN LICENSE BLOCK
2
3 # Copyright (c) 1996-2002 Jesse Vincent <jesse@bestpractical.com>
4
5 # (Except where explictly superceded by other copyright notices)
6
7 # This work is made available to you under the terms of Version 2 of
8 # the GNU General Public License. A copy of that license should have
9 # been provided with this software, but in any event can be snarfed
10 # from www.gnu.org
11
12 # This work is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # General Public License for more details.
16
17
18 # Unless otherwise specified, all modifications, corrections or
19 # extensions to this work which alter its source code become the
20 # property of Best Practical Solutions, LLC when submitted for
21 # inclusion in the work.
22
23
24 # END LICENSE BLOCK
25
26
27 package RT;
28 use strict;
29 use RT::I18N;
30 use RT::CurrentUser;
31 use RT::System;
32
33 use vars qw($VERSION $System $SystemUser $Nobody $Handle $Logger
34         $CORE_CONFIG_FILE
35         $SITE_CONFIG_FILE
36         $VENDOR_CONFIG_FILE
37         $BasePath
38         $EtcPath
39         $VarPath
40         $LocalPath
41         $LocalEtcPath
42         $LocalLexiconPath
43         $LogDir
44         $MasonComponentRoot
45         $MasonLocalComponentRoot
46         $MasonDataDir
47         $MasonSessionDir
48 );
49
50 $VERSION = '3.0.9';
51 $CORE_CONFIG_FILE = "/opt/rt3/etc/RT_Config.pm";
52 $SITE_CONFIG_FILE = "/opt/rt3/etc/RT_SiteConfig.pm";
53
54 $BasePath = '/opt/rt3';
55
56 $EtcPath = '/opt/rt3/etc';
57 $VarPath = '/opt/rt3/var';
58 $LocalPath = '/opt/rt3/local';
59 $LocalEtcPath = '/opt/rt3/local/etc';
60 $LocalLexiconPath = '/opt/rt3/local/po';
61
62 # $MasonComponentRoot is where your rt instance keeps its mason html files
63
64 $MasonComponentRoot = '/opt/rt3/share/html';
65
66 # $MasonLocalComponentRoot is where your rt instance keeps its site-local
67 # mason html files.
68
69 $MasonLocalComponentRoot = '/opt/rt3/local/html';
70
71 # $MasonDataDir Where mason keeps its datafiles
72
73 $MasonDataDir = '/opt/rt3/var/mason_data';
74
75 # RT needs to put session data (for preserving state between connections
76 # via the web interface)
77 $MasonSessionDir = '/opt/rt3/var/session_data';
78
79
80
81 =head1 NAME
82
83         RT - Request Tracker
84
85 =head1 SYNOPSIS
86
87         A fully featured request tracker package
88
89 =head1 DESCRIPTION
90
91
92 =cut
93
94 =item LoadConfig
95
96 Load RT's config file. First, go after the core config file. 
97 After that, try to load the vendor config.
98 After that, go after the site config.
99
100 =cut
101
102 sub LoadConfig {
103      local *Set = sub { $_[0] = $_[1] unless defined $_[0] }; 
104     if ( -f "$SITE_CONFIG_FILE" ) {
105         require $SITE_CONFIG_FILE
106           || die ("Couldn't load RT config file  '$SITE_CONFIG_FILE'\n$@");
107     }
108     require $CORE_CONFIG_FILE
109       || die ("Couldn't load RT config file '$CORE_CONFIG_FILE'\n$@");
110     RT::I18N->Init;
111 }
112
113 =item Init
114
115     Conenct to the database, set up logging.
116     
117 =cut
118
119 sub Init {
120
121     #Get a database connection
122     ConnectToDatabase();
123
124     #RT's system user is a genuine database user. its id lives here
125     $SystemUser = new RT::CurrentUser();
126     $SystemUser->LoadByName('RT_System');
127     
128     #RT's "nobody user" is a genuine database user. its ID lives here.
129     $Nobody = new RT::CurrentUser();
130     $Nobody->LoadByName('Nobody');
131   
132     $System = RT::System->new();
133
134    InitLogging(); 
135 }
136
137   
138 =head2 ConnectToDatabase
139
140 Get a database connection
141
142 =cut
143  
144 sub ConnectToDatabase {
145     require RT::Handle;
146     unless ($Handle && $Handle->dbh && $Handle->dbh->ping) {
147         $Handle = RT::Handle->new();
148     } 
149     $Handle->Connect();
150 }
151     
152 =head2 InitLogging
153
154 Create the RT::Logger object. 
155
156 =cut
157 sub InitLogging {
158
159     # We have to set the record seperator ($, man perlvar)
160     # or Log::Dispatch starts getting
161     # really pissy, as some other module we use unsets it.
162
163     $, = '';
164     use Log::Dispatch 1.6;
165
166     unless ($RT::Logger) {
167
168     $RT::Logger=Log::Dispatch->new();
169     
170     if ($RT::LogToFile) {
171
172     unless (-d $RT::LogDir && -w $RT::LogDir) {
173         # localizing here would be hard when we don't have a current user yet
174         # die $self->loc("Log directory [_1] not found or couldn't be written.\n RT can't run.", $RT::LogDir);
175         die ("Log directory $RT::LogDir not found or couldn't be written.\n RT can't run.");
176     }
177
178         my $filename;
179         if ($RT::LogToFileNamed =~ m![/\\]!) {
180             # looks like an absolute path.
181             $filename = $RT::LogToFileNamed;
182         }
183         else {
184             $filename = "$RT::LogDir/$RT::LogToFileNamed";
185         }
186     require Log::Dispatch::File;
187
188
189           $RT::Logger->add(Log::Dispatch::File->new
190                        ( name=>'rtlog',
191                          min_level=> $RT::LogToFile,
192                          filename=> $filename,
193                          mode=>'append',
194                          callbacks => sub { my %p = @_;
195                                 my ($package, $filename, $line) = caller(5);
196                                 return "[".gmtime(time)."] [".$p{level}."]: $p{message} ($filename:$line)\n"}
197              
198              
199              
200                        ));
201     }
202     if ($RT::LogToScreen) {
203         require Log::Dispatch::Screen;
204         $RT::Logger->add(Log::Dispatch::Screen->new
205                      ( name => 'screen',
206                        min_level => $RT::LogToScreen,
207                          callbacks => sub { my %p = @_;
208                                 my ($package, $filename, $line) = caller(5);
209                                 return "[".gmtime(time)."] [".$p{level}."]: $p{message} ($filename:$line)\n"
210                                 },
211              
212                        stderr => 1
213                      ));
214     }
215     if ($RT::LogToSyslog) {
216         require Log::Dispatch::Syslog;
217         $RT::Logger->add(Log::Dispatch::Syslog->new
218                      ( name => 'syslog',
219                        ident => 'RT',
220                        min_level => $RT::LogToSyslog,
221                          callbacks => sub { my %p = @_;
222                                 my ($package, $filename, $line) = caller(5);
223
224                                 # syswrite() cannot take utf8; turn it off here.
225                                 Encode::_utf8_off($p{message});
226
227                                 if ($p{level} eq 'debug') {
228
229                                 return "$p{message}\n" }
230                                 else {
231                                 return "$p{message} ($filename:$line)\n"}
232                                 },
233              
234                        stderr => 1
235                      ));
236     }
237
238     }
239
240 # {{{ Signal handlers
241
242 ## This is the default handling of warnings and die'ings in the code
243 ## (including other used modules - maybe except for errors catched by
244 ## Mason).  It will log all problems through the standard logging
245 ## mechanism (see above).
246
247 $SIG{__WARN__} = sub {$RT::Logger->warning($_[0])};
248
249 #When we call die, trap it and log->crit with the value of the die.
250
251 $SIG{__DIE__}  = sub {
252     unless ($^S || !defined $^S ) {
253         $RT::Handle->Rollback();
254         $RT::Logger->crit("$_[0]");
255         exit(-1);
256     }
257     else {
258         #Get out of here if we're in an eval
259         die $_[0];
260     }
261 };
262
263 # }}}
264
265 }
266
267 # }}}
268
269
270 sub SystemUser {
271     return($SystemUser);
272 }       
273
274 sub Nobody {
275     return ($Nobody);
276 }
277
278
279 =head2 DropSetGIDPermissions
280
281 Drops setgid permissions.
282
283 =cut
284
285 sub DropSetGIDPermissions {
286     # Now that we got the config read in, we have the database 
287     # password and don't need to be setgid
288     # make the effective group the real group
289     $) = $(;
290 }
291
292
293 =head1 SYNOPSIS
294
295 =head1 BUGS
296
297 Please report them to rt-3.0-bugs@fsck.com, if you know what's broken and have at least some idea of what needs to be fixed.
298 If you're not sure what's going on, report them rt-devel@lists.fsck.com.
299
300 =head1 SEE ALSO
301
302 L<RT::StyleGuide>
303 L<DBIx::SearchBuilder>
304
305
306
307 =begin testing
308
309
310 ok ($RT::Nobody->Name() eq 'Nobody', "Nobody is nobody");
311 ok ($RT::Nobody->Name() ne 'root', "Nobody isn't named root");
312 ok ($RT::SystemUser->Name() eq 'RT_System', "The system user is RT_System");
313 ok ($RT::SystemUser->Name() ne 'noname', "The system user isn't noname");
314
315
316 =end testing
317
318 =cut
319
320 eval "require RT_Local";
321 die $@ if ($@ && $@ !~ qr{^Can't locate RT_Local.pm});
322
323 1;