Is it possible to validate a radio group (so something is checked off, or chosen) using server-side validation with Perl? If so, how?
I already have it for JavaScript, but I want this form to be able to be submitted even without JavaScript enabled. Thus I will need the validation on the server-side.
There is no fixed name for the radio group, it can change, however there must be a name, so that #names = $cgi->param() will give all the names.
I'm thinking along something that will give me the type, like the type in JavaScript, to determine if it's a radio button in a group.
Your CGI script receives form fields as name-value pairs without any information as to what type of visual form element generated the values.
Your CGI script must know the names of the input variables whose values it is going to validate. Having the names supplied to the script based on untrusted user input is risky IMHO—that includes using another field whose value is the name of the radio group.
Say, you have a variable called contact_me which can take on values "yes" and "no". There is absolutely no reason for your CGI script to care if the value was provided using
<select name="contact_me">
<option value="yes" selected="1">Please do!</option>
<option value="no">Oh no!!!</option>
</select>
or using
<input type="radio" name="contact_me" value="yes" checked="1">
<input type="radio" name="contact_me" value="no">
or if the user typed her answer into the text field
<input name="contact_me">
The only thing your CGI script needs to concern itself with is if the value of contact_me is "yes" or "no".
It looks like you do not have a firm grasp of CGI. Please see The World Wide Web Security FAQ: CGI (Server) Scripts as a starting point.
Please stop all of your CGI development until you understand the ramifications. I retract this remark in light of your comments clarifying the use of a config file to define parameter names (which, in principle, is orders of magnitude safer).
Pass another hidden input field containing the name of the radiogroup, then just read
#values = $cgi->param($cgi->param("radiogroup_name")); // IIRC
Related
There are are few posts out there about this. You spend hours going through each answer, testing, reading comments, to find that there is no solution. What have you done in 2019, Chrome 76, that works?
Update, January 2020: It appears that as of Chrome 79, Autocomplete (as defined here) no longer treats autocomplete="some-unrecognised-value" as equal to autocomplete="on", so autocomplete="nope" or similar is now effective at disabling both Autocomplete and Autofill.
Update, April 2020: They changed it again. As of Chrome 81, autocomplete="some-unrecognised-value" is no longer effective at disabling the Autocomplete mechanism. However, Autofill now seems to be a lot more conservative than it was before - it still doesn't follow the spec (a field with name="email" and autocomplete="off" will still receive Autofill suggestions) but it doesn't offer up spurious address fragments on random form fields. My recommendation right now would therefore be to use autocomplete="off". If you want to do that on a field named email, you're probably out of luck though :-(
TL,DR: There appears to be no setting for the autocomplete attribute that will reliably turn off all autocomplete dropdowns. However, the circumstances that have led to this are quite convoluted and worth documenting, to hopefully clear up the masses of conflicting advice...
There are two distinct mechanisms present in current (76.0.3809.132) versions of Chrome, which we'll refer to as Autofill and Autocomplete (not necessarily their official names):
Autofill
The Autofill feature attempts to fill in forms using the address information stored in your browser settings. It can be identified by the "Manage addresses..." option (or similar) at the bottom of the dropdown. This feature does not honour autocomplete="off" or autocomplete="false", as a deliberate decision on the part of the Chrome developers.
In a statement outlining this decision, zkoch offered this workaround:
In cases where you really want to disable autofill, our suggestion at
this point is to utilize the autocomplete attribute to give valid,
semantic meaning to your fields. If we encounter an autocomplete
attribute that we don't recognize, we won't try and fill it.
As an example, if you have an address input field in your CRM tool
that you don't want Chrome to Autofill, you can give it semantic
meaning that makes sense relative to what you're asking for: e.g.
autocomplete="new-user-street-address". If Chrome encounters that, it
won't try and autofill the field.
This is the basis of attempted solutions such as autocomplete="nope"; the Autofill mechanism will skip any fields with autocomplete attribute values it doesn't recognise.
The code that implements this decision, for the record: https://chromium.googlesource.com/chromium/src/+/refs/tags/78.0.3903.1/components/autofill/core/browser/form_structure.cc#1218
Autocomplete
The Autocomplete feature provides a dropdown of previously-submitted values from this form field. This dropdown does not have a "Manage addresses..." option. Autocomplete does honour the autocomplete="off" or autocomplete="false" attribute; any other value (including 'invalid' ones such as autocomplete="nope") will leave it enabled.
Conclusion
Autocompletion dropdowns cannot be turned off through the autocomplete dropdown; any value that disables Autofill will leave Autocomplete enabled, and vice versa. Anyone who thinks they've found a working solution (either through autocomplete or some other method such as CSS hacks) should check that it works against both mechanisms.
Unfortunately it's probably going to be an uphill struggle to convince Chrome's developers that this is broken. The developers of Autofill apparently believe that they made a calculated decision to break autocomplete="off" while offering web developers an alternative; that alternative is broken, for more subtle reasons than they realise. From their perspective, the resulting howls of protest are coming from disgruntled developers too lazy to jump through one little hoop and update their autocomplete="off" attributes. In all the noise, the message isn't getting through: the hoop is broken.
Try using type="search" instead of "text" for your input field, I've done this several time and it works for me.
As of Dec 6, 2019, with Chrome v78.x
Standard methods like autocomplete="off" are now working almost fine for the latest versions of Chrome. Except for this one:
This thing is a real bummer because it doesn't only disrespect the standard/non-standard values like "nope" but there's literally no way to turn this off unless the input is not even remotely related with "addressy" terms.
How on earth we could possibly display address-related input fields without using address-related words? Here comes the easiest solution ever.
Make sure the input element's name and id don't include any address-related terms. Attributes like id="input-street" or name="destination-zip" are big no-no.
This is the most crucial part: If you are required to use any human-readable address terms for the text input or any of its adjacent elements, insert the "invisible" zero width joiner () between the letters of the said term. In this way, we can fool the AI capability of Chrome and bypass its strict autocompletion behavior.
Some working examples:
<input id="input-stret" placeholder="Street" autocomplete="off">
<form action="/action_page.php">
<label for="product-addres">Product Address</label>
<input name="addres" id="product-addres" autocomplete="off">
</form>
And there you go. No more pesky menus for managing addresses, nor any regular autocompletion menus.
As gasman's answer explains, both the autofill and autocomplete features must be disabled, which doesn't seem possible on a single input.
The only working solution I've found is to setting autocomplete="off" on the input and add hidden fake inputs before the real input that fool autofill, like so:
<input name="Fake_Username" id="Fake_Username" type="text" style="display:none">
<input name="Fake_Password" id="Fake_Password" type="password" style="display:none">
<input name="NameInput" id="NameInput" type="text" autocomplete="off">
* This answer is incorrect. I've published a better (but uglier) solution as a new answer and kept this answer since some parts may still be useful. If that's not how to deal with incorrect answers on stackoverflow, feel free to delete this one *
Consider using autocomplete=<nonce>, where <nonce> is unique per field and across page loads.
For example, if a field is the N-th field created after the page was requested at timestamp TS, its <nonce> can be chosen to be nope_<TS>_<N>.
Effect on autocomplete: since <nonce> is a custom value for autocomplete, chromium does not activate the autocomplete function (see form_structure.cc).
Effect on autofill: chromium recognizes a field by comparing its fingerprint with those of earlier encountered fields (see form_field_data.cc). If recognized it may offer a list of remembered values. The fingerprints contain the value of the autocomplete attribute. Since no two nonces are equal, no field is recognized.
Notes:
The terms autocomplete and autofill as used here are swapped compared to gasman's reply.
All fields should be created dynamically on the client-side (unless you are willing to not have the page cached).
Disabling autofill:
Set autocomplete attribute to a non-standard value, e.g. "nope".
Disabling autocomplete:
The autocomplete function stores field names and their values when a form is submitted.
There's (almost, see note 1) nothing sensible to be done to prevent storage except setting autocomplete to "off"/"false" (see why).
Unfortunately that's not an option as it would enable autofill.
However it's possible to prevent retrieval of previous values by appending "!<nonce>" to the field names, where <nonce> is unique per page load
(thus making field names unrecognizable).
On the client side this can be achieved by something like the following line of javascript (upon page load):
Array.prototype.slice.call(document.body.getElementsByTagName('INPUT'))
.forEach(function(elt) { elt.name += '!' + new Date().getTime(); });
On the server side the part (if any) starting at "!" should be dropped from variable names (upon receiving post variables).
PS: this answer is an erratum to my earlier solution which is cleaner but wasn't sufficiently tested and - as gasman rightly pointed out - doesn't work for ordinary forms. This new solution was tested on Chrome Canary 79, does work, has relatively small impact and degrades nicely. Still, I feel guilty about publishing this hack and will feel even more guilty if I ever encounter it in real forms. It is *very* dirty.
Note 1: the only way to prevent storage that does make sense is to not set the name attribute in the first place (or to unset it), which necessitates intercepting the submit event to post the data "manually" (using XMLHttpRequest). Since the question is about forms and this strategy bypasses the traditional form-mechanism I've not elaborated on that approach. It's a nicer solution though.
Addendum: I decided to follow up on note 1 since I really dislike having a non-localized solution. Here's a localized version in vanilla JS that limits all impact to a single spot on the client side. Append it as a script to the document body or put it in the onload handler of the document.
function disableInputSuggestions(form) { // note: code uses ECMA5 features
// tweak the inputs of form
var inputs = Array.prototype.slice.call(form.getElementsByTagName('INPUT'));
var nonce = Date.now();
inputs.forEach(function(input, i) {
input.autocomplete = 'nope'; // prevent autocomplete
input.originalName = input.name || input.id; // to not let this code break form handling of inputs without names (browsers fallback to the id in that case)
input.name = nonce + '_' + i; // prevent autofill (if you're willing to eliminate all input ids first, then clear the name instead)
});
// replace the default submit handler by a custom one
form.onsubmit = function(ev) {
// get the form data using the original variable names
var formData = new FormData();
inputs.forEach(function(input) { formData.set(input.originalName, input.value); });
// submit the form data using XMLHttpRequest (alternatively, use a helper form or temporarily undo the tweaks to form)
var submitter = new XMLHttpRequest();
submitter.open(form.getAttribute('method'), form.getAttribute('action'));
submitter.onreadystatechange = function() {
if(submitter.readyState == 4 && submitter.status == 200) {
// handle the server response, here assuming the default form.target = "_self"
document.open();
document.write(submitter.responseText);
document.close();
}
}
submitter.send(formData);
return false; // prevent submitting form
};
}
disableInputSuggestions(document.forms.myForm); // assumed: the form has id = myForm
In Chrome 91
You need to use a random value, meaning a value that will change each time you load the page.
From the tests that I did, chrome seems to remember any attribute value that it already encountered and will suggest the last seen value for that attribute value the next time. So, if you put autocomplete="nope", chrome will remember that autocomplete="nope" is equal to the last value that you put in autocomplete="nope".
By using a unique random value that chrome has never seen, it won't suggest anything because it has never seen that value.
PHP 7 Example
<input type="text" name="firstname" autocomplete="<?= bin2hex(random_bytes(10)) ?>" />
Limitations
It seems to work on address fields but it has no effect on login fields. I haven't tested with credit card fields.
Chrome version 81.
For me, when input type is TEL, EMAIL or SEARCH, it WORKS with autocomplete='disabled'.
When input type is NUMBER, it WORKS with autocomplete='off'.
But when input type is TEXT .. it may works with autocomplete='off'. If not, it will do with autocomplete='disabled'.
You can try this, perhaps it will work for you (it works in 95% of cases for me) :
// Désactivation de l'autocomplete des input text
function setAutocomplete(val) {
var E = document.getElementsByTagName('INPUT');
for (var i = 0 ; i < E.length ; i++) {
if (E[i].name == 'txt_nom') { console.log('txt_nom', E[i]); }
var type = E[i].type.toUpperCase();
if (E[i].autocomplete != '') { continue; }
if (type == 'HIDDEN') {
//
} else if (type == 'NUMBER') {
E[i].autocomplete = 'off';
} else if ((type == 'TEL') || (type == 'EMAIL') || (type == 'SEARCH')) {
E[i].autocomplete = 'disabled';
} else {
E[i].autocomplete = val;
}
}
}
// Exécution de diverses fonctions à la fin de chaque chargement
window.addEventListener("load", function() {
// Désactivation de l'autocomplete des input text
setAutocomplete('off');
});
try this, I used this little trick and it worked until now (September 2020). i hope this works for a lot of people
--HTML--
<input type="text" name="example" autocomplete="off">
--Javascript--
let elements = document.querySelectorAll('[autocomplete="off"]');
elements.forEach(element => {
element.setAttribute("readonly", "readonly");
element.style.backgroundColor = "inherit";
setTimeout(() => {
element.removeAttribute("readonly");
}, 500);
})
I made a small jQuery plugin that disables any type of autocomplete feature from any browser
It is made to be used on the form tag, it takes few parameters and can be nested with other jQuery methods.
$('#login_form').randomizeFormFields();
It transforms this:
<form id="login_form" action="" method="post">
<input type="text" name="email">
<input type="password" name="secret">
</form>
Into this:
<form id="login_form" action="" method="post">
<input type="text" name="yQoiFZkCrzwWXN3WWgM8Jblby">
<input type="password" name="ono1qamA9CzrH4tW2COoRtFKI">
</form>
It preserves the original names upon submit
// returned post (php example)
array(2) {
["email"]=>
string(16) "email#domain.com"
["secret"]=>
string(19) "supersecretpassword"
}
https://github.com/cicerogeorge/randomize-form-fields
Please fork it if you have ideas
I have tried with autocomplete = "off" and autocomplete = "nope" for EmailId textbox in html form but it is not working for Google Chrome. So I tried with below changes that worked for me.
<input type="email" class="tbx-input" name="Email" style="display:none;">
<input type="email" class="tbx-input" name="Email" id="Email" placeholder=" " required autocomplete="nope">
I couldnt get any of these suggestions to work... so I just made my input a textarea, made cols="1" and disabled adjusting the space.
<textarea style="resize: none;" type='search' class="form-control" rows="1" cols="50" .... >
No more suggestions
autocomplete='nope'
This is the current working solution for Chrome 76.
I'm trying to remove the autocomplete="off" attribute from the input field for the email recipient field
The code of the input field is as follows:
<input
class="ac_input yui-ac-input"
size="96"
id="addressTO1"
title="An"
name="addressTO1"
onkeyup="SE.composeLayout.showAddressDetails(this);"
autocomplete="off" type="text">
Is there a setting that can be accessed via the GUI that changes the behaviour of the email "to" field or what would be the best way to turn on the autocomplete functionality.
Just removing it does not work, as there is some javascript functionality there, that keeps bringing it back.
I'm using suiterCRM version 7.6.5
Sugar Version 6.5.23.
There is no GUI for changing that, the autocomplete=off is hardcoded.
The TO field (addressTO1 dynamically generated name) is not a regular text input field, it will support multiple emails separated by comma, so a autocomplete="email" will not work.
The only solution I could come up with is for you to create a javascript function and attach to the keyup event of the field and show your logic.
Also you will need to save previously filled input with the answers and provide a mechanism to delete that. Not an easy solution I am afraid.
What I have is a form website page that will automatically fill out the required form with the information entered from the form website page. What I am trying to figure out is if #session.checkout.info.firstname_2# does not exist how do you skip it and not make the form worry about it?
So there are two fields one for owner and the other for co-owner, if there is only one owner the page is not opening the form because its looking for something to be entered as firstname_2 but if both owner and co-owner are entered it works fine because all fields are then entered. Does anyone know how I can make it only worry about the fields that have been submitted from the first form and ignore the sessions that have not yet been entered?
<cfif len(#session.checkout.info.firstname_2#)>
<cfpdfformparam
name="co-owner name"
value="#session.checkout.info.firstname_2# #session.checkout.info.middlename_2# #session.checkout.info.lastname_2#">
</cfif>
You can use isDefined to check that the variable does not exist.
<cfif isDefined("session.checkout.info.firstname_2")>
<cfpdfformparam
name="co-owner name"
value="#session.checkout.info.firstname_2# #session.checkout.info.middlename_2# #session.checkout.info.lastname_2#">
</cfif>
If you also need to check length you can combine the above if with what you've written.
Generally it's a better practice to use structKeyExists() but when there are multiple item that may not exist it can be cumbersome, i.e. structKeyExists(session, 'checkout') && structKeyExists(session.checkout, 'info') && structKeyExists(session.checkout.info, 'firstname_2')
A lot of folks on Stack Overflow are probably trying to fix forms that don't submit, but I'm actually hoping to do the opposite!
What I'd like to do for an art project is make a form with a "joke" field -- say, your SSN, your bank account number, your fingerprints or retina scans or DNA code, or something super personal like that. But I don't want the number in our server logs, and I don't want it to be transmitted over the internet at all. I don't want any legal liability!
Basically the idea is just to ask for something audacious, but not to handle the data that may or may not come from users who actually put it in.
So, is there a way to make a field that acts as a normal form field, but where nonetheless we would feel "safe" that users who actually do put their sensitive info in the field will be protected?
What's the "safest" approach to something like this?
Form fields require a name to be submitted:
If any of the following conditions are met, then skip these substeps for this element:
[…]
The field element is not an input element whose type attribute is in the Image Button state, and either the field element does not have a name attribute specified, or its name attribute's value is the empty string.
[…]
So you could simply use an input without name attribute:
<input type="text">
Be careful with your "jokes", if you want that the information of the field is not submitted, then, you can simply leave it out of the form element like this:
<form action="... >
<input type="... >
</form>
<input type="... > <!-- This field won't be submitted-->
I have a service that takes an .odt template file and some text values, and produces an .odt as it's output. I need to make this service available via HTTP, and I don't quite know what is the most RESTful way to make the interface work.
I need to be able to supply the template file, and the input values, to the server - and get the resulting .odt file sent back to me. The options I see for how this would work are:
PUT or POST the template to the server, then do a GET request, passing along the URI of the template I just posted, plus the input values - the GET response body would have the .odt
Send the template and the parameters in a single GET request - the template file would go in the GET request body.
Like (2) above except do the whole thing as a single POST request instead of GET.
The problem with (1) is that I do not want to store the template file on the server. This adds complexity and storing the file is not useful to me beyond the fact that it's a very RESTful approach. Also, a single request would be better than 2, all other things being equal.
The problem with (2) is that putting a body in a GET request is bordering on abuse of HTTP - it is supported by the software I'm using now, but may not always be.
Number (3) seems misleading since this is more naturally a 'read' or 'get' operation than a 'post'.
What I am doing is inherently like a function call - I need to pass a significant amount of data in, and I am really just using HTTP as a convenient way of exposing my code across the network. Perhaps what I'm trying to do is inherently un-RESTful, and there is no REST-friendly solution? Can anyone advise? Thank you!
Wow, so this answer escalated quickly...
Over the last year or so I've attempted to gain a much better understanding of REST through books, mailing lists, etc. For some reason I decided to pick your question as a test of what I've learned.
Sorry :P
Let's make this entire example one step simpler. Rather than worry about the user uploading a file, we'll instead assume that the user just passes a string. So, really, they are going to pass a string, in addition to the arguments of characters to replace (a list of key/values). We'll deal with the file upload part later.
Here's a RESTful way of doing it which doesn't require anything to be stored on the server. I will use some HTML (albeit broken, I'll leave out stuff like HEAD) as my media type, just because it's fairly well known.
A Sample Solution
First, the user will need to access our REST service.
GET /
<body>
<a rel="http://example.com/rels/arguments" href="/arguments">
Start Building Arguments
</a>
</body>
This basically gives the user a way to start actually interacting with our service. Right now they have only one option: use the link to build a new set of arguments (the name/value pairings that will eventually be used to in the string replacement scheme). So the user goes to that link.
GET /arguments
<body>
<a rel="self" href="/arguments"/>
<form rel="http://example.com/rels/arguments" method="get" action="/arguments?{key}={value}">
<input id="key" name="key" type="text"/>
<input id="value" name="value" type="text"/>
</form>
<form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}">
<input id="input_string" name="input_string" />
</form>
</body>
This brings us to an instance of an "arguments" resource. Notice that this isn't a JSON or XML document that returns to you just the plain data of the key/value pairings; it is hypermedia. It contains controls that direct the user to what they can do next (sometimes referred to allowing the user to "follow their nose"). This specific URL ("/arguments") represents an empty list of key/value pairings. I could very well have named the url "/empty_arguments" if I wanted to: this is an example why it's silly to think about REST in terms of URLs: it really shouldn't matter what the URL is.
In this new HTML, the user is given three different resources that they can navigate to:
They can use the link to "self" to navigate to same resource they are currently on.
They can use the first form to navigate to a new resource which represents an argument list with the additional name/value pairing that they specify in the form.
They can use the second form to provide the string that they wish to finally do their replacement on.
Note: You probably noticed that the second form has a strange "action" url:
/arguments?{key}={value}
Here, I cheated: I'm using URI Templates. This allows me to specify how the arguments are going to be placed onto the URL, rather than using the default HTML scheme of just using <input-name>=<input-value>. Obviously, for this to work, the user can't use a browser (as browsers don't implement this): they would need to use software that understands HTML and URI templating. Of course, I'm using HTML as an example, your REST service could use some kind of XML that supports URI Templating as defined by the URI Template spec.
Anyway, let's say the user wants to add their arguments. The user uses the first form (e.g., filling in the "key" input with "Author" and the "value" input with "John Doe"). This results in...
GET /arguments?Author=John%20Doe
<body>
<a rel="self" href="/arguments?Author=John%20Doe"/>
<form rel="http://example.com/rels/arguments" method="get" action="/arguments?Author=John%20Doe&{key}={value}">
<input id="key" name="key" type="text"/>
<input id="value" name="value" type="text"/>
</form>
<form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}?Author=John%20Doe">
<input id="input_string" name="input_string" />
</form>
</body>
This is now a brand new resource. You can describe it as an argument list (key/value pairs) with a single key/value pair: "Author"/"John Doe". The HTML is pretty much the same as before, with a few changes:
The "self" link now points to current resources URL (changed from "/arguments" to "/arguments?Author=John%20Doe"
The "action" attribute of the first form now has the longer URL, but once again we use URI Templates to allow us to build a larger URI.
The second form
The user now wants to add a "Date" argument, so they once again submit the first form, this time with key of "Date" and a value of "2003-01-02".
GET /arguments?Author=John%20Doe&Date=2003-01-02
<body>
<a rel="self" href="/arguments?Author=John%20Doe&Date=2003-01-02"/>
<form rel="http://example.com/rels/arguments" method="get" action="/arguments?Author=John%20Doe&Date=2003-01-02&{key}={value}">
<input id="key" name="key" type="text"/>
<input id="value" name="value" type="text"/>
</form>
<form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}?Author=John%20Doe">
<input id="input_string" name="input_string" />
</form>
</body>
Finally, the user is ready to process their string, so they use the second form and fill in the "input_string" variable. This once again uses URI Templates, thus having bringing the user to the next resource. Let's say that that the string is the following:
{Author} wrote some books in {Date}
The results would be:
GET /processed_string/%7BAuthor%7D+wrote+some+books+in+%7BDate%7D?Author=John%20Doe&Date=2003-01-02
<body>
<a rel="self" href="/processed_string/%7BAuthor%7D+wrote+some+books+in+%7BDate%7D?Author=John%20Doe&Date=2003-01-02">
<span class="results">John Doe wrote some books in 2003-01-02</span>
</body>
PHEW! That's a lot of work! But it's (AFAIC) RESTful, and it fulfills the requirement of not needing to actually store ANYTHING on the server side (including the argument list, or the string that you eventually want to process).
Important Things to Note
One thing that is important here is that I wasn't just talking about URLs. In fact, the majority of time, I'm talking about the HTML. The HTML is the hypermedia, that that's is such a huge part of REST that is forgotten about. All those APIs that say they are "restful" where they say "do a GET on this URL with these parameters and POST on this URL with a document that looks like this" are not practicing REST. Roy Fielding (who literally wrote the book on REST) made this observation himself.
Another thing to note is that it was quite a bit of pain to just set up the arguments. After the initial GET / to get to the root (you can think of it as the "menu") of the service, you would need to do five more GET calls just to build up your argument resource to make an argument resource of four key/value pairings. This could be alleviated by not using HTML. For example, I already did use URI Templates in my example, there's no reason to say that HTML just isn't good enough for REST. Using a hypermedia format (like some derivation of XML) that supports something similar to forms, but with the ability to specify "mappings" of values, you could do this in one go. For example, we could extend the HTML media type to allow another input type called "mappings"...
So long as the client using our API understands what a "mappings" input type is, they will be able to build their arguments resource with a single GET.
At that point, you might not even need an "arguments" resource. You could just skip right to the "processed_string" resource that contains the mapping and the actual string...
What about file upload?
Okay, so originally you mentioned file uploads, and how to get this without needing to store the file. Well, basically, we can use our existing example, but replace the last step with a file.
Here, we are basically doing the same thing as before, except we are uploading a file. What is important to note is that now we are hinting to the user (through the "method" attribute on the form) that they should do a POST rather than a GET. Note that even though everywhere you hear that POST is a non-safe (it could cause changes on the server), non-idempotent operation, there is nothing saying that it MUST be change state on the server.
Finally, the server can return the new file (even better would be to return some hypermedia or LOCATION header with a link to the new file, but that would require storage).
Final Comments
This is just one take on this specific example. While I hope you have gained some sort of insight, I would caution you to accept this as gospel. I'm sure there have been things that I have said that are not really "REST". I plan on posting this question and answer to the REST-Discuss Mailing List and see what others have to say about it.
One main thing I hope to express through this is that your easiest solution might simply be to use RPC. After all, what was your original attempt at making it RESTful attempting to accomplish? If you are trying to be able to tell people that you accomplish "REST", keep in mind that plenty of APIs have claimed themself "RESTful" that have really just been RPC disguised by URLs with nouns rather than verbs.
If it was because you have heard some of the benefits of REST, and how to gain those benefits implicitly by making your API RESTful, the unfortunate truth is that there's more to REST than URLs and whether you GET or POST to them. Hypermedia plays a huge part.
Finally, sometimes you will encounter issues that mean you might do things that SEEM non-RESTful. Perhaps you need to do a POST rather than a GET because the URI (which have a theoretical infinite amount of storage, but plenty of technical limitations) would get too long. Well then, you need to do POST. Maybe
More resources:
REST-Discuss
My e-mail on this answer to REST-Discuss
RESTful Web Services Cookbook
Hypermedia APIs with HTML5 and Node (Not specifically about REST, but a VERY good introduction to Hypermedia)
What you are doing is not REST-ful - or, at least, is difficult to express in REST, because you are thinking about the operation first, not the objects first.
The most REST-ful expression would be to create a new "OdtTemplate" resource (or get the URI of an existing one), create a new "SetOfValues" resource, then create a "FillInTemplateWithValues" job resource that was tied to both those inputs, and which could be read to determine the status of the job, and to obtain a pointer to the final "FilledInDocument" object that contained your result.
REST is all about creating, reading, updating, and destroying objects. If you can't model your process as a CRUD database, it isn't really REST. That means you do need to, eg, store the template on the server.
You might be better off, though, just implementing an RPC over HTTP model, and submitting the template and values, then getting the response synchronously - or one of the other non-REST patterns you named... since that is just what you want.
If there is no value in storing the templates then option 2 is the most RESTful, but as you are aware there is the possibility of having your GET body dropped.
However, if I was a user of this system, I would find it very wasteful to have to upload the template each time I would like to populate it with values. Instead it would seem more appropriate to have the template stored and allow different requests with different values to populate the resulting documents.