PageRenderTime 381ms CodeModel.GetById 181ms app.highlight 155ms RepoModel.GetById 26ms app.codeStats 1ms

/htdocs/wp-includes/ms-functions.php

https://bitbucket.org/dkrzos/phc
PHP | 2016 lines | 976 code | 283 blank | 757 comment | 275 complexity | 4dc74655275eebcc56bafa4287701cf4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * Multisite WordPress API
   4 *
   5 * @package WordPress
   6 * @subpackage Multisite
   7 * @since 3.0.0
   8 */
   9
  10/**
  11 * Gets the network's site and user counts.
  12 *
  13 * @since MU 1.0
  14 * @uses get_blog_count()
  15 * @uses get_user_count()
  16 *
  17 * @return array Site and user count for the network.
  18 */
  19function get_sitestats() {
  20	global $wpdb;
  21
  22	$stats = array(
  23		'blogs' => get_blog_count(),
  24		'users' => get_user_count(),
  25	);
  26
  27	return $stats;
  28}
  29
  30/**
  31 * Get the admin for a domain/path combination.
  32 *
  33 * @since MU 1.0
  34 *
  35 * @param string $sitedomain Optional. Site domain.
  36 * @param string $path Optional. Site path.
  37 * @return array The network admins
  38 */
  39function get_admin_users_for_domain( $sitedomain = '', $path = '' ) {
  40	global $wpdb;
  41
  42	if ( ! $sitedomain )
  43		$site_id = $wpdb->siteid;
  44	else
  45		$site_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->site WHERE domain = %s AND path = %s", $sitedomain, $path ) );
  46
  47	if ( $site_id )
  48		return $wpdb->get_results( $wpdb->prepare( "SELECT u.ID, u.user_login, u.user_pass FROM $wpdb->users AS u, $wpdb->sitemeta AS sm WHERE sm.meta_key = 'admin_user_id' AND u.ID = sm.meta_value AND sm.site_id = %d", $site_id ), ARRAY_A );
  49
  50	return false;
  51}
  52
  53/**
  54 * Get one of a user's active blogs
  55 *
  56 * Returns the user's primary blog, if she has one and
  57 * it is active. If it's inactive, function returns another
  58 * active blog of the user. If none are found, the user
  59 * is added as a Subscriber to the Dashboard Blog and that blog
  60 * is returned.
  61 *
  62 * @since MU 1.0
  63 * @uses get_blogs_of_user()
  64 * @uses add_user_to_blog()
  65 * @uses get_blog_details()
  66 *
  67 * @param int $user_id The unique ID of the user
  68 * @return object The blog object
  69 */
  70function get_active_blog_for_user( $user_id ) {
  71	global $wpdb;
  72	$blogs = get_blogs_of_user( $user_id );
  73	if ( empty( $blogs ) )
  74		return null;
  75
  76	if ( !is_multisite() )
  77		return $blogs[$wpdb->blogid];
  78
  79	$primary_blog = get_user_meta( $user_id, 'primary_blog', true );
  80	$first_blog = current($blogs);
  81	if ( false !== $primary_blog ) {
  82		if ( ! isset( $blogs[ $primary_blog ] ) ) {
  83			update_user_meta( $user_id, 'primary_blog', $first_blog->userblog_id );
  84			$primary = get_blog_details( $first_blog->userblog_id );
  85		} else {
  86			$primary = get_blog_details( $primary_blog );
  87		}
  88	} else {
  89		//TODO Review this call to add_user_to_blog too - to get here the user must have a role on this blog?
  90		add_user_to_blog( $first_blog->userblog_id, $user_id, 'subscriber' );
  91		update_user_meta( $user_id, 'primary_blog', $first_blog->userblog_id );
  92		$primary = $first_blog;
  93	}
  94
  95	if ( ( ! is_object( $primary ) ) || ( $primary->archived == 1 || $primary->spam == 1 || $primary->deleted == 1 ) ) {
  96		$blogs = get_blogs_of_user( $user_id, true ); // if a user's primary blog is shut down, check their other blogs.
  97		$ret = false;
  98		if ( is_array( $blogs ) && count( $blogs ) > 0 ) {
  99			foreach ( (array) $blogs as $blog_id => $blog ) {
 100				if ( $blog->site_id != $wpdb->siteid )
 101					continue;
 102				$details = get_blog_details( $blog_id );
 103				if ( is_object( $details ) && $details->archived == 0 && $details->spam == 0 && $details->deleted == 0 ) {
 104					$ret = $blog;
 105					if ( get_user_meta( $user_id , 'primary_blog', true ) != $blog_id )
 106						update_user_meta( $user_id, 'primary_blog', $blog_id );
 107					if ( !get_user_meta($user_id , 'source_domain', true) )
 108						update_user_meta( $user_id, 'source_domain', $blog->domain );
 109					break;
 110				}
 111			}
 112		} else {
 113			return null;
 114		}
 115		return $ret;
 116	} else {
 117		return $primary;
 118	}
 119}
 120
 121/**
 122 * The number of active users in your installation.
 123 *
 124 * The count is cached and updated twice daily. This is not a live count.
 125 *
 126 * @since MU 2.7
 127 *
 128 * @return int
 129 */
 130function get_user_count() {
 131	return get_site_option( 'user_count' );
 132}
 133
 134/**
 135 * The number of active sites on your installation.
 136 *
 137 * The count is cached and updated twice daily. This is not a live count.
 138 *
 139 * @since MU 1.0
 140 *
 141 * @param int $id Optional. A site_id.
 142 * @return int
 143 */
 144function get_blog_count( $id = 0 ) {
 145	return get_site_option( 'blog_count' );
 146}
 147
 148/**
 149 * Get a blog post from any site on the network.
 150 *
 151 * @since MU 1.0
 152 *
 153 * @param int $blog_id ID of the blog.
 154 * @param int $post_id ID of the post you're looking for.
 155 * @return WP_Post|null WP_Post on success or null on failure
 156 */
 157function get_blog_post( $blog_id, $post_id ) {
 158	switch_to_blog( $blog_id );
 159	$post = get_post( $post_id );
 160	restore_current_blog();
 161
 162	return $post;
 163}
 164
 165/**
 166 * Add a user to a blog.
 167 *
 168 * Use the 'add_user_to_blog' action to fire an event when
 169 * users are added to a blog.
 170 *
 171 * @since MU 1.0
 172 *
 173 * @param int $blog_id ID of the blog you're adding the user to.
 174 * @param int $user_id ID of the user you're adding.
 175 * @param string $role The role you want the user to have
 176 * @return bool
 177 */
 178function add_user_to_blog( $blog_id, $user_id, $role ) {
 179	switch_to_blog($blog_id);
 180
 181	$user = get_userdata( $user_id );
 182
 183	if ( ! $user ) {
 184		restore_current_blog();
 185		return new WP_Error( 'user_does_not_exist', __( 'The requested user does not exist.' ) );
 186	}
 187
 188	if ( !get_user_meta($user_id, 'primary_blog', true) ) {
 189		update_user_meta($user_id, 'primary_blog', $blog_id);
 190		$details = get_blog_details($blog_id);
 191		update_user_meta($user_id, 'source_domain', $details->domain);
 192	}
 193
 194	$user->set_role($role);
 195
 196	do_action('add_user_to_blog', $user_id, $role, $blog_id);
 197	wp_cache_delete( $user_id, 'users' );
 198	restore_current_blog();
 199	return true;
 200}
 201
 202/**
 203 * Remove a user from a blog.
 204 *
 205 * Use the 'remove_user_from_blog' action to fire an event when
 206 * users are removed from a blog.
 207 *
 208 * Accepts an optional $reassign parameter, if you want to
 209 * reassign the user's blog posts to another user upon removal.
 210 *
 211 * @since MU 1.0
 212 *
 213 * @param int $user_id ID of the user you're removing.
 214 * @param int $blog_id ID of the blog you're removing the user from.
 215 * @param string $reassign Optional. A user to whom to reassign posts.
 216 * @return bool
 217 */
 218function remove_user_from_blog($user_id, $blog_id = '', $reassign = '') {
 219	global $wpdb;
 220	switch_to_blog($blog_id);
 221	$user_id = (int) $user_id;
 222	do_action('remove_user_from_blog', $user_id, $blog_id);
 223
 224	// If being removed from the primary blog, set a new primary if the user is assigned
 225	// to multiple blogs.
 226	$primary_blog = get_user_meta($user_id, 'primary_blog', true);
 227	if ( $primary_blog == $blog_id ) {
 228		$new_id = '';
 229		$new_domain = '';
 230		$blogs = get_blogs_of_user($user_id);
 231		foreach ( (array) $blogs as $blog ) {
 232			if ( $blog->userblog_id == $blog_id )
 233				continue;
 234			$new_id = $blog->userblog_id;
 235			$new_domain = $blog->domain;
 236			break;
 237		}
 238
 239		update_user_meta($user_id, 'primary_blog', $new_id);
 240		update_user_meta($user_id, 'source_domain', $new_domain);
 241	}
 242
 243	// wp_revoke_user($user_id);
 244	$user = get_userdata( $user_id );
 245	if ( ! $user ) {
 246		restore_current_blog();
 247		return new WP_Error('user_does_not_exist', __('That user does not exist.'));
 248	}
 249
 250	$user->remove_all_caps();
 251
 252	$blogs = get_blogs_of_user($user_id);
 253	if ( count($blogs) == 0 ) {
 254		update_user_meta($user_id, 'primary_blog', '');
 255		update_user_meta($user_id, 'source_domain', '');
 256	}
 257
 258	if ( $reassign != '' ) {
 259		$reassign = (int) $reassign;
 260		$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_author = %d WHERE post_author = %d", $reassign, $user_id) );
 261		$wpdb->query( $wpdb->prepare("UPDATE $wpdb->links SET link_owner = %d WHERE link_owner = %d", $reassign, $user_id) );
 262	}
 263
 264	restore_current_blog();
 265
 266	return true;
 267}
 268
 269/**
 270 * Create an empty blog.
 271 *
 272 * @since MU 1.0
 273 * @uses install_blog()
 274 *
 275 * @param string $domain The new blog's domain.
 276 * @param string $path The new blog's path.
 277 * @param string $weblog_title The new blog's title.
 278 * @param int $site_id Optional. Defaults to 1.
 279 * @return int The ID of the newly created blog
 280 */
 281function create_empty_blog( $domain, $path, $weblog_title, $site_id = 1 ) {
 282	$domain			= addslashes( $domain );
 283	$weblog_title	= addslashes( $weblog_title );
 284
 285	if ( empty($path) )
 286		$path = '/';
 287
 288	// Check if the domain has been used already. We should return an error message.
 289	if ( domain_exists($domain, $path, $site_id) )
 290		return __( '<strong>ERROR</strong>: Site URL already taken.' );
 291
 292	// Need to back up wpdb table names, and create a new wp_blogs entry for new blog.
 293	// Need to get blog_id from wp_blogs, and create new table names.
 294	// Must restore table names at the end of function.
 295
 296	if ( ! $blog_id = insert_blog($domain, $path, $site_id) )
 297		return __( '<strong>ERROR</strong>: problem creating site entry.' );
 298
 299	switch_to_blog($blog_id);
 300	install_blog($blog_id);
 301	restore_current_blog();
 302
 303	return $blog_id;
 304}
 305
 306/**
 307 * Get the permalink for a post on another blog.
 308 *
 309 * @since MU 1.0
 310 *
 311 * @param int $blog_id ID of the source blog.
 312 * @param int $post_id ID of the desired post.
 313 * @return string The post's permalink
 314 */
 315function get_blog_permalink( $blog_id, $post_id ) {
 316	switch_to_blog( $blog_id );
 317	$link = get_permalink( $post_id );
 318	restore_current_blog();
 319
 320	return $link;
 321}
 322
 323/**
 324 * Get a blog's numeric ID from its URL.
 325 *
 326 * On a subdirectory installation like example.com/blog1/,
 327 * $domain will be the root 'example.com' and $path the
 328 * subdirectory '/blog1/'. With subdomains like blog1.example.com,
 329 * $domain is 'blog1.example.com' and $path is '/'.
 330 *
 331 * @since MU 2.6.5
 332 *
 333 * @param string $domain
 334 * @param string $path Optional. Not required for subdomain installations.
 335 * @return int 0 if no blog found, otherwise the ID of the matching blog
 336 */
 337function get_blog_id_from_url( $domain, $path = '/' ) {
 338	global $wpdb;
 339
 340	$domain = strtolower( $domain );
 341	$path = strtolower( $path );
 342	$id = wp_cache_get( md5( $domain . $path ), 'blog-id-cache' );
 343
 344	if ( $id == -1 ) // blog does not exist
 345		return 0;
 346	elseif ( $id )
 347		return (int) $id;
 348
 349	$id = $wpdb->get_var( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE domain = %s and path = %s /* get_blog_id_from_url */", $domain, $path ) );
 350
 351	if ( ! $id ) {
 352		wp_cache_set( md5( $domain . $path ), -1, 'blog-id-cache' );
 353		return 0;
 354	}
 355
 356	wp_cache_set( md5( $domain . $path ), $id, 'blog-id-cache' );
 357
 358	return $id;
 359}
 360
 361// Admin functions
 362
 363/**
 364 * Checks an email address against a list of banned domains.
 365 *
 366 * This function checks against the Banned Email Domains list
 367 * at wp-admin/network/settings.php. The check is only run on
 368 * self-registrations; user creation at wp-admin/network/users.php
 369 * bypasses this check.
 370 *
 371 * @since MU
 372 *
 373 * @param string $user_email The email provided by the user at registration.
 374 * @return bool Returns true when the email address is banned.
 375 */
 376function is_email_address_unsafe( $user_email ) {
 377	$banned_names = get_site_option( 'banned_email_domains' );
 378	if ( $banned_names && ! is_array( $banned_names ) )
 379		$banned_names = explode( "\n", $banned_names );
 380
 381	$is_email_address_unsafe = false;
 382
 383	if ( $banned_names && is_array( $banned_names ) ) {
 384		list( $email_local_part, $email_domain ) = explode( '@', $user_email );
 385
 386		foreach ( $banned_names as $banned_domain ) {
 387			if ( ! $banned_domain )
 388				continue;
 389
 390			if ( $email_domain == $banned_domain ) {
 391				$is_email_address_unsafe = true;
 392				break;
 393			}
 394
 395			$dotted_domain = ".$banned_domain";
 396			if ( $dotted_domain === substr( $user_email, -strlen( $dotted_domain ) ) ) {
 397				$is_email_address_unsafe = true;
 398				break;
 399			}
 400		}
 401	}
 402
 403	return apply_filters( 'is_email_address_unsafe', $is_email_address_unsafe, $user_email );
 404}
 405
 406/**
 407 * Processes new user registrations.
 408 *
 409 * Checks the data provided by the user during signup. Verifies
 410 * the validity and uniqueness of user names and user email addresses,
 411 * and checks email addresses against admin-provided domain
 412 * whitelists and blacklists.
 413 *
 414 * The hook 'wpmu_validate_user_signup' provides an easy way
 415 * to modify the signup process. The value $result, which is passed
 416 * to the hook, contains both the user-provided info and the error
 417 * messages created by the function. 'wpmu_validate_user_signup' allows
 418 * you to process the data in any way you'd like, and unset the
 419 * relevant errors if necessary.
 420 *
 421 * @since MU
 422 * @uses is_email_address_unsafe()
 423 * @uses username_exists()
 424 * @uses email_exists()
 425 *
 426 * @param string $user_name The login name provided by the user.
 427 * @param string $user_email The email provided by the user.
 428 * @return array Contains username, email, and error messages.
 429 */
 430function wpmu_validate_user_signup($user_name, $user_email) {
 431	global $wpdb;
 432
 433	$errors = new WP_Error();
 434
 435	$orig_username = $user_name;
 436	$user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) );
 437
 438	if ( $user_name != $orig_username || preg_match( '/[^a-z0-9]/', $user_name ) ) {
 439		$errors->add( 'user_name', __( 'Only lowercase letters (a-z) and numbers are allowed.' ) );
 440		$user_name = $orig_username;
 441	}
 442
 443	$user_email = sanitize_email( $user_email );
 444
 445	if ( empty( $user_name ) )
 446	   	$errors->add('user_name', __( 'Please enter a username.' ) );
 447
 448	$illegal_names = get_site_option( 'illegal_names' );
 449	if ( is_array( $illegal_names ) == false ) {
 450		$illegal_names = array(  'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' );
 451		add_site_option( 'illegal_names', $illegal_names );
 452	}
 453	if ( in_array( $user_name, $illegal_names ) == true )
 454		$errors->add('user_name',  __( 'That username is not allowed.' ) );
 455
 456	if ( is_email_address_unsafe( $user_email ) )
 457		$errors->add('user_email',  __('You cannot use that email address to signup. We are having problems with them blocking some of our email. Please use another email provider.'));
 458
 459	if ( strlen( $user_name ) < 4 )
 460		$errors->add('user_name',  __( 'Username must be at least 4 characters.' ) );
 461
 462	if ( strpos( ' ' . $user_name, '_' ) != false )
 463		$errors->add( 'user_name', __( 'Sorry, usernames may not contain the character &#8220;_&#8221;!' ) );
 464
 465	// all numeric?
 466	$match = array();
 467	preg_match( '/[0-9]*/', $user_name, $match );
 468	if ( $match[0] == $user_name )
 469		$errors->add('user_name', __('Sorry, usernames must have letters too!'));
 470
 471	if ( !is_email( $user_email ) )
 472		$errors->add('user_email', __( 'Please enter a valid email address.' ) );
 473
 474	$limited_email_domains = get_site_option( 'limited_email_domains' );
 475	if ( is_array( $limited_email_domains ) && empty( $limited_email_domains ) == false ) {
 476		$emaildomain = substr( $user_email, 1 + strpos( $user_email, '@' ) );
 477		if ( in_array( $emaildomain, $limited_email_domains ) == false )
 478			$errors->add('user_email', __('Sorry, that email address is not allowed!'));
 479	}
 480
 481	// Check if the username has been used already.
 482	if ( username_exists($user_name) )
 483		$errors->add( 'user_name', __( 'Sorry, that username already exists!' ) );
 484
 485	// Check if the email address has been used already.
 486	if ( email_exists($user_email) )
 487		$errors->add( 'user_email', __( 'Sorry, that email address is already used!' ) );
 488
 489	// Has someone already signed up for this username?
 490	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_name) );
 491	if ( $signup != null ) {
 492		$registered_at =  mysql2date('U', $signup->registered);
 493		$now = current_time( 'timestamp', true );
 494		$diff = $now - $registered_at;
 495		// If registered more than two days ago, cancel registration and let this signup go through.
 496		if ( $diff > 2 * DAY_IN_SECONDS )
 497			$wpdb->delete( $wpdb->signups, array( 'user_login' => $user_name ) );
 498		else
 499			$errors->add('user_name', __('That username is currently reserved but may be available in a couple of days.'));
 500
 501		if ( $signup->active == 0 && $signup->user_email == $user_email )
 502			$errors->add('user_email_used', __('username and email used'));
 503	}
 504
 505	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_email = %s", $user_email) );
 506	if ( $signup != null ) {
 507		$diff = current_time( 'timestamp', true ) - mysql2date('U', $signup->registered);
 508		// If registered more than two days ago, cancel registration and let this signup go through.
 509		if ( $diff > 2 * DAY_IN_SECONDS )
 510			$wpdb->delete( $wpdb->signups, array( 'user_email' => $user_email ) );
 511		else
 512			$errors->add('user_email', __('That email address has already been used. Please check your inbox for an activation email. It will become available in a couple of days if you do nothing.'));
 513	}
 514
 515	$result = array('user_name' => $user_name, 'orig_username' => $orig_username, 'user_email' => $user_email, 'errors' => $errors);
 516
 517	return apply_filters('wpmu_validate_user_signup', $result);
 518}
 519
 520/**
 521 * Processes new site registrations.
 522 *
 523 * Checks the data provided by the user during blog signup. Verifies
 524 * the validity and uniqueness of blog paths and domains.
 525 *
 526 * This function prevents the current user from registering a new site
 527 * with a blogname equivalent to another user's login name. Passing the
 528 * $user parameter to the function, where $user is the other user, is
 529 * effectively an override of this limitation.
 530 *
 531 * Filter 'wpmu_validate_blog_signup' if you want to modify
 532 * the way that WordPress validates new site signups.
 533 *
 534 * @since MU
 535 * @uses domain_exists()
 536 * @uses username_exists()
 537 *
 538 * @param string $blogname The blog name provided by the user. Must be unique.
 539 * @param string $blog_title The blog title provided by the user.
 540 * @return array Contains the new site data and error messages.
 541 */
 542function wpmu_validate_blog_signup($blogname, $blog_title, $user = '') {
 543	global $wpdb, $domain, $current_site;
 544
 545	$base = $current_site->path;
 546
 547	$blog_title = strip_tags( $blog_title );
 548	$blog_title = substr( $blog_title, 0, 50 );
 549
 550	$errors = new WP_Error();
 551	$illegal_names = get_site_option( 'illegal_names' );
 552	if ( $illegal_names == false ) {
 553		$illegal_names = array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' );
 554		add_site_option( 'illegal_names', $illegal_names );
 555	}
 556
 557	// On sub dir installs, Some names are so illegal, only a filter can spring them from jail
 558	if (! is_subdomain_install() )
 559		$illegal_names = array_merge($illegal_names, apply_filters( 'subdirectory_reserved_names', array( 'page', 'comments', 'blog', 'files', 'feed' ) ) );
 560
 561	if ( empty( $blogname ) )
 562		$errors->add('blogname', __( 'Please enter a site name.' ) );
 563
 564	if ( preg_match( '/[^a-z0-9]+/', $blogname ) )
 565		$errors->add('blogname', __( 'Only lowercase letters (a-z) and numbers are allowed.' ) );
 566
 567	if ( in_array( $blogname, $illegal_names ) == true )
 568		$errors->add('blogname',  __( 'That name is not allowed.' ) );
 569
 570	if ( strlen( $blogname ) < 4 && !is_super_admin() )
 571		$errors->add('blogname',  __( 'Site name must be at least 4 characters.' ) );
 572
 573	if ( strpos( ' ' . $blogname, '_' ) != false )
 574		$errors->add( 'blogname', __( 'Sorry, site names may not contain the character &#8220;_&#8221;!' ) );
 575
 576	// do not allow users to create a blog that conflicts with a page on the main blog.
 577	if ( !is_subdomain_install() && $wpdb->get_var( $wpdb->prepare( "SELECT post_name FROM " . $wpdb->get_blog_prefix( $current_site->blog_id ) . "posts WHERE post_type = 'page' AND post_name = %s", $blogname ) ) )
 578		$errors->add( 'blogname', __( 'Sorry, you may not use that site name.' ) );
 579
 580	// all numeric?
 581	$match = array();
 582	preg_match( '/[0-9]*/', $blogname, $match );
 583	if ( $match[0] == $blogname )
 584		$errors->add('blogname', __('Sorry, site names must have letters too!'));
 585
 586	$blogname = apply_filters( 'newblogname', $blogname );
 587
 588	$blog_title = stripslashes(  $blog_title );
 589
 590	if ( empty( $blog_title ) )
 591		$errors->add('blog_title', __( 'Please enter a site title.' ) );
 592
 593	// Check if the domain/path has been used already.
 594	if ( is_subdomain_install() ) {
 595		$mydomain = $blogname . '.' . preg_replace( '|^www\.|', '', $domain );
 596		$path = $base;
 597	} else {
 598		$mydomain = "$domain";
 599		$path = $base.$blogname.'/';
 600	}
 601	if ( domain_exists($mydomain, $path, $current_site->id) )
 602		$errors->add( 'blogname', __( 'Sorry, that site already exists!' ) );
 603
 604	if ( username_exists( $blogname ) ) {
 605		if ( is_object( $user ) == false || ( is_object($user) && ( $user->user_login != $blogname ) ) )
 606			$errors->add( 'blogname', __( 'Sorry, that site is reserved!' ) );
 607	}
 608
 609	// Has someone already signed up for this domain?
 610	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE domain = %s AND path = %s", $mydomain, $path) ); // TODO: Check email too?
 611	if ( ! empty($signup) ) {
 612		$diff = current_time( 'timestamp', true ) - mysql2date('U', $signup->registered);
 613		// If registered more than two days ago, cancel registration and let this signup go through.
 614		if ( $diff > 2 * DAY_IN_SECONDS )
 615			$wpdb->delete( $wpdb->signups, array( 'domain' => $mydomain , 'path' => $path ) );
 616		else
 617			$errors->add('blogname', __('That site is currently reserved but may be available in a couple days.'));
 618	}
 619
 620	$result = array('domain' => $mydomain, 'path' => $path, 'blogname' => $blogname, 'blog_title' => $blog_title, 'user' => $user, 'errors' => $errors);
 621	return apply_filters('wpmu_validate_blog_signup', $result);
 622}
 623
 624/**
 625 * Record site signup information for future activation.
 626 *
 627 * @since MU
 628 * @uses wpmu_signup_blog_notification()
 629 *
 630 * @param string $domain The requested domain.
 631 * @param string $path The requested path.
 632 * @param string $title The requested site title.
 633 * @param string $user The user's requested login name.
 634 * @param string $user_email The user's email address.
 635 * @param array $meta By default, contains the requested privacy setting and lang_id.
 636 */
 637function wpmu_signup_blog($domain, $path, $title, $user, $user_email, $meta = '') {
 638	global $wpdb;
 639
 640	$key = substr( md5( time() . rand() . $domain ), 0, 16 );
 641	$meta = serialize($meta);
 642	$domain = $wpdb->escape($domain);
 643	$path = $wpdb->escape($path);
 644	$title = $wpdb->escape($title);
 645
 646	$wpdb->insert( $wpdb->signups, array(
 647		'domain' => $domain,
 648		'path' => $path,
 649		'title' => $title,
 650		'user_login' => $user,
 651		'user_email' => $user_email,
 652		'registered' => current_time('mysql', true),
 653		'activation_key' => $key,
 654		'meta' => $meta
 655	) );
 656
 657	wpmu_signup_blog_notification($domain, $path, $title, $user, $user_email, $key, $meta);
 658}
 659
 660/**
 661 * Record user signup information for future activation.
 662 *
 663 * This function is used when user registration is open but
 664 * new site registration is not.
 665 *
 666 * @since MU
 667 * @uses wpmu_signup_user_notification()
 668 *
 669 * @param string $user The user's requested login name.
 670 * @param string $user_email The user's email address.
 671 * @param array $meta By default, this is an empty array.
 672 */
 673function wpmu_signup_user($user, $user_email, $meta = '') {
 674	global $wpdb;
 675
 676	// Format data
 677	$user = preg_replace( '/\s+/', '', sanitize_user( $user, true ) );
 678	$user_email = sanitize_email( $user_email );
 679	$key = substr( md5( time() . rand() . $user_email ), 0, 16 );
 680	$meta = serialize($meta);
 681
 682	$wpdb->insert( $wpdb->signups, array(
 683		'domain' => '',
 684		'path' => '',
 685		'title' => '',
 686		'user_login' => $user,
 687		'user_email' => $user_email,
 688		'registered' => current_time('mysql', true),
 689		'activation_key' => $key,
 690		'meta' => $meta
 691	) );
 692
 693	wpmu_signup_user_notification($user, $user_email, $key, $meta);
 694}
 695
 696/**
 697 * Notify user of signup success.
 698 *
 699 * This is the notification function used when site registration
 700 * is enabled.
 701 *
 702 * Filter 'wpmu_signup_blog_notification' to bypass this function or
 703 * replace it with your own notification behavior.
 704 *
 705 * Filter 'wpmu_signup_blog_notification_email' and
 706 * 'wpmu_signup_blog_notification_subject' to change the content
 707 * and subject line of the email sent to newly registered users.
 708 *
 709 * @since MU
 710 *
 711 * @param string $domain The new blog domain.
 712 * @param string $path The new blog path.
 713 * @param string $title The site title.
 714 * @param string $user The user's login name.
 715 * @param string $user_email The user's email address.
 716 * @param array $meta By default, contains the requested privacy setting and lang_id.
 717 * @param string $key The activation key created in wpmu_signup_blog()
 718 * @return bool
 719 */
 720function wpmu_signup_blog_notification($domain, $path, $title, $user, $user_email, $key, $meta = '') {
 721	global $current_site;
 722
 723	if ( !apply_filters('wpmu_signup_blog_notification', $domain, $path, $title, $user, $user_email, $key, $meta) )
 724		return false;
 725
 726	// Send email with activation link.
 727	if ( !is_subdomain_install() || $current_site->id != 1 )
 728		$activate_url = network_site_url("wp-activate.php?key=$key");
 729	else
 730		$activate_url = "http://{$domain}{$path}wp-activate.php?key=$key"; // @todo use *_url() API
 731
 732	$activate_url = esc_url($activate_url);
 733	$admin_email = get_site_option( 'admin_email' );
 734	if ( $admin_email == '' )
 735		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
 736	$from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
 737	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
 738	$message = sprintf(
 739		apply_filters( 'wpmu_signup_blog_notification_email',
 740			__( "To activate your blog, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%s" ),
 741			$domain, $path, $title, $user, $user_email, $key, $meta
 742		),
 743		$activate_url,
 744		esc_url( "http://{$domain}{$path}" ),
 745		$key
 746	);
 747	// TODO: Don't hard code activation link.
 748	$subject = sprintf(
 749		apply_filters( 'wpmu_signup_blog_notification_subject',
 750			__( '[%1$s] Activate %2$s' ),
 751			$domain, $path, $title, $user, $user_email, $key, $meta
 752		),
 753		$from_name,
 754		esc_url( 'http://' . $domain . $path )
 755	);
 756	wp_mail($user_email, $subject, $message, $message_headers);
 757	return true;
 758}
 759
 760/**
 761 * Notify user of signup success.
 762 *
 763 * This is the notification function used when no new site has
 764 * been requested.
 765 *
 766 * Filter 'wpmu_signup_user_notification' to bypass this function or
 767 * replace it with your own notification behavior.
 768 *
 769 * Filter 'wpmu_signup_user_notification_email' and
 770 * 'wpmu_signup_user_notification_subject' to change the content
 771 * and subject line of the email sent to newly registered users.
 772 *
 773 * @since MU
 774 *
 775 * @param string $user The user's login name.
 776 * @param string $user_email The user's email address.
 777 * @param array $meta By default, an empty array.
 778 * @param string $key The activation key created in wpmu_signup_user()
 779 * @return bool
 780 */
 781function wpmu_signup_user_notification($user, $user_email, $key, $meta = '') {
 782	if ( !apply_filters('wpmu_signup_user_notification', $user, $user_email, $key, $meta) )
 783		return false;
 784
 785	// Send email with activation link.
 786	$admin_email = get_site_option( 'admin_email' );
 787	if ( $admin_email == '' )
 788		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
 789	$from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
 790	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
 791	$message = sprintf(
 792		apply_filters( 'wpmu_signup_user_notification_email',
 793			__( "To activate your user, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login." ),
 794			$user, $user_email, $key, $meta
 795		),
 796		site_url( "wp-activate.php?key=$key" )
 797	);
 798	// TODO: Don't hard code activation link.
 799	$subject = sprintf(
 800		apply_filters( 'wpmu_signup_user_notification_subject',
 801			__( '[%1$s] Activate %2$s' ),
 802			$user, $user_email, $key, $meta
 803		),
 804		$from_name,
 805		$user
 806	);
 807	wp_mail($user_email, $subject, $message, $message_headers);
 808	return true;
 809}
 810
 811/**
 812 * Activate a signup.
 813 *
 814 * Hook to 'wpmu_activate_user' or 'wpmu_activate_blog' for events
 815 * that should happen only when users or sites are self-created (since
 816 * those actions are not called when users and sites are created
 817 * by a Super Admin).
 818 *
 819 * @since MU
 820 * @uses wp_generate_password()
 821 * @uses wpmu_welcome_user_notification()
 822 * @uses add_user_to_blog()
 823 * @uses add_new_user_to_blog()
 824 * @uses wpmu_create_user()
 825 * @uses wpmu_create_blog()
 826 * @uses wpmu_welcome_notification()
 827 *
 828 * @param string $key The activation key provided to the user.
 829 * @return array An array containing information about the activated user and/or blog
 830 */
 831function wpmu_activate_signup($key) {
 832	global $wpdb, $current_site;
 833
 834	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE activation_key = %s", $key) );
 835
 836	if ( empty( $signup ) )
 837		return new WP_Error( 'invalid_key', __( 'Invalid activation key.' ) );
 838
 839	if ( $signup->active ) {
 840		if ( empty( $signup->domain ) )
 841			return new WP_Error( 'already_active', __( 'The user is already active.' ), $signup );
 842		else
 843			return new WP_Error( 'already_active', __( 'The site is already active.' ), $signup );
 844	}
 845
 846	$meta = maybe_unserialize($signup->meta);
 847	$user_login = $wpdb->escape($signup->user_login);
 848	$user_email = $wpdb->escape($signup->user_email);
 849	$password = wp_generate_password( 12, false );
 850
 851	$user_id = username_exists($user_login);
 852
 853	if ( ! $user_id )
 854		$user_id = wpmu_create_user($user_login, $password, $user_email);
 855	else
 856		$user_already_exists = true;
 857
 858	if ( ! $user_id )
 859		return new WP_Error('create_user', __('Could not create user'), $signup);
 860
 861	$now = current_time('mysql', true);
 862
 863	if ( empty($signup->domain) ) {
 864		$wpdb->update( $wpdb->signups, array('active' => 1, 'activated' => $now), array('activation_key' => $key) );
 865
 866		if ( isset( $user_already_exists ) )
 867			return new WP_Error( 'user_already_exists', __( 'That username is already activated.' ), $signup);
 868
 869		wpmu_welcome_user_notification($user_id, $password, $meta);
 870
 871		add_new_user_to_blog( $user_id, $user_email, $meta );
 872		do_action('wpmu_activate_user', $user_id, $password, $meta);
 873		return array('user_id' => $user_id, 'password' => $password, 'meta' => $meta);
 874	}
 875
 876	$blog_id = wpmu_create_blog( $signup->domain, $signup->path, $signup->title, $user_id, $meta, $wpdb->siteid );
 877
 878	// TODO: What to do if we create a user but cannot create a blog?
 879	if ( is_wp_error($blog_id) ) {
 880		// If blog is taken, that means a previous attempt to activate this blog failed in between creating the blog and
 881		// setting the activation flag. Let's just set the active flag and instruct the user to reset their password.
 882		if ( 'blog_taken' == $blog_id->get_error_code() ) {
 883			$blog_id->add_data( $signup );
 884			$wpdb->update( $wpdb->signups, array( 'active' => 1, 'activated' => $now ), array( 'activation_key' => $key ) );
 885		}
 886		return $blog_id;
 887	}
 888
 889	$wpdb->update( $wpdb->signups, array('active' => 1, 'activated' => $now), array('activation_key' => $key) );
 890	wpmu_welcome_notification($blog_id, $user_id, $password, $signup->title, $meta);
 891	do_action('wpmu_activate_blog', $blog_id, $user_id, $password, $signup->title, $meta);
 892
 893	return array('blog_id' => $blog_id, 'user_id' => $user_id, 'password' => $password, 'title' => $signup->title, 'meta' => $meta);
 894}
 895
 896/**
 897 * Create a user.
 898 *
 899 * This function runs when a user self-registers as well as when
 900 * a Super Admin creates a new user. Hook to 'wpmu_new_user' for events
 901 * that should affect all new users, but only on Multisite (otherwise
 902 * use 'user_register').
 903 *
 904 * @since MU
 905 * @uses wp_create_user()
 906 *
 907 * @param string $user_name The new user's login name.
 908 * @param string $password The new user's password.
 909 * @param string $email The new user's email address.
 910 * @return mixed Returns false on failure, or int $user_id on success
 911 */
 912function wpmu_create_user( $user_name, $password, $email) {
 913	$user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) );
 914
 915	$user_id = wp_create_user( $user_name, $password, $email );
 916	if ( is_wp_error($user_id) )
 917		return false;
 918
 919	// Newly created users have no roles or caps until they are added to a blog.
 920	delete_user_option( $user_id, 'capabilities' );
 921	delete_user_option( $user_id, 'user_level' );
 922
 923	do_action( 'wpmu_new_user', $user_id );
 924
 925	return $user_id;
 926}
 927
 928/**
 929 * Create a site.
 930 *
 931 * This function runs when a user self-registers a new site as well
 932 * as when a Super Admin creates a new site. Hook to 'wpmu_new_blog'
 933 * for events that should affect all new sites.
 934 *
 935 * On subdirectory installs, $domain is the same as the main site's
 936 * domain, and the path is the subdirectory name (eg 'example.com'
 937 * and '/blog1/'). On subdomain installs, $domain is the new subdomain +
 938 * root domain (eg 'blog1.example.com'), and $path is '/'.
 939 *
 940 * @since MU
 941 * @uses domain_exists()
 942 * @uses insert_blog()
 943 * @uses wp_install_defaults()
 944 * @uses add_user_to_blog()
 945 *
 946 * @param string $domain The new site's domain.
 947 * @param string $path The new site's path.
 948 * @param string $title The new site's title.
 949 * @param int $user_id The user ID of the new site's admin.
 950 * @param array $meta Optional. Used to set initial site options.
 951 * @param int $site_id Optional. Only relevant on multi-network installs.
 952 * @return mixed Returns WP_Error object on failure, int $blog_id on success
 953 */
 954function wpmu_create_blog($domain, $path, $title, $user_id, $meta = '', $site_id = 1) {
 955	$domain = preg_replace( '/\s+/', '', sanitize_user( $domain, true ) );
 956
 957	if ( is_subdomain_install() )
 958		$domain = str_replace( '@', '', $domain );
 959
 960	$title = strip_tags( $title );
 961	$user_id = (int) $user_id;
 962
 963	if ( empty($path) )
 964		$path = '/';
 965
 966	// Check if the domain has been used already. We should return an error message.
 967	if ( domain_exists($domain, $path, $site_id) )
 968		return new WP_Error( 'blog_taken', __( 'Sorry, that site already exists!' ) );
 969
 970	if ( !defined('WP_INSTALLING') )
 971		define( 'WP_INSTALLING', true );
 972
 973	if ( ! $blog_id = insert_blog($domain, $path, $site_id) )
 974		return new WP_Error('insert_blog', __('Could not create site.'));
 975
 976	switch_to_blog($blog_id);
 977	install_blog($blog_id, $title);
 978	wp_install_defaults($user_id);
 979
 980	add_user_to_blog($blog_id, $user_id, 'administrator');
 981
 982	if ( is_array($meta) ) foreach ($meta as $key => $value) {
 983		if ( $key == 'public' || $key == 'archived' || $key == 'mature' || $key == 'spam' || $key == 'deleted' || $key == 'lang_id' )
 984			update_blog_status( $blog_id, $key, $value );
 985		else
 986			update_option( $key, $value );
 987	}
 988
 989	add_option( 'WPLANG', get_site_option( 'WPLANG' ) );
 990	update_option( 'blog_public', (int)$meta['public'] );
 991
 992	if ( ! is_super_admin( $user_id ) && ! get_user_meta( $user_id, 'primary_blog', true ) )
 993		update_user_meta( $user_id, 'primary_blog', $blog_id );
 994
 995	restore_current_blog();
 996	do_action( 'wpmu_new_blog', $blog_id, $user_id, $domain, $path, $site_id, $meta );
 997
 998	return $blog_id;
 999}
1000
1001/**
1002 * Notifies the network admin that a new site has been activated.
1003 *
1004 * Filter 'newblog_notify_siteadmin' to change the content of
1005 * the notification email.
1006 *
1007 * @since MU
1008 *
1009 * @param int $blog_id The new site's ID.
1010 * @return bool
1011 */
1012function newblog_notify_siteadmin( $blog_id, $deprecated = '' ) {
1013	if ( get_site_option( 'registrationnotification' ) != 'yes' )
1014		return false;
1015
1016	$email = get_site_option( 'admin_email' );
1017	if ( is_email($email) == false )
1018		return false;
1019
1020	$options_site_url = esc_url(network_admin_url('settings.php'));
1021
1022	switch_to_blog( $blog_id );
1023	$blogname = get_option( 'blogname' );
1024	$siteurl = site_url();
1025	restore_current_blog();
1026
1027	$msg = sprintf( __( 'New Site: %1$s
1028URL: %2$s
1029Remote IP: %3$s
1030
1031Disable these notifications: %4$s' ), $blogname, $siteurl, $_SERVER['REMOTE_ADDR'], $options_site_url);
1032	$msg = apply_filters( 'newblog_notify_siteadmin', $msg );
1033
1034	wp_mail( $email, sprintf( __( 'New Site Registration: %s' ), $siteurl ), $msg );
1035	return true;
1036}
1037
1038/**
1039 * Notifies the network admin that a new user has been activated.
1040 *
1041 * Filter 'newuser_notify_siteadmin' to change the content of
1042 * the notification email.
1043 *
1044 * @since MU
1045 * @uses apply_filters() Filter newuser_notify_siteadmin to change the content of the email message
1046 *
1047 * @param int $user_id The new user's ID.
1048 * @return bool
1049 */
1050function newuser_notify_siteadmin( $user_id ) {
1051	if ( get_site_option( 'registrationnotification' ) != 'yes' )
1052		return false;
1053
1054	$email = get_site_option( 'admin_email' );
1055
1056	if ( is_email($email) == false )
1057		return false;
1058
1059	$user = get_userdata( $user_id );
1060
1061	$options_site_url = esc_url(network_admin_url('settings.php'));
1062	$msg = sprintf(__('New User: %1$s
1063Remote IP: %2$s
1064
1065Disable these notifications: %3$s'), $user->user_login, $_SERVER['REMOTE_ADDR'], $options_site_url);
1066
1067	$msg = apply_filters( 'newuser_notify_siteadmin', $msg, $user );
1068	wp_mail( $email, sprintf(__('New User Registration: %s'), $user->user_login), $msg );
1069	return true;
1070}
1071
1072/**
1073 * Check whether a blogname is already taken.
1074 *
1075 * Used during the new site registration process to ensure
1076 * that each blogname is unique.
1077 *
1078 * @since MU
1079 *
1080 * @param string $domain The domain to be checked.
1081 * @param string $path The path to be checked.
1082 * @param int $site_id Optional. Relevant only on multi-network installs.
1083 * @return int
1084 */
1085function domain_exists($domain, $path, $site_id = 1) {
1086	global $wpdb;
1087	$result = $wpdb->get_var( $wpdb->prepare("SELECT blog_id FROM $wpdb->blogs WHERE domain = %s AND path = %s AND site_id = %d", $domain, $path, $site_id) );
1088	return apply_filters( 'domain_exists', $result, $domain, $path, $site_id );
1089}
1090
1091/**
1092 * Store basic site info in the blogs table.
1093 *
1094 * This function creates a row in the wp_blogs table and returns
1095 * the new blog's ID. It is the first step in creating a new blog.
1096 *
1097 * @since MU
1098 *
1099 * @param string $domain The domain of the new site.
1100 * @param string $path The path of the new site.
1101 * @param int $site_id Unless you're running a multi-network install, be sure to set this value to 1.
1102 * @return int The ID of the new row
1103 */
1104function insert_blog($domain, $path, $site_id) {
1105	global $wpdb;
1106
1107	$path = trailingslashit($path);
1108	$site_id = (int) $site_id;
1109
1110	$result = $wpdb->insert( $wpdb->blogs, array('site_id' => $site_id, 'domain' => $domain, 'path' => $path, 'registered' => current_time('mysql')) );
1111	if ( ! $result )
1112		return false;
1113
1114	refresh_blog_details($wpdb->insert_id);
1115	return $wpdb->insert_id;
1116}
1117
1118/**
1119 * Install an empty blog.
1120 *
1121 * Creates the new blog tables and options. If calling this function
1122 * directly, be sure to use switch_to_blog() first, so that $wpdb
1123 * points to the new blog.
1124 *
1125 * @since MU
1126 * @uses make_db_current_silent()
1127 * @uses populate_roles()
1128 *
1129 * @param int $blog_id The value returned by insert_blog().
1130 * @param string $blog_title The title of the new site.
1131 */
1132function install_blog($blog_id, $blog_title = '') {
1133	global $wpdb, $wp_roles, $current_site;
1134
1135	// Cast for security
1136	$blog_id = (int) $blog_id;
1137
1138	require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
1139
1140	$wpdb->suppress_errors();
1141	if ( $wpdb->get_results( "DESCRIBE {$wpdb->posts}" ) )
1142		die( '<h1>' . __( 'Already Installed' ) . '</h1><p>' . __( 'You appear to have already installed WordPress. To reinstall please clear your old database tables first.' ) . '</p></body></html>' );
1143	$wpdb->suppress_errors( false );
1144
1145	$url = get_blogaddress_by_id( $blog_id );
1146
1147	// Set everything up
1148	make_db_current_silent( 'blog' );
1149	populate_options();
1150	populate_roles();
1151	$wp_roles->_init();
1152
1153	$url = untrailingslashit( $url );
1154
1155	update_option( 'siteurl', $url );
1156	update_option( 'home', $url );
1157
1158	if ( get_site_option( 'ms_files_rewriting' ) )
1159		update_option( 'upload_path', UPLOADBLOGSDIR . "/$blog_id/files" );
1160	else
1161		update_option( 'upload_path', get_blog_option( $current_site->blog_id, 'upload_path' ) );
1162
1163	update_option( 'blogname', stripslashes( $blog_title ) );
1164	update_option( 'admin_email', '' );
1165
1166	// remove all perms
1167	$table_prefix = $wpdb->get_blog_prefix();
1168	delete_metadata( 'user', 0, $table_prefix . 'user_level',   null, true ); // delete all
1169	delete_metadata( 'user', 0, $table_prefix . 'capabilities', null, true ); // delete all
1170}
1171
1172/**
1173 * Set blog defaults.
1174 *
1175 * This function creates a row in the wp_blogs table.
1176 *
1177 * @since MU
1178 * @deprecated MU
1179 * @deprecated Use wp_install_defaults()
1180 * @uses wp_install_defaults()
1181 *
1182 * @param int $blog_id Ignored in this function.
1183 * @param int $user_id
1184 */
1185function install_blog_defaults($blog_id, $user_id) {
1186	global $wpdb;
1187
1188	require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
1189
1190	$wpdb->suppress_errors();
1191
1192	wp_install_defaults($user_id);
1193
1194	$wpdb->suppress_errors( false );
1195}
1196
1197/**
1198 * Notify a user that her blog activation has been successful.
1199 *
1200 * Filter 'wpmu_welcome_notification' to disable or bypass.
1201 *
1202 * Filter 'update_welcome_email' and 'update_welcome_subject' to
1203 * modify the content and subject line of the notification email.
1204 *
1205 * @since MU
1206 *
1207 * @param int $blog_id
1208 * @param int $user_id
1209 * @param string $password
1210 * @param string $title The new blog's title
1211 * @param array $meta Optional. Not used in the default function, but is passed along to hooks for customization.
1212 * @return bool
1213 */
1214function wpmu_welcome_notification($blog_id, $user_id, $password, $title, $meta = '') {
1215	global $current_site;
1216
1217	if ( !apply_filters('wpmu_welcome_notification', $blog_id, $user_id, $password, $title, $meta) )
1218		return false;
1219
1220	$welcome_email = stripslashes( get_site_option( 'welcome_email' ) );
1221	if ( $welcome_email == false )
1222		$welcome_email = stripslashes( __( 'Dear User,
1223
1224Your new SITE_NAME site has been successfully set up at:
1225BLOG_URL
1226
1227You can log in to the administrator account with the following information:
1228Username: USERNAME
1229Password: PASSWORD
1230Log in here: BLOG_URLwp-login.php
1231
1232We hope you enjoy your new site. Thanks!
1233
1234--The Team @ SITE_NAME' ) );
1235
1236	$url = get_blogaddress_by_id($blog_id);
1237	$user = get_userdata( $user_id );
1238
1239	$welcome_email = str_replace( 'SITE_NAME', $current_site->site_name, $welcome_email );
1240	$welcome_email = str_replace( 'BLOG_TITLE', $title, $welcome_email );
1241	$welcome_email = str_replace( 'BLOG_URL', $url, $welcome_email );
1242	$welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email );
1243	$welcome_email = str_replace( 'PASSWORD', $password, $welcome_email );
1244
1245	$welcome_email = apply_filters( 'update_welcome_email', $welcome_email, $blog_id, $user_id, $password, $title, $meta);
1246	$admin_email = get_site_option( 'admin_email' );
1247
1248	if ( $admin_email == '' )
1249		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
1250
1251	$from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
1252	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
1253	$message = $welcome_email;
1254
1255	if ( empty( $current_site->site_name ) )
1256		$current_site->site_name = 'WordPress';
1257
1258	$subject = apply_filters( 'update_welcome_subject', sprintf(__('New %1$s Site: %2$s'), $current_site->site_name, stripslashes( $title ) ) );
1259	wp_mail($user->user_email, $subject, $message, $message_headers);
1260	return true;
1261}
1262
1263/**
1264 * Notify a user that her account activation has been successful.
1265 *
1266 * Filter 'wpmu_welcome_user_notification' to disable or bypass.
1267 *
1268 * Filter 'update_welcome_user_email' and 'update_welcome_user_subject' to
1269 * modify the content and subject line of the notification email.
1270 *
1271 * @since MU
1272 *
1273 * @param int $user_id
1274 * @param string $password
1275 * @param array $meta Optional. Not used in the default function, but is passed along to hooks for customization.
1276 * @return bool
1277 */
1278function wpmu_welcome_user_notification($user_id, $password, $meta = '') {
1279	global $current_site;
1280
1281	if ( !apply_filters('wpmu_welcome_user_notification', $user_id, $password, $meta) )
1282		return false;
1283
1284	$welcome_email = get_site_option( 'welcome_user_email' );
1285
1286	$user = get_userdata( $user_id );
1287
1288	$welcome_email = apply_filters( 'update_welcome_user_email', $welcome_email, $user_id, $password, $meta);
1289	$welcome_email = str_replace( 'SITE_NAME', $current_site->site_name, $welcome_email );
1290	$welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email );
1291	$welcome_email = str_replace( 'PASSWORD', $password, $welcome_email );
1292	$welcome_email = str_replace( 'LOGINLINK', wp_login_url(), $welcome_email );
1293
1294	$admin_email = get_site_option( 'admin_email' );
1295
1296	if ( $admin_email == '' )
1297		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
1298
1299	$from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
1300	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
1301	$message = $welcome_email;
1302
1303	if ( empty( $current_site->site_name ) )
1304		$current_site->site_name = 'WordPress';
1305
1306	$subject = apply_filters( 'update_welcome_user_subject', sprintf(__('New %1$s User: %2$s'), $current_site->site_name, $user->user_login) );
1307	wp_mail($user->user_email, $subject, $message, $message_headers);
1308	return true;
1309}
1310
1311/**
1312 * Get the current site info.
1313 *
1314 * Returns an object containing the ID, domain, path, and site_name
1315 * of the site being viewed.
1316 *
1317 * @since MU
1318 *
1319 * @return object
1320 */
1321function get_current_site() {
1322	global $current_site;
1323	return $current_site;
1324}
1325
1326/**
1327 * Get a numeric user ID from either an email address or a login.
1328 *
1329 * @since MU
1330 * @uses is_email()
1331 *
1332 * @param string $string
1333 * @return int
1334 */
1335function get_user_id_from_string( $string ) {
1336	$user_id = 0;
1337	if ( is_email( $string ) ) {
1338		$user = get_user_by('email', $string);
1339		if ( $user )
1340			$user_id = $user->ID;
1341	} elseif ( is_numeric( $string ) ) {
1342		$user_id = $string;
1343	} else {
1344		$user = get_user_by('login', $string);
1345		if ( $user )
1346			$user_id = $user->ID;
1347	}
1348
1349	return $user_id;
1350}
1351
1352/**
1353 * Get a user's most recent post.
1354 *
1355 * Walks through each of a user's blogs to find the post with
1356 * the most recent post_date_gmt.
1357 *
1358 * @since MU
1359 * @uses get_blogs_of_user()
1360 *
1361 * @param int $user_id
1362 * @return array Contains the blog_id, post_id, post_date_gmt, and post_gmt_ts
1363 */
1364function get_most_recent_post_of_user( $user_id ) {
1365	global $wpdb;
1366
1367	$user_blogs = get_blogs_of_user( (int) $user_id );
1368	$most_recent_post = array();
1369
1370	// Walk through each blog and get the most recent post
1371	// published by $user_id
1372	foreach ( (array) $user_blogs as $blog ) {
1373		$prefix = $wpdb->get_blog_prefix( $blog->userblog_id );
1374		$recent_post = $wpdb->get_row( $wpdb->prepare("SELECT ID, post_date_gmt FROM {$prefix}posts WHERE post_author = %d AND post_type = 'post' AND post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1", $user_id ), ARRAY_A);
1375
1376		// Make sure we found a post
1377		if ( isset($recent_post['ID']) ) {
1378			$post_gmt_ts = strtotime($recent_post['post_date_gmt']);
1379
1380			// If this is the first post checked or if this post is
1381			// newer than the current recent post, make it the new
1382			// most recent post.
1383			if ( !isset($most_recent_post['post_gmt_ts']) || ( $post_gmt_ts > $most_recent_post['post_gmt_ts'] ) ) {
1384				$most_recent_post = array(
1385					'blog_id'		=> $blog->userblog_id,
1386					'post_id'		=> $recent_post['ID'],
1387					'post_date_gmt'	=> $recent_post['post_date_gmt'],
1388					'post_gmt_ts'	=> $post_gmt_ts
1389				);
1390			}
1391		}
1392	}
1393
1394	return $most_recent_post;
1395}
1396
1397// Misc functions
1398
1399/**
1400 * Get the size of a directory.
1401 *
1402 * A helper function that is used primarily to check whether
1403 * a blog has exceeded its allowed upload space.
1404 *
1405 * @since MU
1406 * @uses recurse_dirsize()
1407 *
1408 * @param string $directory
1409 * @return int
1410 */
1411function get_dirsize( $directory ) {
1412	$dirsize = get_transient( 'dirsize_cache' );
1413	if ( is_array( $dirsize ) && isset( $dirsize[ $directory ][ 'size' ] ) )
1414		return $dirsize[ $directory ][ 'size' ];
1415
1416	if ( false == is_array( $dirsize ) )
1417		$dirsize = array();
1418
1419	$dirsize[ $directory ][ 'size' ] = recurse_dirsize( $directory );
1420
1421	set_transient( 'dirsize_cache', $dirsize, HOUR_IN_SECONDS );
1422	return $dirsize[ $directory ][ 'size' ];
1423}
1424
1425/**
1426 * Get the size of a directory recursively.
1427 *
1428 * Used by get_dirsize() to get a directory's size when it contains
1429 * other directories.
1430 *
1431 * @since MU
1432 *
1433 * @param string $directory
1434 * @return int
1435 */
1436function recurse_dirsize( $directory ) {
1437	$size = 0;
1438
1439	$directory = untrailingslashit( $directory );
1440
1441	if ( !file_exists($directory) || !is_dir( $directory ) || !is_readable( $directory ) )
1442		return false;
1443
1444	if ($handle = opendir($directory)) {
1445		while(($file = readdir($handle)) !== false) {
1446			$path = $directory.'/'.$file;
1447			if ($file != '.' && $file != '..') {
1448				if (is_file($path)) {
1449					$size += filesize($path);
1450				} elseif (is_dir($path)) {
1451					$handlesize = recurse_dirsize($path);
1452					if ($handlesize > 0)
1453						$size += $handlesize;
1454				}
1455			}
1456		}
1457		closedir($handle);
1458	}
1459	return $size;
1460}
1461
1462/**
1463 * Check an array of MIME types against a whitelist.
1464 *
1465 * WordPress ships with a set of allowed upload filetypes,
1466 * which is defined in wp-includes/functions.php in
1467 * get_allowed_mime_types(). This function is used to filter
1468 * that list against the filetype whitelist provided by Multisite
1469 * Super Admins at wp-admin/network/settings.php.
1470 *
1471 * @since MU
1472 *
1473 * @param array $mimes
1474 * @return array
1475 */
1476function check_upload_mimes( $mimes ) {
1477	$site_exts = explode( ' ', get_site_option( 'upload_filetypes' ) );
1478	foreach ( $site_exts as $ext ) {
1479		foreach ( $mimes as $ext_pattern => $mime ) {
1480			if ( $ext != '' && strpos( $ext_pattern, $ext ) !== false )
1481				$site_mimes[$ext_pattern] = $mime;
1482		}
1483	}
1484	return $site_mimes;
1485}
1486
1487/**
1488 * Update a blog's post count.
1489 *
1490 * WordPress MS stores a blog's post count as an option so as
1491 * to avoid extraneous COUNTs when a blog's details are fetched
1492 * with get_blog_details(). This function is called when posts
1493 * are published to make sure the count stays current.
1494 *
1495 * @since MU
1496 */
1497function update_posts_count( $deprecated = '' ) {
1498	global $wpdb;
1499	update_option( 'post_count', (int) $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_status = 'publish' and post_type = 'post'" ) );
1500}
1501
1502/**
1503 * Logs user registrations.
1504 *
1505 * @since MU
1506 *
1507 * @param int $blog_id
1508 * @param int $user_id
1509 */
1510function wpmu_log_new_registrations( $blog_id, $user_id ) {
1511	global $wpdb;
1512	$user = get_userdata( (int) $user_id );
1513	$wpdb->insert( $wpdb->registration_log, array('email' => $user->user_email, 'IP' => preg_replace( '/[^0-9., ]/', '',$_SERVER['REMOTE_ADDR'] ), 'blog_id' => $blog_id, 'date_registered' => current_time('mysql')) );
1514}
1515
1516/**
1517 * Maintains a canonical list 

Large files files are truncated, but you can click here to view the full file