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

inc/actions.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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){
360
    global $INFO;
361
    @unlink($INFO['draft']);
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) {
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