National Geographic Expeditions

Back to NationalGeographic.com 1-888-966-8687

:

national geographic private safaris

National Geographic has teamed up with Great Plains Conservation to create a collection of extraordinary private safaris. Track elephants in the shadow of Mount Kilimanjaro; observe the interactions of lions and buffalo in Duba Plains, Botswana; or watch lions on the prowl in the Serengeti. Choose one of the private safari itineraries featured below, or we'll work with you to craft your own custom safari — just fill in our custom safari inquiry form.

Bring your spouse, your family, or a few friends and choose what time of year you want to travel. We'll handle all the arrangements. Stay in incomparable properties—luxury safari camps that offer top amenities as well as local charm and character. Gain an insiders' perspective on some of the research and conservation programs that National Geographic and Great Plains are collaborating on in these regions.


recommended itineraries

click to learn about great plains conservation

featured safari camps

click to inquire about a custom safari

Your participation in a National Geographic Expedition provides support to National Geographic's mission of increasing global understanding through exploration, geography education, and research.
Error in Include(/www/htdocs/nge/privatesafaris/index.html):
Headers already sent. at /www/CPAN/lib/site_perl/5.8.8/Mungo/Response.pm line 184.

[    1]    1: package Mungo::Response;
[    2]    2: 
[    3]    3: # Copyright (c) 2007 OmniTI Computer Consulting, Inc. All rights reserved.
[    4]    4: # For information on licensing see:
[    5]    5: #   https://labs.omniti.com/zetaback/trunk/LICENSE
[    6]    6: 
[    7]    7: =head1 NAME
[    8]    8: 
[    9]    9: Mungo::Response - Represent response side of HTTP request cycle
[   10]   10: 
[   11]   11: =head1 SYNOPSIS
[   12]   12: 
[   13]   13:   <!-- You get a Response object for free when you use Mungo -->
[   14]   14:   <% if ($Response) { ... } %>
[   15]   15: 
[   16]   16:   <!-- Read and Mungo-process other files -->
[   17]   17:   <%
[   18]   18:      # Prints to browser
[   19]   19:      $Response->Include('/some/file.html', $arg1);
[   20]   20: 
[   21]   21:      # Caputured
[   22]   22:      my $output = $Response->TrapInclude('/some/file.html');
[   23]   23: 
[   24]   24:      # Can also print to browser via Response
[   25]   25:      print $Response "Hello world!";
[   26]   26:   %>
[   27]   27: 
[   28]   28:   <!-- May also set headers -->
[   29]   29:   <%
[   30]   30:      $Response->AddHeader('header_name' => $value);
[   31]   31:   %>
[   32]   32: 
[   33]   33:   <!-- Halt processing and jump out of the handler -->
[   34]   34:   <%
[   35]   35:      # With a 302
[   36]   36:      $Response->Redirect('/new/url/');
[   37]   37: 
[   38]   38:      # Just end
[   39]   39:      $Response->End();
[   40]   40:   %>
[   41]   41: 
[   42]   42:   <!-- Cookie facility -->
[   43]   43:   <%
[   44]   44:      # Single valued cookies
[   45]   45:      $Response->Cookies($cookie_name, $cookie_value);
[   46]   46: 
[   47]   47:      # Multivalued cookies
[   48]   48:      $Response->Cookies($cookie_name, $key, $value);
[   49]   49: 
[   50]   50:      # Cookie options
[   51]   51:      $Response->Cookies($cookie_name, 'Domain', $value);
[   52]   52:      $Response->Cookies($cookie_name, 'Expires', $value);
[   53]   53:      $Response->Cookies($cookie_name, 'Path', $value);
[   54]   54:      $Response->Cookies($cookie_name, 'Secure', $value);
[   55]   55:   %>
[   56]   56: 
[   57]   57: =head1 DESCRIPTION
[   58]   58: 
[   59]   59: Represents the response side of the Mungo request cycle.
[   60]   60: 
[   61]   61: =cut
[   62]   62: 
[   63]   63: 
[   64]   64: use strict;
[   65]   65: use IO::Handle;
[   66]   66: use Mungo::Arbiter::Response;
[   67]   67: use Mungo::Response::Trap;
[   68]   68: use Mungo::Cookie;
[   69]   69: use Mungo::Utils;
[   70]   70: use HTML::Entities;
[   71]   71: our $AUTOLOAD;
[   72]   72: 
[   73]   73: my $one_true_buffer = '';
[   74]   74: 
[   75]   75: sub new {
[   76]   76:   my $class = shift;
[   77]   77:   my $parent = shift;
[   78]   78:   my $r = $parent->{'Apache::Request'};
[   79]   79:   my $singleton = $r->pnotes(__PACKAGE__);
[   80]   80:   return $singleton if ($singleton);
[   81]   81:   my %core_data = (
[   82]   82:     'Apache::Request' => $r,
[   83]   83:     'ContentType' => $r->dir_config('MungoContentType') || $r->content_type || 'text/html',
[   84]   84:     # We don't set buffer here, we set it after it has been tied.
[   85]   85:     # 'Buffer' => $r->dir_config('MungoBuffer') || 0,
[   86]   86:     'Buffer' => 0,
[   87]   87:     'CacheControl' => $r->dir_config('MungoCacheControl') || 'private',
[   88]   88:     'Charset' => $r->dir_config('MungoCharset') || undef,
[   89]   89:     'Status' => 200,
[   90]   90:     'Mungo' => $parent,
[   91]   91:     'CookieClass' => $r->dir_config('MungoCookieClass') || 'Mungo::Cookie',
[   92]   92:     'Cookies' => undef, # placeholder for visibility
[   93]   93:   );
[   94]   94:   my %data;
[   95]   95:   $singleton = bless \%data, $class;
[   96]   96:   tie %data, 'Mungo::Arbiter::Response', $singleton, \%core_data;
[   97]   97:   $singleton->{Buffer} = $r->dir_config('MungoBuffer') || 0;
[   98]   98:   $r->pnotes(__PACKAGE__, $singleton);
[   99]   99:   return $singleton;
[  100]  100: }
[  101]  101: 
[  102]  102: sub DESTROY {
[  103]  103:   my $self = shift;
[  104]  104:   $self->cleanse();
[  105]  105: }
[  106]  106: 
[  107]  107: sub cleanse {
[  108]  108:   my $self = shift;
[  109]  109:   my $_r = tied %$self;
[  110]  110:   if(ref $_r->{data}->{'IO_stack'} eq 'ARRAY') {
[  111]  111:     while (@{$_r->{data}->{'IO_stack'}}) {
[  112]  112:       my $fh = pop @{$_r->{data}->{'IO_stack'}};
[  113]  113:       close(select($fh));
[  114]  114:     }
[  115]  115:   }
[  116]  116:   delete $_r->{data}->{$_} for keys %$self;
[  117]  117:   untie %$self if tied %$self;
[  118]  118: }
[  119]  119: 
[  120]  120: sub send_http_header {
[  121]  121:   my $self = shift;
[  122]  122:   my $_r = tied %$self;
[  123]  123:   my $r = $_r->{data}->{'Apache::Request'};
[  124]  124:   return if($_r->{data}->{'__HEADERS_SENT__'});
[  125]  125:   $_r->{data}->{'__HEADERS_SENT__'} = 1;
[  126]  126:   if($_r->{data}->{CacheControl} eq 'no-cache') {
[  127]  127:     $r->no_cache(1);
[  128]  128:   }
[  129]  129:   else {
[  130]  130:     if($r->can('headers_out')) {
[  131]  131:       $r->err_headers_out->set('Cache-Control' => $_r->{data}->{CacheControl});
[  132]  132:     }
[  133]  133:     else {
[  134]  134:       $r->err_header_out('Cache-Control' => $_r->{data}->{CacheControl});
[  135]  135:     }
[  136]  136:   }
[  137]  137:   # Must use Internal as the tiehash is magic for cookies
[  138]  138:   $_r->{'__Internal__'}->{Cookies}->inject_headers($r);
[  139]  139:   $r->status($_r->{data}->{Status});
[  140]  140:   $r->can('send_http_header') ?
[  141]  141:     $r->send_http_header($_r->{data}->{ContentType}) :
[  142]  142:     $r->content_type($_r->{data}->{ContentType});;
[  143]  143: }
[  144]  144: 
[  145]  145: sub start {
[  146]  146:   my $self = shift;
[  147]  147:   my $_r = tied %$self;
[  148]  148:   return if(exists $_r->{data}->{'IO_stack'} &&
[  149]  149:             scalar(@{$_r->{data}->{'IO_stack'}}) > 0);
[  150]  150:   $_r->{data}->{'IO_stack'} = [];
[  151]  151:   tie *DIRECT, ref $self, $self;
[  152]  152:   push @{$_r->{data}->{'IO_stack'}}, select(DIRECT);
[  153]  153: }
[  154]  154: 
[  155]  155: sub finish {
[  156]  156:   my $self = shift;
[  157]  157:   my $_r = tied %$self;
[  158]  158:   # Unbuffer outselves, this will actually induce a flush (must go through tiehash)
[  159]  159:   $_r->{'__Internal__'}->{Buffer} = 0;
[  160]  160:   untie *DIRECT if tied *DIRECT;
[  161]  161:   return unless(exists $_r->{data}->{'IO_stack'});
[  162]  162:   my $fh = $_r->{data}->{'IO_stack'}->[0];
[  163]  163:   die __PACKAGE__." IO stack of wrong depth" if(scalar(@{$_r->{data}->{'IO_stack'}}) != 1);
[  164]  164: }
[  165]  165: 
[  166]  166: =head2 $Response->AddHeader('header_name' => 'header_value');
[  167]  167: 
[  168]  168: Adds an HTTP header to the response.
[  169]  169: 
[  170]  170: Dies if headers (or any other output) has already been sent.
[  171]  171: 
[  172]  172: =cut
[  173]  173: 
[  174]  174: sub AddHeader {
[  175]  175:   my $self = shift;
[  176]  176:   my $_r = tied %$self;
[  177]  177:   my $r = $_r->{data}->{'Apache::Request'};
[  178]  178:   die "Headers already sent." if($_r->{data}->{'__HEADERS_SENT__'});
[  179]  179:   $r->can('headers_out') ? $r->err_headers_out->set(@_) : $r->err_header_out(@_);
[  180]  180: }
[  181]  181: sub Cookies {
[  182]  182:   my $self = shift;
[  183]  183:   my $_r = tied %$self;
[* 184]  184:   die "Headers already sent." if($_r->{data}->{'__HEADERS_SENT__'});
[  185]  185:   # Must use Internal as the tiehash is magic for cookies
[  186]  186:   my $cookie = $_r->{'__Internal__'}->{'Cookies'};
[  187]  187:   $cookie->__set(@_);
[  188]  188: }
[  189]  189: 
[  190]  190: =head2 $Response->Redirect($url);
[  191]  191: 
[  192]  192: Issues a 302 redirect with the new location as $url.
[  193]  193: 
[  194]  194: Dies if headers (or any other output) has already been sent.
[  195]  195: 
[  196]  196: =cut
[  197]  197: 
[  198]  198: sub Redirect {
[  199]  199:   my $self = shift;
[  200]  200:   my $url = shift;
[  201]  201:   my $_r = tied %$self;
[  202]  202:   die "Cannot redirect, headers already sent\n" if($_r->{data}->{'__HEADERS_SENT__'});
[  203]  203:   $_r->{data}->{Status} = shift || 302;
[  204]  204:   my $r = $_r->{data}->{'Apache::Request'};
[  205]  205:   $r->can('headers_out') ? $r->err_headers_out->set('Location', $url) :
[  206]  206:                            $r->err_header_out('Location', $url);
[  207]  207:   $self->send_http_header();
[  208]  208:   $self->End();
[  209]  209: }
[  210]  210: 
[  211]  211: 
[  212]  212: =head2 $res->Include($filename, $arg1, $arg2, ...);
[  213]  213: 
[  214]  214: =head2 $res->Include(\$string, $arg1, $arg2, ...);
[  215]  215: 
[  216]  216: Reads the given filename or string and interprets it as Mungo ASP code.
[  217]  217: 
[  218]  218: Any passed arguments are available in the @_ array within the ASP code.
[  219]  219: 
[  220]  220: The results of evaluating the code is printed to STDOUT.
[  221]  221: 
[  222]  222: =cut
[  223]  223: 
[  224]  224: sub Include {
[  225]  225:   my $self = shift;
[  226]  226:   my $subject = shift;
[  227]  227:   my $_r = tied %$self;
[  228]  228:   my $rv;
[  229]  229:   eval {
[  230]  230:     local $SIG{__DIE__} = \&Mungo::MungoDie;
[  231]  231:     if(ref $subject) {
[  232]  232:       $rv = $_r->{data}->{Mungo}->include_mem($subject, @_);
[  233]  233:     }
[  234]  234:     else {
[  235]  235:       $rv = $_r->{data}->{Mungo}->include_file($subject, @_);
[  236]  236:     }
[  237]  237:   };
[  238]  238:   if($@) {
[  239]  239:     # If we have more than 1 item in the IO stack, we should just re-raise.
[  240]  240:     if (scalar(@{$_r->{data}->{'IO_stack'} || []}) > 1) {
[  241]  241:       local $SIG{__DIE__} = undef;
[  242]  242:       die $@;
[  243]  243:     }
[  244]  244:     my $hashref = $@;
[  245]  245:     eval {
[  246]  246:       if($_r->{data}->{OnError}) {
[  247]  247:         $_r->{data}->{OnError}->($self, $hashref, $subject);
[  248]  248:       }
[  249]  249:       else {
[  250]  250:         $self->defaultErrorHandler($hashref, $subject);
[  251]  251:       }
[  252]  252:     };
[  253]  253:     if($@) {
[  254]  254:       # Oh, dear lord this is bad.  We'd died trying to print out death.
[  255]  255:       print STDERR "Mungo::Response -> die in error renderer\n";
[  256]  256:       print STDERR $hashref;
[  257]  257:       print STDERR $@;
[  258]  258:     }
[  259]  259:     return undef;
[  260]  260:   }
[  261]  261:   return $rv;
[  262]  262: }
[  263]  263: 
[  264]  264: sub defaultErrorHandler {
[  265]  265:   use Data::Dumper;
[  266]  266:   my $self = shift;
[  267]  267:   my $href = shift; # Our Error
[  268]  268:   my $subject = shift;
[  269]  269:   my $_r = tied %$self;
[  270]  270:   print "Error in Include($subject):<br />\n";
[  271]  271:   my $pkg = $href->{callstack}->[0]->[0];
[  272]  272:   my $preamble = eval "\$${pkg}::Mungo_preamble;";
[  273]  273:   my $postamble = eval "\$${pkg}::Mungo_postamble;";
[  274]  274:   my $contents = eval "\$${pkg}::Mungo_contents;";
[  275]  275:   print "<pre class=\"error\">$href->{error}</pre><br />\n";
[  276]  276: 
[  277]  277:   unless($contents) {
[  278]  278:     my $filename = $href->{callstack}->[0]->[1];
[  279]  279:     if(open(FILE, "<$filename")) {
[  280]  280:       local $/ = undef;
[  281]  281:       $$contents = <FILE>;
[  282]  282:       close(FILE);
[  283]  283:     }
[  284]  284:   }
[  285]  285: 
[  286]  286:   if($contents) {
[  287]  287:     if($_r->{data}->{'Apache::Request'}->dir_config('Debug')) {
[  288]  288:       print Mungo::Utils::pretty_print_code($preamble, $contents, $postamble, $href->{callstack}->[0]->[2]);
[  289]  289:     }
[  290]  290:   } else {
[  291]  291:     print '<pre>'.Dumper($@).'</pre>';
[  292]  292:   }
[  293]  293: }
[  294]  294: 
[  295]  295: =head2 $output = $Response->TrapInclude($filename, @args);
[  296]  296: 
[  297]  297: Like Include(), but results are returned as a string, instead of being printed.
[  298]  298: 
[  299]  299: =cut
[  300]  300: 
[  301]  301: sub TrapInclude {
[  302]  302:   my $self = shift;
[  303]  303:   my $_r = tied %$self;
[  304]  304:   my $output;
[  305]  305:   my $handle = \do { local *HANDLE };
[  306]  306:   tie *{$handle}, 'Mungo::Response::Trap', \$output;
[  307]  307:   push @{$_r->{data}->{'IO_stack'}}, select(*{$handle});
[  308]  308:   eval {
[  309]  309:     $self->Include(@_);
[  310]  310:   };
[  311]  311:   untie *{$handle} if tied *{$handle};
[  312]  312:   select(pop @{$_r->{data}->{'IO_stack'}});
[  313]  313:   if($@) {
[  314]  314:     local $SIG{__DIE__} = undef;
[  315]  315:     die $@;
[  316]  316:   }
[  317]  317:   return $output;
[  318]  318: }
[  319]  319: 
[  320]  320: =head2 $Response->End()
[  321]  321: 
[  322]  322: Stops processing the current response, shuts down the 
[  323]  323: output handle, and jumps out of the response handler.  
[  324]  324: No further processing will occur.
[  325]  325: 
[  326]  326: =cut
[  327]  327: 
[  328]  328: sub End {
[  329]  329:   my $self = shift;
[  330]  330:   my $_r = tied %$self;
[  331]  331:   while(scalar(@{$_r->{data}->{'IO_stack'} || []}) > 1) {
[  332]  332:     my $oldfh = select(pop @{$_r->{data}->{'IO_stack'}});
[  333]  333:     if(my $obj = tied *{$oldfh}) {
[  334]  334:       untie *{$oldfh};
[  335]  335:       print $$obj;
[  336]  336:     }
[  337]  337:   }
[  338]  338:   $self->Flush();
[  339]  339:   eval { goto  MUNGO_HANDLER_FINISH; }; # Jump back to Mungo::handler()
[  340]  340: }
[  341]  341: 
[  342]  342: sub Flush {
[  343]  343:   my $self = shift;
[  344]  344:   my $_r = tied %$self;
[  345]  345:   # Flush doesn't apply unless we're immediately above STDOUT
[  346]  346:   return if(scalar(@{$_r->{data}->{'IO_stack'} || []}) > 1);
[  347]  347:   unless($_r->{data}->{'__OUTPUT_STARTED__'}) {
[  348]  348:     $self->send_http_header;
[  349]  349:     $_r->{data}->{'__OUTPUT_STARTED__'} = 1;
[  350]  350:   }
[  351]  351:   if (@{$_r->{data}->{'IO_stack'} || []}) {
[  352]  352:       $_r->{data}->{'IO_stack'}->[-1]->print($one_true_buffer);
[  353]  353:   } else {
[  354]  354:       print $one_true_buffer;
[  355]  355:   }
[  356]  356: 
[  357]  357:   $one_true_buffer = '';
[  358]  358: }
[  359]  359: 
[  360]  360: sub AUTOLOAD {
[  361]  361:   my $self = shift;
[  362]  362:   my $name = $AUTOLOAD;
[  363]  363:   $name =~ s/.*://;   # strip fully-qualified portion
[  364]  364:   die __PACKAGE__." does not implement $name";
[  365]  365: }
[  366]  366: 
[  367]  367: sub TIEHANDLE {
[  368]  368:   my $class = shift;
[  369]  369:   my $self = shift;
[  370]  370:   return $self;
[  371]  371: }
[  372]  372: sub PRINT {
[  373]  373:   my $self = shift;
[  374]  374:   my $output = shift;
[  375]  375:   my $_r = tied %$self;
[  376]  376:   if(scalar(@{$_r->{data}->{'IO_stack'} || []}) == 1) {
[  377]  377:     # Buffering a just-in-time headers only applies if we
[  378]  378:     # immediately above STDOUT
[  379]  379:     if($_r->{data}->{Buffer}) {
[  380]  380:       $one_true_buffer .= $output;
[  381]  381:       return;
[  382]  382:     }
[  383]  383:     unless($_r->{data}->{'__OUTPUT_STARTED__'}) {
[  384]  384:       $_r->{data}->{'__OUTPUT_STARTED__'} = 1;
[  385]  385:       $self->send_http_header;
[  386]  386:     }
[  387]  387:   }
[  388]  388:   if (@{$_r->{data}->{'IO_stack'} || []}) {
[  389]  389:       $_r->{data}->{'IO_stack'}->[-1]->print($output);
[  390]  390:   } else {
[  391]  391:       print $output;
[  392]  392:   }
[  393]  393: }
[  394]  394: sub PRINTF {
[  395]  395:   my $self = shift;
[  396]  396:   my $_r = tied %$self;
[  397]  397:   if(scalar(@{$_r->{data}->{'IO_stack'} || []}) == 1) {
[  398]  398:     # Buffering a just-in-time headers only applies if we
[  399]  399:     # immediately above STDOUT
[  400]  400:     if($_r->{data}->{Buffer}) {
[  401]  401:       $one_true_buffer .= sprintf(@_);
[  402]  402:       return;
[  403]  403:     }
[  404]  404:     unless($_r->{data}->{'__OUTPUT_STARTED__'}) {
[  405]  405:       $_r->{data}->{'__OUTPUT_STARTED__'} = 1;
[  406]  406:       $self->send_http_header;
[  407]  407:     }
[  408]  408:   }
[  409]  409:   if (@{$_r->{data}->{'IO_stack'} || []}) {
[  410]  410:       $_r->{data}->{'IO_stack'}->[-1]->printf(@_);
[  411]  411:   } else {
[  412]  412:       printf(@_);
[  413]  413:   }
[  414]  414: }
[  415]  415: sub CLOSE {
[  416]  416:   my $self = shift;
[  417]  417:   my $_r = tied %$self;
[  418]  418:   # Unbuffer outselves, this will actually induce a flush (must go through tiehash)
[  419]  419:   $_r->{data}->{Buffer} = 0;
[  420]  420: }
[  421]  421: sub UNTIE { }
[  422]  422: 
[  423]  423: =head1 AUTHOR
[  424]  424: 
[  425]  425: Theo Schlossnagle
[  426]  426: 
[  427]  427: Clinton Wolfe (docs)
[  428]  428: 
[  429]  429: =cut
[  430]  430: 
[  431]  431: 1;