[OS/2] Bug 301367: Tag Files with Source URL, p=Rich Walsh, r=me, sr=darin

This commit is contained in:
mozilla%weilbacher.org 2006-06-26 20:40:08 +00:00
Родитель 769abf4738
Коммит 4578273740
6 изменённых файлов: 363 добавлений и 93 удалений

Просмотреть файл

@ -44,6 +44,9 @@
#ifdef XP_MAC
#include "nsILocalFileMac.h"
#endif
#ifdef XP_OS2
#include "nsILocalFileOS2.h"
#endif
#include "nsNetUtil.h"
#include "nsComponentManagerUtils.h"
@ -726,9 +729,29 @@ NS_IMETHODIMP nsWebBrowserPersist::OnStopRequest(
OutputData *data = (OutputData *) mOutputMap.Get(&key);
if (data)
{
#if defined(XP_OS2)
// delete 'data'; this will close the stream and let
// us tag the file it created with its source URI
nsCOMPtr<nsIURI> uriSource = data->mOriginalLocation;
nsCOMPtr<nsILocalFile> localFile;
GetLocalFileFromURI(data->mFile, getter_AddRefs(localFile));
delete data;
mOutputMap.Remove(&key);
if (localFile)
{
nsCOMPtr<nsILocalFileOS2> localFileOS2 = do_QueryInterface(localFile);
if (localFileOS2)
{
nsCAutoString url;
uriSource->GetSpec(url);
localFileOS2->SetFileSource(url);
}
}
#else
// This will close automatically close the output stream
delete data;
mOutputMap.Remove(&key);
#endif
}
else
{
@ -1643,6 +1666,16 @@ nsresult nsWebBrowserPersist::SaveDocumentInternal(
cleanupData->mIsDirectory = PR_TRUE;
mCleanupList.AppendElement(cleanupData);
}
#if defined(XP_OS2)
// tag the directory with the URI that originated its contents
nsCOMPtr<nsILocalFileOS2> localFileOS2 = do_QueryInterface(localDataPath);
if (localFileOS2)
{
nsCAutoString url;
mCurrentBaseURI->GetSpec(url);
localFileOS2->SetFileSource(url);
}
#endif
}
}
@ -3622,6 +3655,20 @@ nsWebBrowserPersist::SaveDocumentWithFixup(
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
}
}
#if defined(XP_OS2)
else
{
// close the stream, then tag the file it created with its source URI
outputStream->Close();
nsCOMPtr<nsILocalFileOS2> localFileOS2 = do_QueryInterface(localFile);
if (localFileOS2)
{
nsCAutoString url;
mCurrentBaseURI->GetSpec(url);
localFileOS2->SetFileSource(url);
}
}
#endif
return rv;
}

Просмотреть файл

@ -93,7 +93,9 @@
#include "nsILocalFileMac.h"
#include "nsIInternetConfigService.h"
#include "nsIAppleFileDecoder.h"
#endif // defined(XP_MAC) || defined (XP_MACOSX)
#elif defined(XP_OS2)
#include "nsILocalFileOS2.h"
#endif
#include "nsIPluginHost.h" // XXX needed for ext->type mapping (bug 233289)
#include "nsEscape.h"
@ -2202,6 +2204,19 @@ nsresult nsExternalAppHandler::MoveFile(nsIFile * aNewFileLocation)
SendStatusChange(kWriteError, rv, nsnull, path);
Cancel(rv); // Cancel (and clean up temp file).
}
#if defined(XP_OS2)
else
{
// tag the file with its source URI
nsCOMPtr<nsILocalFileOS2> localFileOS2 = do_QueryInterface(fileToUse);
if (localFileOS2)
{
nsCAutoString url;
mSourceUrl->GetSpec(url);
localFileOS2->SetFileSource(url);
}
}
#endif
}
return rv;

Просмотреть файл

@ -64,7 +64,8 @@ REQUIRES = gfx \
plugin \
docshell \
webbrowserpersist \
imglib2 \
content \
imglib2 \
unicharutil \
$(NULL)

Просмотреть файл

@ -52,6 +52,8 @@
#include "nsOS2Uni.h"
#include "nsdefs.h"
#include "wdgtos2rc.h"
#include "nsILocalFileOS2.h"
#include "nsIDocument.h"
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
@ -91,7 +93,8 @@ nsresult GetAtom( ATOM aAtom, char** outText);
nsresult GetFileName(PDRAGITEM pditem, char** outText);
nsresult GetFileContents(PCSZ pszPath, char** outText);
nsresult GetTempFileName(char** outText);
void WriteTypeEA(PCSZ filename, PCSZ type);
void SaveTypeAndSource(nsILocalFile *file, nsIDOMDocument *domDoc,
PCSZ pszType);
int UnicodeToCodepage( const nsAString& inString, char **outText);
int CodepageToUnicode( const nsACString& inString, PRUnichar **outText);
void RemoveCarriageReturns(char * pszText);
@ -489,27 +492,30 @@ NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor,
nsresult nsDragService::SaveAsContents(PCSZ pszDest, nsIURL* aURL)
{
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsILocalFile> file;
if (NS_SUCCEEDED( NS_NewNativeLocalFile(nsDependentCString(pszDest),
TRUE, getter_AddRefs(file)))) {
nsCOMPtr<nsIURI> linkURI (do_QueryInterface(aURL));
if (linkURI) {
nsCOMPtr<nsIWebBrowserPersist> webPersist(
do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1"));
if (webPersist) {
nsCAutoString temp;
file->GetNativePath(temp);
FILE* fp = fopen(temp.get(), "wb+");
fwrite("", 0, 1, fp);
fclose(fp);
webPersist->SaveURI(linkURI, nsnull, nsnull, nsnull, nsnull, file);
rv = NS_OK;
}
}
}
nsCOMPtr<nsIURI> linkURI(do_QueryInterface(aURL));
if (!linkURI)
return NS_ERROR_FAILURE;
return rv;
nsCOMPtr<nsIWebBrowserPersist> webPersist(
do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1"));
if (!webPersist)
return NS_ERROR_FAILURE;
nsCOMPtr<nsILocalFile> file;
NS_NewNativeLocalFile(nsDependentCString(pszDest), PR_TRUE,
getter_AddRefs(file));
if (!file)
return NS_ERROR_FAILURE;
FILE* fp;
if (NS_FAILED(file->OpenANSIFileDesc("wb+", &fp)))
return NS_ERROR_FAILURE;
fwrite("", 0, 1, fp);
fclose(fp);
webPersist->SaveURI(linkURI, nsnull, nsnull, nsnull, nsnull, file);
return NS_OK;
}
// --------------------------------------------------------------------------
@ -518,21 +524,30 @@ nsresult nsDragService::SaveAsContents(PCSZ pszDest, nsIURL* aURL)
nsresult nsDragService::SaveAsURL(PCSZ pszDest, nsIURI* aURI)
{
nsresult rv = NS_ERROR_FAILURE;
nsCAutoString strUri;
aURI->GetSpec(strUri);
if (!strUri.IsEmpty()) {
FILE* fp = fopen(pszDest, "wb+");
if (fp) {
fwrite(strUri.get(), strUri.Length(), 1, fp);
fclose(fp);
WriteTypeEA(pszDest, "UniformResourceLocator");
rv = NS_OK;
}
}
if (strUri.IsEmpty())
return NS_ERROR_FAILURE;
return rv;
nsCOMPtr<nsILocalFile> file;
NS_NewNativeLocalFile(nsDependentCString(pszDest), PR_TRUE,
getter_AddRefs(file));
if (!file)
return NS_ERROR_FAILURE;
FILE* fp;
if (NS_FAILED(file->OpenANSIFileDesc("wb+", &fp)))
return NS_ERROR_FAILURE;
fwrite(strUri.get(), strUri.Length(), 1, fp);
fclose(fp);
nsCOMPtr<nsIDOMDocument> domDoc;
GetSourceDocument(getter_AddRefs(domDoc));
SaveTypeAndSource(file, domDoc, "UniformResourceLocator");
return NS_OK;
}
// --------------------------------------------------------------------------
@ -541,24 +556,35 @@ nsresult nsDragService::SaveAsURL(PCSZ pszDest, nsIURI* aURI)
nsresult nsDragService::SaveAsText(PCSZ pszDest, nsISupportsString* aString)
{
nsresult rv = NS_ERROR_FAILURE;
nsAutoString strData;
aString->GetData(strData);
if (!strData.IsEmpty()) {
nsXPIDLCString textStr;
int cnt = UnicodeToCodepage( strData, getter_Copies(textStr));
if (cnt) {
FILE* fp = fopen(pszDest, "wb+");
if (fp) {
fwrite(textStr.get(), cnt, 1, fp);
fclose(fp);
rv = NS_OK;
}
}
}
if (strData.IsEmpty())
return NS_ERROR_FAILURE;
return rv;
nsCOMPtr<nsILocalFile> file;
NS_NewNativeLocalFile(nsDependentCString(pszDest), PR_TRUE,
getter_AddRefs(file));
if (!file)
return NS_ERROR_FAILURE;
nsXPIDLCString textStr;
int cnt = UnicodeToCodepage(strData, getter_Copies(textStr));
if (!cnt)
return NS_ERROR_FAILURE;
FILE* fp;
if (NS_FAILED(file->OpenANSIFileDesc("wb+", &fp)))
return NS_ERROR_FAILURE;
fwrite(textStr.get(), cnt, 1, fp);
fclose(fp);
nsCOMPtr<nsIDOMDocument> domDoc;
GetSourceDocument(getter_AddRefs(domDoc));
SaveTypeAndSource(file, domDoc, "Plain Text");
return NS_OK;
}
// --------------------------------------------------------------------------
@ -1638,55 +1664,57 @@ nsresult GetTempFileName(char** outText)
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void WriteTypeEA(PCSZ filename, PCSZ type)
// set the file's .TYPE and .SUBJECT EAs; since this is non-critical
// (though highly desirable), errors aren't reported
void SaveTypeAndSource(nsILocalFile *file, nsIDOMDocument *domDoc,
PCSZ pszType)
{
// this struct combines an FEA2LIST, an FEA2, plus a custom struct
// needed to write a single .TYPE EA in the correct MVMT format;
#pragma pack(1)
struct {
struct {
ULONG ulcbList;
ULONG uloNextEntryOffset;
BYTE bfEA;
BYTE bcbName;
USHORT uscbValue;
char chszName[sizeof(".TYPE")];
} hdr;
struct {
USHORT usEAType;
USHORT usCodePage;
USHORT usNumEntries;
USHORT usDataType;
USHORT usDataLth;
} info;
char data[64];
} ea;
#pragma pack()
USHORT lth = (USHORT)strlen(type);
if (lth >= sizeof(ea.data))
if (!file)
return;
ea.hdr.ulcbList = sizeof(ea.hdr) + sizeof(ea.info) + lth;
ea.hdr.uloNextEntryOffset = 0;
ea.hdr.bfEA = 0;
ea.hdr.bcbName = sizeof(".TYPE") - 1;
ea.hdr.uscbValue = sizeof(ea.info) + lth;
strcpy(ea.hdr.chszName, ".TYPE");
nsCOMPtr<nsILocalFileOS2> os2file(do_QueryInterface(file));
if (!os2file ||
NS_FAILED(os2file->SetFileTypes(nsDependentCString(pszType))))
return;
ea.info.usEAType = EAT_MVMT;
ea.info.usCodePage = 0;
ea.info.usNumEntries = 1;
ea.info.usDataType = EAT_ASCII;
ea.info.usDataLth = lth;
strcpy(ea.data, type);
// since the filetype has to be saved, this function
// may be called even if there isn't any document
if (!domDoc)
return;
EAOP2 eaop2;
eaop2.fpGEA2List = 0;
eaop2.fpFEA2List = (PFEA2LIST)&ea;
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc)
return;
// this gets the top-level content URL when frames are used;
// when nextDoc is zero, currDoc is the browser window, and
// prevDoc points to the content;
// note: neither GetParentDocument() nor GetDocumentURI()
// refcount the pointers they return, so nsCOMPtr isn't needed
nsIDocument *prevDoc;
nsIDocument *currDoc = doc;
nsIDocument *nextDoc = doc;
do {
prevDoc = currDoc;
currDoc = nextDoc;
nextDoc = currDoc->GetParentDocument();
} while (nextDoc);
nsIURI* srcUri = prevDoc->GetDocumentURI();
if (!srcUri)
return;
// identifying content as coming from chrome is none too useful...
PRBool ignore = PR_FALSE;
srcUri->SchemeIs("chrome", &ignore);
if (ignore)
return;
nsCAutoString url;
srcUri->GetSpec(url);
os2file->SetFileSource(url);
DosSetPathInfo(filename, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), 0);
return;
}

Просмотреть файл

@ -41,7 +41,7 @@
interface nsIArray;
[scriptable, uuid(4c712847-8f55-4a2b-bbbc-2cb550cce019)]
[scriptable, uuid(26de2089-239d-4697-818b-bae1fe8e8e0d)]
interface nsILocalFileOS2 : nsILocalFile
{
/**
@ -53,6 +53,18 @@ interface nsILocalFileOS2 : nsILocalFile
*/
nsIArray getFileTypes( );
/**
* setFileTypes
*
* Sets the file's .TYPE extended attribute from a comma-separated
* list of types (this format is used because clients are unlikely
* to write more than a single type).
* @param fileTypes
* a string in the filesystem's native character set
*
*/
void setFileTypes( in ACString fileTypes );
/**
* isFileType
*
@ -63,5 +75,16 @@ interface nsILocalFileOS2 : nsILocalFile
*
*/
PRBool isFileType( in ACString fileType );
};
/**
* setFileSource
*
* Identifies the origin of a downloaded file by writing the
* source URI's spec to the .SUBJECT extended attribute.
*
* @param aURI
* the source URI
*
*/
void setFileSource( in AUTF8String aURI );
};

Просмотреть файл

@ -1207,6 +1207,162 @@ nsLocalFile::IsFileType(const nsACString& fileType, PRBool *_retval)
//-----------------------------------------------------------------------------
// this struct combines an FEA2LIST, an FEA2, plus additional fields
// needed to write a .TYPE EA in the correct EAT_MVMT format
#pragma pack(1)
typedef struct _TYPEEA {
struct {
ULONG ulcbList;
ULONG uloNextEntryOffset;
BYTE bfEA;
BYTE bcbName;
USHORT uscbValue;
char chszName[sizeof(".TYPE")];
} hdr;
struct {
USHORT usEAType;
USHORT usCodePage;
USHORT usNumEntries;
USHORT usDataType;
USHORT usDataLth;
} info;
char data[1];
} TYPEEA;
typedef struct _TYPEEA2 {
USHORT usDataType;
USHORT usDataLth;
} TYPEEA2;
#pragma pack()
// writes one or more .TYPE extended attributes taken
// from a comma-delimited string
NS_IMETHODIMP
nsLocalFile::SetFileTypes(const nsACString& fileTypes)
{
if (fileTypes.IsEmpty())
return NS_ERROR_FAILURE;
PRUint32 cnt = CountCharInReadable(fileTypes, ',');
PRUint32 lth = fileTypes.Length() - cnt + (cnt * sizeof(TYPEEA2));
PRUint32 size = sizeof(TYPEEA) + lth;
char *pBuf = (char*)NS_Alloc(size);
if (!pBuf)
return NS_ERROR_OUT_OF_MEMORY;
TYPEEA *pEA = (TYPEEA *)pBuf;
// the buffer has an extra byte due to TYPEEA.data[1]
pEA->hdr.ulcbList = size - 1;
pEA->hdr.uloNextEntryOffset = 0;
pEA->hdr.bfEA = 0;
pEA->hdr.bcbName = sizeof(".TYPE") - 1;
pEA->hdr.uscbValue = sizeof(pEA->info) + lth;
strcpy(pEA->hdr.chszName, ".TYPE");
pEA->info.usEAType = EAT_MVMT;
pEA->info.usCodePage = 0;
pEA->info.usNumEntries = ++cnt;
nsACString::const_iterator begin, end, delim;
fileTypes.BeginReading(begin);
fileTypes.EndReading(end);
delim = begin;
// fill in type & length, copy the current type name (which
// is not zero-terminated), then advance the ptr so the next
// iteration can reuse the trailing members of the structure
do {
FindCharInReadable( ',', delim, end);
lth = delim.get() - begin.get();
pEA->info.usDataType = EAT_ASCII;
pEA->info.usDataLth = lth;
memcpy(pEA->data, begin.get(), lth);
pEA = (TYPEEA *)((char*)pEA + lth + sizeof(TYPEEA2));
begin = ++delim;
} while (--cnt);
// write the EA, then free the buffer
EAOP2 eaop2;
eaop2.fpGEA2List = 0;
eaop2.fpFEA2List = (PFEA2LIST)pBuf;
int rc = DosSetPathInfo(mWorkingPath.get(), FIL_QUERYEASIZE,
&eaop2, sizeof(eaop2), 0);
NS_Free(pBuf);
if (rc)
return ConvertOS2Error(rc);
return NS_OK;
}
//-----------------------------------------------------------------------------
// this struct combines an FEA2LIST, an FEA2, plus additional fields
// needed to write a .SUBJECT EA in the correct EAT_ASCII format;
#pragma pack(1)
typedef struct _SUBJEA {
struct {
ULONG ulcbList;
ULONG uloNextEntryOffset;
BYTE bfEA;
BYTE bcbName;
USHORT uscbValue;
char chszName[sizeof(".SUBJECT")];
} hdr;
struct {
USHORT usEAType;
USHORT usDataLth;
} info;
char data[1];
} SUBJEA;
#pragma pack()
// saves the file's source URI in its .SUBJECT extended attribute
NS_IMETHODIMP
nsLocalFile::SetFileSource(const nsACString& aURI)
{
if (aURI.IsEmpty())
return NS_ERROR_FAILURE;
// this includes an extra character for the spec's trailing null
PRUint32 lth = sizeof(SUBJEA) + aURI.Length();
char * pBuf = (char*)NS_Alloc(lth);
if (!pBuf)
return NS_ERROR_OUT_OF_MEMORY;
SUBJEA *pEA = (SUBJEA *)pBuf;
// the trailing null doesn't get saved, so don't include it in the size
pEA->hdr.ulcbList = lth - 1;
pEA->hdr.uloNextEntryOffset = 0;
pEA->hdr.bfEA = 0;
pEA->hdr.bcbName = sizeof(".SUBJECT") - 1;
pEA->hdr.uscbValue = sizeof(pEA->info) + aURI.Length();
strcpy(pEA->hdr.chszName, ".SUBJECT");
pEA->info.usEAType = EAT_ASCII;
pEA->info.usDataLth = aURI.Length();
strcpy(pEA->data, PromiseFlatCString(aURI).get());
// write the EA, then free the buffer
EAOP2 eaop2;
eaop2.fpGEA2List = 0;
eaop2.fpFEA2List = (PFEA2LIST)pEA;
int rc = DosSetPathInfo(mWorkingPath.get(), FIL_QUERYEASIZE,
&eaop2, sizeof(eaop2), 0);
NS_Free(pBuf);
if (rc)
return ConvertOS2Error(rc);
return NS_OK;
}
//-----------------------------------------------------------------------------
nsresult
nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent,
const nsACString &newName, PRBool move)