import rt 3.0.12
[freeside.git] / rt / lib / RT.pm.in
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         $BasePath
37         $EtcPath
38         $VarPath
39         $LocalPath
40         $LocalEtcPath
41         $LocalLexiconPath
42         $LogDir
43         $MasonComponentRoot
44         $MasonLocalComponentRoot
45         $MasonDataDir
46         $MasonSessionDir
47 );
48
49 $VERSION = '@RT_VERSION_MAJOR@.@RT_VERSION_MINOR@.@RT_VERSION_PATCH@';
50 $CORE_CONFIG_FILE = "@CONFIG_FILE_PATH@/RT_Config.pm";
51 $SITE_CONFIG_FILE = "@CONFIG_FILE_PATH@/RT_SiteConfig.pm";
52
53 $BasePath = '@RT_PATH@';
54
55 $EtcPath = '@RT_ETC_PATH@';
56 $VarPath = '@RT_VAR_PATH@';
57 $LocalPath = '@RT_LOCAL_PATH@';
58 $LocalEtcPath = '@LOCAL_ETC_PATH@';
59 $LocalLexiconPath = '@LOCAL_LEXICON_PATH@';
60
61 # $MasonComponentRoot is where your rt instance keeps its mason html files
62
63 $MasonComponentRoot = '@MASON_HTML_PATH@';
64
65 # $MasonLocalComponentRoot is where your rt instance keeps its site-local
66 # mason html files.
67
68 $MasonLocalComponentRoot = '@MASON_LOCAL_HTML_PATH@';
69
70 # $MasonDataDir Where mason keeps its datafiles
71
72 $MasonDataDir = '@MASON_DATA_PATH@';
73
74 # RT needs to put session data (for preserving state between connections
75 # via the web interface)
76 $MasonSessionDir = '@MASON_SESSION_PATH@';
77
78
79
80 =head1 NAME
81
82         RT - Request Tracker
83
84 =head1 SYNOPSIS
85
86         A fully featured request tracker package
87
88 =head1 DESCRIPTION
89
90
91 =cut
92
93 =item LoadConfig
94
95 Load RT's config file. First, go after the core config file. 
96 After that, go after the site config.
97
98 =cut
99
100 sub LoadConfig {
101      local *Set = sub { $_[0] = $_[1] unless defined $_[0] }; 
102     if ( -f "$SITE_CONFIG_FILE" ) {
103         require $SITE_CONFIG_FILE
104           || die ("Couldn't load RT config file  '$SITE_CONFIG_FILE'\n$@");
105     }
106     require $CORE_CONFIG_FILE
107       || die ("Couldn't load RT config file '$CORE_CONFIG_FILE'\n$@");
108     RT::I18N->Init;
109 }
110
111 =item Init
112
113     Conenct to the database, set up logging.
114     
115 =cut
116
117 sub Init {
118
119     #Get a database connection
120     ConnectToDatabase();
121
122     #RT's system user is a genuine database user. its id lives here
123     $SystemUser = new RT::CurrentUser();
124     $SystemUser->LoadByName('RT_System');
125     
126     #RT's "nobody user" is a genuine database user. its ID lives here.
127     $Nobody = new RT::CurrentUser();
128     $Nobody->LoadByName('Nobody');
129   
130     $System = RT::System->new();
131
132    InitLogging(); 
133 }
134
135   
136 =head2 ConnectToDatabase
137
138 Get a database connection
139
140 =cut
141  
142 sub ConnectToDatabase {
143     require RT::Handle;
144     unless ($Handle && $Handle->dbh && $Handle->dbh->ping) {
145         $Handle = RT::Handle->new();
146     } 
147     $Handle->Connect();
148 }
149     
150 =head2 InitLogging
151
152 Create the RT::Logger object. 
153
154 =cut
155 sub InitLogging {
156
157     # We have to set the record seperator ($, man perlvar)
158     # or Log::Dispatch starts getting
159     # really pissy, as some other module we use unsets it.
160
161     $, = '';
162     use Log::Dispatch 1.6;
163
164     unless ($RT::Logger) {
165
166     $RT::Logger=Log::Dispatch->new();
167     
168     if ($RT::LogToFile) {
169         my ($filename, $logdir);
170         if ($RT::LogToFileNamed =~ m![/\\]!) {
171             # looks like an absolute path.
172             $filename = $RT::LogToFileNamed;
173             ($logdir) = $RT::LogToFileNamed =~ m!^(.*[/\\])!;
174         }
175         else {
176             $filename = "$RT::LogDir/$RT::LogToFileNamed";
177             $logdir = $RT::LogDir;
178         }
179
180     unless ( -d $logdir && ( ( -f $filename && -w $filename ) || -w $logdir ) ) {
181         # localizing here would be hard when we don't have a current user yet
182         # die $self->loc("Log directory [_1] not found or couldn't be written.\n RT can't run.", $RT::LogDir);
183         die ("Log file $filename couldn't be written or created.\n RT can't run.");
184     }
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                @RT::LogToSyslogConf
236                      ));
237     }
238
239     }
240
241 # {{{ Signal handlers
242
243 ## This is the default handling of warnings and die'ings in the code
244 ## (including other used modules - maybe except for errors catched by
245 ## Mason).  It will log all problems through the standard logging
246 ## mechanism (see above).
247
248 $SIG{__WARN__} = sub {$RT::Logger->warning($_[0])};
249
250 #When we call die, trap it and log->crit with the value of the die.
251
252 $SIG{__DIE__}  = sub {
253     unless ($^S || !defined $^S ) {
254         $RT::Handle->Rollback();
255         $RT::Logger->crit("$_[0]");
256         exit(-1);
257     }
258     else {
259         #Get out of here if we're in an eval
260         die $_[0];
261     }
262 };
263
264 # }}}
265
266 }
267
268 # }}}
269
270
271 sub SystemUser {
272     return($SystemUser);
273 }       
274
275 sub Nobody {
276     return ($Nobody);
277 }
278
279
280 =head2 DropSetGIDPermissions
281
282 Drops setgid permissions.
283
284 =cut
285
286 sub DropSetGIDPermissions {
287     # Now that we got the config read in, we have the database 
288     # password and don't need to be setgid
289     # make the effective group the real group
290     $) = $(;
291 }
292
293
294 =head1 SYNOPSIS
295
296 =head1 BUGS
297
298 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.
299 If you're not sure what's going on, report them rt-devel@lists.fsck.com.
300
301 =head1 SEE ALSO
302
303 L<RT::StyleGuide>
304 L<DBIx::SearchBuilder>
305
306
307
308 =begin testing
309
310
311 ok ($RT::Nobody->Name() eq 'Nobody', "Nobody is nobody");
312 ok ($RT::Nobody->Name() ne 'root', "Nobody isn't named root");
313 ok ($RT::SystemUser->Name() eq 'RT_System', "The system user is RT_System");
314 ok ($RT::SystemUser->Name() ne 'noname', "The system user isn't noname");
315
316
317 =end testing
318
319 =cut
320
321 eval "require RT_Local";
322 die $@ if ($@ && $@ !~ qr{^Can't locate RT_Local.pm});
323
324 1;