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