Completed
Pull Request — master (#2472)
by Kevin
23:34 queued 05:01
created

html/inc/user.inc::delete_account()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 1
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2008 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
require_once("../inc/credit.inc");
20
require_once("../inc/email.inc");
21
require_once("../inc/util.inc");
22
require_once("../inc/team.inc");
23
require_once("../inc/friend.inc");
24
require_once("../inc/forum_db.inc");
25
require_once("../inc/notify.inc");
26
require_once("../inc/ldap.inc");
27
28
if (!defined('REMOTE_PROJECTS_TTL')) {
29
    define('REMOTE_PROJECTS_TTL', 86400);
30
}
31
32
// add an element "projects" to user consisting of array of projects
33
// they've participated in
34
//
35
function get_other_projects($user) {
36
    $cpid = md5($user->cross_project_id . $user->email_addr);
37
    $url = "http://boinc.netsoft-online.com/get_user.php?cpid=".$cpid;
38
39
    // Check the cache for that URL
40
    //
41
    $cacheddata = get_cached_data(REMOTE_PROJECTS_TTL, $url);
42
    if ($cacheddata) {
43
        $remote = unserialize($cacheddata);
44
    } else {
45
        // Fetch the XML, use curl if fopen() is disallowed
46
        //
47
        if (ini_get('allow_url_fopen')) {
48
            $timeout = 3;
49
            $old_timeout = ini_set('default_socket_timeout', $timeout);
50
            $xml_object = null;
51
            $f = @file_get_contents($url);
52
            if ($f) {
53
                $xml_object = @simplexml_load_string($f);
54
            }
55
            ini_set('default_socket_timeout', $old_timeout);
56
            if (!$xml_object) {
57
                return $user;
58
            }
59
        } else {
60
            $ch = curl_init($url);
61
            curl_setopt($ch, CURLOPT_HEADER, false);
62
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
63
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
64
            curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
65
            curl_setopt($ch, CURLOPT_TIMEOUT, 3);
66
            $rawxml = @curl_exec($ch);
67
            $xml_object = null;
68
            if ($rawxml) {
69
                $xml_object = @simplexml_load_string($rawxml);
70
            }
71
            curl_close($ch);
72
            if (!xml_object) {
73
                return $user;
74
            }
75
        }
76
77
        // auto-cast the project list to an array of stdClass projects
78
        //
79
        $remote = @json_decode(json_encode((array)$xml_object))->project;
80
        if (count($remote) == 1) {
81
            $remote = array($remote);
82
        }
83
        
84
        if (!$remote) {
85
            return $user;
86
        } else {
87
            // Cache the results
88
            set_cached_data(REMOTE_PROJECTS_TTL, serialize($remote), $url);
89
        }
90
    }
91
    
92
    $user->projects = $remote;
93
    return $user;
94
}
95
96
function show_project($project) {
97
    if ($project->url == "http://www.worldcommunitygrid.org/") {
98
        $x = $project->name;
99
    } else {
100
        $x = "<a href=\"$project->url"."show_user.php?userid=$project->id\">$project->name</a>";
101
    }
102
    echo "<tr>
103
        <td>$x</td>
104
        <td align=\"right\">".number_format($project->total_credit, 0)."</td>
105
        <td align=\"right\">".number_format($project->expavg_credit, 0)."</td>
106
        <td align=\"right\">".date_str($project->create_time)."</td>
107
        </tr>
108
    ";
109
}
110
111
function cmp($a, $b) {
112
    if ($a->expavg_credit == $b->expavg_credit) return 0;
113
    return ($a->expavg_credit < $b->expavg_credit) ? 1 : -1;
114
}
115
116
function show_other_projects($user, $personal) {
117
    if (!isset($user->projects)) return;
118
    if (count($user->projects) < 2) return;
119
120
    usort($user->projects, "cmp");
121
    if ($personal) {
122
        echo "<h3>".tra("Projects in which you are participating")."</h3>";
123
    } else {
124
        echo "<h3>".tra("Projects in which %1 is participating", $user->name)."</h3>";
125
    }
126
    start_table('table-striped');
127
    row_heading_array(
128
        array(
129
            tra("Project")."<br/><small>".tra("Click for user page")."</small>",
130
            tra("Total credit"),
131
            tra("Average credit"),
132
            tra("Since")
133
        ),
134
        array("", ALIGN_RIGHT, ALIGN_RIGHT, ALIGN_RIGHT)
135
    );
136
    foreach ($user->projects as $project) {
137
        show_project($project);
138
    }
139
    end_table();
140
}
141
142
function total_posts($user) {
143
    return BoincPost::count("user=$user->id");
144
}
145
146
function show_credit($user) {
147
    row2(tra("Total credit"), format_credit_large($user->total_credit));
148
    row2(tra("Recent average credit"), format_credit($user->expavg_credit));
149
    if (function_exists("project_user_credit")) {
150
        project_user_credit($user);
151
    }
152
}
153
154
require_once("../inc/stats_sites.inc");
155
// show dynamic user info (private)
156
//
157
function show_user_stats_private($user) {
158
    global $cpid_stats_sites;
159
160
    if (NO_COMPUTING && NO_STATS && NO_HOSTS) {
161
        return;
162
    }
163
    row1(tra("Computing"));
164
165
    if (!NO_STATS) {
166
        show_credit($user);
167
    }
168
169
    if (!NO_HOSTS) {
170
        row2(tra("Computers on this account"), "<a href=\"hosts_user.php\">".tra("View")."</a>");
171
    }
172
    if (!NO_COMPUTING) {
173
        row2(tra("Tasks"), "<a href=\"results.php?userid=$user->id\">".tra("View")."</a>");
174
    }
175
176
    if (!NO_STATS) {
177
        $cpid = md5($user->cross_project_id . $user->email_addr);
178
        $x = "";
179
        shuffle($cpid_stats_sites);
180
        foreach ($cpid_stats_sites as $site) {
181
            $name = $site[0];
182
            $y = sprintf($site[1], $cpid);
183
            $x .= "<a href=\"$y\">$name</a><br/>\n";
184
        }
185
        $x .= "<br/><small>".tra("Cross-project ID").": $cpid</small>\n";
186
        row2(tra("Cross-project statistics"), $x);
187
        $x = '<a href="cert1.php">'.tra("Account").'</a>';
188
        if ($user->teamid) {
189
            $x .= ' &middot; <a href="cert_team.php">'.tra("Team").'</a>';
190
        }
191
        $x .= ' &middot; <a href="cert_all.php">'.tra("Cross-project").'</a>';
192
        row2(tra("Certificate"), $x);
193
        row2(tra("Stats on your cell phone"), url_base()."userw.php?id=$user->id");
194
    }
195
}
196
197
function notify_description($notify) {
198
    switch ($notify->type) {
199
    case NOTIFY_FRIEND_REQ:
200
        return friend_notify_req_web_line($notify);
201
    case NOTIFY_FRIEND_ACCEPT:
202
        return friend_notify_accept_web_line($notify);
203
    case NOTIFY_PM:
204
        return pm_web_line($notify);
205
    case NOTIFY_SUBSCRIBED_POST:
206
        return subscribed_post_web_line($notify);
207
    }
208
    return null;
209
}
210
211
function weak_auth($user) {
212
    $x = md5($user->authenticator.$user->passwd_hash);
213
    return "{$user->id}_$x";
214
}
215
216
// originally user URLs were assumed to be http://,
217
// and this prefix wasn't stored.
218
// Now the prefix can be http:// or https://.
219
// This function takes a user URL in any form and converts
220
// it to a canonical form, with the protocol prefix.
221
//
222
function normalize_user_url($url) {
223
    $x = strtolower($url);
224
    if (substr($x, 0, 7) == 'http://') {
225
        return 'http://'.substr($url, 7);
226
    }
227
    if (substr($x, 0, 8) == 'https://') {
228
        return 'https://'.substr($url, 8);
229
    }
230
    return 'http://'.$url;
231
}
232
233
// show static user info (private)
234
//
235
function show_user_info_private($user) {
236
    row2(tra("Name"), $user->name);
237
    if (LDAP_HOST && is_ldap_email($user->email_addr)) {
238
        row2("LDAP ID", ldap_email_to_uid($user->email_addr));
239
    } else {
240
        $email_text = $user->email_addr;
241
        if (defined("SHOW_NONVALIDATED_EMAIL_ADDR") && !$user->email_validated) {
242
            $email_text .= " (<a href=validate_email_addr.php>must be validated</a>)";
243
        }
244
        row2(tra("Email address"), $email_text);
245
    }
246 View Code Duplication
    if (strlen($user->url)) {
247
        $u = normalize_user_url($user->url);
248
        row2(tra("URL"), sprintf('<a href="%s">%s</a>', $u, $u));
249
    }
250
    row2(tra("Country"), $user->country);
251
    if (POSTAL_CODE) {
252
        row2(tra("Postal code"), $user->postal_code);
253
    }
254
    row2(tra("%1 member since", PROJECT), date_str($user->create_time));
255
    $url_tokens = url_tokens($user->authenticator);
256
    if (LDAP_HOST && is_ldap_email($user->email_addr)) {
257
        // LDAP accounts can't change email or password
258
        //
259
        row2(tra("Change"),
260
            "<a href=\"edit_user_info_form.php?$url_tokens\">Account info</a>"
261
        );
262
    } else {
263
        $delete_account_str = "";
264
        $config = get_config();
265
        if (parse_bool($config, "enable_delete_account")) {
266
            $delete_account_str = " &middot; <a href=\"delete_account_request.php\">".tra("delete account")."</a>";
267
        }
268
        
269
        row2(tra("Change"),
270
            "<a href=\"edit_email_form.php\">".tra("email address")."</a>
271
            &middot; <a href=\"".secure_url_base()."/edit_passwd_form.php\">".tra("password")."</a>
272
            &middot; <a href=\"edit_user_info_form.php?$url_tokens\">".tra("other account info")."</a>"
273
            .$delete_account_str
274
        );
275
    }
276
    row2(tra("User ID")."<br/><p class=\"small\">".tra("Used in community functions")."</p>", $user->id);
277
    if (!NO_COMPUTING) {
278
        row2(
279
            tra("Account keys"),
280
            "<a href=\"weak_auth.php\">".tra("View")."</a>"
281
        );
282
    }
283
}
284
285
function show_preference_links() {
286
    row1("<a name=\"prefs\"></a>".tra("Preferences"));
287
    if (!NO_GLOBAL_PREFS) {
288
        row2(
289
            tra("When and how BOINC uses your computer"),
290
            "<a href=\"prefs.php?subset=global\">".tra("Computing preferences")."</a>"
291
        );
292
    }
293
    row2(tra("Message boards and private messages"),
294
        "<a href=\"edit_forum_preferences_form.php\">".tra("Community preferences")."</a>"
295
    );
296
    if (!NO_COMPUTING) {
297
        row2(tra("Preferences for this project"),
298
            "<a href=\"prefs.php?subset=project\">".tra("%1 preferences", PROJECT)."</a>"
299
        );
300
    }
301
}
302
303
function friend_links($user) {
304
    if (is_banished($user)) {
305
        return "";
306
    }
307
    $x = "<table height=\"100\" width=\"150\" border=\"0\" cellpadding=\"4\"><tr><td class=\"friend\">";
308
    if ($user->has_profile) {
309
        $profile = BoincProfile::lookup_fields("has_picture", "userid=$user->id");
310
        if ($profile && $profile->has_picture) {
311
            $img_url = profile_thumb_url($user->id);
312
        } else {
313
            $img_url = url_base()."img/head_20.png";
314
        }
315
        $title = tra("View the profile of %1", $user->name);
316
        $alt = tra("Profile");
317
        $x .= ' <a href="'.url_base().'view_profile.php?userid='.$user->id.'"><img title="'.$title.'" src="'.$img_url.'" alt="'.$alt.'"></a><br>';
318
    }
319
    $x .= " <a href=\"".url_base()."show_user.php?userid=".$user->id."\">".$user->name."</a>";
320
    if (function_exists("project_user_links")) {
321
        $x .= project_user_links($user);
322
    }
323
    $x .= "</td></tr></table>\n";
324
    return $x;
325
}
326
327
// show user name, with links to profile if present.
328
// if $badge_height is > 0, show badges
329
//
330
function user_links($user, $badge_height=0) {
331
    BoincForumPrefs::lookup($user);
332
    if (is_banished($user)) {
333
        return "(banished: ID $user->id)";
334
    }
335
    $x = "";
336
    if ($user->has_profile) {
337
        $img_url = url_base()."img/head_20.png";
338
        $x .= ' <a href="'.url_base().'view_profile.php?userid='.$user->id.'"><img title="View the profile of '.$user->name.'" src="'.$img_url.'" alt="Profile"></a>';
339
    }
340
    $x .= " <a href=\"".url_base()."show_user.php?userid=".$user->id."\">".$user->name."</a>";
341
    if (function_exists("project_user_links")){
342
        $x .= project_user_links($user);
343
    }
344
    if ($badge_height) {
345
        $x .= badges_string(true, $user, $badge_height);
346
    }
347
    return $x;
348
}
349
350
function show_community_private($user) {
351
    show_badges_row(true, $user);
352
    if (!DISABLE_PROFILES) {
353
        if ($user->has_profile) {
354
            $x = "<a href=\"view_profile.php?userid=$user->id\">".tra("View")."</a> &middot; <a href=\"delete_profile.php\">".tra("Delete")."</a>";
355
        } else {
356
            $x = "<a href=\"create_profile.php\">".tra("Create")."</a>";
357
        }
358
        row2(tra("Profile"), $x);
359
    }
360 View Code Duplication
    if (!DISABLE_FORUMS) {
361
        $tot = total_posts($user);
362
        if ($tot) {
363
            row2(tra("Message boards"), "<a href=\"".url_base()."forum_user_posts.php?userid=$user->id\">".tra("%1 posts", $tot)."</a>");
364
        }
365
    }
366
    
367
    row2(tra("Private messages"), pm_notification($user).pm_email_remind($user));
368
369
    $notifies = BoincNotify::enum("userid=$user->id");
370
    if (count($notifies)) {
371
        $x = "";
372
        foreach ($notifies as $notify) {
373
            $y = notify_description($notify);
374
            if ($y) {
375
                $x .= "&bull; $y<br>";
376
            } else {
377
                $notify->delete();
378
            }
379
        }
380
        $x .= "<a href=\"".notify_rss_url($user)."\"><img vspace=\"4\" border=\"0\" src=\"img/rss_icon.gif\" alt=\"RSS\" /></a>";
381
        row2(tra("Notifications"), $x);
382
    }
383
384
    if (!DISABLE_TEAMS) {
385
        if ($user->teamid && ($team = BoincTeam::lookup_id($user->teamid))) {
386
            $x = "<a href=\"team_display.php?teamid=$team->id\">$team->name</a>
387
                &middot; <a href=\"team_quit_form.php\">".tra("Quit team")."</a>";
388
            if (is_team_admin($user, $team)) {
389
                $x .= " &middot; <a href=\"team_manage.php?teamid=$user->teamid\">".tra("Administer")."</a>";
390
            }
391
392
            // if there's a foundership request, notify the founder
393
            //
394
            if ($user->id==$team->userid && $team->ping_user >0) {
395
                $x .= "<p class=\"text-danger\">".tra("(foundership change request pending)")."</p>";
396
            }
397
            row2(tra("Member of team"), $x);
398 View Code Duplication
        } else {
399
            row2(tra("Team"), tra("None")." &middot; <a href=\"team_search.php\">".tra("find a team")."</a>");
400
        }
401
        
402
        $teams_founded = BoincTeam::enum("userid=$user->id");
403
        foreach ($teams_founded as $team) {
404
            if ($team->id != $user->teamid) {
405
                $x = "<a href=\"team_display.php?teamid=$team->id\">$team->name</a>";
406
                $x .= " | <a href=\"team_manage.php?teamid=".$team->id."\">".tra("Administer")."</a>";
407
                if ($team->ping_user > 0) {
408
                    $x .= "<p class=\"text-danger\">".tra("(foundership change request pending)")."</span>";
409
                }
410
                row2(tra("Founder but not member of"), $x);
411
            }
412
        }
413
    }
414
415
    $friends = BoincFriend::enum("user_src=$user->id and reciprocated=1");
416
    $x = "<a href=\"user_search.php\">".tra("Find friends")."</a><br/>\n";
417
    $n = count($friends);
418
    if ($n) {
419 View Code Duplication
        foreach($friends as $friend) {
420
            $fuser = BoincUser::lookup_id($friend->user_dest);
421
            if (!$fuser) continue;
422
            $x .= friend_links($fuser);
423
        }
424
        row2(tra("Friends")." ($n)", $x);
425
    } else {
426
        row2(tra("Friends"), $x);
427
    }
428
}
429
430
// show summary of dynamic and static info (public)
431
//
432
function show_user_summary_public($user) {
433
    global $g_logged_in_user;
434
    row2(tra("User ID"), $user->id);
435
    row2(tra("%1 member since", PROJECT), date_str($user->create_time));
436
    row2(tra("Country"), $user->country);
437
    // don't show URL if user has no recent credit (spam suppression)
438
    //
439 View Code Duplication
    if (strlen($user->url)) {
440
        if (!NO_COMPUTING || $user->expavg_credit > 1) {
441
            $u = normalize_user_url($user->url);
442
            row2(tra("URL"), sprintf('<a href="%s">%s</a>', $u, $u));
443
        }
444
    }
445
    if (!NO_COMPUTING) {
446
        show_credit($user);
447
448
        if ($user->show_hosts) {
449
            row2(tra("Computers"), "<a href=\"".url_base()."hosts_user.php?userid=$user->id\">".tra("View")."</a>");
450
        } else {
451
            row2(tra("Computers"), tra("hidden"));
452
        }
453
    }
454
    if (function_exists("project_user_summary_public")) {
455
        project_user_summary_public($user);
456
    }
457
}
458
459
// Returns a cacheable community links data object
460
// @param user The user to produce a community links object for
461
462
function get_community_links_object($user){
463
    $cache_object = new StdClass;
464
    $cache_object->post_count = total_posts($user);
465
    $cache_object->user = $user;
466
    $cache_object->team = BoincTeam::lookup_id($user->teamid);
467
    $cache_object->friends = array();
468
469
    $friends = BoincFriend::enum("user_src=$user->id and reciprocated=1");
470 View Code Duplication
    foreach($friends as $friend) {
471
        $fuser = BoincUser::lookup_id($friend->user_dest);
472
        if (!$fuser) continue;
473
        $cache_object->friends[] = $fuser;
474
    }
475
    return $cache_object;
476
}
477
478
function community_links($clo, $logged_in_user){
479
    $user = $clo->user;
480
    $team = $clo->team;
481
    $friends = $clo->friends;
482
    $tot = $clo->post_count;
483
    
484
    if (!DISABLE_TEAMS) {
485
        if ($user->teamid && $team) {
486
            row2(tra("Team"), "<a href=\"".url_base()."team_display.php?teamid=$team->id\">$team->name</a>");
487
        } else {
488
            row2(tra("Team"), tra("None"));
489
        }
490
    }
491 View Code Duplication
    if (!DISABLE_FORUMS) {
492
        if ($tot) {
493
            row2(tra("Message boards"), "<a href=\"".url_base()."forum_user_posts.php?userid=$user->id\">".tra("%1 posts", $tot)."</a>");
494
        }
495
    }
496
    if ($logged_in_user && $logged_in_user->id != $user->id) {
497
        row2(tra("Contact"), "<a href=\"pm.php?action=new&userid=".$user->id."\">".tra("Send private message")."</a>");
498
        $friend = BoincFriend::lookup($logged_in_user->id, $user->id);
499
        if ($friend && $friend->reciprocated) {
500
            row2(tra("This person is a friend"), 
501
                "<a href=\"friend.php?action=cancel_confirm&userid=$user->id\">".tra("Cancel friendship")."</a>"
502
            );
503
        } else if ($friend) {
504
            row2(tra("Friends"),  "<a href=\"friend.php?action=add&userid=$user->id\">".tra("Request pending")."</a>");
505
        } else {
506
            row2(tra("Friends"),  "<a href=\"friend.php?action=add&userid=$user->id\">".tra("Add as friend")."</a>");
507
        }
508
    }
509
    
510
    if ($friends) {
511
        $x = "";
512
        foreach($friends as $friend) {
513
            $x .= friend_links($friend);
514
        }
515
        row2(tra("Friends")." (".sizeof($friends).")", $x);
516
    }
517
}
518
519
function show_profile_link($user) {
520
    if ($user->has_profile) {
521
        row2(tra("Profile"), "<a href=\"view_profile.php?userid=$user->id\">".tra("View")."</a>");
522
    }
523
}
524
525
function show_account_private($user) {
526
    grid(
527
        false,
528
        function() use ($user) {
529
            start_table();
530
            row1(tra("Account information"), 2, 'heading');
531
            show_user_info_private($user);
532
            show_preference_links();
533
            show_user_stats_private($user);
534
535
            if (function_exists('show_user_donations_private')) {
536
                show_user_donations_private($user);
537
            }
538
            end_table();
539
            if (!NO_COMPUTING) {
540
                show_other_projects($user, true);
541
            }
542
            if (function_exists("project_user_page_private")) {
543
                project_user_page_private($user);
544
            }
545
        },
546
        function() use ($user) {
547
            start_table();
548
            row1(tra("Community"));
549
            show_community_private($user);
550
            end_table();
551
        }
552
    );
553
}
554
555
556
$cvs_version_tracker[]="\$Id$";  //Generated automatically - do not edit
557
558
?>
559