From 5e2b6ac3aee89649d4bf8f6dd49f0628646b3515 Mon Sep 17 00:00:00 2001
From: unknown <Peter@.(none)>
Date: Thu, 16 Apr 2009 06:44:43 +0200
Subject: [PATCH] Loacal avatar

---
 account_prefs_avatar_add.php        |   57 +++++
 account_prefs_avatar_upload_inc.php |   81 +++++++
 account_prefs_inc.php               |    8 +
 config_defaults_inc.php             |    4 +-
 core/bug_api.php                    |    2 +-
 core/file_api.php                   |  441 +++++++++++++++--------------------
 core/print_api.php                  |   15 +-
 core/user_api.php                   |  166 +++++++-------
 file_download.php                   |   45 ++--
 manage_user_page.php                |    4 +
 10 files changed, 457 insertions(+), 366 deletions(-)
 create mode 100644 account_prefs_avatar_add.php
 create mode 100644 account_prefs_avatar_upload_inc.php

diff --git a/account_prefs_avatar_add.php b/account_prefs_avatar_add.php
new file mode 100644
index 0000000..052f021
--- /dev/null
+++ b/account_prefs_avatar_add.php
@@ -0,0 +1,57 @@
+<?php
+# Mantis - a php based bugtracking system
+
+# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
+# Copyright (C) 2002 - 2008  Mantis Team   - mantisbt-dev@lists.sourceforge.net
+
+# Mantis is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Mantis is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Mantis.  If not, see <http://www.gnu.org/licenses/>.
+
+	# Add avatar to the user profile
+
+	require_once( 'core.php' );
+
+	$t_core_path = config_get( 'core_path' );
+
+	require_once( $t_core_path.'file_api.php' );
+
+	# helper_ensure_post();
+
+	# avatar id is actually the same as user id
+	$f_user_id = gpc_get_int( 'avatar_id', -1 );
+	$f_file	   = gpc_get_file( 'file', -1 );
+
+	if ( $f_user_id == -1 && $f_file == -1 ) {
+		# _POST/_FILES does not seem to get populated if you exceed size limit so check if user_id is -1
+		trigger_error( ERROR_FILE_TOO_BIG, ERROR );
+	}
+	
+	access_ensure_global_level( config_get( 'show_avatar_threshold' ), $f_user_id );
+
+	file_add( $f_user_id, $f_file, 'avatar' );
+
+	# Determine which view page to redirect back to.
+	$t_redirect_url = 'account_prefs_page.php';
+
+	html_page_top( null, $t_redirect_url );
+?>
+<br />
+<div align="center">
+<?php
+	echo lang_get( 'operation_successful' ) . '<br />';
+	print_bracket_link( $t_redirect_url, lang_get( 'proceed' ) );
+?>
+</div>
+
+<?php
+	html_page_bottom( __FILE__ );
diff --git a/account_prefs_avatar_upload_inc.php b/account_prefs_avatar_upload_inc.php
new file mode 100644
index 0000000..ae514ad
--- /dev/null
+++ b/account_prefs_avatar_upload_inc.php
@@ -0,0 +1,81 @@
+<?php
+# MantisBT - a php based bugtracking system
+
+# MantisBT is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# MantisBT is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MantisBT.  If not, see <http://www.gnu.org/licenses/>.
+
+	/**
+	 * This include file prints out the bug file upload form
+	 * It POSTs to bug_file_add.php
+	 * @package MantisBT
+	 * @copyright Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
+	 * @copyright Copyright (C) 2002 - 2009  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+	 * @link http://www.mantisbt.org
+	 */
+
+	$t_core_path = config_get( 'core_path' );
+	require_once( $t_core_path.'file_api.php' );
+
+	$t_max_file_size = (int)min( ini_get_number( 'upload_max_filesize' ), ini_get_number( 'post_max_size' ), config_get( 'max_file_size' ) );
+?>
+<br />
+
+<?php
+	collapse_open( 'upload_form' );
+?>
+<form method="post" enctype="multipart/form-data" action="account_prefs_avatar_add.php">
+<table class="width75" cellspacing="1">
+<tr>
+	<td class="form-title" colspan="2">
+<?php
+		collapse_icon( 'upload_form' );
+		echo lang_get( 'upload_file' ) ?>
+	</td>
+	<td>
+<?php 
+		print_avatar ( $p_user_id ); ?>
+	</td>
+</tr>
+<tr class="row-1">
+	<td class="category" width="15%">
+		<?php echo lang_get( 'select_file' ) ?><br />
+		<?php echo '<span class="small">(' . lang_get( 'max_file_size' ) . ': ' . number_format( $t_max_file_size/1000 ) . 'k)</span>'?>
+	</td>
+	<td width="85%" colspan="2">
+		<input type="hidden" name="avatar_id" value="<?php echo $p_user_id ?>" />
+		<input type="hidden" name="max_file_size" value="<?php echo $t_max_file_size ?>" />
+		<input name="file" type="file" size="40" />
+		<input type="submit" class="button" value="<?php echo lang_get( 'upload_file_button' ) ?>" />
+	</td>
+</tr>
+</table>
+</form>
+<?php
+	collapse_closed( 'upload_form' );
+?>
+<table class="width75" cellspacing="1">
+<tr>
+	<td class="form-title" colspan="2">
+		<?php
+			collapse_icon( 'upload_form' );
+			echo lang_get( 'upload_file' ) ?>
+	</td>
+	<td>
+		<?php 
+			print_avatar ( $p_user_id ); ?>
+	</td>
+</tr>
+</table>
+
+<?php
+	collapse_end( 'upload_form' );
diff --git a/account_prefs_inc.php b/account_prefs_inc.php
index 404d3b4..06dde6e 100644
--- a/account_prefs_inc.php
+++ b/account_prefs_inc.php
@@ -307,6 +307,14 @@
 </tr>
 </table>
 </form>
+
+<?php
+# File upload box
+if ( config_get( 'show_avatar' ) ) {
+	include( $t_mantis_dir . 'account_prefs_avatar_upload_inc.php' );
+}
+?>
+
 </div>
 
 <br />
diff --git a/config_defaults_inc.php b/config_defaults_inc.php
index 1b754f5..eca438b 100644
--- a/config_defaults_inc.php
+++ b/config_defaults_inc.php
@@ -1571,7 +1571,8 @@
 	 * @global string $g_document_files_prefix
 	 */
 	$g_document_files_prefix = 'doc';
-
+	$g_avatar_files_prefix = 'avatar';
+	
 	/**
 	 * absolute path to the default upload folder.  Requires trailing / or \
 	 * @global string $g_absolute_path_default_upload_folder
@@ -2553,6 +2554,7 @@
 	 * table names
 	 * @global array $g_db_table
 	 */
+	$g_db_table['mantis_avatar_file_table']				= '%db_table_prefix%_avatar_file%db_table_suffix%';
 	$g_db_table['mantis_bug_file_table']				= '%db_table_prefix%_bug_file%db_table_suffix%';
 	$g_db_table['mantis_bug_history_table']				= '%db_table_prefix%_bug_history%db_table_suffix%';
 	$g_db_table['mantis_bug_monitor_table']				= '%db_table_prefix%_bug_monitor%db_table_suffix%';
diff --git a/core/bug_api.php b/core/bug_api.php
index 8473404..a08846b 100644
--- a/core/bug_api.php
+++ b/core/bug_api.php
@@ -765,7 +765,7 @@ function bug_copy( $p_bug_id, $p_target_project_id = null, $p_copy_custom_fields
 
 			# prepare the new diskfile name and then copy the file
 			$t_file_path = dirname( $t_bug_file['folder'] );
-			$t_new_diskfile_name = $t_file_path . file_generate_unique_name( 'bug-' . $t_bug_file['filename'], $t_file_path );
+			$t_new_diskfile_name = $t_file_path . file_generate_unique_name( 'bug' );
 			$t_new_file_name = file_get_display_name( $t_bug_file['filename'] );
 			if(( config_get( 'file_upload_method' ) == DISK ) ) {
 				copy( $t_bug_file['diskfile'], $t_new_diskfile_name );
diff --git a/core/file_api.php b/core/file_api.php
index 625e924..88f0d6c 100644
--- a/core/file_api.php
+++ b/core/file_api.php
@@ -36,7 +36,15 @@ require_once( $t_core_dir . 'bug_api.php' );
 $g_cache_file_count = array();
 
 # ## File API ###
-# Gets the filename without the bug id prefix.
+
+/**
+ * Gets the filename without the bug id prefix 
+ * 
+ * In fact no code really cares for whats coming from here
+ * 
+ * @param	string	$p_filename	The file name
+ * @return	string				The file name
+ */
 function file_get_display_name( $p_filename ) {
 	$t_array = explode( '-', $p_filename, 2 );
 
@@ -48,18 +56,21 @@ function file_get_display_name( $p_filename ) {
 	$t_name = preg_split( $t_doc_match, $p_filename );
 	if( isset( $t_name[1] ) ) {
 		return $t_name[1];
-	} else {
-		$t_bug_match = '/^\d{7}-/';
-		$t_name = preg_split( $t_bug_match, $p_filename );
-		if( isset( $t_name[1] ) ) {
-			return $t_name[1];
-		} else {
-			return $p_filename;
-		}
 	}
+	$t_bug_match = '/^\d{7}-/';
+	$t_name = preg_split( $t_bug_match, $p_filename );
+	if( isset( $t_name[1] ) ) {
+		return $t_name[1];
+	}
+	return $p_filename;
 }
 
-# Check the number of attachments a bug has (if any)
+/**
+ * Check the number of attachments a bug has (if any)
+ * 
+ *  @param	integer	$p_bug_id
+ *  @return	integer				Number of attachments
+ */
 function file_bug_attachment_count( $p_bug_id ) {
 	global $g_cache_file_count;
 
@@ -102,7 +113,11 @@ function file_bug_attachment_count( $p_bug_id ) {
 	return $t_file_count;
 }
 
-# Check if a specific bug has attachments
+/**
+ * Check if a specific bug has attachments
+ * @param	integer	$p_bug_id
+ * @return	bool
+ */
 function file_bug_has_attachments( $p_bug_id ) {
 	if( file_bug_attachment_count( $p_bug_id ) > 0 ) {
 		return true;
@@ -111,45 +126,50 @@ function file_bug_has_attachments( $p_bug_id ) {
 	}
 }
 
-# Check if the current user can view attachments for the specified bug.
-function file_can_view_bug_attachments( $p_bug_id ) {
+function file_can_do_with_bug ( $p_bug_id, $p_what ) {
 	$t_reported_by_me = bug_is_user_reporter( $p_bug_id, auth_get_current_user_id() );
-	$t_can_view = access_has_bug_level( config_get( 'view_attachments_threshold' ), $p_bug_id );
+	$t_can_do = access_has_bug_level( config_get( $p_what.'_attachments_threshold' ), $p_bug_id );
+	$t_can_do_own = config_get( 'allow_'.$p_what.'_own_attachments' ); 
 
-	/** @todo Fix this to be readable */
-	$t_can_view = $t_can_view || ( $t_reported_by_me && config_get( 'allow_view_own_attachments' ) );
+	$t_can_do = $t_can_do || ( $t_reported_by_me && $t_can_do_own );
 
-	return $t_can_view;
+	return $t_can_do;
+}
+/**
+ * Check if the current user can view attachments for the specified bug.
+ * @param	integer	$p_bug_id
+ * @return	bool
+ */
+function file_can_view_bug_attachments( $p_bug_id ) {
+	return file_can_do_with_bug ( $p_bug_id, 'view');
 }
 
-# Check if the current user can download attachments for the specified bug.
+/**
+ * Check if the current user can download attachments for the specified bug.
+ * @param	integer	$p_bug_id
+ * @return	bool
+ */
 function file_can_download_bug_attachments( $p_bug_id ) {
-	$t_reported_by_me = bug_is_user_reporter( $p_bug_id, auth_get_current_user_id() );
-	$t_can_download = access_has_bug_level( config_get( 'download_attachments_threshold' ), $p_bug_id );
-
-	/** @todo Fix this to be readable */
-	$t_can_download = $t_can_download || ( $t_reported_by_me && config_get( 'allow_download_own_attachments' ) );
-
-	return $t_can_download;
+	return file_can_do_with_bug ( $p_bug_id, 'download');
 }
 
-# Check if the current user can delete attachments from the specified bug.
+/**
+ * Check if the current user can delete attachments from the specified bug.
+ * @param	integer	$p_bug_id
+ * @return	bool
+ */
 function file_can_delete_bug_attachments( $p_bug_id ) {
 	if( bug_is_readonly( $p_bug_id ) ) {
 		return false;
 	}
-
-	$t_reported_by_me = bug_is_user_reporter( $p_bug_id, auth_get_current_user_id() );
-	$t_can_download = access_has_bug_level( config_get( 'delete_attachments_threshold' ), $p_bug_id );
-
-	/** @todo Fix this to be readable */
-	$t_can_download = $t_can_download || ( $t_reported_by_me && config_get( 'allow_delete_own_attachments' ) );
-
-	return $t_can_download;
+	return file_can_do_with_bug ( $p_bug_id, 'delete');
 }
 
-# Get icon corresponding to the specified filename
-# returns an associative array with "url" and "alt" text.
+/**
+ * Get icon corresponding to the specified filename
+ * @param	string	$p_display_filename
+ * @return	array						which has url and alt members
+ */
 function file_get_icon_url( $p_display_filename ) {
 	$t_file_type_icons = config_get( 'file_type_icons' );
 
@@ -165,8 +185,8 @@ function file_get_icon_url( $p_display_filename ) {
 /**
  * Combines a path and a file name making sure that the separator exists.
  *
- * @param string $p_path       The path.
- * @param string $p_filename   The file name.
+ * @param string $p_path		The path.
+ * @param string $p_filename	The file name.
  *
  * @return The combined full path.
  */
@@ -182,16 +202,18 @@ function file_path_combine( $p_path, $p_filename ) {
 }
 
 /**
- * Nomalizes the disk file path based on the following algorithm:
- * 1. If disk file exists, then return as is.
- * 2. If not, and a project path is available, then check with that, if exists return it.
- * 3. If not, then use default upload path, then check with that, if exists return it.
- * 4. If disk file doesn't include a path, then return expected path based on project path or default path.
- * 5. Otherwise return as is.
+ * Nomalizes the disk file path.
+ * 
+ * Uses the following algorithm:
+ * 1 If disk file exists, then return as is
+ * 2 If not, and a project path is available, then check with that, if exists return it
+ * 3 If not, then use default upload path, then check with that, if exists return it
+ * 4 If disk file doesn't include a path, then return expected path based on project path or default path
+ * 5 Otherwise return as is.
  *
- * @param string $p_diskfile  The disk file (full path or just filename).
- * @param integer The project id - shouldn't be 0 (ALL_PROJECTS).
- * @return The normalized full path.
+ * @param string $p_diskfile	The disk file (full path or just filename).
+ * @param integer $p_project_id	The project id - shouldn't be 0 (ALL_PROJECTS).
+ * @return string				The normalized full path.
  */
 function file_normalize_attachment_path( $p_diskfile, $p_project_id ) {
 	if ( file_exists( $p_diskfile ) ) {
@@ -239,21 +261,26 @@ function file_normalize_attachment_path( $p_diskfile, $p_project_id ) {
 	return $p_diskfile;
 }
 
-# --------------------
-# Gets an array of attachments that are visible to the currently logged in user.
-# Each element of the array contains the following:
-# display_name - The attachment display name (i.e. file name dot extension)
-# size - The attachment size in bytes.
-# date_added - The date where the attachment was added.
-# can_download - true: logged in user has access to download the attachment, false: otherwise.
-# diskfile - The name of the file on disk.  Typically this is a hash without an extension.
-# download_url - The download URL for the attachment (only set if can_download is true).
-# exists - Applicable for DISK attachments.  true: file exists, otherwise false.
-# can_delete - The logged in user can delete the attachments.
-# preview - true: the attachment should be previewable, otherwise false.
-# type - Can be "image", "text" or empty for other types.
-# alt - The alternate text to be associated with the icon.
-# icon - array with icon information, contains 'url' and 'alt' elements.
+/**
+ * Gets an array of attachments that are visible to the currently logged in user.
+ * 
+ * Each element of the array contains the following:
+ * display_name	- The attachment display name (file name dot extension)
+ * size			- The attachment size in bytes
+ * date_added	- The date where the attachment was added
+ * can_download	- true: logged in user has access to download the attachment, false: otherwise
+ * diskfile		- The name of the file on disk Typically this is a hash without an extension
+ * download_url - The download URL for the attachment (only set if can_download is true) 
+ * exists - Applicable for DISK attachments.  true: file exists, otherwise false.
+ * can_delete - The logged in user can delete the attachments.
+ * preview - true: the attachment should be previewable, otherwise false.
+ * type - Can be "image", "text" or empty for other types.
+ * alt - The alternate text to be associated with the icon.
+ * icon - array with icon information, contains 'url' and 'alt' elements.
+ * 
+ * @param	integer	$p_bug_id
+ * @return	array
+ */
 function file_get_visible_attachments( $p_bug_id ) {
 	$t_attachment_rows = bug_get_attachments( $p_bug_id );
 	$t_visible_attachments = array();
@@ -324,101 +351,64 @@ function file_get_visible_attachments( $p_bug_id ) {
 	return $t_attachments;
 }
 
-# delete all files that are associated with the given bug
-function file_delete_attachments( $p_bug_id ) {
-	$c_bug_id = db_prepare_int( $p_bug_id );
-
-	$t_bug_file_table = db_get_table( 'mantis_bug_file_table' );
-
+/**
+ * Remove files from the given table based on the key
+ * 
+ * This is used to remove all the attachments, documents or avatars This function
+ * should be called only by the specialized functions which know the table from
+ * where to delete.
+ * 
+ * @param	integer	$p_id
+ * @param	string	$p_table
+ * @return	boolean	true
+ * @access	private
+ */
+function file_delete_many ( $p_id, $p_table ) {
+	$c_id = db_prepare_int( $p_id );
+	$t_file_table = db_get_table( 'mantis_'.$p_table.'_file_table' );
 	$t_method = config_get( 'file_upload_method' );
 
 	# Delete files from disk
-	$query = "SELECT diskfile, filename
-				FROM $t_bug_file_table
-				WHERE bug_id=" . db_param();
-	$result = db_query_bound( $query, Array( $c_bug_id ) );
+	$query = "SELECT id
+				FROM $t_file_table
+				WHERE ".$p_table."_id=" . db_param();
+	$result = db_query_bound( $query, Array( $c_id ) );
 
 	$file_count = db_num_rows( $result );
 	if( 0 == $file_count ) {
 		return true;
 	}
-
-	if(( DISK == $t_method ) || ( FTP == $t_method ) ) {
-
-		# there may be more than one file
-		$ftp = 0;
-		if( FTP == $t_method ) {
-			$ftp = file_ftp_connect();
-		}
-
-		for( $i = 0;$i < $file_count;$i++ ) {
-			$row = db_fetch_array( $result );
-
-			$t_local_diskfile = file_normalize_attachment_path( $row['diskfile'], bug_get_field( $p_bug_id, 'project_id' ) );
-			file_delete_local( $t_local_diskfile );
-
-			if( FTP == $t_method ) {
-				file_ftp_delete( $ftp, $row['diskfile'] );
-			}
-		}
-
-		if( FTP == $t_method ) {
-			file_ftp_disconnect( $ftp );
-		}
-	}
-
-	# Delete the corresponding db records
-	$query = "DELETE FROM $t_bug_file_table
-				  WHERE bug_id=" . db_param();
-	$result = db_query_bound( $query, Array( $c_bug_id ) );
-
+	for( $i = 0;$i < $file_count;$i++ ) {
+		$row = db_fetch_array( $result );
+		file_delete ( $row['id'], $p_table );
+	}	
 	# db_query errors on failure so:
 	return true;
 }
 
-function file_delete_project_files( $p_project_id ) {
-	$t_project_file_table = db_get_table( 'mantis_project_file_table' );
-	$t_method = config_get( 'file_upload_method' );
-
-	# Delete the file physically (if stored via DISK or FTP)
-	if(( DISK == $t_method ) || ( FTP == $t_method ) ) {
-
-		# Delete files from disk
-		$query = "SELECT diskfile, filename
-					FROM $t_project_file_table
-					WHERE project_id=" . db_param();
-		$result = db_query_bound( $query, array( (int) $p_project_id ) );
-
-		$file_count = db_num_rows( $result );
-
-		$ftp = 0;
-		if( FTP == $t_method ) {
-			$ftp = file_ftp_connect();
-		}
-
-		for( $i = 0;$i < $file_count;$i++ ) {
-			$row = db_fetch_array( $result );
-
-			$t_local_diskfile = file_normalize_attachment_path( $row['diskfile'], $p_project_id );
-			file_delete_local( $t_local_diskfile );
 
-			if( FTP == $t_method ) {
-				file_ftp_delete( $ftp, $row['diskfile'] );
-			}
-		}
+/**
+ * Delete all files that are associated with the given bug
+ * @param $p_bug_id
+ * @return unknown_type
+ */
+function file_delete_attachments( $p_bug_id ) {
+	return file_delete_many ( $p_bug_id, 'bug');
+}
 
-		if( FTP == $t_method ) {
-			file_ftp_disconnect( $ftp );
-		}
-	}
+function file_delete_project_files( $p_project_id ) {
+	return file_delete_many ( $p_project_id, 'project');
+}
 
-	# Delete the corresponding db records
-	$query = "DELETE FROM $t_project_file_table
-				WHERE project_id=" . db_param();
-	$result = db_query_bound( $query, Array( (int) $p_project_id ) );
+function file_delete_avatars( $p_avatar_id ) {
+	return file_delete_many ( $p_avatar_id, 'avatar');
 }
 
-# Delete all cached files that are older than configured number of days.
+/**
+ * Delete all cached files that are older than configured number of days.
+ * 
+ * @return unknown_type
+ */
 function file_ftp_cache_cleanup() {
 }
 
@@ -434,7 +424,14 @@ function file_ftp_connect() {
 	return $conn_id;
 }
 
-# Put a file to the ftp server.
+/**
+ * Put a file to the ftp server.
+ * 
+ * @param $p_conn_id
+ * @param $p_remote_filename
+ * @param $p_local_filename
+ * @return unknown_type
+ */
 function file_ftp_put( $p_conn_id, $p_remote_filename, $p_local_filename ) {
 	helper_begin_long_process();
 	$upload = ftp_put( $p_conn_id, $p_remote_filename, $p_local_filename, FTP_BINARY );
@@ -485,11 +482,10 @@ function file_delete( $p_file_id, $p_table = 'bug' ) {
 	$t_filename = file_get_field( $p_file_id, 'filename', $p_table );
 	$t_diskfile = file_get_field( $p_file_id, 'diskfile', $p_table );
 
+	$t_project_id = file_get_field( $p_file_id, $p_table.'_id', $p_table );
+	$t_bug_id = $t_project_id;
 	if ( $p_table == 'bug' ) {
-		$t_bug_id = file_get_field( $p_file_id, 'bug_id', $p_table );
 		$t_project_id = bug_get_field( $t_bug_id, 'project_id' );
-	} else {
-		$t_project_id = file_get_field( $p_file_id, 'project_id', $p_table );
 	}
 
 	if(( DISK == $t_upload_method ) || ( FTP == $t_upload_method ) ) {
@@ -523,35 +519,23 @@ function file_delete( $p_file_id, $p_table = 'bug' ) {
 
 # File type check
 function file_type_check( $p_file_name ) {
-	$t_allowed_files = config_get( 'allowed_files' );
-	$t_disallowed_files = config_get( 'disallowed_files' );;
+	$t_allowed_files = strtolower(config_get( 'allowed_files' ));
+	$t_disallowed_files = strtolower(config_get( 'disallowed_files' ));
 
 	# grab extension
-	$t_ext_array = explode( '.', $p_file_name );
-	$last_position = count( $t_ext_array ) - 1;
-	$t_extension = $t_ext_array[$last_position];
+	$t_extension = strtolower(file_get_extension( $p_file_name ));
 
 	# check against disallowed files
-	$t_disallowed_arr = explode( ',', $t_disallowed_files );
-	foreach( $t_disallowed_arr as $t_val ) {
-		if( 0 == strcasecmp( $t_val, $t_extension ) ) {
-			return false;
-		}
+	if ( in_array($t_extension, explode( ',', $t_disallowed_files ))) {
+		return false;
 	}
 
 	# if the allowed list is note populated then the file must be allowed
-	if( is_blank( $t_allowed_files ) ) {
+	# or check against allowed files
+	if ( is_blank( $t_allowed_files ) || in_array($t_extension, explode( ',', $t_allowed_files ))) {
 		return true;
 	}
 
-	# check against allowed files
-	$t_allowed_arr = explode( ',', $t_allowed_files );
-	foreach( $t_allowed_arr as $t_val ) {
-		if( 0 == strcasecmp( $t_val, $t_extension ) ) {
-			return true;
-		}
-	}
-
 	return false;
 }
 
@@ -560,53 +544,29 @@ function file_clean_name( $p_filename ) {
 	return preg_replace( "/[\/\\ :&]/", "_", $p_filename );
 }
 
-# Generate a string to use as the identifier for the file
-# It is not guaranteed to be unique and should be checked
-# The string returned should be 32 characters in length
-function file_generate_name( $p_seed ) {
-	$t_val = md5( $p_seed . time() );
-
-	return substr( $t_val, 0, 32 );
-}
-
-# Generate a UNIQUE string to use as the identifier for the file
-# The string returned should be 64 characters in length
-function file_generate_unique_name( $p_seed, $p_filepath ) {
-	do {
-		$t_string = file_generate_name( $p_seed );
-	}
-	while( !diskfile_is_name_unique( $t_string, $p_filepath ) );
-
-	return $t_string;
-}
-
-# Return true if the diskfile name identifier is unique, false otherwise
-function diskfile_is_name_unique( $p_name, $p_filepath ) {
-	$t_file_table = db_get_table( 'mantis_bug_file_table' );
-
-	$c_name = $p_filepath . $p_name;
-
-	$query = "SELECT COUNT(*)
-				  FROM $t_file_table
-				  WHERE diskfile=" . db_param();
-	$result = db_query_bound( $query, Array( $c_name ) );
-	$t_count = db_result( $result );
-
-	if( $t_count > 0 ) {
-		return false;
-	} else {
-		return true;
-	}
+function file_generate_unique_name( $p_prefix ) {
+	return uniqid( $p_prefix, true );
 }
 
-# Return true if the file name identifier is unique, false otherwise
-function file_is_name_unique( $p_name, $p_bug_id ) {
-	$t_file_table = db_get_table( 'mantis_bug_file_table' );
+/**
+ * Check if filename is unique.
+ * 
+ * The function will check the appropriate table for
+ * duplicate file names.
+ * 
+ * @param	string	$p_name		file name
+ * @param 	integer	$p_key_id	bug_id, avatar_id or document_id
+ * @param 	string	$p_table	bug, doc, avatar
+ * @return	boolean
+ */
+function file_is_name_unique( $p_name, $p_key_id, $p_table = 'bug' ) {
+	if ( 'doc' == $p_table ) { $p_table = 'project'; }
+	$t_file_table = db_get_table( 'mantis_'.$p_table.'_file_table' );
 
 	$query = "SELECT COUNT(*)
 				  FROM $t_file_table
-				  WHERE filename=" . db_param() . " AND bug_id=" . db_param();
-	$result = db_query_bound( $query, Array( $p_name, $p_bug_id ) );
+				  WHERE filename=" . db_param() . " AND ".$p_table."_id=" . db_param();
+	$result = db_query_bound( $query, Array( $p_name, $p_key_id ) );
 	$t_count = db_result( $result );
 
 	if( $t_count > 0 ) {
@@ -622,30 +582,42 @@ function file_is_name_unique( $p_name, $p_bug_id ) {
  * @param integer $p_bug_id the bug id
  * @param array $p_file the uploaded file info, as retrieved from gpc_get_file()
  */
-function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc = '' ) {
+function file_add( $p_key_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc = '' ) {
 
 	file_ensure_uploaded( $p_file );
 	$t_file_name = $p_file['name'];
 	$t_tmp_file = $p_file['tmp_name'];
-
+	$t_file_table = db_get_table( 'mantis_' . $p_table . '_file_table' );
+	
 	if( !file_type_check( $t_file_name ) ) {
 		trigger_error( ERROR_FILE_NOT_ALLOWED, ERROR );
 	}
-
-	if( !file_is_name_unique( $t_file_name, $p_bug_id ) ) {
+	
+	if( !file_is_name_unique( $t_file_name, $p_key_id, $p_table ) ) {
 		trigger_error( ERROR_DUPLICATE_FILE, ERROR );
 	}
-
-	if( 'bug' == $p_table ) {
-		$t_project_id = bug_get_field( $p_bug_id, 'project_id' );
-		$t_bug_id = bug_format_id( $p_bug_id );
-	} else {
-		$t_project_id = helper_get_current_project();
-		$t_bug_id = 0;
+	
+	switch ( $p_table ) {
+		case 'bug':
+			$t_project_id = bug_get_field( $p_key_id, 'project_id' );
+			$t_key_id = bug_format_id( $p_key_id );
+			$t_file_hash = $t_key_id;
+			$c_id = db_prepare_int( $p_key_id );
+			break;
+		case 'avatar':
+			$t_project_id = ALL_PROJECTS;
+			$t_file_name = config_get( 'avatar_files_prefix' ) . '-' . $p_key_id;
+			$c_id = db_prepare_int( $p_key_id );
+			break;
+		default:
+			$t_project_id = helper_get_current_project();
+			$t_file_name = config_get( 'document_files_prefix' ) . '-' . $t_project_id;
+			$c_id = db_prepare_int( $t_project_id );
+			break;
 	}
 
 	# prepare variables for insertion
-	$c_bug_id = db_prepare_int( $p_bug_id );
+	$c_key_id = db_prepare_int( $p_key_id );
 	$c_project_id = db_prepare_int( $t_project_id );
 	$c_file_type = db_prepare_string( $p_file['type'] );
 	$c_title = db_prepare_string( $p_title );
@@ -661,9 +633,7 @@ function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc
 	}
 	$c_file_path = db_prepare_string( $t_file_path );
 	$c_new_file_name = db_prepare_string( $t_file_name );
-
-	$t_file_hash = ( 'bug' == $p_table ) ? $t_bug_id : config_get( 'document_files_prefix' ) . '-' . $t_project_id;
-	$t_unique_name = file_generate_unique_name( $t_file_hash . '-' . $t_file_name, $t_file_path );
+	$t_unique_name = file_generate_unique_name( $p_table );
 	$t_disk_file_name = $t_file_path . $t_unique_name;
 	$c_unique_name = db_prepare_string( $t_unique_name );
 
@@ -709,9 +679,6 @@ function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc
 			trigger_error( ERROR_GENERIC, ERROR );
 	}
 
-	$t_file_table = db_get_table( 'mantis_' . $p_table . '_file_table' );
-	$c_id = ( 'bug' == $p_table ) ? $c_bug_id : $c_project_id;
-
 	$query = "INSERT INTO $t_file_table
 						(" . $p_table . "_id, title, description, diskfile, filename, folder, filesize, file_type, date_added, content)
 					  VALUES
@@ -721,10 +688,10 @@ function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc
 	if( 'bug' == $p_table ) {
 
 		# updated the last_updated date
-		$result = bug_update_date( $p_bug_id );
+		$result = bug_update_date( $p_key_id );
 
 		# log new bug
-		history_log_event_special( $p_bug_id, FILE_ADDED, $t_file_name );
+		history_log_event_special( $p_key_id, FILE_ADDED, $t_file_name );
 	}
 }
 
@@ -836,27 +803,5 @@ function file_ensure_uploaded( $p_file ) {
 
 # Get extension given the filename or its full path.
 function file_get_extension( $p_filename ) {
-	$ext = '';
-	$dot_found = false;
-	$i = strlen( $p_filename ) - 1;
-	while( $i >= 0 ) {
-		if( '.' == $p_filename[$i] ) {
-			$dot_found = true;
-			break;
-		}
-
-		# foung a directoryarker before a period.
-		if(( $p_filename[$i] == "/" ) || ( $p_filename[$i] == "\\" ) ) {
-			return '';
-		}
-
-		$ext = $p_filename[$i] . $ext;
-		$i--;
-	}
-
-	if( $dot_found ) {
-		return $ext;
-	} else {
-		return '';
-	}
+	return pathinfo($p_filename, PATHINFO_EXTENSION);
 }
diff --git a/core/print_api.php b/core/print_api.php
index c2c4eea..7cb304b 100644
--- a/core/print_api.php
+++ b/core/print_api.php
@@ -146,22 +146,23 @@ function print_successful_redirect( $p_redirect_to ) {
 }
 
 # Print avatar image for the given user ID
-function print_avatar( $p_user_id, $p_size = 80 ) {
-	if( !user_exists( $p_user_id ) ) {
+function print_avatar( $p_user_id ) {
+	if ( !user_exists( $p_user_id ) ) {
 		return;
 	}
 
-	if( access_has_project_level( config_get( 'show_avatar_threshold' ), null, $p_user_id ) ) {
-		$t_avatar = user_get_avatar( $p_user_id, $p_size );
-		if( false !== $t_avatar ) {
+	if ( access_has_project_level( config_get( 'show_avatar_threshold' ), null, $p_user_id ) ) {
+		$t_avatar = user_get_avatar( $p_user_id );
+		if ( false !== $t_avatar ) {
 			$t_avatar_url = $t_avatar[0];
 			$t_width = $t_avatar[1];
 			$t_height = $t_avatar[2];
-			echo '<a rel="nofollow" href="http://site.gravatar.com">' . '<img class="avatar" src="' . $t_avatar_url . '" alt="User avatar"' . ' width="' . $t_width . '" height="' . $t_height . '" /></a>';
+			$t_href = $t_avatar[3];
+			echo '<a rel="nofollow" href="'.$t_href.'"><img class="avatar" src="'.$t_avatar_url.'" alt="User avatar" width="'.$t_width.'" height="'.$t_height.'" /></a>';
 		}
 	}
 }
-
+	
 # --------------------
 # prints the name of the user given the id.  also makes it an email link.
 function print_user( $p_user_id ) {
diff --git a/core/user_api.php b/core/user_api.php
index cb908fb..4569319 100644
--- a/core/user_api.php
+++ b/core/user_api.php
@@ -518,18 +518,16 @@ function user_signup( $p_username, $p_email = null ) {
 	return user_create( $p_username, $t_password, $p_email );
 }
 
-# --------------------
-# delete project-specific user access levels.
-# returns true when successfully deleted
-function user_delete_project_specific_access_levels( $p_user_id ) {
+function user_delete_from ( $p_user_id, $p_key_id, $p_table ) {
 	$c_user_id = db_prepare_int( $p_user_id );
 
 	user_ensure_unprotected( $p_user_id );
 
-	$t_project_user_list_table = db_get_table( 'mantis_project_user_list_table' );
+	$t_table = db_get_table( $p_table );
 
-	$query = "DELETE FROM $t_project_user_list_table
-				  WHERE user_id=" . db_param();
+	# Remove associated profiles
+	$query = "DELETE FROM $t_table
+				  WHERE '.$p_key_id.'=" . db_param();
 	db_query_bound( $query, Array( $c_user_id ) );
 
 	user_clear_cache( $p_user_id );
@@ -538,23 +536,26 @@ function user_delete_project_specific_access_levels( $p_user_id ) {
 }
 
 # --------------------
+# delete project-specific user access levels.
+# returns true when successfully deleted
+function user_delete_project_specific_access_levels( $p_user_id ) {
+	return user_delete_from ( $p_user_id, 'user_id', 'mantis_project_user_list_table' );
+}
+
+# --------------------
 # delete profiles for the specified user
 # returns true when successfully deleted
 function user_delete_profiles( $p_user_id ) {
-	$c_user_id = db_prepare_int( $p_user_id );
-
-	user_ensure_unprotected( $p_user_id );
-
-	$t_user_profile_table = db_get_table( 'mantis_user_profile_table' );
-
-	# Remove associated profiles
-	$query = "DELETE FROM $t_user_profile_table
-				  WHERE user_id=" . db_param();
-	db_query_bound( $query, Array( $c_user_id ) );
-
-	user_clear_cache( $p_user_id );
+	return user_delete_from ( $p_user_id, 'user_id', 'mantis_user_profile_table' );
+}
 
-	return true;
+# --------------------
+# delete avatar(s) for the specified user
+# returns true when successfully deleted
+function user_delete_avatar ( $p_avatar_id ) {
+	user_ensure_unprotected( $p_avatar_id );
+	file_delete_avatars ( $p_avatar_id );
+	return user_delete_from ( $p_avatar_id, 'avatar_id', 'mantis_avatar_profile_table' );
 }
 
 # --------------------
@@ -567,6 +568,9 @@ function user_delete( $p_user_id ) {
 	user_ensure_unprotected( $p_user_id );
 
 	# Remove associated profiles
+	user_delete_avatar( $p_user_id );
+	
+	# Remove associated profiles
 	user_delete_profiles( $p_user_id );
 
 	# Remove associated preferences
@@ -608,11 +612,9 @@ function user_delete( $p_user_id ) {
 # Data Access
 # ===================================
 # --------------------
-# get a user id from a username
-#  return false if the username does not exist
-function user_get_id_by_name( $p_username ) {
+function user_get_id_by ( $p_key, $p_value ) {
 	global $g_cache_user;
-	if( $t_user = user_search_cache( 'username', $p_username ) ) {
+	if( $t_user = user_search_cache( $p_key, $p_value ) ) {
 		return $t_user['id'];
 	}
 
@@ -620,8 +622,8 @@ function user_get_id_by_name( $p_username ) {
 
 	$query = "SELECT *
 				  FROM $t_user_table
-				  WHERE username=" . db_param();
-	$result = db_query_bound( $query, Array( $p_username ) );
+				  WHERE $p_key=" . db_param();
+	$result = db_query_bound( $query, Array( $p_value ) );
 
 	if( 0 == db_num_rows( $result ) ) {
 		return false;
@@ -632,50 +634,19 @@ function user_get_id_by_name( $p_username ) {
 	}
 }
 
-# Get a user id from an email address
-function user_get_id_by_email( $p_email ) {
-	global $g_cache_user;
-	if( $t_user = user_search_cache( 'email', $p_email ) ) {
-		return $t_user['id'];
-	}
-
-	$t_user_table = db_get_table( 'mantis_user_table' );
 
-	$query = "SELECT *
-				  FROM $t_user_table
-				  WHERE email=" . db_param();
-	$result = db_query_bound( $query, Array( $p_email ) );
+function user_get_id_by_name( $p_username ) {
+	return user_get_id_by ( 'username', $p_username );
+}
 
-	if( 0 == db_num_rows( $result ) ) {
-		return false;
-	} else {
-		$row = db_fetch_array( $result );
-		user_cache_database_result( $row );
-		return $row['id'];
-	}
+# Get a user id from an email address
+function user_get_id_by_email( $p_email ) {
+	return user_get_id_by ( 'email', $p_email );
 }
 
 # Get a user id from their real name
 function user_get_id_by_realname( $p_realname ) {
-	global $g_cache_user;
-	if( $t_user = user_search_cache( 'realname', $p_realname ) ) {
-		return $t_user['id'];
-	}
-
-	$t_user_table = db_get_table( 'mantis_user_table' );
-
-	$query = "SELECT *
-				  FROM $t_user_table
-				  WHERE realname=" . db_param();
-	$result = db_query_bound( $query, Array( $p_realname ) );
-
-	if( 0 == db_num_rows( $result ) ) {
-		return false;
-	} else {
-		$row = db_fetch_array( $result );
-		user_cache_database_result( $row );
-		return $row['id'];
-	}
+	return user_get_id_by ( 'realname', $p_realname );
 }
 
 # --------------------
@@ -770,30 +741,59 @@ function user_get_name( $p_user_id ) {
 * @return array|bool an array( URL, width, height ) or false when the given user has no avatar
 */
 function user_get_avatar( $p_user_id, $p_size = 80 ) {
-	$t_email = strtolower( user_get_email( $p_user_id ) );
-	if( is_blank( $t_email ) ) {
-		$t_result = false;
-	} else {
-		$t_default_image = config_get( 'default_avatar' );
-		$t_size = $p_size;
+	$t_avatar_type = strtolower ( config_get ( 'avatar_type' ) );
+	$t_found_local_avatar = false;
 
-		$t_use_ssl = false;
-		if( isset( $_SERVER['HTTPS'] ) && ( strtolower( $_SERVER['HTTPS'] ) != 'off' ) ) {
-			$t_use_ssl = true;
+	if ( $t_avatar_type == 'local' ) {
+		$c_user_id = db_prepare_int ( $p_user_id );
+		$t_avatar_table = db_get_table ( 'mantis_avatar_file_table' );
+		$query = "SELECT id
+				  FROM $t_avatar_table
+				  WHERE avatar_id='$c_user_id'";
+		$t_db_result = db_query ( $query );
+		/*
+		 * theoretically you could have more than one local avatar
+		 * but for now only one is allowed.
+		 */
+		if ( 1 == db_num_rows( $t_db_result )) {
+			$t_found_local_avatar = true;
+			$t_avatar_id = db_result ( $t_db_result );
+			$t_avatar_url = "file_download.php?type=avatar&amp;file_id=".$t_avatar_id;
+			$t_avatar_ref = "manage_user_edit_page.php?user_id=".$p_user_id;
+			$t_size = $p_size;
+			$t_result = array( $t_avatar_url, $t_size, $t_size, $t_avatar_ref );
 		}
+	}
 
-		if( !$t_use_ssl ) {
-			$t_gravatar_domain = 'http://www.gravatar.com/';
+	// if local avatar is disabled or not found check the gravatar
+	if ( ! $t_found_local_avatar ) {
+		// for gravatar you need a valid email
+		$t_email = strtolower( user_get_email( $p_user_id ) );
+		if( is_blank( $t_email ) ) {
+			$t_result = false;
 		} else {
-			$t_gravatar_domain = 'https://secure.gravatar.com/';
+			$t_default_image = config_get( 'default_avatar' );
+			$t_size = $p_size;
+	
+			$t_use_ssl = false;
+			if( isset( $_SERVER['HTTPS'] ) && ( strtolower( $_SERVER['HTTPS'] ) != 'off' ) ) {
+				$t_use_ssl = true;
+			}
+	
+			if( !$t_use_ssl ) {
+				$t_avatar_domain = 'http://www.gravatar.com/';
+			} else {
+				$t_avatar_domain = 'https://secure.gravatar.com/';
+			}
+	
+			$t_avatar_url = $t_avatar_domain . 'avatar.php?gravatar_id=' . md5( $t_email ) . '&amp;default=' . urlencode( $t_default_image ) . '&amp;size=' . $t_size . '&amp;rating=G';
+			$t_result = array(
+				$t_avatar_url,
+				$t_size,
+				$t_size,
+				$t_avatar_domain,
+			);
 		}
-
-		$t_avatar_url = $t_gravatar_domain . 'avatar.php?gravatar_id=' . md5( $t_email ) . '&amp;default=' . urlencode( $t_default_image ) . '&amp;size=' . $t_size . '&amp;rating=G';
-		$t_result = array(
-			$t_avatar_url,
-			$t_size,
-			$t_size,
-		);
 	}
 
 	return $t_result;
diff --git a/file_download.php b/file_download.php
index eec4d4d..9b4cd8a 100644
--- a/file_download.php
+++ b/file_download.php
@@ -34,54 +34,47 @@
 ?>
 <?php auth_ensure_user_authenticated() ?>
 <?php
+	$f_type	= gpc_get_string( 'type' );
+	$t_allowed_tables = array ( 'bug', 'doc', 'avatar' );
+	if ( ! in_array ($f_type, $t_allowed_tables) ) {
+		access_denied();
+	}
+	
+	if ( $f_type == 'doc' ) {
+		$f_type = 'project';
+	}
 	$f_file_id	= gpc_get_int( 'file_id' );
-	$f_type		= gpc_get_string( 'type' );
-
 	$c_file_id = (integer)$f_file_id;
 
 	# we handle the case where the file is attached to a bug
 	# or attached to a project as a project doc.
 	$query = '';
-	switch ( $f_type ) {
-		case 'bug':
-			$t_bug_file_table = db_get_table( 'mantis_bug_file_table' );
-			$query = "SELECT *
-				FROM $t_bug_file_table
-				WHERE id=" . db_param();
-			break;
-		case 'doc':
-			$t_project_file_table = db_get_table( 'mantis_project_file_table' );
-			$query = "SELECT *
-				FROM $t_project_file_table
-				WHERE id=" . db_param();
-			break;
-		default:
-			access_denied();
-	}
+	$t_file_table = db_get_table( 'mantis_'.$f_type.'_file_table' );
+	$query = "SELECT *
+		FROM $t_file_table
+		WHERE id=" . db_param();
 	$result = db_query_bound( $query, Array( $c_file_id ) );
 	$row = db_fetch_array( $result );
 	extract( $row, EXTR_PREFIX_ALL, 'v' );
 
-	if ( $f_type == 'bug' ) {
-		$t_project_id = bug_get_field( $v_bug_id, 'project_id' );
-	} else {
-		$t_project_id = $v_project_id;
-	}
-
 	# Check access rights
 	switch ( $f_type ) {
 		case 'bug':
 			if ( !file_can_download_bug_attachments( $v_bug_id ) ) {
 				access_denied();
 			}
+			$t_project_id = bug_get_field( $v_bug_id, 'project_id' );
 			break;
-		case 'doc':
+		case 'project':
 			# Check if project documentation feature is enabled.
 			if ( OFF == config_get( 'enable_project_documentation' ) ) {
 				access_denied();
 			}
-
 			access_ensure_project_level( config_get( 'view_proj_doc_threshold' ), $v_project_id );
+			$t_project_id = $v_project_id;
+			break;
+		case 'avatar':
+			$t_project_id = $v_avatar_id;
 			break;
 	}
 
diff --git a/manage_user_page.php b/manage_user_page.php
index b674dbd..e06a3f1 100644
--- a/manage_user_page.php
+++ b/manage_user_page.php
@@ -270,6 +270,7 @@
 		<?php print_manage_user_sort_link(  'manage_user_page.php', lang_get( 'last_visit' ), 'last_visit', $c_dir, $c_sort, $c_hide, $c_filter ) ?>
 		<?php print_sort_icon( $c_dir, $c_sort, 'last_visit' ) ?>
 	</td>
+	<td>Avatar</td>
 </tr>
 <?php
 	$t_date_format = config_get( 'normal_date_format' );
@@ -305,6 +306,9 @@
         </td>
 	<td><?php echo $u_date_created ?></td>
 	<td><?php echo $u_last_visit ?></td>
+	<?php if ( config_get( 'show_avatar' ) ) {?>
+	<td><?php print_avatar ( $u_id ); ?></td>
+	<?php }	?>
 </tr>
 <?php
 	}  # end for
-- 
1.6.2.msysgit.0.186.gf7512

