The bug is that when printing you don't want to do the auto default selection stuff because it ends up calling into the DOM and changing the radios on the page. Bug 96367 r=timeless sr=attinasi a=dbaron git-svn-id: svn://10.0.0.236/trunk@101700 18797224-902f-48f8-a5cc-f745e15eee43
1837 lines
61 KiB
C++
1837 lines
61 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
* Adrian Havill <havill@redhat.com>
|
|
*/
|
|
|
|
|
|
|
|
#define NS_IMPL_IDS
|
|
#include "nsICharsetConverterManager.h"
|
|
#include "nsICharsetAlias.h"
|
|
#include "nsIPlatformCharset.h"
|
|
#undef NS_IMPL_IDS
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsXPIDLString.h"
|
|
|
|
#include "nsID.h"
|
|
|
|
|
|
#include "nsFormFrame.h"
|
|
#include "nsIFormControlFrame.h"
|
|
#include "nsFormControlFrame.h"
|
|
#include "nsFileControlFrame.h"
|
|
#include "nsRadioControlGroup.h"
|
|
|
|
#include "nsIForm.h"
|
|
#include "nsIFormControl.h"
|
|
#include "nsIAtom.h"
|
|
#include "nsHTMLIIDs.h"
|
|
#include "nsIRenderingContext.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIPresContext.h"
|
|
#include "nsIStyleContext.h"
|
|
#include "nsCSSRendering.h"
|
|
#include "nsHTMLIIDs.h"
|
|
#include "nsDebug.h"
|
|
#include "nsIWidget.h"
|
|
#include "nsVoidArray.h"
|
|
#include "nsHTMLAtoms.h"
|
|
#include "nsCRT.h"
|
|
#include "nsIURL.h"
|
|
#include "nsIHTMLDocument.h"
|
|
#include "nsIScriptGlobalObject.h"
|
|
#include "nsIPrintContext.h"
|
|
|
|
#include "nsIFormProcessor.h"
|
|
|
|
#include "nsIIOService.h"
|
|
#include "nsIPref.h"
|
|
#include "nsIURL.h"
|
|
#include "nsNetUtil.h"
|
|
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
|
#include "nsIDocument.h"
|
|
#include "nsILinkHandler.h"
|
|
#include "nsGfxRadioControlFrame.h"
|
|
#include "nsIDOMHTMLFormElement.h"
|
|
#include "nsIDOMNSHTMLFormElement.h"
|
|
#include "nsDOMError.h"
|
|
#include "nsHTMLParts.h"
|
|
#include "nsIReflowCommand.h"
|
|
|
|
#include "nsIUnicodeEncoder.h"
|
|
|
|
// FormSubmit observer notification
|
|
#include "nsIFormSubmitObserver.h"
|
|
#include "nsIObserverService.h"
|
|
#include "nsIServiceManager.h"
|
|
|
|
// Get base target for submission
|
|
#include "nsIHTMLContent.h"
|
|
#include "nsIDOMHTMLInputElement.h"
|
|
|
|
#include "xp_file.h"
|
|
#include "prio.h"
|
|
#include "prmem.h"
|
|
#include "prenv.h"
|
|
#include "prlong.h"
|
|
|
|
// Rewrite of Multipart form posting
|
|
#include "nsSpecialSystemDirectory.h"
|
|
#include "nsIFileSpec.h"
|
|
#include "nsFileSpec.h"
|
|
#include "nsIProtocolHandler.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsEscape.h"
|
|
#include "nsLinebreakConverter.h"
|
|
#include "nsCExternalHandlerService.h"
|
|
#include "nsIMIMEService.h"
|
|
|
|
#include "nsILocalFile.h" // Using nsILocalFile to get file size
|
|
|
|
// Security
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsIDOMWindowInternal.h"
|
|
|
|
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
|
static NS_DEFINE_CID(kPlatformCharsetCID, NS_PLATFORMCHARSET_CID);
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
|
|
//ahmed 15-1
|
|
#ifdef IBMBIDI
|
|
#include "nsIUBidiUtils.h"
|
|
static NS_DEFINE_CID(kUBidiUtilCID, NS_UNICHARBIDIUTIL_CID);
|
|
#endif
|
|
//end
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
{
|
|
if (aIID.Equals(NS_GET_IID(nsIFormManager))) {
|
|
*aInstancePtr = (void*)(nsIFormManager*)this;
|
|
return NS_OK;
|
|
}
|
|
return nsBlockFrame::QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
|
|
nsrefcnt nsFormFrame::AddRef(void)
|
|
{
|
|
NS_ERROR("not supported");
|
|
return 0;
|
|
}
|
|
|
|
nsrefcnt nsFormFrame::Release(void)
|
|
{
|
|
NS_ERROR("not supported");
|
|
return 0;
|
|
}
|
|
|
|
nsFormFrame::nsFormFrame()
|
|
: nsBlockFrame()
|
|
{
|
|
}
|
|
|
|
nsFormFrame::~nsFormFrame()
|
|
{
|
|
RemoveRadioGroups();
|
|
PRInt32 numControls = mFormControls.Count();
|
|
PRInt32 i;
|
|
// Traverse list from end to 0 -> void array remove method does less work
|
|
for (i = (numControls-1); i>=0; i--) {
|
|
nsIFormControlFrame* fcFrame = (nsIFormControlFrame*) mFormControls.ElementAt(i);
|
|
fcFrame->SetFormFrame(nsnull);
|
|
mFormControls.RemoveElement(fcFrame);
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::GetAction(nsString* aAction)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (mContent) {
|
|
nsIDOMHTMLFormElement* form = nsnull;
|
|
result = mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLFormElement), (void**)&form);
|
|
if ((NS_OK == result) && form) {
|
|
form->GetAction(*aAction);
|
|
NS_RELEASE(form);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::GetTarget(nsString* aTarget)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (mContent) {
|
|
nsIDOMHTMLFormElement* form = nsnull;
|
|
result = mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLFormElement), (void**)&form);
|
|
if ((NS_OK == result) && form) {
|
|
form->GetTarget(*aTarget);
|
|
if ((*aTarget).Length() == 0) {
|
|
nsIHTMLContent* content = nsnull;
|
|
result = form->QueryInterface(kIHTMLContentIID, (void**)&content);
|
|
if ((NS_OK == result) && content) {
|
|
content->GetBaseTarget(*aTarget);
|
|
NS_RELEASE(content);
|
|
}
|
|
}
|
|
NS_RELEASE(form);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::GetMethod(PRInt32* aMethod)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (mContent) {
|
|
nsIHTMLContent* form = nsnull;
|
|
result = mContent->QueryInterface(kIHTMLContentIID, (void**)&form);
|
|
if ((NS_OK == result) && form) {
|
|
nsHTMLValue value;
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == (form->GetHTMLAttribute(nsHTMLAtoms::method, value))) {
|
|
if (eHTMLUnit_Enumerated == value.GetUnit()) {
|
|
*aMethod = value.GetIntValue();
|
|
NS_RELEASE(form);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
NS_RELEASE(form);
|
|
}
|
|
}
|
|
*aMethod = NS_FORM_METHOD_GET;
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::GetEnctype(PRInt32* aEnctype)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (mContent) {
|
|
nsIHTMLContent* form = nsnull;
|
|
result = mContent->QueryInterface(kIHTMLContentIID, (void**)&form);
|
|
if ((NS_OK == result) && form) {
|
|
nsHTMLValue value;
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == (form->GetHTMLAttribute(nsHTMLAtoms::enctype, value))) {
|
|
if (eHTMLUnit_Enumerated == value.GetUnit()) {
|
|
*aEnctype = value.GetIntValue();
|
|
NS_RELEASE(form);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
NS_RELEASE(form);
|
|
}
|
|
}
|
|
*aEnctype = NS_FORM_ENCTYPE_URLENCODED;
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::OnReset(nsIPresContext* aPresContext)
|
|
{
|
|
PRInt32 numControls = mFormControls.Count();
|
|
for (int i = 0; i < numControls; i++) {
|
|
nsIFormControlFrame* fcFrame = (nsIFormControlFrame*) mFormControls.ElementAt(i);
|
|
fcFrame->Reset(aPresContext);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void nsFormFrame::RemoveRadioGroups()
|
|
{
|
|
int numRadioGroups = mRadioGroups.Count();
|
|
for (int i = 0; i < numRadioGroups; i++) {
|
|
nsRadioControlGroup* radioGroup = (nsRadioControlGroup *) mRadioGroups.ElementAt(i);
|
|
delete radioGroup;
|
|
}
|
|
mRadioGroups.Clear();
|
|
}
|
|
|
|
void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFrame& aFrame)
|
|
{
|
|
// Make sure we have a form control
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = aFrame.QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
|
|
if ((NS_OK != result) || (nsnull == fcFrame)) {
|
|
return;
|
|
}
|
|
|
|
// Get this control's form frame and add this control to it
|
|
nsCOMPtr<nsIContent> iContent;
|
|
result = aFrame.GetContent(getter_AddRefs(iContent));
|
|
if (NS_SUCCEEDED(result) && iContent) {
|
|
nsCOMPtr<nsIFormControl> formControl;
|
|
result = iContent->QueryInterface(NS_GET_IID(nsIFormControl), getter_AddRefs(formControl));
|
|
if (NS_SUCCEEDED(result) && formControl) {
|
|
nsCOMPtr<nsIDOMHTMLFormElement> formElem;
|
|
result = formControl->GetForm(getter_AddRefs(formElem));
|
|
if (NS_SUCCEEDED(result) && formElem) {
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
result = aPresContext->GetShell(getter_AddRefs(presShell));
|
|
if (NS_SUCCEEDED(result) && presShell) {
|
|
nsIContent* formContent;
|
|
result = formElem->QueryInterface(NS_GET_IID(nsIContent), (void**)&formContent);
|
|
if (NS_SUCCEEDED(result) && formContent) {
|
|
nsFormFrame* formFrame = nsnull;
|
|
result = presShell->GetPrimaryFrameFor(formContent, (nsIFrame**)&formFrame);
|
|
if (NS_SUCCEEDED(result) && formFrame) {
|
|
fcFrame->SetFormFrame(formFrame);
|
|
formFrame->AddFormControlFrame(aPresContext, *fcFrame);
|
|
}
|
|
NS_RELEASE(formContent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void nsFormFrame::RemoveFormControlFrame(nsIFormControlFrame& aFrame)
|
|
{
|
|
// Remove form control from array
|
|
mFormControls.RemoveElement(&aFrame);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::RemoveFrame(nsIPresContext* aPresContext,
|
|
nsIPresShell& aPresShell,
|
|
nsIAtom* aListName,
|
|
nsIFrame* aOldFrame)
|
|
{
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = aOldFrame->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
|
|
if ((NS_OK == result) || (nsnull != fcFrame)) {
|
|
PRInt32 type;
|
|
fcFrame->GetType(&type);
|
|
if (NS_FORM_INPUT_RADIO == type) {
|
|
nsRadioControlGroup * group;
|
|
nsAutoString name;
|
|
nsresult rv = GetRadioInfo(fcFrame, name, group);
|
|
if (NS_SUCCEEDED(rv) && nsnull != group) {
|
|
DoDefaultSelection(aPresContext, group, (nsGfxRadioControlFrame*)fcFrame);
|
|
}
|
|
}
|
|
}
|
|
|
|
return nsBlockFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
|
|
}
|
|
|
|
nsresult nsFormFrame::GetRadioInfo(nsIFormControlFrame* aFrame,
|
|
nsString& aName,
|
|
nsRadioControlGroup *& aGroup)
|
|
{
|
|
aGroup = nsnull;
|
|
aName.SetLength(0);
|
|
aFrame->GetName(&aName);
|
|
PRBool hasName = aName.Length() > 0;
|
|
|
|
// radio group processing
|
|
if (hasName) {
|
|
int numGroups = mRadioGroups.Count();
|
|
nsRadioControlGroup* group;
|
|
for (int j = 0; j < numGroups; j++) {
|
|
group = (nsRadioControlGroup *) mRadioGroups.ElementAt(j);
|
|
nsString groupName;
|
|
group->GetName(groupName);
|
|
if (groupName.Equals(aName)) {
|
|
aGroup = group;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
void nsFormFrame::DoDefaultSelection(nsIPresContext* aPresContext,
|
|
nsRadioControlGroup * aGroup,
|
|
nsGfxRadioControlFrame * aRadioToIgnore)
|
|
{
|
|
#if 1
|
|
// We do not want to do the default selection when printing
|
|
// The code below ends up calling into the content, which then sets
|
|
// the state on the "primary" frame the frame being displayed
|
|
// this causes it to be "reset" to the default selection,
|
|
// then when we go to get the current state of the UI it has been reset back
|
|
// and then the printed state has the wrong value also
|
|
//nsCOMPtr<nsIPrintContext> printContext = do_QueryInterface(aPresContext);
|
|
//if (printContext) {
|
|
// return;
|
|
//}
|
|
// If in standard mode, then a radio group MUST default
|
|
// to the first item in the group (it must be selected)
|
|
nsCompatibility mode;
|
|
nsFormControlHelper::GetFormCompatibilityMode(aPresContext, mode);
|
|
if (eCompatibility_Standard == mode) {
|
|
// first find out if any have a default selection
|
|
PRInt32 i;
|
|
PRInt32 numItems = aGroup->GetNumRadios();
|
|
PRBool oneIsDefSelected = PR_FALSE;
|
|
for (i=0;i<numItems;i++) {
|
|
nsGfxRadioControlFrame * radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(i);
|
|
nsCOMPtr<nsIContent> content;
|
|
radioBtn->GetContent(getter_AddRefs(content));
|
|
if (content) {
|
|
nsCOMPtr<nsIDOMHTMLInputElement> input(do_QueryInterface(content));
|
|
if (input) {
|
|
PRBool initiallyChecked = PR_FALSE;
|
|
if (radioBtn->IsRestored()) {
|
|
initiallyChecked = radioBtn->GetRestoredChecked();
|
|
} else {
|
|
initiallyChecked = radioBtn->GetDefaultChecked();
|
|
}
|
|
|
|
PRBool currentValue = radioBtn->GetChecked();
|
|
if (currentValue != initiallyChecked ) {
|
|
input->SetChecked(initiallyChecked);
|
|
//radioBtn->SetChecked(aPresContext, initSelected, PR_FALSE);
|
|
}
|
|
if (initiallyChecked) {
|
|
oneIsDefSelected = PR_TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if there isn't a default selcted radio then
|
|
// select the firdst one in the group.
|
|
// if aRadioToIgnore is not null then it is being deleted
|
|
// so don't select that item, select the next one if there is one.
|
|
if (!oneIsDefSelected && numItems > 0) {
|
|
nsGfxRadioControlFrame * radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(0);
|
|
if (aRadioToIgnore != nsnull && aRadioToIgnore == radioBtn) {
|
|
if (numItems == 1) {
|
|
return;
|
|
}
|
|
radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(1);
|
|
}
|
|
nsCOMPtr<nsIContent> content;
|
|
radioBtn->GetContent(getter_AddRefs(content));
|
|
if (content) {
|
|
nsCOMPtr<nsIDOMHTMLInputElement> input(do_QueryInterface(content));
|
|
if (input) {
|
|
input->SetChecked(PR_TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFormControlFrame& aFrame)
|
|
{
|
|
// Add this control to the list
|
|
// Sort by content ID - this assures we submit in document order (bug 18728)
|
|
PRInt32 i = mFormControls.Count();
|
|
|
|
nsCOMPtr<nsIContent> newContent;
|
|
nsIFrame* newFrame = nsnull;
|
|
nsresult rv = aFrame.QueryInterface(NS_GET_IID(nsIFrame), (void **)&newFrame);
|
|
if (NS_SUCCEEDED(rv) && newFrame) {
|
|
rv = newFrame->GetContent(getter_AddRefs(newContent));
|
|
if (NS_SUCCEEDED(rv) && newContent) {
|
|
PRUint32 newID;
|
|
newContent->GetContentID(&newID);
|
|
for (; i>0; i--) {
|
|
nsIFormControlFrame* thisControl = (nsIFormControlFrame*) mFormControls.ElementAt(i-1);
|
|
if (thisControl) {
|
|
nsCOMPtr<nsIContent> thisContent;
|
|
nsIFrame* thisFrame = nsnull;
|
|
rv = thisControl->QueryInterface(NS_GET_IID(nsIFrame), (void **)&thisFrame);
|
|
if (NS_SUCCEEDED(rv) && thisFrame) {
|
|
rv = thisFrame->GetContent(getter_AddRefs(thisContent));
|
|
if (NS_SUCCEEDED(rv) && thisContent) {
|
|
PRUint32 thisID;
|
|
thisContent->GetContentID(&thisID);
|
|
if (newID > thisID)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mFormControls.InsertElementAt(&aFrame, i);
|
|
|
|
// determine which radio buttons belong to which radio groups, unnamed radio buttons
|
|
// don't go into any group since they can't be submitted.
|
|
|
|
PRInt32 type;
|
|
aFrame.GetType(&type);
|
|
if (NS_FORM_INPUT_RADIO == type) {
|
|
nsGfxRadioControlFrame* radioFrame = (nsGfxRadioControlFrame*)&aFrame;
|
|
// gets the name of the radio group and the group
|
|
nsRadioControlGroup * group;
|
|
nsAutoString name;
|
|
rv = GetRadioInfo(&aFrame, name, group);
|
|
if (NS_SUCCEEDED(rv) && nsnull != group) {
|
|
group->AddRadio(radioFrame);
|
|
} else {
|
|
group = new nsRadioControlGroup(name);
|
|
mRadioGroups.AppendElement(group);
|
|
group->AddRadio(radioFrame);
|
|
}
|
|
// allow only one checked radio button
|
|
PRBool initiallyChecked = PR_FALSE;
|
|
if (radioFrame->IsRestored()) {
|
|
initiallyChecked = radioFrame->GetRestoredChecked();
|
|
} else {
|
|
initiallyChecked = radioFrame->GetDefaultChecked();
|
|
}
|
|
if (initiallyChecked) {
|
|
if (nsnull == group->GetCheckedRadio()) {
|
|
group->SetCheckedRadio(radioFrame);
|
|
} else {
|
|
radioFrame->SetChecked(aPresContext, PR_FALSE, PR_FALSE);
|
|
}
|
|
}
|
|
DoDefaultSelection(aPresContext, group);
|
|
}
|
|
}
|
|
|
|
void nsFormFrame::RemoveRadioControlFrame(nsIFormControlFrame * aFrame)
|
|
{
|
|
PRInt32 type;
|
|
aFrame->GetType(&type);
|
|
|
|
// radio group processing
|
|
if (NS_FORM_INPUT_RADIO == type) {
|
|
nsGfxRadioControlFrame* radioFrame = (nsGfxRadioControlFrame*)aFrame;
|
|
// gets the name of the radio group and the group
|
|
nsRadioControlGroup * group;
|
|
nsAutoString name;
|
|
nsresult rv = GetRadioInfo(aFrame, name, group);
|
|
if (NS_SUCCEEDED(rv) && nsnull != group) {
|
|
group->RemoveRadio(radioFrame);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------
|
|
// Return the content of the currently selected item in
|
|
// the radio group of the incoming radiobutton.
|
|
//--------------------------------------------------------
|
|
nsresult
|
|
nsFormFrame::GetRadioGroupSelectedContent(nsGfxRadioControlFrame* aControl,
|
|
nsIContent ** aRadiobtn)
|
|
{
|
|
NS_ASSERTION(aControl, "nsGfxRadioControlFrame can't be null");
|
|
|
|
// first get correct interface
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = aControl->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
|
|
if (NS_SUCCEEDED(result)) {
|
|
// get the form frame for the radio btn
|
|
nsFormFrame * formFrame = ((nsFormControlFrame *)aControl)->GetFormFrame();
|
|
if (formFrame != nsnull) {
|
|
// now get the radio group by name
|
|
nsAutoString groupName;
|
|
nsRadioControlGroup * group = nsnull;
|
|
result = formFrame->GetRadioInfo(fcFrame, groupName, group);
|
|
if (NS_SUCCEEDED(result) && nsnull != group) {
|
|
// get the currently checked radio button
|
|
nsGfxRadioControlFrame* currentCheckBtn = group->GetCheckedRadio();
|
|
if (currentCheckBtn != nsnull) {
|
|
currentCheckBtn->GetContent(aRadiobtn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// returns NS_ERROR_FAILURE if the radiobtn doesn't have a group
|
|
// returns NS_OK is it did have a radio group
|
|
//--------------------------------------------------------
|
|
nsresult
|
|
nsFormFrame::OnRadioChecked(nsIPresContext* aPresContext,
|
|
nsGfxRadioControlFrame& aControl,
|
|
PRBool aNewCheckedVal)
|
|
{
|
|
// first get correct interface
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = aControl.QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
|
|
if (NS_SUCCEEDED(result)) {
|
|
// now get the radio group by name
|
|
nsAutoString groupName;
|
|
nsRadioControlGroup * group = nsnull;
|
|
result = GetRadioInfo(fcFrame, groupName, group);
|
|
if (NS_SUCCEEDED(result) && nsnull != group) {
|
|
// get the currently checked radio button
|
|
nsGfxRadioControlFrame* currentCheckBtn = group->GetCheckedRadio();
|
|
// is the new checked btn different than the current button?
|
|
if (&aControl != currentCheckBtn) {
|
|
// if the new button is being set to false
|
|
// then don't do anything
|
|
if (aNewCheckedVal) {
|
|
// the current btn could be null
|
|
if (currentCheckBtn != nsnull) {
|
|
currentCheckBtn->SetChecked(aPresContext, !aNewCheckedVal, PR_FALSE);
|
|
}
|
|
aControl.SetChecked(aPresContext, aNewCheckedVal, PR_FALSE);
|
|
group->SetCheckedRadio(&aControl);
|
|
}
|
|
} else {
|
|
// here we are setting the same radio button
|
|
// as the one that is currently checked
|
|
//
|
|
if (currentCheckBtn != nsnull) {
|
|
currentCheckBtn->SetChecked(aPresContext, aNewCheckedVal, PR_FALSE);
|
|
// So if we are setting the current btn to be 0 or off
|
|
// then we must set a default selction
|
|
if (!aNewCheckedVal) {
|
|
DoDefaultSelection(aPresContext, group, currentCheckBtn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult
|
|
NS_NewFormFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags)
|
|
{
|
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
|
if (nsnull == aNewFrame) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
nsFormFrame* it = new (aPresShell) nsFormFrame;
|
|
if (!it) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
it->SetFlags(aFlags);
|
|
*aNewFrame = it;
|
|
return NS_OK;
|
|
}
|
|
|
|
#if 0
|
|
|
|
PRIVATE
|
|
void DebugPrint(char* aLabel, nsString aString)
|
|
{
|
|
char* out = aString.ToNewCString();
|
|
printf("\n %s=%s\n", aLabel, out);
|
|
delete [] out;
|
|
}
|
|
|
|
#endif
|
|
|
|
// Give the form process observer a chance to modify the value passed for form submission
|
|
nsresult
|
|
nsFormFrame::ProcessValue(nsIFormProcessor& aFormProcessor, nsIFormControlFrame* aFrameControl, const nsString& aName, nsString& aValue)
|
|
{
|
|
nsresult res = NS_OK;
|
|
|
|
nsIFrame *frame = nsnull;
|
|
res = aFrameControl->QueryInterface(NS_GET_IID(nsIFrame), (void **)&frame);
|
|
if (NS_SUCCEEDED(res) && (frame)) {
|
|
nsCOMPtr<nsIContent> content;
|
|
nsresult rv = frame->GetContent(getter_AddRefs(content));
|
|
if (NS_SUCCEEDED(rv) && content) {
|
|
nsCOMPtr<nsIDOMHTMLElement> formElement;
|
|
res = content->QueryInterface(NS_GET_IID(nsIDOMHTMLElement), getter_AddRefs(formElement));
|
|
if (NS_SUCCEEDED(res) && formElement) {
|
|
res = aFormProcessor.ProcessValue(formElement, aName, aValue);
|
|
NS_ASSERTION(NS_SUCCEEDED(res), "unable Notify form process observer");
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
// submission
|
|
|
|
NS_IMETHODIMP
|
|
nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame)
|
|
{
|
|
if (!mContent) {
|
|
return NS_FORM_NOTOK;
|
|
}
|
|
|
|
//ahmed
|
|
#ifdef IBMBIDI
|
|
PRUint32 bidiOptions;
|
|
aPresContext->GetBidi(&bidiOptions);
|
|
mCtrlsModAtSubmit = GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions);
|
|
mTextDir = GET_BIDI_OPTION_DIRECTION(bidiOptions);
|
|
#endif
|
|
//ahmed end
|
|
// Get a service to process the value part of the form data
|
|
// If one doesn't exist, that fine. It's not required.
|
|
nsresult result = NS_OK;
|
|
nsCOMPtr<nsIFormProcessor> formProcessor =
|
|
do_GetService(kFormProcessorCID, &result);
|
|
|
|
nsString data; // this could be more efficient, by allocating a larger buffer
|
|
|
|
PRInt32 method, enctype;
|
|
GetMethod(&method);
|
|
GetEnctype(&enctype);
|
|
|
|
PRBool isURLEncoded = (NS_FORM_ENCTYPE_MULTIPART != enctype);
|
|
|
|
// for enctype=multipart/form-data, force it to be post
|
|
// if method is "" (not specified) use "get" as default
|
|
PRBool isPost = (NS_FORM_METHOD_POST == method) || !isURLEncoded;
|
|
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
|
|
// Since JS Submit() calls are not linked to an element, aFrame is null.
|
|
// fcframe will remain null, but IsSuccess will return succes in this case.
|
|
if (aFrame != nsnull) {
|
|
aFrame->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
|
|
}
|
|
|
|
nsIFileSpec* multipartDataFile = nsnull;
|
|
if (isURLEncoded) {
|
|
result = ProcessAsURLEncoded(formProcessor, isPost, data, fcFrame);
|
|
}
|
|
else {
|
|
result = ProcessAsMultipart(formProcessor, multipartDataFile, fcFrame);
|
|
}
|
|
|
|
// Don't bother submitting form if we failed to generate a valid submission
|
|
if (NS_FAILED(result)) {
|
|
NS_IF_RELEASE(multipartDataFile);
|
|
return result;
|
|
}
|
|
|
|
// make the url string
|
|
nsCOMPtr<nsILinkHandler> handler;
|
|
if (NS_OK == aPresContext->GetLinkHandler(getter_AddRefs(handler))) {
|
|
nsAutoString href;
|
|
GetAction(&href);
|
|
|
|
// Get the document.
|
|
// We'll need it now to form the URL we're submitting to.
|
|
// We'll also need it later to get the DOM window when notifying form submit observers (bug 33203)
|
|
nsCOMPtr<nsIDocument> document;
|
|
mContent->GetDocument(*getter_AddRefs(document));
|
|
if (!document) return NS_OK; // No doc means don't submit, see Bug 28988
|
|
|
|
// Resolve url to an absolute url
|
|
nsCOMPtr<nsIURI> docURL;
|
|
document->GetBaseURL(*getter_AddRefs(docURL));
|
|
NS_ASSERTION(docURL, "No Base URL found in Form Submit!\n");
|
|
if (!docURL) return NS_OK; // No base URL -> exit early, see Bug 30721
|
|
|
|
// If an action is not specified and we are inside
|
|
// a HTML document then reload the URL. This makes us
|
|
// compatible with 4.x browsers.
|
|
// If we are in some other type of document such as XML or
|
|
// XUL, do nothing. This prevents undesirable reloading of
|
|
// a document inside XUL.
|
|
|
|
if (href.IsEmpty()) {
|
|
nsCOMPtr<nsIHTMLDocument> htmlDoc;
|
|
if (PR_FALSE == NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIHTMLDocument),
|
|
getter_AddRefs(htmlDoc)))) {
|
|
// Must be a XML, XUL or other non-HTML document type
|
|
// so do nothing.
|
|
return NS_OK;
|
|
}
|
|
|
|
// Necko's MakeAbsoluteURI doesn't reuse the baseURL's rel path if it is
|
|
// passed a zero length rel path.
|
|
nsXPIDLCString relPath;
|
|
docURL->GetSpec(getter_Copies(relPath));
|
|
NS_ASSERTION(relPath, "Rel path couldn't be formed in form submit!\n");
|
|
if (relPath) {
|
|
href.AppendWithConversion(relPath);
|
|
|
|
} else {
|
|
result = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
} else {
|
|
// Get security manager, check to see if access to action URI is allowed.
|
|
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
|
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &result);
|
|
nsCOMPtr<nsIURI> actionURL;
|
|
if (NS_FAILED(result)) return result;
|
|
|
|
result = NS_NewURI(getter_AddRefs(actionURL), href, docURL);
|
|
if (NS_SUCCEEDED(result)) {
|
|
result = securityManager->CheckLoadURI(docURL, actionURL, nsIScriptSecurityManager::STANDARD);
|
|
if (NS_FAILED(result)) return result;
|
|
}
|
|
|
|
nsXPIDLCString scheme;
|
|
PRBool isMailto = PR_FALSE;
|
|
if (actionURL && NS_FAILED(result = actionURL->SchemeIs("mailto",
|
|
&isMailto)))
|
|
return result;
|
|
if (isMailto) {
|
|
PRBool enabled;
|
|
if (NS_FAILED(result = securityManager->IsCapabilityEnabled("UniversalSendMail", &enabled)))
|
|
{
|
|
return result;
|
|
}
|
|
if (!enabled) {
|
|
// Form submit to a mailto: URI requires the UniversalSendMail privilege
|
|
return NS_ERROR_DOM_SECURITY_ERR;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsAutoString target;
|
|
GetTarget(&target);
|
|
|
|
// Add the URI encoded form values to the URI
|
|
// Get the scheme of the URI.
|
|
nsCOMPtr<nsIURI> actionURL;
|
|
nsXPIDLCString scheme;
|
|
if (NS_SUCCEEDED(result = NS_NewURI(getter_AddRefs(actionURL), href, docURL))) {
|
|
result = actionURL->GetScheme(getter_Copies(scheme));
|
|
}
|
|
nsAutoString theScheme; theScheme.AssignWithConversion( NS_STATIC_CAST(const char*, scheme) );
|
|
// Append the URI encoded variable/value pairs for GET's
|
|
if (!isPost) {
|
|
if (!theScheme.EqualsIgnoreCase("javascript")) { // Not for JS URIs, see bug 26917
|
|
|
|
// Bug 42616: Trim off named anchor and save it to add later
|
|
PRInt32 namedAnchorPos = href.FindChar('#', PR_FALSE, 0);
|
|
nsAutoString namedAnchor;
|
|
if (kNotFound != namedAnchorPos) {
|
|
href.Right(namedAnchor, (href.Length() - namedAnchorPos));
|
|
href.Truncate(namedAnchorPos);
|
|
}
|
|
|
|
// Chop off old query string (bug 25330, 57333)
|
|
// Only do this for GET not POST (bug 41585)
|
|
PRInt32 queryStart = href.FindChar('?');
|
|
if (kNotFound != queryStart) {
|
|
href.Truncate(queryStart);
|
|
}
|
|
|
|
href.Append(PRUnichar('?'));
|
|
href.Append(data);
|
|
|
|
// Bug 42616: Add named anchor to end after query string
|
|
if (namedAnchor.Length()) {
|
|
href.Append(namedAnchor);
|
|
}
|
|
}
|
|
}
|
|
|
|
nsAutoString absURLSpec;
|
|
result = NS_MakeAbsoluteURI(absURLSpec, href, docURL);
|
|
if (NS_FAILED(result)) return result;
|
|
|
|
// Notify observers that the form is being submitted.
|
|
result = NS_OK;
|
|
nsCOMPtr<nsIObserverService> service =
|
|
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &result);
|
|
if (NS_FAILED(result)) return result;
|
|
|
|
nsString theTopic; theTopic.AssignWithConversion(NS_FORMSUBMIT_SUBJECT);
|
|
nsCOMPtr<nsIEnumerator> theEnum;
|
|
result = service->EnumerateObserverList(theTopic.get(), getter_AddRefs(theEnum));
|
|
if (NS_SUCCEEDED(result) && theEnum){
|
|
nsCOMPtr<nsISupports> inst;
|
|
PRBool cancelSubmit = PR_FALSE;
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> globalObject;
|
|
document->GetScriptGlobalObject(getter_AddRefs(globalObject));
|
|
nsCOMPtr<nsIDOMWindowInternal> window = do_QueryInterface(globalObject);
|
|
|
|
for (theEnum->First(); theEnum->IsDone() != NS_OK; theEnum->Next()) {
|
|
nsresult gotObserver = NS_OK;
|
|
gotObserver = theEnum->CurrentItem(getter_AddRefs(inst));
|
|
if (NS_SUCCEEDED(gotObserver) && inst) {
|
|
nsCOMPtr<nsIFormSubmitObserver> formSubmitObserver = do_QueryInterface(inst, &result);
|
|
if (NS_SUCCEEDED(result) && formSubmitObserver) {
|
|
nsresult notifyStatus = formSubmitObserver->Notify(mContent, window, actionURL, &cancelSubmit);
|
|
if (NS_FAILED(notifyStatus)) { // assert/warn if we get here?
|
|
return notifyStatus;
|
|
}
|
|
}
|
|
}
|
|
if (cancelSubmit) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Now pass on absolute url to the click handler
|
|
nsCOMPtr<nsIInputStream> postDataStream;
|
|
if (isPost) {
|
|
if (isURLEncoded) {
|
|
nsCAutoString postBuffer;
|
|
postBuffer.AssignWithConversion(data);
|
|
NS_NewPostDataStream(getter_AddRefs(postDataStream), !isURLEncoded,
|
|
postBuffer.get(), 0);
|
|
} else {
|
|
// Cut-and-paste of NS_NewPostDataStream
|
|
nsCOMPtr<nsIIOService> serv(do_GetService(kIOServiceCID));
|
|
if (serv && multipartDataFile) {
|
|
nsCOMPtr<nsIInputStream> rawStream;
|
|
multipartDataFile->GetInputStream(getter_AddRefs(rawStream));
|
|
if (rawStream) {
|
|
NS_NewBufferedInputStream(getter_AddRefs(postDataStream),
|
|
rawStream, 8192);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (handler) {
|
|
#if defined(DEBUG_rods) || defined(DEBUG_pollmann)
|
|
{
|
|
printf("******\n");
|
|
char * str = data.ToNewCString();
|
|
printf("postBuffer[%s]\n", str);
|
|
Recycle(str);
|
|
|
|
str = absURLSpec.ToNewCString();
|
|
printf("absURLSpec[%s]\n", str);
|
|
Recycle(str);
|
|
|
|
str = target.ToNewCString();
|
|
printf("target [%s]\n", str);
|
|
Recycle(str);
|
|
printf("******\n");
|
|
}
|
|
#endif
|
|
handler->OnLinkClick(mContent, eLinkVerb_Replace,
|
|
absURLSpec.get(),
|
|
target.get(), postDataStream);
|
|
}
|
|
// We need to delete the data file somewhere...
|
|
// if (!isURLEncoded) {
|
|
// nsFileSpec mdf = nsnull;
|
|
// result = multipartDataFile->GetFileSpec(&mdf);
|
|
// if (NS_SUCCEEDED(result) && mdf) {
|
|
// mdf.Delete(PR_FALSE);
|
|
// }
|
|
// }
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// XXX i18n helper routines
|
|
char*
|
|
nsFormFrame::UnicodeToNewBytes(const PRUnichar* aSrc, PRUint32 aLen, nsIUnicodeEncoder* encoder)
|
|
{
|
|
#ifdef IBMBIDI_0 // Until we finalize the conversion routine
|
|
//ahmed 15-1
|
|
nsString temp;
|
|
nsresult rv = NS_OK;
|
|
nsIUBidiUtils* bidiUtils = do_getService("@mozilla.org/intl/unicharbidiutil;1");
|
|
nsString newBuffer;
|
|
//This condition handle the RTL,LTR for a logical file
|
|
if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_VISUAL )&&( mCharset.EqualsIgnoreCase("windows-1256") ) ){
|
|
bidiUtils->Conv_06_FE_WithReverse(nsString(aSrc), newBuffer,mTextDir);
|
|
aSrc = (PRUnichar *)newBuffer.get();
|
|
aLen=newBuffer.Length();
|
|
}
|
|
else if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_LOGICAL )&&( mCharset.EqualsIgnoreCase("IBM864") ) ){
|
|
//For 864 file, When it is logical, if LTR then only convert
|
|
//If RTL will mak a reverse for the buffer
|
|
bidiUtils->Conv_FE_06(nsString(aSrc), newBuffer);
|
|
aSrc = (PRUnichar *)newBuffer.get();
|
|
temp = newBuffer;
|
|
aLen=newBuffer.Length();
|
|
if (mTextDir == 2) { //RTL
|
|
//Now we need to reverse the Buffer, it is by searshing the buffer
|
|
PRUint32 loop = aLen;
|
|
for (int z=0; z<=aLen; z++){
|
|
temp.SetCharAt((PRUnichar)aSrc[loop], z);
|
|
loop--;
|
|
}
|
|
}
|
|
aSrc = (PRUnichar *)temp.get();
|
|
}
|
|
else if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_VISUAL )&&( mCharset.EqualsIgnoreCase("IBM864"))&& (mTextDir == IBMBIDI_TEXTDIRECTION_RTL) ){
|
|
|
|
bidiUtils->Conv_FE_06(nsString(aSrc), newBuffer);
|
|
aSrc = (PRUnichar *)newBuffer.get();
|
|
temp = newBuffer;
|
|
aLen=newBuffer.Length();
|
|
//Now we need to reverse the Buffer, it is by searshing the buffer
|
|
PRUint32 loop = aLen;
|
|
for (int z=0; z<=aLen; z++){
|
|
temp.SetCharAt((PRUnichar)aSrc[loop], z);
|
|
loop--;
|
|
}
|
|
aSrc = (PRUnichar *)temp.get();
|
|
}
|
|
#endif
|
|
char* res = nsnull;
|
|
if(NS_SUCCEEDED(encoder->Reset()))
|
|
{
|
|
PRInt32 maxByteLen = 0;
|
|
if(NS_SUCCEEDED(encoder->GetMaxLength(aSrc, (PRInt32) aLen, &maxByteLen)))
|
|
{
|
|
res = new char[maxByteLen+1];
|
|
if(nsnull != res)
|
|
{
|
|
PRInt32 reslen = maxByteLen;
|
|
PRInt32 reslen2 ;
|
|
PRInt32 srclen = aLen;
|
|
encoder->Convert(aSrc, &srclen, res, &reslen);
|
|
reslen2 = maxByteLen-reslen;
|
|
encoder->Finish(res+reslen, &reslen2);
|
|
res[reslen+reslen2] = '\0';
|
|
}
|
|
}
|
|
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// XXX i18n helper routines
|
|
nsString*
|
|
nsFormFrame::URLEncode(const nsString& aString, nsIUnicodeEncoder* encoder)
|
|
{
|
|
char* inBuf = nsnull;
|
|
if(encoder)
|
|
inBuf = UnicodeToNewBytes(aString.get(), aString.Length(), encoder);
|
|
|
|
if(nsnull == inBuf)
|
|
inBuf = aString.ToNewCString();
|
|
|
|
// convert to CRLF breaks
|
|
char* convertedBuf = nsLinebreakConverter::ConvertLineBreaks(inBuf,
|
|
nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakNet);
|
|
delete [] inBuf;
|
|
|
|
char* outBuf = nsEscape(convertedBuf, url_XPAlphas);
|
|
nsString* result = new nsString;
|
|
result->AssignWithConversion(outBuf);
|
|
nsCRT::free(outBuf);
|
|
nsMemory::Free(convertedBuf);
|
|
return result;
|
|
}
|
|
|
|
void nsFormFrame::GetSubmitCharset(nsString& oCharset)
|
|
{
|
|
oCharset.AssignWithConversion("UTF-8"); // default to utf-8
|
|
nsresult rv;
|
|
// XXX
|
|
// We may want to get it from the HTML 4 Accept-Charset attribute first
|
|
// see 17.3 The FORM element in HTML 4 for details
|
|
nsresult result = NS_OK;
|
|
nsAutoString acceptCharsetValue;
|
|
if (mContent) {
|
|
nsIHTMLContent* form = nsnull;
|
|
result = mContent->QueryInterface(kIHTMLContentIID, (void**)&form);
|
|
if (NS_SUCCEEDED(result) && (nsnull != form)) {
|
|
nsHTMLValue value;
|
|
result = form->GetHTMLAttribute(nsHTMLAtoms::acceptcharset, value);
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == result) {
|
|
if (eHTMLUnit_String == value.GetUnit()) {
|
|
value.GetStringValue(acceptCharsetValue);
|
|
}
|
|
}
|
|
NS_RELEASE(form);
|
|
}
|
|
}
|
|
#ifdef DEBUG_ftang
|
|
printf("accept-charset = %s\n", acceptCharsetValue.ToNewUTF8String());
|
|
#endif
|
|
PRInt32 l = acceptCharsetValue.Length();
|
|
if(l > 0 ) {
|
|
PRInt32 offset=0;
|
|
PRInt32 spPos=0;
|
|
// get charset from charsets one by one
|
|
nsCOMPtr<nsICharsetAlias> calias(do_GetService(kCharsetAliasCID, &rv));
|
|
if(NS_SUCCEEDED(rv) && (nsnull != calias)) {
|
|
do {
|
|
spPos = acceptCharsetValue.FindChar(PRUnichar(' '),PR_TRUE, offset);
|
|
PRInt32 cnt = ((-1==spPos)?(l-offset):(spPos-offset));
|
|
if(cnt > 0) {
|
|
nsAutoString charset;
|
|
acceptCharsetValue.Mid(charset, offset, cnt);
|
|
#ifdef DEBUG_ftang
|
|
printf("charset[i] = %s\n",charset.ToNewUTF8String());
|
|
#endif
|
|
if(NS_SUCCEEDED(calias->GetPreferred(charset,oCharset)))
|
|
return;
|
|
}
|
|
offset = spPos + 1;
|
|
} while(spPos != -1);
|
|
}
|
|
}
|
|
// if there are no accept-charset or all the charset are not supported
|
|
// Get the charset from document
|
|
nsIDocument* doc = nsnull;
|
|
mContent->GetDocument(doc);
|
|
if( nsnull != doc ) {
|
|
rv = doc->GetDocumentCharacterSet(oCharset);
|
|
NS_RELEASE(doc);
|
|
}
|
|
|
|
#ifdef IBMBIDI
|
|
//ahmed 15-1 why it is here, I think you have to put it after the next conditions
|
|
mCharset=oCharset;
|
|
//ahmed
|
|
if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_VISUAL )&&( oCharset.EqualsIgnoreCase("windows-1256") ) ) {
|
|
//Mohamed
|
|
oCharset.AssignWithConversion("IBM864");
|
|
}
|
|
else if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_LOGICAL )&&( oCharset.EqualsIgnoreCase("IBM864") ) ) {
|
|
oCharset.AssignWithConversion("IBM864i");
|
|
}
|
|
else if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_VISUAL )&&( oCharset.EqualsIgnoreCase("ISO-8859-6") ) ) {
|
|
oCharset.AssignWithConversion("IBM864");
|
|
}
|
|
else if( ( mCtrlsModAtSubmit==IBMBIDI_CONTROLSTEXTMODE_VISUAL )&&( oCharset.EqualsIgnoreCase("UTF-8") ) ) {
|
|
oCharset.AssignWithConversion("IBM864");
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
NS_IMETHODIMP nsFormFrame::GetEncoder(nsIUnicodeEncoder** encoder)
|
|
{
|
|
*encoder = nsnull;
|
|
nsAutoString charset;
|
|
nsresult rv = NS_OK;
|
|
GetSubmitCharset(charset);
|
|
#ifdef DEBUG_ftang
|
|
printf("charset=%s\n", charset.ToNewCString());
|
|
#endif
|
|
|
|
// Get Charset, get the encoder.
|
|
nsICharsetConverterManager * ccm = nsnull;
|
|
rv = nsServiceManager::GetService(kCharsetConverterManagerCID ,
|
|
NS_GET_IID(nsICharsetConverterManager),
|
|
(nsISupports**)&ccm);
|
|
if(NS_SUCCEEDED(rv) && (nsnull != ccm)) {
|
|
rv = ccm->GetUnicodeEncoder(&charset, encoder);
|
|
nsServiceManager::ReleaseService( kCharsetConverterManagerCID, ccm);
|
|
if (nsnull == encoder) {
|
|
rv = NS_ERROR_FAILURE;
|
|
}
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = (*encoder)->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, nsnull, (PRUnichar)'?');
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsFormFrame::GetPlatformEncoder(nsIUnicodeEncoder** encoder)
|
|
{
|
|
*encoder = nsnull;
|
|
nsAutoString localeCharset;
|
|
nsresult rv = NS_OK;
|
|
|
|
// Get Charset, get the encoder.
|
|
nsICharsetConverterManager * ccm = nsnull;
|
|
rv = nsServiceManager::GetService(kCharsetConverterManagerCID ,
|
|
NS_GET_IID(nsICharsetConverterManager),
|
|
(nsISupports**)&ccm);
|
|
|
|
if(NS_SUCCEEDED(rv) && (nsnull != ccm)) {
|
|
|
|
nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, localeCharset);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
NS_ASSERTION(0, "error getting locale charset, using ISO-8859-1");
|
|
localeCharset.AssignWithConversion("ISO-8859-1");
|
|
rv = NS_OK;
|
|
}
|
|
|
|
// get unicode converter mgr
|
|
//nsCOMPtr<nsICharsetConverterManager> ccm =
|
|
// do_GetService(kCharsetConverterManagerCID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = ccm->GetUnicodeEncoder(&localeCharset, encoder);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
#define CRLF "\015\012"
|
|
nsresult nsFormFrame::ProcessAsURLEncoded(nsIFormProcessor* aFormProcessor, PRBool isPost, nsString& aData, nsIFormControlFrame* aFrame)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsString buf;
|
|
PRBool firstTime = PR_TRUE;
|
|
PRUint32 numChildren = mFormControls.Count();
|
|
|
|
nsCOMPtr<nsIUnicodeEncoder> encoder;
|
|
if(NS_FAILED(GetEncoder(getter_AddRefs(encoder)))) // Non-fatal error
|
|
encoder = nsnull;
|
|
|
|
// collect and encode the data from the children controls
|
|
for (PRUint32 childX = 0; childX < numChildren; childX++) {
|
|
nsIFormControlFrame* child = (nsIFormControlFrame*) mFormControls.ElementAt(childX);
|
|
if (child && child->IsSuccessful(aFrame)) {
|
|
PRInt32 numValues = 0;
|
|
PRInt32 maxNumValues = child->GetMaxNumValues();
|
|
if (0 >= maxNumValues) {
|
|
continue;
|
|
}
|
|
nsString* names = new nsString[maxNumValues];
|
|
if (!names) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
} else {
|
|
nsString* values = new nsString[maxNumValues];
|
|
if (!values) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
} else {
|
|
if (PR_TRUE == child->GetNamesValues(maxNumValues, numValues, values, names)) {
|
|
for (int valueX = 0; valueX < numValues; valueX++){
|
|
if (PR_TRUE == firstTime) {
|
|
firstTime = PR_FALSE;
|
|
} else {
|
|
buf.AppendWithConversion("&");
|
|
}
|
|
nsString* convName = URLEncode(names[valueX], encoder);
|
|
buf += *convName;
|
|
delete convName;
|
|
buf.AppendWithConversion("=");
|
|
nsAutoString newValue;
|
|
newValue.Append(values[valueX]);
|
|
if (aFormProcessor) {
|
|
ProcessValue(*aFormProcessor, child, names[valueX], newValue);
|
|
}
|
|
nsString* convValue = URLEncode(newValue, encoder);
|
|
buf += *convValue;
|
|
delete convValue;
|
|
}
|
|
}
|
|
delete [] values;
|
|
}
|
|
delete [] names;
|
|
}
|
|
}
|
|
}
|
|
aData.SetLength(0);
|
|
if (isPost) {
|
|
char size[16];
|
|
sprintf(size, "%d", buf.Length());
|
|
aData.AssignWithConversion("Content-type: application/x-www-form-urlencoded");
|
|
#ifdef SPECIFY_CHARSET_IN_CONTENT_TYPE
|
|
nsString charset;
|
|
GetSubmitCharset(charset);
|
|
aData += "; charset=";
|
|
aData += charset;
|
|
#endif
|
|
aData.AppendWithConversion(CRLF);
|
|
aData.AppendWithConversion("Content-Length: ");
|
|
aData.AppendWithConversion(size);
|
|
aData.AppendWithConversion(CRLF);
|
|
aData.AppendWithConversion(CRLF);
|
|
}
|
|
aData += buf;
|
|
// Need to append CRLF to end of stream for compatability with Nav and IE
|
|
if (isPost) {
|
|
aData.AppendWithConversion(CRLF);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
// return the filename without the leading directories (Unix basename)
|
|
PRUint32
|
|
nsFormFrame::GetFileNameWithinPath(nsString aPathName)
|
|
{
|
|
// We need to operator on Unicode strings and not on nsCStrings
|
|
// because Shift_JIS and Big5 encoded filenames can have
|
|
// embedded directory separators in them.
|
|
#ifdef XP_MAC
|
|
// On a Mac the only invalid character in a file name is a :
|
|
// so we have to avoid the test for '\'. We can't use
|
|
// PR_DIRECTORY_SEPARATOR_STR (even though ':' is a dir sep for MacOS)
|
|
// because this is set to '/' for reasons unknown to this coder.
|
|
PRInt32 fileNameStart = aPathName.RFind(":");
|
|
#else
|
|
PRInt32 fileNameStart = aPathName.RFind(PR_DIRECTORY_SEPARATOR_STR);
|
|
#endif
|
|
// if no directory separator is found (-1), return the whole
|
|
// string, otherwise return the basename only
|
|
return (PRUint32) (fileNameStart + 1);
|
|
}
|
|
|
|
nsresult
|
|
nsFormFrame::GetContentType(char* aPathName, char** aContentType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
NS_ASSERTION(aContentType, "null pointer");
|
|
|
|
if (aPathName && *aPathName) {
|
|
// Get file extension and mimetype from that.g936
|
|
char* fileExt = aPathName + nsCRT::strlen(aPathName);
|
|
while (fileExt > aPathName) {
|
|
if (*(--fileExt) == '.') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*fileExt == '.' && *(fileExt + 1)) {
|
|
nsCOMPtr<nsIMIMEService> MIMEService =
|
|
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
rv = MIMEService->GetTypeFromExtension(fileExt + 1, aContentType);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
*aContentType = nsCRT::strdup("application/octet-stream");
|
|
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
|
|
return NS_OK;
|
|
}
|
|
|
|
#define CONTENT_DISP "Content-Disposition: form-data; name=\""
|
|
#define FILENAME "\"; filename=\""
|
|
#define CONTENT_TYPE "Content-Type: "
|
|
#define CONTENT_ENCODING "Content-Encoding: "
|
|
#define CONTENT_TRANSFER "Content-Transfer-Encoding: "
|
|
#define BINARY_CONTENT "binary"
|
|
#define BUFSIZE 1024
|
|
#define MULTIPART "multipart/form-data"
|
|
#define SEP "--"
|
|
|
|
nsresult nsFormFrame::ProcessAsMultipart(nsIFormProcessor* aFormProcessor,nsIFileSpec*& aMultipartDataFile, nsIFormControlFrame* aFrame)
|
|
{
|
|
PRBool compatibleSubmit = PR_TRUE;
|
|
nsCOMPtr<nsIPref> prefService(do_GetService(NS_PREF_CONTRACTID));
|
|
if (prefService)
|
|
prefService->GetBoolPref("browser.forms.submit.backwards_compatible",
|
|
&compatibleSubmit);
|
|
|
|
char buffer[BUFSIZE];
|
|
PRInt32 numChildren = mFormControls.Count();
|
|
|
|
// Create a temporary file to write the form post data to
|
|
nsSpecialSystemDirectory tempDir(nsSpecialSystemDirectory::OS_TemporaryDirectory);
|
|
tempDir += "formpost";
|
|
tempDir.MakeUnique();
|
|
nsIFileSpec* postDataFile = nsnull;
|
|
nsresult rv = NS_NewFileSpecWithSpec(tempDir, &postDataFile);
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Post data file couldn't be created!");
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// write the content-type, boundary to the tmp file
|
|
char boundary[80];
|
|
sprintf(boundary, "---------------------------%d%d%d",
|
|
rand(), rand(), rand());
|
|
sprintf(buffer, "Content-type: %s; boundary=%s" CRLF, MULTIPART, boundary);
|
|
PRInt32 wantbytes = 0, gotbytes = 0;
|
|
rv = postDataFile->Write(buffer, wantbytes = PL_strlen(buffer), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) return rv;
|
|
|
|
nsCOMPtr<nsIUnicodeEncoder> encoder;
|
|
if(NS_FAILED( GetEncoder(getter_AddRefs(encoder)))) // Non-fatal error
|
|
encoder = nsnull;
|
|
|
|
nsCOMPtr<nsIUnicodeEncoder> platformencoder;
|
|
if(NS_FAILED(GetPlatformEncoder(getter_AddRefs(platformencoder)))) // Non-fatal error
|
|
platformencoder = nsnull;
|
|
|
|
|
|
PRInt32 boundaryLen = PL_strlen(boundary);
|
|
PRInt32 contDispLen = PL_strlen(CONTENT_DISP);
|
|
PRInt32 crlfLen = PL_strlen(CRLF);
|
|
PRInt32 sepLen = PL_strlen(SEP);
|
|
|
|
// compute the content length
|
|
/////////////////////////////
|
|
|
|
PRInt32 contentLen = 0; // extra crlf after content-length header not counted
|
|
PRInt32 childX; // stupid compiler
|
|
for (childX = 0; childX < numChildren; childX++) {
|
|
nsIFormControlFrame* child = (nsIFormControlFrame*) mFormControls.ElementAt(childX);
|
|
if (child) {
|
|
PRInt32 type;
|
|
child->GetType(&type);
|
|
if (child->IsSuccessful(aFrame)) {
|
|
PRInt32 numValues = 0;
|
|
PRInt32 maxNumValues = child->GetMaxNumValues();
|
|
if (maxNumValues <= 0) {
|
|
continue;
|
|
}
|
|
nsString* names = new nsString[maxNumValues];
|
|
nsString* values = new nsString[maxNumValues];
|
|
if (PR_FALSE == child->GetNamesValues(maxNumValues, numValues, values, names)) {
|
|
continue;
|
|
}
|
|
for (int valueX = 0; valueX < numValues; valueX++) {
|
|
char* name = nsnull;
|
|
char* value = nsnull;
|
|
char* fname = nsnull; // basename (path removed)
|
|
|
|
nsString valueStr = values[valueX];
|
|
if (aFormProcessor) {
|
|
ProcessValue(*aFormProcessor, child, names[valueX], valueStr);
|
|
}
|
|
|
|
if(encoder) {
|
|
name = UnicodeToNewBytes(names[valueX].get(), names[valueX].Length(), encoder);
|
|
}
|
|
|
|
//use the platformencoder only for values containing file names
|
|
PRUint32 fileNameStart = 0;
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
fileNameStart = GetFileNameWithinPath(valueStr);
|
|
if(platformencoder) {
|
|
value = UnicodeToNewBytes(valueStr.get(), valueStr.Length(), platformencoder);
|
|
|
|
// filename with the leading dirs stripped
|
|
fname = UnicodeToNewBytes(valueStr.get() + fileNameStart,
|
|
valueStr.Length() - fileNameStart,
|
|
platformencoder);
|
|
}
|
|
} else {
|
|
if(encoder) {
|
|
value = UnicodeToNewBytes(valueStr.get(), valueStr.Length(), encoder);
|
|
}
|
|
}
|
|
|
|
if(nsnull == name)
|
|
name = names[valueX].ToNewCString();
|
|
if(nsnull == value)
|
|
value = valueStr.ToNewCString();
|
|
|
|
if (0 == names[valueX].Length()) {
|
|
continue;
|
|
}
|
|
|
|
// convert value to CRLF line breaks
|
|
char* newValue = nsLinebreakConverter::ConvertLineBreaks(value,
|
|
nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakNet);
|
|
if (value)
|
|
nsMemory::Free(value);
|
|
value = newValue;
|
|
|
|
// Add boundary line
|
|
contentLen += sepLen + boundaryLen + crlfLen;
|
|
|
|
// File inputs should include Content-Transfer-Encoding
|
|
if (NS_FORM_INPUT_FILE == type && !compatibleSubmit) {
|
|
contentLen += PL_strlen(CONTENT_TRANSFER);
|
|
// XXX is there any way to tell when "8bit" or "7bit" etc may be more appropriate than
|
|
// always using "binary"?
|
|
contentLen += PL_strlen(BINARY_CONTENT);
|
|
contentLen += crlfLen;
|
|
}
|
|
// End Content-Transfer-Encoding line
|
|
|
|
// Add Content-Disp line
|
|
contentLen += contDispLen;
|
|
contentLen += PL_strlen(name);
|
|
|
|
// File inputs also list filename on Content-Disp line
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
contentLen += PL_strlen(FILENAME);
|
|
contentLen += PL_strlen(fname);
|
|
}
|
|
// End Content-Disp Line (quote plus CRLF)
|
|
contentLen += 1 + crlfLen; // ending name quote plus CRLF
|
|
|
|
// File inputs add Content-Type line
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
char* contentType = nsnull;
|
|
rv = GetContentType(value, &contentType);
|
|
if (NS_FAILED(rv)) break; // Need to free up anything here?
|
|
contentLen += PL_strlen(CONTENT_TYPE);
|
|
contentLen += PL_strlen(contentType) + crlfLen;
|
|
nsCRT::free(contentType);
|
|
}
|
|
|
|
// Blank line before value
|
|
contentLen += crlfLen;
|
|
|
|
// File inputs add file contents next
|
|
if (NS_FORM_INPUT_FILE == type &&
|
|
PL_strlen(value)) { // Don't bother if no file specified
|
|
do {
|
|
// Because we have a native path to the file we can't use PR_GetFileInfo
|
|
// on the Mac as it expects a Unix style path. Instead we'll use our
|
|
// spiffy new nsILocalFile
|
|
nsILocalFile* tempFile = nsnull;
|
|
rv = NS_NewLocalFile(value, PR_TRUE, &tempFile);
|
|
NS_ASSERTION(tempFile, "Couldn't create nsIFileSpec to get file size!");
|
|
if (NS_FAILED(rv) || !tempFile)
|
|
break; // NS_ERROR_OUT_OF_MEMORY
|
|
PRUint32 fileSize32 = 0;
|
|
PRInt64 fileSize = LL_Zero();
|
|
rv = tempFile->GetFileSize(&fileSize);
|
|
if (NS_FAILED(rv)) {
|
|
NS_RELEASE(tempFile);
|
|
break;
|
|
}
|
|
LL_L2UI(fileSize32, fileSize);
|
|
contentLen += fileSize32;
|
|
NS_RELEASE(tempFile);
|
|
} while (PR_FALSE);
|
|
|
|
// Add CRLF after file
|
|
contentLen += crlfLen;
|
|
} else {
|
|
// Non-file inputs add value line
|
|
contentLen += PL_strlen(value) + crlfLen;
|
|
}
|
|
if (name)
|
|
nsMemory::Free(name);
|
|
if (value)
|
|
nsMemory::Free(value);
|
|
if (fname)
|
|
nsMemory::Free(fname);
|
|
}
|
|
delete [] names;
|
|
delete [] values;
|
|
}
|
|
|
|
aMultipartDataFile = postDataFile;
|
|
}
|
|
}
|
|
|
|
// Add the post file boundary line
|
|
contentLen += sepLen + boundaryLen + sepLen + crlfLen;
|
|
|
|
// write the content
|
|
////////////////////
|
|
|
|
sprintf(buffer, "Content-Length: %d" CRLF CRLF, contentLen);
|
|
rv = postDataFile->Write(buffer, wantbytes = PL_strlen(buffer), &gotbytes);
|
|
if (NS_SUCCEEDED(rv) && (wantbytes == gotbytes)) {
|
|
|
|
// write the content passing through all of the form controls a 2nd time
|
|
for (childX = 0; childX < numChildren; childX++) {
|
|
nsIFormControlFrame* child = (nsIFormControlFrame*) mFormControls.ElementAt(childX);
|
|
if (child) {
|
|
PRInt32 type;
|
|
child->GetType(&type);
|
|
if (child->IsSuccessful(aFrame)) {
|
|
PRInt32 numValues = 0;
|
|
PRInt32 maxNumValues = child->GetMaxNumValues();
|
|
if (maxNumValues <= 0) {
|
|
continue;
|
|
}
|
|
nsString* names = new nsString[maxNumValues];
|
|
nsString* values = new nsString[maxNumValues];
|
|
if (PR_FALSE == child->GetNamesValues(maxNumValues, numValues, values, names)) {
|
|
continue;
|
|
}
|
|
for (int valueX = 0; valueX < numValues; valueX++) {
|
|
char* name = nsnull;
|
|
char* value = nsnull;
|
|
char* fname = nsnull; // basename (path removed)
|
|
|
|
nsString valueStr = values[valueX];
|
|
|
|
if(encoder) {
|
|
name = UnicodeToNewBytes(names[valueX].get(), names[valueX].Length(), encoder);
|
|
}
|
|
|
|
//use the platformencoder only for values containing file names
|
|
PRUint32 fileNameStart = 0;
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
fileNameStart = GetFileNameWithinPath(valueStr);
|
|
if(platformencoder) {
|
|
value = UnicodeToNewBytes(valueStr.get(), valueStr.Length(), platformencoder);
|
|
|
|
// filename with the leading dirs stripped
|
|
fname = UnicodeToNewBytes(valueStr.get() + fileNameStart,
|
|
valueStr.Length() - fileNameStart, platformencoder);
|
|
}
|
|
} else {
|
|
if(encoder) {
|
|
value = UnicodeToNewBytes(valueStr.get(), valueStr.Length(), encoder);
|
|
}
|
|
}
|
|
|
|
if(nsnull == name)
|
|
name = names[valueX].ToNewCString();
|
|
if(nsnull == value)
|
|
value = valueStr.ToNewCString();
|
|
|
|
if (0 == names[valueX].Length()) {
|
|
continue;
|
|
}
|
|
|
|
// convert value to CRLF line breaks
|
|
char* newValue = nsLinebreakConverter::ConvertLineBreaks(value,
|
|
nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakNet);
|
|
if (value)
|
|
nsMemory::Free(value);
|
|
value = newValue;
|
|
|
|
// Print boundary line
|
|
sprintf(buffer, SEP "%s" CRLF, boundary);
|
|
rv = postDataFile->Write(buffer, wantbytes = PL_strlen(buffer), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
|
|
// File inputs should include Content-Transfer-Encoding to prep server side
|
|
// MIME decoders
|
|
if (NS_FORM_INPUT_FILE == type && !compatibleSubmit) {
|
|
rv = postDataFile->Write(CONTENT_TRANSFER, wantbytes = PL_strlen(CONTENT_TRANSFER), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
|
|
// XXX is there any way to tell when "8bit" or "7bit" etc may be more appropriate than
|
|
// always using "binary"?
|
|
|
|
rv = postDataFile->Write(BINARY_CONTENT, wantbytes = PL_strlen(BINARY_CONTENT), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
|
|
rv = postDataFile->Write(CRLF, wantbytes = PL_strlen(CRLF), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
}
|
|
|
|
// Print Content-Disp line
|
|
rv = postDataFile->Write(CONTENT_DISP, wantbytes = contDispLen, &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
rv = postDataFile->Write(name, wantbytes = PL_strlen(name), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
|
|
// File inputs also list filename on Content-Disp line
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
rv = postDataFile->Write(FILENAME, wantbytes = PL_strlen(FILENAME), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
rv = postDataFile->Write(fname, wantbytes = PL_strlen(fname), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
}
|
|
|
|
// End Content Disp
|
|
rv = postDataFile->Write("\"" CRLF , wantbytes = PL_strlen("\"" CRLF), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
|
|
// File inputs write Content-Type line
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
char* contentType = nsnull;
|
|
rv = GetContentType(value, &contentType);
|
|
if (NS_FAILED(rv)) break;
|
|
rv = postDataFile->Write(CONTENT_TYPE, wantbytes = PL_strlen(CONTENT_TYPE), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
rv = postDataFile->Write(contentType, wantbytes = PL_strlen(contentType), &gotbytes);
|
|
nsCRT::free(contentType);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
rv = postDataFile->Write(CRLF, wantbytes = PL_strlen(CRLF), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
// end content-type header
|
|
}
|
|
|
|
// Blank line before value
|
|
rv = postDataFile->Write(CRLF, wantbytes = PL_strlen(CRLF), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
|
|
// File inputs print file contents next
|
|
if (NS_FORM_INPUT_FILE == type) {
|
|
nsIFileSpec* contentFile = nsnull;
|
|
rv = NS_NewFileSpec(&contentFile);
|
|
NS_ASSERTION(contentFile, "Post content file couldn't be created!");
|
|
if (NS_FAILED(rv) || !contentFile) break; // NS_ERROR_OUT_OF_MEMORY
|
|
rv = contentFile->SetNativePath(value);
|
|
NS_ASSERTION(contentFile, "Post content file path couldn't be set!");
|
|
if (NS_FAILED(rv)) {
|
|
NS_RELEASE(contentFile);
|
|
break;
|
|
}
|
|
// Print file contents
|
|
PRInt32 size = 1;
|
|
while (1) {
|
|
char* readbuffer = nsnull;
|
|
rv = contentFile->Read(&readbuffer, BUFSIZE, &size);
|
|
if (NS_FAILED(rv) || 0 >= size) break;
|
|
rv = postDataFile->Write(readbuffer, wantbytes = size, &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
}
|
|
NS_RELEASE(contentFile);
|
|
// Print CRLF after file
|
|
rv = postDataFile->Write(CRLF, wantbytes = PL_strlen(CRLF), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
}
|
|
|
|
// Non-file inputs print value line
|
|
else {
|
|
rv = postDataFile->Write(value, wantbytes = PL_strlen(value), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
rv = postDataFile->Write(CRLF, wantbytes = PL_strlen(CRLF), &gotbytes);
|
|
if (NS_FAILED(rv) || (wantbytes != gotbytes)) break;
|
|
}
|
|
if (name)
|
|
nsMemory::Free(name);
|
|
if (value)
|
|
nsMemory::Free(value);
|
|
if (fname)
|
|
nsMemory::Free(fname);
|
|
}
|
|
delete [] names;
|
|
delete [] values;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
sprintf(buffer, SEP "%s" SEP CRLF, boundary);
|
|
rv = postDataFile->Write(buffer, wantbytes = PL_strlen(buffer), &gotbytes);
|
|
if (NS_SUCCEEDED(rv) && (wantbytes == gotbytes)) {
|
|
rv = postDataFile->CloseStream();
|
|
}
|
|
}
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Generating the form post temp file failed.\n");
|
|
return rv;
|
|
}
|
|
|
|
// static helper functions for nsIFormControls
|
|
|
|
PRBool
|
|
nsFormFrame::GetDisabled(nsIFrame* aChildFrame, nsIContent* aContent)
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
|
|
nsIContent* content = aContent;
|
|
if (nsnull == content) {
|
|
aChildFrame->GetContent(&content);
|
|
}
|
|
if (nsnull != content) {
|
|
nsIHTMLContent* htmlContent = nsnull;
|
|
content->QueryInterface(kIHTMLContentIID, (void**)&htmlContent);
|
|
if (nsnull != htmlContent) {
|
|
nsHTMLValue value;
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == htmlContent->GetHTMLAttribute(nsHTMLAtoms::disabled, value)) {
|
|
result = PR_TRUE;
|
|
}
|
|
NS_RELEASE(htmlContent);
|
|
}
|
|
if (nsnull == aContent) {
|
|
NS_RELEASE(content);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PRBool
|
|
nsFormFrame::GetReadonly(nsIFrame* aChildFrame, nsIContent* aContent)
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
|
|
nsIContent* content = aContent;
|
|
if (nsnull == content) {
|
|
aChildFrame->GetContent(&content);
|
|
}
|
|
if (nsnull != content) {
|
|
nsIHTMLContent* htmlContent = nsnull;
|
|
content->QueryInterface(kIHTMLContentIID, (void**)&htmlContent);
|
|
if (nsnull != htmlContent) {
|
|
nsHTMLValue value;
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == htmlContent->GetHTMLAttribute(nsHTMLAtoms::readonly, value)) {
|
|
result = PR_TRUE;
|
|
}
|
|
NS_RELEASE(htmlContent);
|
|
}
|
|
if (nsnull == aContent) {
|
|
NS_RELEASE(content);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsFormFrame::GetName(nsIFrame* aChildFrame, nsString& aName, nsIContent* aContent)
|
|
{
|
|
nsresult result = NS_FORM_NOTOK;
|
|
|
|
nsIContent* content = aContent;
|
|
if (nsnull == content) {
|
|
aChildFrame->GetContent(&content);
|
|
}
|
|
if (nsnull != content) {
|
|
nsIHTMLContent* htmlContent = nsnull;
|
|
result = content->QueryInterface(kIHTMLContentIID, (void**)&htmlContent);
|
|
if (NS_SUCCEEDED(result) && (nsnull != htmlContent)) {
|
|
nsHTMLValue value;
|
|
result = htmlContent->GetHTMLAttribute(nsHTMLAtoms::name, value);
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == result) {
|
|
if (eHTMLUnit_String == value.GetUnit()) {
|
|
value.GetStringValue(aName);
|
|
}
|
|
}
|
|
NS_RELEASE(htmlContent);
|
|
}
|
|
if (nsnull == aContent) {
|
|
NS_RELEASE(content);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
nsresult
|
|
nsFormFrame::GetValue(nsIFrame* aChildFrame, nsString& aValue, nsIContent* aContent)
|
|
{
|
|
nsresult result = NS_FORM_NOTOK;
|
|
|
|
nsIContent* content = aContent;
|
|
if (nsnull == content) {
|
|
aChildFrame->GetContent(&content);
|
|
}
|
|
if (nsnull != content) {
|
|
nsIHTMLContent* htmlContent = nsnull;
|
|
result = content->QueryInterface(kIHTMLContentIID, (void**)&htmlContent);
|
|
if (NS_SUCCEEDED(result) && (nsnull != htmlContent)) {
|
|
nsHTMLValue value;
|
|
result = htmlContent->GetHTMLAttribute(nsHTMLAtoms::value, value);
|
|
if (NS_CONTENT_ATTR_HAS_VALUE == result) {
|
|
if (eHTMLUnit_String == value.GetUnit()) {
|
|
value.GetStringValue(aValue);
|
|
}
|
|
}
|
|
NS_RELEASE(htmlContent);
|
|
}
|
|
if (nsnull == aContent) {
|
|
NS_RELEASE(content);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void
|
|
nsFormFrame::StyleChangeReflow(nsIPresContext* aPresContext,
|
|
nsIFrame* aFrame)
|
|
{
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
nsIReflowCommand* reflowCmd;
|
|
nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame,
|
|
nsIReflowCommand::StyleChanged);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
shell->AppendReflowCommand(reflowCmd);
|
|
NS_RELEASE(reflowCmd);
|
|
}
|
|
}
|