source: trunk/common/textblock.php @ 1184

Revision 1167, 7.4 KB checked in by bogdan2412, 3 months ago (diff)

Fixed memory leaks in image resizing code.

Also contains various other fixes from live.

  • Updated hphp config sample file
  • Fixed a crash in scripts/check-attachments for files existing in the db, but not on the hard disk.
  • Fixed unsafe includes in views/task_filter_results.php
  • Property svn:eol-style set to native
Line 
1<?php
2
3require_once(IA_ROOT_DIR . "common/db/textblock.php");
4require_once(IA_ROOT_DIR . "common/cache.php");
5require_once(IA_ROOT_DIR . "common/external_libs/simple_html_dom.php");
6
7// Hijacks title from $text if already there. If $url is null the title
8// will not have a link.
9function hijack_title(&$text, $url, $title) {
10    if (preg_match('/^\s*<h1>(.*)<\/h1>(.*)$/sxi', $text, $matches)) {
11        $text = $matches[2];
12        if (is_null($url)) {
13            return '<h1>'.$matches[1].'</h1>';
14        } else {
15            return '<h1>'.format_link($url, $matches[1], false).'</h1>';
16        }
17    } else {
18        if (is_null($url)) {
19            return '<h1>'.html_escape($title).'</h1>';
20        } else {
21            return '<h1>'.format_link($url, $title).'</h1>';
22        }
23    }
24}
25
26// Returns a snippet of a textblock. The snippet does not contain images
27// (if $remove_images = true) and it doesn't exceed $max_num_words.
28//
29// Some exceptions:
30//    * news -- they are fully rendered in the snippet if $whole_news is true
31//    * blog posts having a huge first paragraph -- although we exceed the
32//        number of words allowed we should have a snippet for this kind of
33//        posts after all
34function get_snippet($tb, $max_num_words, $whole_news = false,
35        $remove_images = true) {
36    $cache_id = 'snip_' . preg_replace('/[^a-z0-9\.\-_]/i', '_',
37                $tb['name']) . '_' . $max_num_words . '_' . $whole_news .
38                $remove_images . '_' . db_date_parse($tb['timestamp']);
39    $cache_res = disk_cache_get($cache_id);
40
41    if ($cache_res == false) {
42        $url = url_textblock($tb['name']);
43        $html_text = wiki_process_textblock_recursive($tb);
44
45        $cache_res .= hijack_title($html_text, $url, $tb['title']);
46        $cache_res .= '<div class="wiki_text_block">';
47
48        // May be there is a better way to find out if $tb is tagged
49        // 'stiri'. On the other hand, this operation is cached and we
50        // shouldn't worry too much about performance.
51        if ($whole_news && tag_exists('textblock', $tb['name'], tag_get_id(
52            array("name" => 'stiri', "type" => "tag", "parent" => 0)))) {
53            // Don't compute snippet for news -- they should be rendered as
54            // they are in the snippet.
55            $cache_res .= $html_text;
56        } else {
57            $html_dom = str_get_html($html_text);
58            $num_words = 0;
59
60            if ($remove_images) {
61                // Remove all the images -- ussually they look bad in a snippet.
62                foreach ($html_dom->find('img') as $element) {
63                    $element->outertext = '';
64                }
65            }
66
67            // Select some paragraphs so that the maximum number of words is
68            // not exceeded and at least one paragraph is selected.
69            foreach ($html_dom->find('p') as $element) {
70                $par_words = count(explode(" ", $element->plaintext));
71                if ($num_words + $par_words >= $max_num_words && $num_words > 0) {
72                    break;
73                }
74                $num_words += $par_words;
75                $cache_res .= $element->outertext();
76            }
77
78            $cache_res .= '<a href="' . html_escape($url) .
79                '"> &raquo; Citeste restul insemnarii</a>';
80            $html_dom->__destruct();
81            unset($html_dom);
82        }
83
84        $cache_res .= '</div>';
85        disk_cache_set($cache_id, $cache_res, 3);
86    }
87
88    return $cache_res;
89}
90
91// Check if textblock security string is valid
92// FIXME: check task/round existence?
93function is_textblock_security_descriptor($descriptor)
94{
95    return preg_match("/^ \s* task: \s* (".IA_RE_TASK_ID.") \s* $/xi", $descriptor) ||
96           preg_match("/^ \s* round: \s* (".IA_RE_ROUND_ID.") \s* $/xi", $descriptor) ||
97           preg_match('/^ \s* (private|protected|public) \s* $/xi', $descriptor);
98}
99
100// Validates a textblock.
101// NOTE: this might be incomplete, so don't rely on it exclusively
102function textblock_validate($tb) {
103    $errors = array();
104
105    // FIXME How to handle this?
106    log_assert(is_array($tb), "You didn't even pass an array");
107
108    if (!is_normal_page_name(getattr($tb, 'name', ''))) {
109        $errors['name'] = 'Nume de pagina invalid.';
110    }
111
112    // FIXME: move this in textblock edit controller
113    if (strlen(getattr($tb, 'title', '')) < 1) {
114        $errors['title'] = 'Titlu prea scurt.';
115    }
116
117    // FIXME: move this in textblock edit controller
118    if (strlen(getattr($tb, 'title', '')) > 64) {
119        $errors['title'] = 'Titlu prea lung.';
120    }
121
122    if (!is_user_id(getattr($tb, 'user_id'))) {
123        $errors['user_id'] = 'ID de utilizator invalid';
124    }
125
126    if (!is_null(getattr($tb, 'forum_topic')) && !is_whole_number(getattr($tb, 'forum_topic'))) {
127        $errors['forum_topic'] = 'Topic forum invalid';
128    }
129
130    // NOTE: missing timestamp is OK!!!
131    // It stands for 'current moment'.
132    if (!is_db_date(getattr($tb, 'timestamp', db_date_format()))) {
133        $errors['timestamp'] = 'Timestamp invalid.';
134    }
135
136    if (!is_db_date(getattr($tb, 'creation_timestamp', db_date_format()))) {
137        $errors['creation_timestamp'] = 'Timestamp invalid.';
138    }
139
140    if (!is_textblock_security_descriptor(getattr($tb, 'security'))) {
141        $errors['security'] = "Descriptor de securitate gresit.";
142    }
143
144    return $errors;
145}
146
147// This function copies all starting with $srcprefix and copies the over to
148// $destprefix.
149// It also does template-replacing for everything in $replace, if non-null.
150// You can also change the security descriptor on all those files.
151//
152// Use this like textblock_copy_replace('template/newtask', 'problema/capsuni');
153function textblock_copy_replace($srcprefix, $dstprefix, $replace, $security,
154        $user_id, $remote_ip_info = null) {
155    log_assert($srcprefix != $dstprefix);
156    log_assert($security === null ||
157               is_textblock_security_descriptor($security));
158    log_assert(is_whole_number($user_id));
159
160    $textblocks = textblock_get_by_prefix($srcprefix, true, false);
161    foreach ($textblocks as $textblock) {
162        if ($replace !== null) {
163            textblock_template_replace($textblock, $replace);
164        }
165        if ($security !== null) {
166            $textblock['security'] = $security;
167        }
168        $new_name = preg_replace('/^'.preg_quote($srcprefix, '/').'/i',
169            $dstprefix, $textblock['name']);
170
171        textblock_copy($textblock, $new_name, $user_id, $remote_ip_info);
172    }
173}
174
175// Does template replacing in a textblock.
176// Replaces all occurences of %key% with value, for all key, value pairs
177// in the $replace array.
178//
179// You should mainly use this horrible painful hack on templates.
180//
181// MODIFIES $textblock
182//
183// FIXME: optimize.
184function textblock_template_replace(&$textblock, $replace)
185{
186    foreach ($replace as $key => $value) {
187        $textblock['title'] = str_replace("%$key%", $value, $textblock['title']);
188        $textblock['text'] = str_replace("%$key%", $value, $textblock['text']);
189    }
190}
191
192// Checks if the textblock is task and returns the task_id if true or false if false
193function textblock_security_is_task($textblock) {
194    if (preg_match("/^ \s* task: \s* (".IA_RE_TASK_ID.") \s* $/xi", $textblock, $matches)) {
195        return $matches[1];
196    }
197    return false;
198}
199
200// Checks if the textblock is round and returns the round_id if true or false if false
201function textblock_security_is_round($textblock) {
202    if (preg_match("/^ \s* round: \s* (".IA_RE_ROUND_ID.") \s* $/xi", $textblock, $matches)) {
203        return $matches[1];
204    }
205    return false;
206}
207
208
209?>
Note: See TracBrowser for help on using the repository browser.