Issues (1963)

html/user/create_profile.php (13 issues)

1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2021 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19
// TODO: the following is organized in a funky way.  Clean it up
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
20
21
require_once("../inc/util.inc");
22
require_once("../inc/profile.inc");
23
require_once("../inc/akismet.inc");
24
require_once("../inc/recaptchalib.inc");
25
26
if (DISABLE_PROFILES) error_page("Profiles are disabled");
27
28
check_get_args(array());
29
30
// output a select form item with the given name,
31
// from a list of newline-delineated items from the text file.
32
// If $selection is provided, and if it matches one of the entries in the file,
33
// it will be selected by default.
34
//
35
function show_combo_box($name, $filename, $selection=null) {
36
    echo "<select name=\"$name\" class=\"form-control\">\n";
37
38
    $file = fopen($filename, "r");
39
40
    while ($line = trim(fgets($file, 1024))) {
41
        if ($line == $selection) {
42
            echo "<option SELECTED value=\"$line\">$line\n";
43
        } else {
44
            echo "<option value=\"$line\">$line\n";
45
        }
46
    }
47
48
    echo "</select>\n";
49
    fclose($file);
50
}
51
52
53
function show_picture_option($profile) {
54
    row1(tra("Picture"));
55
56
    $warning = "";
57
    if (profile_screening() && $profile && $profile->has_picture) {
58
        $warning = offensive_profile_warning($profile->verification);
59
    }
60
61
    if ($profile && ($profile->has_picture)) {
62
        echo "
63
<tr><td colspan=2>
64
<table border=0 cellpadding=5
65
<tr>
66
<td valign=top><a href=\"" . IMAGE_URL . $profile->userid . '.jpg' . "\"><img src=\"" . IMAGE_URL . $profile->userid . '_sm.jpg' . "\"></a>
67
</td>
68
<td valign=top>" .tra("%1 Your profile picture is shown to the left.",  $warning) ."
69
<p>".
70
tra("To replace it, click the \"Browse\" button and select a JPEG or PNG file (%1 or less).", "50KB") ."<br />
71
<input name=picture type=file><br>
72
<p>".
73
tra("To remove it from your profile, check this box:") . "
74
<input type=checkbox name=delete_pic>
75
<p>
76
</td></tr>";
77
        rowify("<br>");
78
        end_table();
79
        echo "</td></tr>";
80
    } else {
81
        rowify(tra("If you would like include a picture with your profile, click the \"Browse\" button and select a JPEG or PNG file. Please select images of %1 or less.", "50KB") . "
82
<p>
83
<input name=picture type=file>
84
        ");
85
        rowify("<br>");
86
    }
87
}
88
89
function show_language_selection($profile) {
90
    if (!file_exists(LANGUAGE_FILE)) {
91
        return;
92
    }
93
    row1(tra("Language"));
94
    echo "<tr><td>
95
        <p>" .
96
        tra("Select the language in which your profile is written:") . "
97
        <p>
98
    ";
99
    if (isset($profile->language)) {
100
        show_combo_box("language", LANGUAGE_FILE, $profile->language);
101
    } else {
102
        show_combo_box("language", LANGUAGE_FILE, "English");
103
    }
104
    echo "</td></tr>\n";
105
}
106
107
function show_submit() {
108
    row1(tra("Submit profile"));
109
    if (recaptcha_public_key()) {
110
        table_row(boinc_recaptcha_get_html(recaptcha_public_key()));
111
    }
112
    table_row("<p><input class=\"btn btn-success\" type=\"submit\" value=\"".tra("Create/edit profile") ."\" name=\"submit\">");
113
}
114
115
// Returns an array containing:
116
// [0]: The original image refered to by $fileName if its dimensions are
117
//    less than MAX_IMG_WIDTH x MAX_IMG_HEIGHT, or a version scaled to
118
//    those dimensions if it was too large.
119
// [1]: A scaled version of the above.
120
121
function getImages($fileName) {
122
    $size = getImageSize($fileName);
0 ignored issues
show
Calls to inbuilt PHP functions must be lowercase; expected "getimagesize" but found "getImageSize"
Loading history...
123
124
    // Determine if the filetype uploaded is supported.
125
    // TODO: Change these to constants.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
126
    switch($size[2]) {
127
    case '2':    // JPEG
128
        $image = imageCreateFromJPEG($fileName);
0 ignored issues
show
Calls to inbuilt PHP functions must be lowercase; expected "imagecreatefromjpeg" but found "imageCreateFromJPEG"
Loading history...
129
        break;
130
    case '3':    // PNG
131
        $image = imageCreateFromPNG($fileName);
0 ignored issues
show
Calls to inbuilt PHP functions must be lowercase; expected "imagecreatefrompng" but found "imageCreateFromPNG"
Loading history...
132
        break;
133
    default:
0 ignored issues
show
DEFAULT keyword must be indented 4 spaces from SWITCH keyword
Loading history...
DEFAULT case must have a breaking statement
Loading history...
134
        error_page(tra("The format of your uploaded image is not supported."));
135
    }
136
137
    $width = $size[0];
138
    $height = $size[1];
139
140
    $smallImage = scale_image($image, $width, $height, SMALL_IMG_WIDTH, SMALL_IMG_HEIGHT);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $image does not seem to be defined for all execution paths leading up to this point.
Loading history...
141
142
    if ($width > MAX_IMG_WIDTH || $height > MAX_IMG_HEIGHT) {
143
        $image = scale_image($image, $width, $height, MAX_IMG_WIDTH, MAX_IMG_HEIGHT);
144
    }
145
146
    /*
147
    echo "<br><br>Image type: $size[2]";
148
    echo "<br>Original width: $width";
149
    echo "<br>Original height: $height";
150
    echo "<br>Scalar: $scalar";
151
    echo "<br>Dest width: " . ($width / $scalar);
152
    echo "<br>Dest height: " . ($height / $scalar);
153
    echo "<br>Horizontal offset: $horiz_offset";
154
    echo "<br>Vertical offset: $vert_offset";
155
    echo "<br><br><a href=\"images/user_profile/test.jpg\">View result</a>";
156
    */
157
158
    return array($image, $smallImage);
159
}
160
161
function show_description() {
162
    echo "
163
        <p>" .tra("Your %1 profile %2 lets you share your opinions and background with the %3 community.", "<b>", "</b>", PROJECT) . "
164
        <p>
165
    ";
166
}
167
168
function show_questions($profile) {
169
    $response1 = "";
170
    $response2 = "";
171
    if (isset($profile->response1)) {
172
        $response1 = $profile->response1;
173
    }
174
    if (isset($profile->response2)) {
175
        $response2 = $profile->response2;
176
    }
177
178
    row1(show_profile_heading1());
179
    rowify(show_profile_question1().bbcode_info());
180
    show_textarea("response1", $response1);
181
    row1( show_profile_heading2());
182
    rowify( show_profile_question2().bbcode_info());
183
    show_textarea("response2", $response2);
184
    show_language_selection($profile);
185
}
186
187
function show_textarea($name, $text) {
188
    rowify("<textarea name=\"$name\" class=\"form-control\" rows=\"10\">" . $text . "</textarea>");
189
}
190
191
// $profile is null if user doesn't already have a profile.
192
// Don't assign to $profile->x if this is the case.
193
//
194
function process_create_profile($user, $profile) {
195
    $response1 = post_str('response1', true);
196
    $response2 = post_str('response2', true);
197
    $language = post_str('language', true);
198
199
    if (recaptcha_private_key()) {
200
        if (!boinc_recaptcha_isValidated(recaptcha_private_key())) {
201
            $profile->response1 = $response1;
202
            $profile->response2 = $response2;
203
            show_profile_form($profile,
204
                tra("Your ReCaptcha response was not correct.  Please try again.")
205
            );
206
            return;
207
        }
208
    }
209
    if (!akismet_check($user, $response1)) {
210
        $profile->response1 = $response1;
211
        $profile->response2 = $response2;
212
        show_profile_form($profile,
213
            tra("Your first response was flagged as spam by the Akismet anti-spam system.  Please modify your text and try again.")
214
        );
215
        return;
216
    }
217
    if (!akismet_check($user, $response2)) {
218
        $profile->response1 = $response1;
219
        $profile->response2 = $response2;
220
        show_profile_form($profile,
221
            tra("Your second response was flagged as spam by the Akismet anti-spam system.  Please modify your text and try again.")
222
        );
223
        return;
224
    }
225
226
    if (isset($_POST['delete_pic'])) {
227
        $delete_pic = $_POST['delete_pic'];
228
    } else {
229
        $delete_pic = "off";
230
    }
231
232
    if (strlen($response1)==0 &&
233
        strlen($response2)==0 &&
234
        $delete_pic != "on" &&
235
        !is_uploaded_file($_FILES['picture']['tmp_name'])
236
    ) {
237
        error_page(tra("Your profile submission was empty."));
238
        exit();
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
239
    }
240
241
    if ($delete_pic == "on") {
242
        delete_user_pictures($profile->userid);
243
        $profile->has_picture = false;
244
        $profile->verification = 0;
245
    }
246
247
    $profile ? $has_picture = $profile->has_picture: $has_picture = false;
248
249
    if (is_uploaded_file($_FILES['picture']['tmp_name'])) {
250
        $has_picture = true;
251
        if ($profile) $profile->verification = 0;
252
253
        // echo "<br>Name: " . $_FILES['picture']['name'];
254
        // echo "<br>Type: " . $_FILES['picture']['type'];
255
        // echo "<br>Size: " . $_FILES['picture']['size'];
256
        // echo "<br>Temp name: " . $_FILES['picture']['tmp_name'];
257
258
        $images = getImages($_FILES['picture']['tmp_name']);
259
260
        // Write the original image file to disk.
261
        // TODO: define a constant for image quality.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
262
        ImageJPEG($images[0], IMAGE_PATH . $user->id . '.jpg');
0 ignored issues
show
Calls to inbuilt PHP functions must be lowercase; expected "imagejpeg" but found "ImageJPEG"
Loading history...
263
        ImageJPEG($images[1], IMAGE_PATH . $user->id . '_sm.jpg');
0 ignored issues
show
Calls to inbuilt PHP functions must be lowercase; expected "imagejpeg" but found "ImageJPEG"
Loading history...
264
    }
265
    $response1 = sanitize_html($response1);
266
    $response2 = sanitize_html($response2);
267
268
    $has_picture = $has_picture?1:0;
269
    if ($profile) {
270
        $query = " response1 = '".BoincDb::escape_string($response1)."',"
271
            ." response2 = '".BoincDb::escape_string($response2)."',"
272
            ." language = '".BoincDb::escape_string($language)."',"
273
            ." has_picture = $has_picture,"
274
            ." verification = $profile->verification"
275
            ." WHERE userid = $user->id";
276
        $result = BoincProfile::update_aux($query);
277
        if (!$result) {
278
            error_page(tra("Could not update the profile: database error"));
279
        }
280
    } else {
281
        $query = 'SET '
282
            ." userid=$user->id,"
283
            ." language = '".BoincDb::escape_string($language)."',"
284
            ." response1 = '".BoincDb::escape_string($response1)."',"
285
            ." response2 = '".BoincDb::escape_string($response2)."',"
286
            ." has_picture = $has_picture,"
287
            ." recommend=0, "
288
            ." reject=0, "
289
            ." posts=0, "
290
            ." uotd_time=0, "
291
            ." verification=0";
292
        $result = BoincProfile::insert($query);
293
        if (!$result) {
294
            error_page(tra("Could not create the profile: database error"));
295
        }
296
    }
297
    $user->update("has_profile=1");
298
299
    page_head(tra("Profile saved"));
300
301
    echo tra("Congratulations! Your profile was successfully entered into our database.")
302
        ."<br><br>"
303
        ."<a href=\"view_profile.php?userid=".$user->id."\">"
304
        .tra("View your profile")
305
        ."</a><br>"
306
    ;
0 ignored issues
show
Space found before semicolon; expected ""</a><br>";" but found ""</a><br>"
;"
Loading history...
307
    page_tail();
308
}
309
310
function show_profile_form($profile, $warning=null) {
311
    if ($profile) {
312
        page_head(tra("Edit your profile"), null, null, null, boinc_recaptcha_get_head_extra());
313
    } else {
314
        page_head(tra("Create a profile"), null, null, null, boinc_recaptcha_get_head_extra());
315
    }
316
317
    if ($warning) {
318
        echo "<p class=\"text-danger\">$warning</p>
319
        ";
320
    }
321
322
    echo "
323
        <form action=", $_SERVER['PHP_SELF'], " method=\"POST\", ENCTYPE=\"multipart/form-data\">
324
    ";
325
    start_table();
326
    show_description();
327
    show_questions($profile);
328
    show_picture_option($profile);
329
    show_submit();
330
    end_table();
331
    echo "</form>";
332
    page_tail();
333
334
}
335
336
$user = get_logged_in_user(true);
337
if (VALIDATE_EMAIL_TO_POST) {
338
    check_validated_email($user);
339
}
340
341
$profile = get_profile($user->id);
342
$config = get_config();
343
$min_credit = parse_config($config, "<profile_min_credit>");
344
if ($min_credit && $user->expavg_credit < $min_credit) {
345
    error_page(
346
        tra("To prevent spam, an average credit of %1 or greater is required to create or edit a profile.  We apologize for this inconvenience.", $min_credit)
347
    );
348
}
349
350
if (post_str("submit", true)) {
351
    process_create_profile($user, $profile);
352
    clear_cache_entry("view_profile.php", "userid=$user->id");
353
    exit;
354
}
355
356
show_profile_form($profile);
357
358
?>
359