Index: t3lib/class.t3lib_refindex.php
===================================================================
--- t3lib/class.t3lib_refindex.php	(revision 3929)
+++ t3lib/class.t3lib_refindex.php	(working copy)
@@ -204,6 +204,7 @@
  						case 'db':
  							$this->createEntryData_dbRels($table,$uid,$fieldname,'',$deleted,$dat['itemArray']);
  						break;
+						case 'file_reference':
  						case 'file':
  							$this->createEntryData_fileRels($table,$uid,$fieldname,'',$deleted,$dat['newValueFiles']);
  						break;
@@ -341,6 +342,7 @@
 								 	list($tableName,$recordId) = explode(':',$el['subst']['recordRef']);
 								 	$this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,$tableName,$recordId,'',-1,$spKey,$subKey);
 								 break;
+								 case 'file_reference':
 								 case 'file':
 								 	$this->relations[] = $this->createEntryData($table,$uid,$fieldname,$flexpointer,$deleted,'_FILE',0,$el['subst']['relFileName'],-1,$spKey,$subKey);
 								 break;
@@ -536,7 +538,7 @@
 	 */
 	function getRelations_procFiles($value, $conf, $uid)	{
 			// Take care of files...
-		if ($conf['type']=='group' && $conf['internal_type']=='file')	{
+		if ($conf['type']=='group' && ($conf['internal_type']=='file' || $conf['internal_type']=='file_reference'))	{
 
 				// Collect file values in array:
 			if ($conf['MM'])	{
@@ -554,7 +556,7 @@
 			}
 
 				// Traverse the files and add them:
-			$uploadFolder = $conf['uploadfolder'];
+			$uploadFolder = $conf['internal_type']=='file' ? $conf['uploadfolder'] : '';
 			$dest = $this->destPathFromUploadFolder($uploadFolder);
 			$newValue = array();
 			$newValueFiles = array();
@@ -564,7 +566,7 @@
 					$realFile = $dest.'/'.trim($file);
 #					if (@is_file($realFile))	{		// Now, the refernece index should NOT look if files exist - just faithfully include them if they are in the records!
 						$newValueFiles[] = array(
-							'filename' => $file,
+							'filename' => basename($file),
 							'ID' => md5($realFile),
 							'ID_absFile' => $realFile
 						);	// the order should be preserved here because.. (?)
@@ -667,6 +669,7 @@
 		 							$error = $this->setReferenceValue_dbRels($refRec,$dat['itemArray'],$newValue,$dataArray);
 									if ($error)	return $error;
 		 						break;
+								case 'file_reference':
 		 						case 'file':
 		 							$this->setReferenceValue_fileRels($refRec,$dat['newValueFiles'],$newValue,$dataArray);
 									if ($error)	return $error;
@@ -974,6 +977,9 @@
 	 * @return	string		Input folder prefixed with PATH_site. No checking for existence is done. Output must be a folder without trailing slash.
 	 */
 	function destPathFromUploadFolder($folder)	{
+		if (!$folder) {
+			return substr(PATH_site, 0, -1);
+		}
 		return PATH_site.$folder;
 	}
 
Index: t3lib/class.t3lib_tceforms.php
===================================================================
--- t3lib/class.t3lib_tceforms.php	(revision 3929)
+++ t3lib/class.t3lib_tceforms.php	(working copy)
@@ -2001,6 +2001,8 @@
 
 			// Acting according to either "file" or "db" type:
 		switch((string)$config['internal_type'])	{
+			case 'file_reference':
+				$config['uploadfolder'] = '';
 			case 'file':	// If the element is of the internal type "file":
 
 					// Creating string showing allowed types:
@@ -2067,7 +2069,9 @@
 
 				if(!$disabled && !(isset($config['disable_controls']) && t3lib_div::inList($config['disable_controls'], 'upload'))) {
 						// Adding the upload field:
-					if ($this->edit_docModuleUpload)	$item.='<input type="file" name="'.$PA['itemFormElName_file'].'"'.$this->formWidth().' size="60" />';
+					if ($this->edit_docModuleUpload && $config['uploadfolder']) {
+						$item.='<input type="file" name="'.$PA['itemFormElName_file'].'"'.$this->formWidth().' size="60" />';
+					}
 				}
 			break;
 			case 'folder':	// If the element is of the internal type "folder":
@@ -3370,12 +3374,13 @@
 						}
 					}
 				break;
+				case 'file_reference':
 				case 'file':
 				case 'folder':
 					while(list(,$pp)=each($itemArray))	{
 						$pParts = explode('|',$pp);
 						$uidList[]=$pUid=$pTitle = $pParts[0];
-						$opt[]='<option value="'.htmlspecialchars(rawurldecode($pParts[0])).'">'.htmlspecialchars(rawurldecode($pParts[0])).'</option>';
+						$opt[]='<option value="'.htmlspecialchars(rawurldecode($pParts[0])).'">'.htmlspecialchars(basename(rawurldecode($pParts[0]))).'</option>';
 					}
 				break;
 				default:
@@ -3413,7 +3418,7 @@
 				}
 				$aOnClick='setFormValueOpenBrowser(\''.$mode.'\',\''.($fName.'|||'.$allowed.'|'.$aOnClickInline).'\'); return false;';
 				$icons['R'][]='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
-						'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert3.gif','width="14" height="14"').' border="0" '.t3lib_BEfunc::titleAltAttrib($this->getLL('l_browse_'.($mode=='file'?'file':'db'))).' />'.
+						'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert3.gif','width="14" height="14"').' border="0" '.t3lib_BEfunc::titleAltAttrib($this->getLL('l_browse_'.($mode=='db'?'db':'file'))).' />'.
 						'</a>';
 			}
 			if (!$params['dontShowMoveIcons'])	{
@@ -3440,12 +3445,12 @@
 				$aOnClick = '';
 	#			$counter = 0;
 				foreach($clipElements as $elValue)	{
-					if ($mode=='file')	{
-						$itemTitle = 'unescape(\''.rawurlencode(basename($elValue)).'\')';
-					} else {	// 'db' mode assumed
+					if ($mode=='db')	{
 						list($itemTable,$itemUid) = explode('|', $elValue);
 						$itemTitle = $GLOBALS['LANG']->JScharCode(t3lib_BEfunc::getRecordTitle($itemTable, t3lib_BEfunc::getRecordWSOL($itemTable,$itemUid)));
 						$elValue = $itemTable.'_'.$itemUid;
+					} else {	// 'file' mode assumed
+						$itemTitle = 'unescape(\''.rawurlencode(basename($elValue)).'\')';
 					}
 					$aOnClick.= 'setFormValueFromBrowseWin(\''.$fName.'\',unescape(\''.rawurlencode(str_replace('%20',' ',$elValue)).'\'),'.$itemTitle.');';
 
@@ -3454,7 +3459,7 @@
 				}
 				$aOnClick.= 'return false;';
 				$icons['R'][]='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
-						'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert5.png','width="14" height="14"').' border="0" '.t3lib_BEfunc::titleAltAttrib(sprintf($this->getLL('l_clipInsert_'.($mode=='file'?'file':'db')),count($clipElements))).' />'.
+						'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert5.png','width="14" height="14"').' border="0" '.t3lib_BEfunc::titleAltAttrib(sprintf($this->getLL('l_clipInsert_'.($mode=='db'?'db':'file')),count($clipElements))).' />'.
 						'</a>';
 			}
 			$rOnClick = $rOnClickInline.'setFormValueManipulate(\''.$fName.'\',\'Remove\'); return false';
@@ -3506,6 +3511,7 @@
 
 		if (is_object($this->clipObj))	{
 			switch($mode)	{
+				case 'file_reference':
 				case 'file':
 					$elFromTable = $this->clipObj->elFromTable('_FILE');
 					$allowedExts = t3lib_div::trimExplode(',', $allowed, 1);
@@ -5780,7 +5786,12 @@
 	 * @return 	string		HTML formatted output
 	 */
 	function previewFieldValue($value, $config)	{
-		if ($config['config']['type']==='group' && $config['config']['internal_type'] === 'file')	{
+		if ($config['config']['type']==='group' && ($config['config']['internal_type'] === 'file' || $config['config']['internal_type'] === 'file_reference'))	{
+				// Ignore uploadfolder if internal_type is file_reference
+			if ($config['config']['internal_type'] === 'file_reference') {
+				$config['config']['uploadfolder'] = '';
+			}
+			
 			$show_thumbs = TRUE;
 			$table = 'tt_content';
 
Index: t3lib/class.t3lib_tcemain.php
===================================================================
--- t3lib/class.t3lib_tcemain.php	(revision 3929)
+++ t3lib/class.t3lib_tcemain.php	(working copy)
@@ -270,6 +270,7 @@
 	var $defaultValues = array();			// Array [table][fields]=value: New records are created with default values and you can set this array on the form $defaultValues[$table][$field] = $value to override the default values fetched from TCA. If ->setDefaultsFromUserTS is called UserTSconfig default values will overrule existing values in this array (thus UserTSconfig overrules externally set defaults which overrules TCA defaults)
 	var $overrideValues = array();			// Array [table][fields]=value: You can set this array on the form $overrideValues[$table][$field] = $value to override the incoming data. You must set this externally. You must make sure the fields in this array are also found in the table, because it's not checked. All columns can be set by this array!
 	var $alternativeFileName = array();		// Array [filename]=alternative_filename: Use this array to force another name onto a file. Eg. if you set ['/tmp/blablabal'] = 'my_file.txt' and '/tmp/blablabal' is set for a certain file-field, then 'my_file.txt' will be used as the name instead.
+	var $alternativeFilePath = array();		// Array [filename]=alternative_filepath: Same as alternativeFileName but with relative path to the file 
 	var $data_disableFields=array();		// If entries are set in this array corresponding to fields for update, they are ignored and thus NOT updated. You could set this array from a series of checkboxes with value=0 and hidden fields before the checkbox with 1. Then an empty checkbox will disable the field.
 	var $suggestedInsertUids=array();		// Use this array to validate suggested uids for tables by setting [table]:[uid]. This is a dangerous option since it will force the inserted record to have a certain UID. The value just have to be true, but if you set it to "DELETE" it will make sure any record with that UID will be deleted first (raw delete). The option is used for import of T3D files when synchronizing between two mirrored servers. As a security measure this feature is available only for Admin Users (for now)
 
@@ -1497,6 +1498,7 @@
 			// For group types:
 		if ($tcaFieldConf['type']=='group')	{
 			switch($tcaFieldConf['internal_type'])	{
+				case 'file_reference':
 				case 'file':
 					$valueArray = $this->checkValue_group_select_file(
 						$valueArray,
@@ -1581,7 +1583,7 @@
 		}
 
 			// If there is an upload folder defined:
-		if ($tcaFieldConf['uploadfolder'])	{
+		if ($tcaFieldConf['uploadfolder'] && $tcaFieldConf['internal_type'] == 'file') {
 			if (!$this->bypassFileHandling)	{	// If filehandling should NOT be bypassed, do processing:
 					// For logging..
 				$propArr = $this->getRecordProperties($table,$id);
@@ -1714,6 +1716,68 @@
 				}
 				$valueArray = $dbAnalysis->countItems();
 			}
+		//store path relative to site root (if uploadfolder is not set or internal_type is file_reference)
+		} else {
+			if (count($valueArray)){
+				if (!$this->bypassFileHandling) {	// If filehandling should NOT be bypassed, do processing:
+					$propArr = $this->getRecordProperties($table,$id); // For logging..
+					foreach($valueArray as &$theFile){ 
+						
+						// if alernative File Path is set for the file, then it was an import
+						if ($this->alternativeFilePath[$theFile]){
+							
+							// don't import the file if it already exists
+							if (@is_file(PATH_site.$this->alternativeFilePath[$theFile])){
+								$theFile = PATH_site.$this->alternativeFilePath[$theFile];
+							
+							// import the file
+							} else if (@is_file($theFile)){
+								$dest = dirname(PATH_site.$this->alternativeFilePath[$theFile]);
+								if (!@is_dir($dest)) {
+									t3lib_div::mkdir_deep(PATH_site, dirname($this->alternativeFilePath[$theFile]).'/');
+								}
+								
+								// Init:
+								$maxSize = intval($tcaFieldConf['max_size']);
+								$cmd='';
+								$theDestFile='';		// Must be cleared. Else a faulty fileref may be inserted if the below code returns an error!
+								$fileSize = filesize($theFile);
+
+								if (!$maxSize || $fileSize<=($maxSize*1024))	{	// Check file size:
+										// Prepare filename:
+									$theEndFileName = isset($this->alternativeFileName[$theFile]) ? $this->alternativeFileName[$theFile] : $theFile;
+									$fI = t3lib_div::split_fileref($theEndFileName);
+
+										// Check for allowed extension:
+									if ($this->fileFunc->checkIfAllowed($fI['fileext'], $dest, $theEndFileName)) {
+										$theDestFile = PATH_site.$this->alternativeFilePath[$theFile];
+
+											// Write the file:
+										if ($theDestFile)	{
+											t3lib_div::upload_copy_move($theFile,$theDestFile);
+											$this->copiedFileMap[$theFile] = $theDestFile;
+											clearstatcache();
+											if (!@is_file($theDestFile))	$this->log($table,$id,5,0,1,"Copying file '%s' failed!: The destination path (%s) may be write protected. Please make it write enabled!. (%s)",16,array($theFile, dirname($theDestFile), $recFID),$propArr['event_pid']);
+										} else $this->log($table,$id,5,0,1,"Copying file '%s' failed!: No destination file (%s) possible!. (%s)",11,array($theFile, $theDestFile, $recFID),$propArr['event_pid']);
+									} else $this->log($table,$id,5,0,1,"Fileextension '%s' not allowed. (%s)",12,array($fI['fileext'], $recFID),$propArr['event_pid']);
+								} else $this->log($table,$id,5,0,1,"Filesize (%s) of file '%s' exceeds limit (%s). (%s)",13,array(t3lib_div::formatSize($fileSize),$theFile,t3lib_div::formatSize($maxSize*1024),$recFID),$propArr['event_pid']);
+
+									// If the destination file was created, we will set the new filename in the value array, otherwise unset the entry in the value array!
+								if (@is_file($theDestFile))	{
+									$theFile = $theDestFile; // The value is set to the new filename
+								} else {
+									unset($theFile); // The value is set to the new filename
+								}
+							}
+						}
+					}
+					
+					$theFile = t3lib_div::fixWindowsFilePath($theFile);
+					if (t3lib_div::isFirstPartOfStr($theFile,PATH_site)) {
+						$theFile = substr($theFile,strlen(PATH_site));
+					}
+				}
+			}
 		}
 
 		return $valueArray;
@@ -3148,7 +3212,7 @@
 	function copyRecord_procFilesRefs($conf, $uid, $value)	{
 
 			// Prepend absolute paths to files:
-		if ($conf['type']=='group' && $conf['internal_type']=='file')	{
+		if ($conf['type']=='group' && ($conf['internal_type']=='file' || $conf['internal_type']=='file_reference'))	{
 
 				// Get an array with files as values:
 			if ($conf['MM'])	{
@@ -3168,13 +3232,13 @@
 			}
 
 				// Traverse this array of files:
-			$uploadFolder = $conf['uploadfolder'];
+			$uploadFolder = $conf['internal_type']=='file' ? $conf['uploadfolder'] : '';
 			$dest = $this->destPathFromUploadFolder($uploadFolder);
 			$newValue = array();
 
 			foreach($theFileValues as $file)	{
 				if (trim($file))	{
-					$realFile = $dest.'/'.trim($file);
+					$realFile = str_replace('//', '/', $dest.'/'.trim($file));
 					if (@is_file($realFile))	{
 						$newValue[] = $realFile;
 					}
@@ -6473,7 +6537,7 @@
 		if ($TCA[$table]['columns'])	{
 			reset($TCA[$table]['columns']);
 			while (list($field,$configArr)=each($TCA[$table]['columns']))	{
-				if ($configArr['config']['type']=='group' && $configArr['config']['internal_type']=='file')	{
+				if ($configArr['config']['type']=='group' && ($configArr['config']['internal_type']=='file' || $configArr['config']['internal_type']=='file_reference'))	{
 					$listArr[]=$field;
 				}
 			}
@@ -6642,7 +6706,7 @@
 		global $TCA;
 		t3lib_div::loadTCA($table);
 		$uploadFolder = $TCA[$table]['columns'][$field]['config']['uploadfolder'];
-		if ($uploadFolder && trim($filelist))	{
+		if ($uploadFolder && trim($filelist) && $TCA[$table]['columns'][$field]['config']['internal_type'] == 'file')	{
 			$uploadPath = $this->destPathFromUploadFolder($uploadFolder);
 			$fileArray = explode(',',$filelist);
 			while (list(,$theFile)=each($fileArray))	{
Index: typo3/sysext/impexp/class.tx_impexp.php
===================================================================
--- typo3/sysext/impexp/class.tx_impexp.php	(revision 3929)
+++ typo3/sysext/impexp/class.tx_impexp.php	(working copy)
@@ -783,6 +783,7 @@
 				$fileRec['filesize'] = filesize($fI['ID_absFile']);
 				$fileRec['filename'] = basename($fI['ID_absFile']);
 				$fileRec['filemtime'] = filemtime($fI['ID_absFile']);
+				$fileRec['relFileRef'] = substr($fI['ID_absFile'],strlen(PATH_site)); //for internal type file_reference
 				if ($recordRef)	{
 					$fileRec['record_ref'] = $recordRef.'/'.$fieldname;
 				}
@@ -1167,6 +1168,7 @@
 			// Temporary files stack initialized:
 		$this->unlinkFiles = array();
 		$this->alternativeFileName = array();
+		$this->alternativeFilePath = array();
 
 			// Write records, first pages, then the rest
 			// Fields with "hard" relations to database, files and flexform fields are kept empty during this run
@@ -1486,6 +1488,7 @@
 		$tce->dontProcessTransformations = 1;
 		$tce->enableLogging = $this->enableLogging;
 		$tce->alternativeFileName = $this->alternativeFileName;
+		$tce->alternativeFilePath = $this->alternativeFilePath;
 		return $tce;
 	}
 
@@ -1623,6 +1626,7 @@
 				$this->unlinkFiles[] = $tmpFile;
 				if (filesize($tmpFile)==$this->dat['files'][$fI['ID']]['filesize'])	{
 					$this->alternativeFileName[$tmpFile] = $fI['filename'];
+					$this->alternativeFilePath[$tmpFile] = $this->dat['files'][$fI['ID']]['relFileRef'];
 
 					return $tmpFile;
 				} else $this->error('Error: temporary file '.$tmpFile.' had a size ('.filesize($tmpFile).') different from the original ('.$this->dat['files'][$fI['ID']]['filesize'].')',1);
