1 /** 2 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21 #include "config.h" 22 23 #if ENABLE(WML) 24 #include "WMLGoElement.h" 25 26 #include "Attribute.h" 27 #include "FormData.h" 28 #include "FormDataBuilder.h" 29 #include "FormSubmission.h" 30 #include "Frame.h" 31 #include "FrameLoader.h" 32 #include "HTMLNames.h" 33 #include "ResourceRequest.h" 34 #include "TextEncoding.h" 35 #include "WMLCardElement.h" 36 #include "WMLDocument.h" 37 #include "WMLNames.h" 38 #include "WMLPageState.h" 39 #include "WMLPostfieldElement.h" 40 #include "WMLTimerElement.h" 41 #include "WMLVariables.h" 42 #include <wtf/text/CString.h> 43 44 namespace WebCore { 45 46 using namespace WMLNames; 47 48 WMLGoElement::WMLGoElement(const QualifiedName& tagName, Document* doc) 49 : WMLTaskElement(tagName, doc) 50 { 51 } 52 53 PassRefPtr<WMLGoElement> WMLGoElement::create(const QualifiedName& tagName, Document* document) 54 { 55 return adoptRef(new WMLGoElement(tagName, document)); 56 } 57 58 void WMLGoElement::registerPostfieldElement(WMLPostfieldElement* postfield) 59 { 60 ASSERT(m_postfieldElements.find(postfield) == WTF::notFound); 61 m_postfieldElements.append(postfield); 62 } 63 64 void WMLGoElement::deregisterPostfieldElement(WMLPostfieldElement* postfield) 65 { 66 size_t position = m_postfieldElements.find(postfield); 67 ASSERT(position != WTF::notFound); 68 m_postfieldElements.remove(position); 69 } 70 71 void WMLGoElement::parseMappedAttribute(Attribute* attr) 72 { 73 if (attr->name() == HTMLNames::methodAttr) 74 m_formAttributes.parseMethodType(attr->value()); 75 else if (attr->name() == HTMLNames::enctypeAttr) 76 m_formAttributes.parseEncodingType(parseValueSubstitutingVariableReferences(attr->value())); 77 else if (attr->name() == HTMLNames::accept_charsetAttr) 78 m_formAttributes.setAcceptCharset(parseValueForbiddingVariableReferences(attr->value())); 79 else 80 WMLTaskElement::parseMappedAttribute(attr); 81 } 82 83 void WMLGoElement::executeTask() 84 { 85 ASSERT(document()->isWMLDocument()); 86 WMLDocument* document = static_cast<WMLDocument*>(this->document()); 87 88 WMLPageState* pageState = wmlPageStateForDocument(document); 89 if (!pageState) 90 return; 91 92 WMLCardElement* card = document->activeCard(); 93 if (!card) 94 return; 95 96 Frame* frame = document->frame(); 97 if (!frame) 98 return; 99 100 FrameLoader* loader = frame->loader(); 101 if (!loader) 102 return; 103 104 String href = getAttribute(HTMLNames::hrefAttr); 105 if (href.isEmpty()) 106 return; 107 108 // Substitute variables within target url attribute value 109 KURL url = document->completeURL(substituteVariableReferences(href, document, WMLVariableEscapingEscape)); 110 if (url.isEmpty()) 111 return; 112 113 storeVariableState(pageState); 114 115 // Stop the timer of the current card if it is active 116 if (WMLTimerElement* eventTimer = card->eventTimer()) 117 eventTimer->stop(); 118 119 // FIXME: 'newcontext' handling not implemented for external cards 120 bool inSameDeck = document->url().path() == url.path(); 121 if (inSameDeck && url.hasFragmentIdentifier()) { 122 if (WMLCardElement* card = WMLCardElement::findNamedCardInDocument(document, url.fragmentIdentifier())) { 123 if (card->isNewContext()) 124 pageState->reset(); 125 } 126 } 127 128 // Prepare loading the destination url 129 ResourceRequest request(url); 130 131 if (getAttribute(sendrefererAttr) == "true") 132 request.setHTTPReferrer(loader->outgoingReferrer()); 133 134 String cacheControl = getAttribute(cache_controlAttr); 135 136 if (m_formAttributes.method() == FormSubmission::PostMethod) 137 preparePOSTRequest(request, inSameDeck, cacheControl); 138 else 139 prepareGETRequest(request, url); 140 141 // Set HTTP cache-control header if needed 142 if (!cacheControl.isEmpty()) { 143 request.setHTTPHeaderField("cache-control", cacheControl); 144 145 if (cacheControl == "no-cache") 146 request.setCachePolicy(ReloadIgnoringCacheData); 147 } 148 149 loader->load(request, false); 150 } 151 152 void WMLGoElement::preparePOSTRequest(ResourceRequest& request, bool inSameDeck, const String& cacheControl) 153 { 154 request.setHTTPMethod("POST"); 155 156 if (inSameDeck && cacheControl != "no-cache") { 157 request.setCachePolicy(ReturnCacheDataDontLoad); 158 return; 159 } 160 161 RefPtr<FormData> data; 162 163 if (m_formAttributes.isMultiPartForm()) { // multipart/form-data 164 Vector<char> boundary = FormDataBuilder::generateUniqueBoundaryString(); 165 data = createFormData(boundary.data()); 166 request.setHTTPContentType(m_formAttributes.encodingType() + "; boundary=" + boundary.data()); 167 } else { 168 // text/plain or application/x-www-form-urlencoded 169 data = createFormData(CString()); 170 request.setHTTPContentType(m_formAttributes.encodingType()); 171 } 172 173 request.setHTTPBody(data.get()); 174 } 175 176 void WMLGoElement::prepareGETRequest(ResourceRequest& request, const KURL& url) 177 { 178 request.setHTTPMethod("GET"); 179 180 // Eventually display error message? 181 if (m_formAttributes.isMultiPartForm()) 182 return; 183 184 RefPtr<FormData> data = createFormData(CString()); 185 186 KURL remoteURL(url); 187 remoteURL.setQuery(data->flattenToString()); 188 request.setURL(remoteURL); 189 } 190 191 PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary) 192 { 193 CString key; 194 CString value; 195 196 Vector<char> encodedData; 197 TextEncoding encoding = FormDataBuilder::encodingFromAcceptCharset(m_formAttributes.acceptCharset(), document()).encodingForFormSubmission(); 198 199 Vector<WMLPostfieldElement*>::iterator it = m_postfieldElements.begin(); 200 Vector<WMLPostfieldElement*>::iterator end = m_postfieldElements.end(); 201 202 RefPtr<FormData> result = FormData::create(); 203 for (; it != end; ++it) { 204 (*it)->encodeData(encoding, key, value); 205 206 if (m_formAttributes.isMultiPartForm()) { 207 Vector<char> header; 208 FormDataBuilder::beginMultiPartHeader(header, boundary, key); 209 FormDataBuilder::finishMultiPartHeader(header); 210 result->appendData(header.data(), header.size()); 211 212 if (size_t dataSize = value.length()) 213 result->appendData(value.data(), dataSize); 214 215 result->appendData("\r\n", 2); 216 } else 217 FormDataBuilder::addKeyValuePairAsFormData(encodedData, key, value); 218 } 219 220 if (m_formAttributes.isMultiPartForm()) 221 FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, boundary, true); 222 223 result->appendData(encodedData.data(), encodedData.size()); 224 return result; 225 } 226 227 } 228 229 #endif 230