Completed
Push — actionrefactor ( 6e4bf0 )
by Andreas
04:36
created

actions.php ➔ XXX_act_dispatch()   F

Complexity

Conditions 41
Paths > 20000

Size

Total Lines 185
Code Lines 98

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 41
eloc 98
nc 55738372
nop 0
dl 0
loc 185
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * DokuWiki Actions
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Andreas Gohr <[email protected]>
7
 */
8
9
if(!defined('DOKU_INC')) die('meh.');
10
11
12
function act_dispatch(){
13
    $router = \dokuwiki\ActionRouter::getInstance(); // is this needed here or could we delegate it to tpl_content() later?
14
15
16
17
    //call template FIXME: all needed vars available?
18
    $headers[] = 'Content-Type: text/html; charset=utf-8';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$headers was never initialized. Although not strictly required by PHP, it is generally a good practice to add $headers = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
19
    trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
20
21
    // clear internal variables
22
    unset($router);
23
    unset($headers);
24
    // make all globals available to the template
25
    extract($GLOBALS);
26
27
    include(template('main.php'));
28
    // output for the commands is now handled in inc/templates.php
29
    // in function tpl_content()
30
}
31
32
/**
33
 * Call the needed action handlers
34
 *
35
 * @author Andreas Gohr <[email protected]>
36
 * @triggers ACTION_ACT_PREPROCESS
37
 * @triggers ACTION_HEADERS_SEND
38
 */
39
function XXX_act_dispatch(){
40
    global $ACT;
41
    global $ID;
42
    global $INFO;
43
    global $QUERY;
44
    /* @var Input $INPUT */
45
    global $INPUT;
46
    global $lang;
47
    global $conf;
48
49
    $preact = $ACT;
50
51
    // give plugins an opportunity to process the action
52
    $evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT);
53
54
    $headers = array();
55
    if ($evt->advise_before()) {
56
57
        //sanitize $ACT
58
        $ACT = act_validate($ACT);
59
60
        //check if searchword was given - else just show
61
        $s = cleanID($QUERY);
62
        if($ACT == 'search' && empty($s)){
63
            $ACT = 'show';
64
        }
65
66
        //login stuff
67
        if(in_array($ACT,array('login','logout'))){
68
            $ACT = act_auth($ACT);
69
        }
70
71
        //check if user is asking to (un)subscribe a page
72
        if($ACT == 'subscribe') {
73
            try {
74
                $ACT = act_subscription($ACT);
75
            } catch (Exception $e) {
76
                msg($e->getMessage(), -1);
77
            }
78
        }
79
80
        //display some info
81
        if($ACT == 'check'){
82
            check();
83
            $ACT = 'show';
84
        }
85
86
        //check permissions
87
        $ACT = act_permcheck($ACT);
88
89
        //sitemap
90
        if ($ACT == 'sitemap'){
91
            act_sitemap($ACT);
92
        }
93
94
        //recent changes
95
        if ($ACT == 'recent'){
96
            $show_changes = $INPUT->str('show_changes');
97
            if (!empty($show_changes)) {
98
                set_doku_pref('show_changes', $show_changes);
99
            }
100
        }
101
102
        //diff
103
        if ($ACT == 'diff'){
104
            $difftype = $INPUT->str('difftype');
105
            if (!empty($difftype)) {
106
                set_doku_pref('difftype', $difftype);
107
            }
108
        }
109
110
        //register
111
        if($ACT == 'register' && $INPUT->post->bool('save') && register()){
112
            $ACT = 'login';
113
        }
114
115
        if ($ACT == 'resendpwd' && act_resendpwd()) {
116
            $ACT = 'login';
117
        }
118
119
        // user profile changes
120
        if (in_array($ACT, array('profile','profile_delete'))) {
121
            if(!$INPUT->server->str('REMOTE_USER')) {
122
                $ACT = 'login';
123
            } else {
124
                switch ($ACT) {
125
                    case 'profile' :
126
                        if(updateprofile()) {
127
                            msg($lang['profchanged'],1);
128
                            $ACT = 'show';
129
                        }
130
                        break;
131
                    case 'profile_delete' :
132
                        if(auth_deleteprofile()){
133
                            msg($lang['profdeleted'],1);
134
                            $ACT = 'show';
135
                        } else {
136
                            $ACT = 'profile';
137
                        }
138
                        break;
139
                }
140
            }
141
        }
142
143
        //revert
144
        if($ACT == 'revert'){
145
            if(checkSecurityToken()){
146
                $ACT = act_revert($ACT);
147
            }else{
148
                $ACT = 'show';
149
            }
150
        }
151
152
        //save
153
        if($ACT == 'save'){
154
            if(checkSecurityToken()){
155
                $ACT = act_save($ACT);
156
            }else{
157
                $ACT = 'preview';
158
            }
159
        }
160
161
        //cancel conflicting edit
162
        if($ACT == 'cancel')
163
            $ACT = 'show';
164
165
        //draft deletion
166
        if($ACT == 'draftdel')
167
            $ACT = act_draftdel($ACT);
168
169
        //draft saving on preview
170
        if($ACT == 'preview') {
171
            $headers[] = "X-XSS-Protection: 0";
172
            $ACT = act_draftsave($ACT);
173
        }
174
175
        //edit
176
        if(in_array($ACT, array('edit', 'preview', 'recover'))) {
177
            $ACT = act_edit($ACT);
178
        }else{
179
            unlock($ID); //try to unlock
180
        }
181
182
        //handle export
183
        if(substr($ACT,0,7) == 'export_')
184
            $ACT = act_export($ACT);
185
186
        //handle admin tasks
187
        if($ACT == 'admin'){
188
            // retrieve admin plugin name from $_REQUEST['page']
189
            if (($page = $INPUT->str('page', '', true)) != '') {
190
                /** @var $plugin DokuWiki_Admin_Plugin */
191
                if ($plugin = plugin_getRequestAdminPlugin()){
192
                    $plugin->handle();
193
                }
194
            }
195
        }
196
197
        // check permissions again - the action may have changed
198
        $ACT = act_permcheck($ACT);
199
    }  // end event ACTION_ACT_PREPROCESS default action
200
    $evt->advise_after();
201
    // Make sure plugs can handle 'denied'
202
    if($conf['send404'] && $ACT == 'denied') {
203
        http_status(403);
204
    }
205
    unset($evt);
206
207
    // when action 'show', the intial not 'show' and POST, do a redirect
208
    if($ACT == 'show' && $preact != 'show' && strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post'){
209
        act_redirect($ID,$preact);
210
    }
211
212
    global $INFO;
213
    global $conf;
214
    global $license;
215
216
    //call template FIXME: all needed vars available?
217
    $headers[] = 'Content-Type: text/html; charset=utf-8';
218
    trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
219
220
    include(template('main.php'));
221
    // output for the commands is now handled in inc/templates.php
222
    // in function tpl_content()
223
}
224
225
/**
226
 * Send the given headers using header()
227
 *
228
 * @param array $headers The headers that shall be sent
229
 */
230
function act_sendheaders($headers) {
231
    foreach ($headers as $hdr) header($hdr);
232
}
233
234
/**
235
 * Sanitize the action command
236
 *
237
 * @author Andreas Gohr <[email protected]>
238
 *
239
 * @param array|string $act
240
 * @return string
241
 */
242
function act_clean($act){
243
    // check if the action was given as array key
244
    if(is_array($act)){
245
        list($act) = array_keys($act);
246
    }
247
248
    //remove all bad chars
249
    $act = strtolower($act);
250
    $act = preg_replace('/[^1-9a-z_]+/','',$act);
251
252
    if($act == 'export_html') $act = 'export_xhtml';
253
    if($act == 'export_htmlbody') $act = 'export_xhtmlbody';
254
255
    if($act === '') $act = 'show';
256
    return $act;
257
}
258
259
/**
260
 * Sanitize and validate action commands.
261
 *
262
 * Add all allowed commands here.
263
 *
264
 * @author Andreas Gohr <[email protected]>
265
 *
266
 * @param array|string $act
267
 * @return string
268
 */
269
function act_validate($act) {
270
    global $conf;
271
    global $INFO;
272
273
    $act = act_clean($act);
274
275
    // check if action is disabled
276
    if(!actionOK($act)){
277
        msg('Command disabled: '.htmlspecialchars($act),-1);
278
        return 'show';
279
    }
280
281
    //disable all acl related commands if ACL is disabled
282
    if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
283
                    'subscribe','unsubscribe','profile','revert',
284
                    'resendpwd','profile_delete'))){
285
        msg('Command unavailable: '.htmlspecialchars($act),-1);
286
        return 'show';
287
    }
288
289
    //is there really a draft?
290
    if($act == 'draft' && !file_exists($INFO['draft'])) return 'edit';
291
292
    if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
293
                    'preview','search','show','check','index','revisions',
294
                    'diff','recent','backlink','admin','subscribe','revert',
295
                    'unsubscribe','profile','profile_delete','resendpwd','recover',
296
                    'draftdel','sitemap','media')) && substr($act,0,7) != 'export_' ) {
297
        msg('Command unknown: '.htmlspecialchars($act),-1);
298
        return 'show';
299
    }
300
    return $act;
301
}
302
303
/**
304
 * Run permissionchecks
305
 *
306
 * @author Andreas Gohr <[email protected]>
307
 *
308
 * @param string $act action command
309
 * @return string action command
310
 */
311
function act_permcheck($act){
312
    global $INFO;
313
314
    if(in_array($act,array('save','preview','edit','recover'))){
315
        if($INFO['exists']){
316
            if($act == 'edit'){
317
                //the edit function will check again and do a source show
318
                //when no AUTH_EDIT available
319
                $permneed = AUTH_READ;
320
            }else{
321
                $permneed = AUTH_EDIT;
322
            }
323
        }else{
324
            $permneed = AUTH_CREATE;
325
        }
326
    }elseif(in_array($act,array('login','search','recent','profile','profile_delete','index', 'sitemap'))){
327
        $permneed = AUTH_NONE;
328
    }elseif($act == 'revert'){
329
        $permneed = AUTH_ADMIN;
330
        if($INFO['ismanager']) $permneed = AUTH_EDIT;
331
    }elseif($act == 'register'){
332
        $permneed = AUTH_NONE;
333
    }elseif($act == 'resendpwd'){
334
        $permneed = AUTH_NONE;
335
    }elseif($act == 'admin'){
336
        if($INFO['ismanager']){
337
            // if the manager has the needed permissions for a certain admin
338
            // action is checked later
339
            $permneed = AUTH_READ;
340
        }else{
341
            $permneed = AUTH_ADMIN;
342
        }
343
    }else{
344
        $permneed = AUTH_READ;
345
    }
346
    if($INFO['perm'] >= $permneed) return $act;
347
348
    return 'denied';
349
}
350
351
/**
352
 * Handle 'draftdel'
353
 *
354
 * Deletes the draft for the current page and user
355
 *
356
 * @param string $act action command
357
 * @return string action command
358
 */
359
function act_draftdel($act){
0 ignored issues
show
Unused Code introduced by
The parameter $act is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
360
    global $INFO;
361
    @unlink($INFO['draft']);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
362
    $INFO['draft'] = null;
363
    return 'show';
364
}
365
366
/**
367
 * Saves a draft on preview
368
 *
369
 * @todo this currently duplicates code from ajax.php :-/
370
 *
371
 * @param string $act action command
372
 * @return string action command
373
 */
374
function act_draftsave($act){
375
    global $INFO;
376
    global $ID;
377
    global $INPUT;
378
    global $conf;
379
    if($conf['usedraft'] && $INPUT->post->has('wikitext')) {
380
        $draft = array('id'     => $ID,
381
                'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
382
                'text'   => $INPUT->post->str('wikitext'),
383
                'suffix' => $INPUT->post->str('suffix'),
384
                'date'   => $INPUT->post->int('date'),
385
                'client' => $INFO['client'],
386
                );
387
        $cname = getCacheName($draft['client'].$ID,'.draft');
388
        if(io_saveFile($cname,serialize($draft))){
389
            $INFO['draft'] = $cname;
390
        }
391
    }
392
    return $act;
393
}
394
395
/**
396
 * Handle 'save'
397
 *
398
 * Checks for spam and conflicts and saves the page.
399
 * Does a redirect to show the page afterwards or
400
 * returns a new action.
401
 *
402
 * @author Andreas Gohr <[email protected]>
403
 *
404
 * @param string $act action command
405
 * @return string action command
406
 */
407
function act_save($act){
408
    global $ID;
409
    global $DATE;
410
    global $PRE;
411
    global $TEXT;
412
    global $SUF;
413
    global $SUM;
414
    global $lang;
415
    global $INFO;
416
    global $INPUT;
417
418
    //spam check
419
    if(checkwordblock()) {
420
        msg($lang['wordblock'], -1);
421
        return 'edit';
422
    }
423
    //conflict check
424
    if($DATE != 0 && $INFO['meta']['date']['modified'] > $DATE )
425
        return 'conflict';
426
427
    //save it
428
    saveWikiText($ID,con($PRE,$TEXT,$SUF,true),$SUM,$INPUT->bool('minor')); //use pretty mode for con
429
    //unlock it
430
    unlock($ID);
431
432
    //delete draft
433
    act_draftdel($act);
434
    session_write_close();
435
436
    // when done, show page
437
    return 'show';
438
}
439
440
/**
441
 * Revert to a certain revision
442
 *
443
 * @author Andreas Gohr <[email protected]>
444
 *
445
 * @param string $act action command
446
 * @return string action command
447
 */
448
function act_revert($act){
449
    global $ID;
450
    global $REV;
451
    global $lang;
452
    /* @var Input $INPUT */
453
    global $INPUT;
454
    // FIXME $INFO['writable'] currently refers to the attic version
455
    // global $INFO;
456
    // if (!$INFO['writable']) {
457
    //     return 'show';
458
    // }
459
460
    // when no revision is given, delete current one
461
    // FIXME this feature is not exposed in the GUI currently
462
    $text = '';
463
    $sum  = $lang['deleted'];
464
    if($REV){
465
        $text = rawWiki($ID,$REV);
466
        if(!$text) return 'show'; //something went wrong
467
        $sum = sprintf($lang['restored'], dformat($REV));
468
    }
469
470
    // spam check
471
472
    if (checkwordblock($text)) {
473
        msg($lang['wordblock'], -1);
474
        return 'edit';
475
    }
476
477
    saveWikiText($ID,$text,$sum,false);
478
    msg($sum,1);
479
480
    //delete any draft
481
    act_draftdel($act);
482
    session_write_close();
483
484
    // when done, show current page
485
    $INPUT->server->set('REQUEST_METHOD','post'); //should force a redirect
486
    $REV = '';
487
    return 'show';
488
}
489
490
/**
491
 * Do a redirect after receiving post data
492
 *
493
 * Tries to add the section id as hash mark after section editing
494
 *
495
 * @param string $id page id
496
 * @param string $preact action command before redirect
497
 */
498
function act_redirect($id,$preact){
499
    global $PRE;
500
    global $TEXT;
501
502
    $opts = array(
503
            'id'       => $id,
504
            'preact'   => $preact
505
            );
506
    //get section name when coming from section edit
507
    if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
508
        $check = false; //Byref
509
        $opts['fragment'] = sectionID($match[0], $check);
510
    }
511
512
    trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
513
}
514
515
/**
516
 * Execute the redirect
517
 *
518
 * @param array $opts id and fragment for the redirect and the preact
519
 */
520
function act_redirect_execute($opts){
521
    $go = wl($opts['id'],'',true);
522
    if(isset($opts['fragment'])) $go .= '#'.$opts['fragment'];
523
524
    //show it
525
    send_redirect($go);
526
}
527
528
/**
529
 * Handle 'login', 'logout'
530
 *
531
 * @author Andreas Gohr <[email protected]>
532
 *
533
 * @param string $act action command
534
 * @return string action command
535
 */
536
function act_auth($act){
537
    global $ID;
538
    global $INFO;
539
    /* @var Input $INPUT */
540
    global $INPUT;
541
542
    //already logged in?
543
    if($INPUT->server->has('REMOTE_USER') && $act=='login'){
544
        return 'show';
545
    }
546
547
    //handle logout
548
    if($act=='logout'){
549
        $lockedby = checklock($ID); //page still locked?
550
        if($lockedby == $INPUT->server->str('REMOTE_USER')){
551
            unlock($ID); //try to unlock
552
        }
553
554
        // do the logout stuff
555
        auth_logoff();
556
557
        // rebuild info array
558
        $INFO = pageinfo();
559
560
        act_redirect($ID,'login');
561
    }
562
563
    return $act;
564
}
565
566
/**
567
 * Handle 'edit', 'preview', 'recover'
568
 *
569
 * @author Andreas Gohr <[email protected]>
570
 *
571
 * @param string $act action command
572
 * @return string action command
573
 */
574
function act_edit($act){
575
    global $ID;
576
    global $INFO;
577
578
    global $TEXT;
579
    global $RANGE;
580
    global $PRE;
581
    global $SUF;
582
    global $REV;
583
    global $SUM;
584
    global $lang;
585
    global $DATE;
586
587
    if (!isset($TEXT)) {
588
        if ($INFO['exists']) {
589
            if ($RANGE) {
590
                list($PRE,$TEXT,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
591
            } else {
592
                $TEXT = rawWiki($ID,$REV);
593
            }
594
        } else {
595
            $TEXT = pageTemplate($ID);
596
        }
597
    }
598
599
    //set summary default
600
    if(!$SUM){
601
        if($REV){
602
            $SUM = sprintf($lang['restored'], dformat($REV));
603
        }elseif(!$INFO['exists']){
604
            $SUM = $lang['created'];
605
        }
606
    }
607
608
    // Use the date of the newest revision, not of the revision we edit
609
    // This is used for conflict detection
610
    if(!$DATE) $DATE = @filemtime(wikiFN($ID));
611
612
    //check if locked by anyone - if not lock for my self
613
    //do not lock when the user can't edit anyway
614
    if ($INFO['writable']) {
615
        $lockedby = checklock($ID);
616
        if($lockedby) return 'locked';
617
618
        lock($ID);
619
    }
620
621
    return $act;
622
}
623
624
/**
625
 * Export a wiki page for various formats
626
 *
627
 * Triggers ACTION_EXPORT_POSTPROCESS
628
 *
629
 *  Event data:
630
 *    data['id']      -- page id
631
 *    data['mode']    -- requested export mode
632
 *    data['headers'] -- export headers
633
 *    data['output']  -- export output
634
 *
635
 * @author Andreas Gohr <[email protected]>
636
 * @author Michael Klier <[email protected]>
637
 *
638
 * @param string $act action command
639
 * @return string action command
640
 */
641
function act_export($act){
642
    global $ID;
643
    global $REV;
644
    global $conf;
645
    global $lang;
646
647
    $pre = '';
648
    $post = '';
649
    $headers = array();
650
651
    // search engines: never cache exported docs! (Google only currently)
652
    $headers['X-Robots-Tag'] = 'noindex';
653
654
    $mode = substr($act,7);
655
    switch($mode) {
656
        case 'raw':
657
            $headers['Content-Type'] = 'text/plain; charset=utf-8';
658
            $headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
659
            $output = rawWiki($ID,$REV);
660
            break;
661
        case 'xhtml':
662
            $pre .= '<!DOCTYPE html>' . DOKU_LF;
663
            $pre .= '<html lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">' . DOKU_LF;
664
            $pre .= '<head>' . DOKU_LF;
665
            $pre .= '  <meta charset="utf-8" />' . DOKU_LF;
666
            $pre .= '  <title>'.$ID.'</title>' . DOKU_LF;
667
668
            // get metaheaders
669
            ob_start();
670
            tpl_metaheaders();
671
            $pre .= ob_get_clean();
672
673
            $pre .= '</head>' . DOKU_LF;
674
            $pre .= '<body>' . DOKU_LF;
675
            $pre .= '<div class="dokuwiki export">' . DOKU_LF;
676
677
            // get toc
678
            $pre .= tpl_toc(true);
679
680
            $headers['Content-Type'] = 'text/html; charset=utf-8';
681
            $output = p_wiki_xhtml($ID,$REV,false);
682
683
            $post .= '</div>' . DOKU_LF;
684
            $post .= '</body>' . DOKU_LF;
685
            $post .= '</html>' . DOKU_LF;
686
            break;
687
        case 'xhtmlbody':
688
            $headers['Content-Type'] = 'text/html; charset=utf-8';
689
            $output = p_wiki_xhtml($ID,$REV,false);
690
            break;
691
        default:
692
            $output = p_cached_output(wikiFN($ID,$REV), $mode, $ID);
693
            $headers = p_get_metadata($ID,"format $mode");
694
            break;
695
    }
696
697
    // prepare event data
698
    $data = array();
699
    $data['id'] = $ID;
700
    $data['mode'] = $mode;
701
    $data['headers'] = $headers;
702
    $data['output'] =& $output;
703
704
    trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
705
706
    if(!empty($data['output'])){
707
        if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
708
            header("$key: $val");
709
        }
710
        print $pre.$data['output'].$post;
711
        exit;
712
    }
713
    return 'show';
714
}
715
716
/**
717
 * Handle sitemap delivery
718
 *
719
 * @author Michael Hamann <[email protected]>
720
 *
721
 * @param string $act action command
722
 */
723
function act_sitemap($act) {
0 ignored issues
show
Unused Code introduced by
The parameter $act is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
724
    global $conf;
725
726
    if ($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) {
727
        http_status(404);
728
        print "Sitemap generation is disabled.";
729
        exit;
730
    }
731
732
    $sitemap = Sitemapper::getFilePath();
733
    if (Sitemapper::sitemapIsCompressed()) {
734
        $mime = 'application/x-gzip';
735
    }else{
736
        $mime = 'application/xml; charset=utf-8';
737
    }
738
739
    // Check if sitemap file exists, otherwise create it
740
    if (!is_readable($sitemap)) {
741
        Sitemapper::generate();
742
    }
743
744
    if (is_readable($sitemap)) {
745
        // Send headers
746
        header('Content-Type: '.$mime);
747
        header('Content-Disposition: attachment; filename='.utf8_basename($sitemap));
748
749
        http_conditionalRequest(filemtime($sitemap));
750
751
        // Send file
752
        //use x-sendfile header to pass the delivery to compatible webservers
753
        http_sendfile($sitemap);
754
755
        readfile($sitemap);
756
        exit;
757
    }
758
759
    http_status(500);
760
    print "Could not read the sitemap file - bad permissions?";
761
    exit;
762
}
763
764
/**
765
 * Handle page 'subscribe'
766
 *
767
 * Throws exception on error.
768
 *
769
 * @author Adrian Lang <[email protected]>
770
 *
771
 * @param string $act action command
772
 * @return string action command
773
 * @throws Exception if (un)subscribing fails
774
 */
775
function act_subscription($act){
776
    global $lang;
777
    global $INFO;
778
    global $ID;
779
    /* @var Input $INPUT */
780
    global $INPUT;
781
782
    // subcriptions work for logged in users only
783
    if(!$INPUT->server->str('REMOTE_USER')) return 'show';
784
785
    // get and preprocess data.
786
    $params = array();
787
    foreach(array('target', 'style', 'action') as $param) {
788
        if ($INPUT->has("sub_$param")) {
789
            $params[$param] = $INPUT->str("sub_$param");
790
        }
791
    }
792
793
    // any action given? if not just return and show the subscription page
794
    if(empty($params['action']) || !checkSecurityToken()) return $act;
795
796
    // Handle POST data, may throw exception.
797
    trigger_event('ACTION_HANDLE_SUBSCRIBE', $params, 'subscription_handle_post');
798
799
    $target = $params['target'];
800
    $style  = $params['style'];
801
    $action = $params['action'];
802
803
    // Perform action.
804
    $sub = new Subscription();
805
    if($action == 'unsubscribe'){
806
        $ok = $sub->remove($target, $INPUT->server->str('REMOTE_USER'), $style);
807
    }else{
808
        $ok = $sub->add($target, $INPUT->server->str('REMOTE_USER'), $style);
809
    }
810
811
    if($ok) {
812
        msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']),
813
                    prettyprint_id($target)), 1);
814
        act_redirect($ID, $act);
815
    } else {
816
        throw new Exception(sprintf($lang["subscr_{$action}_error"],
817
                                    hsc($INFO['userinfo']['name']),
818
                                    prettyprint_id($target)));
819
    }
820
821
    // Assure that we have valid data if act_redirect somehow fails.
822
    $INFO['subscribed'] = $sub->user_subscription();
823
    return 'show';
824
}
825
826
/**
827
 * Validate POST data
828
 *
829
 * Validates POST data for a subscribe or unsubscribe request. This is the
830
 * default action for the event ACTION_HANDLE_SUBSCRIBE.
831
 *
832
 * @author Adrian Lang <[email protected]>
833
 *
834
 * @param array &$params the parameters: target, style and action
835
 * @throws Exception
836
 */
837
function subscription_handle_post(&$params) {
838
    global $INFO;
839
    global $lang;
840
    /* @var Input $INPUT */
841
    global $INPUT;
842
843
    // Get and validate parameters.
844
    if (!isset($params['target'])) {
845
        throw new Exception('no subscription target given');
846
    }
847
    $target = $params['target'];
848
    $valid_styles = array('every', 'digest');
849
    if (substr($target, -1, 1) === ':') {
850
        // Allow “list” subscribe style since the target is a namespace.
851
        $valid_styles[] = 'list';
852
    }
853
    $style  = valid_input_set('style', $valid_styles, $params,
854
                              'invalid subscription style given');
855
    $action = valid_input_set('action', array('subscribe', 'unsubscribe'),
856
                              $params, 'invalid subscription action given');
857
858
    // Check other conditions.
859
    if ($action === 'subscribe') {
860
        if ($INFO['userinfo']['mail'] === '') {
861
            throw new Exception($lang['subscr_subscribe_noaddress']);
862
        }
863
    } elseif ($action === 'unsubscribe') {
864
        $is = false;
865
        foreach($INFO['subscribed'] as $subscr) {
866
            if ($subscr['target'] === $target) {
867
                $is = true;
868
            }
869
        }
870
        if ($is === false) {
871
            throw new Exception(sprintf($lang['subscr_not_subscribed'],
872
                                        $INPUT->server->str('REMOTE_USER'),
873
                                        prettyprint_id($target)));
874
        }
875
        // subscription_set deletes a subscription if style = null.
876
        $style = null;
877
    }
878
879
    $params = compact('target', 'style', 'action');
880
}
881
882
//Setup VIM: ex: et ts=2 :
883