I know how to upload an image file to a server and show the image file to a page.
But what if I want a preview on a confirmation page?
I can probably generate a temp file that isn't saved in the database but is a file in a physical location, but what if I decided to hit the "no" button. How would this temp file be deleted?
The code below shrinks the image and shows it on the page. But it also creates an image within the directory, that will stay there after I hit OK or NO. The NO is button, while the OK naturally is a submit.
<!--- Make Temp Image as Preview --->
<cfset mediapath = expandpath('../images/about')>
<cfif structKeyExists(form,"image") and len(form.image)>
<cffile action="upload"
filefield="image"
destination="#MediaPath#"
nameconflict="makeunique">
<cfimage name="uploadedImage"
source="#MediaPath#/#file.serverFile#" >
<cfset imagesize = 320>
<cfif uploadedImage.width gt uploadedImage.height>
<cfset percentage = (imagesize / uploadedImage.width)>
<cfelse>
<cfset percentage = (imagesize / uploadedImage.height)>
</cfif>
<cfset newWidth = round(uploadedImage.width * percentage)>
<cfset newHeight = round(uploadedImage.height * percentage)>
<!--- Show Image --->
<cfoutput>
<img src="../images/about/#file.serverFile#" style="height:#newHeight#; width:#newWidth#;">
I assume I may have to do URL Passing or do some sort of CFScript. On the Return buttons Onclick event.
Here is my approach take it for what you will.
Ok this is probably more than you need but this should get you somewhere on this image delete problem thing.
Here is your code. But I broke it into two pages. Of course I cannot see what else is going on this page and your form handling stuff so we will start with what you are giving us.
<cfset mediapath = expandpath('../images/about')>
nice use of structKeyExists() :)
<cfif structKeyExists(form,"image") and len(form.image)>
Here I would pause and suggest you limit
your uploads to just .gif, .jpeg, .jpg, .png
(your main image types) to prevent uploading any
and everyfile type. I added an accept parameter below.
<cffile action="upload"
filefield="image"
destination="#MediaPath#"
nameconflict="makeunique"
accept="image/*">
<cfimage name="uploadedImage"
source="#MediaPath#/#file.serverFile#" >
Ok the file is uploaded lets seperate concerns
At this point I would ask them if they want to preview the file. If they click 'preview' take them to a preview.cfm page.
Then you have a file name you need to pass if you have nothing else (like an ID or some primary key).
So I pulled this handy-dandy script out of the Adobe Coldfusion docs on their website and I am going to use this to turn your filename into 'something else' ;)
<cfscript>
theKey="123abc";
theKey=generateSecretKey("AES")
superDuperSecretSoDontTell=encrypt(file.serverFile, theKey, "AES", "hex");
</cfscript>
Let's send this piggy!
and off you go to the preview page...
<cfoutput>
(pointing up) This is pageA.cfm
(pointing down) This is pageB.cfm
Now I have the rest of your code below and lets pull your file based on the pass through querystring variable/value pairs.
<cfscript>
IWannaKnowTheSecret=decrypt(url.fileName, url.theKey, "AES", "hex");
</cfscript>
Here I would pause and suggest you limit
your uploads to just .gif, .jpeg, .jpg, .png
(your main image types) to prevent uploading any
and everyfile type. I added an accept parameter below.
<cffile action="read" file="#MediaPath##IWannaKnowTheSecret#" variable="uploadedImage">
<cfset imagesize = 320>
Interesting handle here. So you are taking the
larger of the two values and using that
to percentage down the size. Neat.
<cfif uploadedImage.width GT uploadedImage.height>
<cfset percentage = (imagesize / uploadedImage.width)>
<cfelse>
<cfset percentage = (imagesize / uploadedImage.height)>
</cfif>
<cfset newWidth = round(uploadedImage.width * percentage)>
<cfset newHeight = round(uploadedImage.height * percentage)>
Then do a form like this:
<form action="" method="post" enctype="multipart/form-data">
Your current Image:
<cfoutput>
Name: #uploadedImage#<br>
<img src="../images/about/#uploadedImage#" style="height:#newHeight#; width:#newWidth#;">
</cfoutput>
Do you want to remove this?<br>
<input type="checkbox"
name="removeImage"
value="1" />: Remove the logo image</cfif><br />
Wnat to replace your image?<br>
<input type="file" name="replacementImage"> (
<input type="hidden"
name="uploadedImage"
value="<cfoutput>#uploadedImage#</cfoutput>">
<input type="submit" value="submit" name="submit"
</form>
Cancel and go back
If they continue and want to fix the image or replace it. Submit then you can use something like this.
Then we delete...
And if the replacementImage file filed is populated then we add that file.
And there you have it...
You are seperating some concerns.
You are giving improved options.
You are allowing a change or no change.
You are giving them an out to go back to where ever you want.
Edit: Here is proof for the encoding and decoding stuff (if you wanted to play with it:
<cfscript>
theKey="123abc";
theKey=generateSecretKey("AES");
superDuperSecretSoDontTell=encrypt("monkeytoots", theKey, "AES", "hex");
</cfscript>
<cfoutput>Let's send this piggy!</cfoutput>
<cfif isdefined("url.fileName") and isdefined("url.theKey")>
<cfscript>
IWannaKnowTheSecret=decrypt(url.fileName, url.theKey, "AES", "hex");
</cfscript>
<cfoutput>
#IWannaKnowTheSecret#
</cfoutput>
</cfif>
This answer is in response to Adam Cameron's comment. It illustrates some potentially unexpected results that can occur with two submit buttons. Start with this code.
<cfdump var="#form#">
<form action="abc.cfm" method="post">
<input type="text" name="text1" />
<input type="submit" name="submit1" value="no" />
<input type="submit" name="submit2" value="yes" />
</form>
The default behaviour of most, if not all browsers is that there are occasions whereby a form will be submitted when the user presses the enter key. What would you expect to see with this form if you had your curser in the text box and pressed Enter? Try it and see if you were right.
Related
I am new to coldfusion ,
please check my code below
<cfif isDefined("form.submit")>
<cfoutput>
<h3>hi</h3>
</cfoutput>
</cfif>
<cfform action="#CGI.SCRIPT_NAME#">
User Name:<cfinput type="Text" name="usr_nm"><br>
<cfinput type="Radio" name="access_flg" value="0">Admin
<cfinput type="Radio" name="access_flg" value="1">User</br>
<cfinput type="submit" name="submit" value="submit"><br>
</cfform>
But ,When I am clicking submit button ,I am expecting result as hi
I haven't see hi message, Is there any thing wrong in my code ,Any one please help me
Since you're new to ColdFusion, I'll give you some advice straight away:
1. Do not submit a form to the same page.
Submit the form to a separate page for processing. Reason being, as you get into more advanced applications, you'll need to restrict pages/URLs to only respond to an appropriate HTML Verb.
Your form page should respond to HTTP GET.
Your form processing page should only respond to HTTP POST.
2. Do not use CFFORM.
The function of CFFORM is to create JavaScript validation and server-side interactions. This can easily be done with modern JavaScript libraries like
https://jquery.com/
http://jqueryvalidation.org/
3. Give your form elements an ID, as well as a NAME.
This allows easier reference to the form elements when using JavaScript.
4. Do not name your submit button "submit".
If you ever want to use JavaScript to submit a form, the function is submit().
For example: $('#myForm').submit();
Having a form element named the same as a function will cause errors.
Here's my_form.cfm:
<form id="myForm" name="myForm" action="my_form_action.cfm" method="post">
User Name:<input type="Text" id="usr_nm" name="usr_nm"><br>
<input type="Radio" id="access_flg_0" name="access_flg" value="0">Admin
<input type="Radio" id="access_flg_1" name="access_flg" value="1">User</br>
<input type="submit" id="my_form_submit" name="my_form_submit" value="Submit"><br>
</form>
5. You don't need to use CFOUTPUT unless you are rendering data from the server.
Here's my_form_action.cfm:
<cfif structKeyExists(form, "my_form_submit")>
<h3>Hi!<lt>
</cfif>
Even better:
<cfif (cgi.request_method IS "post") AND (structKeyExists(form, "my_form_submit"))>
<h3>Hi!<lt>
</cfif>
This is an elaboration of this part of Adrian's answer:
<cfif (cgi.request_method IS "post") AND (structKeyExists form, "my_form_submit"))>
<h3>Hi!</h3>
</cfif>
This is a candidate for code re-use. In one of our applications, I wrote a custom tag that does something like this:
if (StructKeyExists(attributes, 'ScopeToCheck') is false)
attributes.ScopeToCheck = "form";
if (StructKeyExists(caller, attributes.ScopeToCheck) is false)
Redirect = true;
else if (StructIsEmpty(caller[attributes.ScopeToCheck]) is true)
Redirect = true;
else
Redirect = false;
if (Redirect == true)
location(somewhere, false);
The custom tag approach was appropriate for my situation. For other situations, the same logic can be put into a udf that returns either true or false. Then the calling page can decide what to do with that information.
Im trying to create an admin area but cannot get a login system to work. I have three parts to this. The login.cfm page, login_action.cfm and the app.cfc.
When using this code, and try and login it only stays on the same page.
Login.cfm
<form name="fLogin" id="fLogin" action="<cfoutput>#FormAction#</cfoutput>" method="post">
<label>Username:</label>
<input type="text" name="username" required>
<label>Password:</label>
<input type="password" name="Password" required>
<br>
<input type="submit" id="sub" value="Login">
</form>
Login_action.cfm
<cflogin idletimeout="1800">
<!--- SETS the action page of the login form to whatever
page the user was trying to go to. Since the login
will actually be processed in the application.cfm file
(or a template included in it), then the FORM action
is the page that will be loaded after the login has
been completed. --->
<!--- IF there IS NOT a Query String passed in the URL,
only the requested page name is used --->
<cfif CGI.QUERY_STRING IS "">
<cfset FormAction = #CGI.SCRIPT_NAME#>
<cfelse>
<cfset FormAction = "#CGI.SCRIPT_NAME#?#CGI.QUERY_STRING#">
</cfif>
<cfif not (isDefined("cookie.XXXX.email"))>
<cfif NOT (IsDefined ("Form.username") AND IsDefined ("Form.Password"))>
<cfinclude template="login.cfm">
<cfabort>
<cfelse>
<cfif IsDefined("Form.username")>
<cfset username = #Form.username#>
</cfif>
<CFQUERY NAME="login">
select * from t_admin where username = '#username#'
</CFQUERY>
<cfif login.RecordCount gt 0>
<cfif #Form.password# eq "#login.password#">
<cfloginuser name="#username#" password="#login.password#" roles="admin">
<cfcookie name="XXXX.email" value="#login.email#" expires="never" >
<cfset session.userId = #login.id#>
<cfelse>
<cfset Invalid = "Yes">
<cfinclude template="login.cfm">
<cfabort>
</cfif>
</cfif>
</cfif>
<cfelse>
<CFQUERY NAME="cookielogin">
select * from t_admin where email = '#cookie.XXX.email#'
</CFQUERY>
<cfloginuser name="#cookielogin.email#" password="#cookielogin.password#" roles="admin">
<cfset session.userId = #cookielogin.id#>
<cfset session.email = #cookielogin.email#>
</cfif>
</cflogin>
and Application.cfc.
<cffunction name="OnRequestStart">
<cfinclude template="login_action.cfm">
<cfif isDefined ('cookie.XXXX.email')>
<cfset session.email = cookie.XXXX.email>
</cfif>
</cffunction>
If anyone could help that'll be great thanks
There are quite a lot of fundamental mistakes in this code.
Don't build an URL with the query string that came from the browser. You cannot trust anything that comes from the browser, therefore you must not use anything without scrubbing it down. Things like this are asking for trouble:
<cfset FormAction = "#CGI.SCRIPT_NAME#?#CGI.QUERY_STRING#">
Generally don't ever write anything to the HTML of your page that came from the user without properly sanitizing and HTML-encoding it. Use HTMLEditFormat() and URLEncodedFormat() extensively.
Don't ever use user-supplied values to build an SQL string. There is <cfqueryparam>, use it. This is bad and wrong:
select * from t_admin where username = '#username#'
While we're at it: Don't ever use select * in production code.
Don't ever store plain text passwords in a database. This is a big thing, you really must fix that before you do anything else. ColdFusion provides a number of hashing algorithms, use them (and read about salted hashes).
Is the login form sent through HTTPS? (Everything in that application should probably be HTTPS, but the login form absolutely must be.)
Login cookies should be marked as secure and httponly (see) to prevent session hijacking.
Login cookies that expire never might be not a good idea. Depends.
I am working with a very old login system that my company used before on a website that used frames.
Before, when someone tried a wrong user/pass combination the frame would load a simple cfinclude file with the login form and an error message on top of it.
Now I am using a form in a popup window that calls the application.cfc but instead of getting the error message back on my popup window the page load the cfinclude file from the application component to a new page.
So I need a few things to happen for this application. First, I need the initial popup window to stay up and the page should not submit if the combination of user/pass is wrong, and finally I need the error message to appear somewhere on the popup.
If anyone did something like this before I would really appreciate your feedback.
This is a partial of my code:
Login Form:
<!--- loginErrMsg display - to tell why login is denied --->
<cfif isdefined("loginErrMsg")><span style="color:red">#loginErrMsg#</span><br /></cfif>
<form name="LoginForm" id="LoginForm" action="<cfif test is false>https://secure.example.com</cfif>#loginFormAction#" method="post" target="_top">
</cfoutput>
<input type="hidden" name="loginPost" value="true">
<p>
Login below to take advantage of the great services we offer:
</p>
E-mail:<input name="j_username" class="loginform" type="text" size="30" maxlength="50" id="j_username">
Password: <input name="j_password" type="password" size="30" maxlength="16" class="loginform">
<br />
<input type="submit" name="btn" value="Submit" class="bluebuttonnormal">
</form>
Application.cfc Code:
<cflogin applicationtoken="swmadmin">
<cfif NOT IsDefined("cflogin")>
<cfinclude template="login.cfm">
<cfabort>
<cfelse>
<cfquery name="userlookup" datasource="#ds#">
SELECT clientadminID, roles, isFaxOnly, acctEnabled FROM clientadmin
WHERE
username=<cfqueryparam value="#cflogin.name#" CFSQLTYPE="CF_SQL_VARCHAR" maxlength="50">
and password=<cfqueryparam value="#cflogin.password#" CFSQLTYPE="CF_SQL_VARCHAR" maxlength="16">
</cfquery>
<cfif userlookup.recordcount eq 0>
<cfset loginErrMsg = "Invalid login.">
<cfinclude template="login.cfm">
<cfabort>
</cflogin>
I am working with a very old login system that my company used before
on a website that used frames.
If this is a new website, don't use it. Login forms are a dime a dozen and can be done in your sleep. Start fresh and do it right.
So I need a few things to happen for this application. First, I need
the initial popup window to stay up and the page should not submit if
the combination of user/pass is wrong, and finally I need the error
message to appear somewhere on the popup.
You're going to want to use an AJAX solution here, either write your own or use a good library like jQuery. Once you check the login values you can use jQuery or simple javascript to unhide or update the innerHTML of an empty element to display your error message.
<cflogin ...>
...
</cflogin>
CFLogin makes me sad. Another one of ColdFusion's tags meant to simplify something commonly done that doesn't really help much and sacrifices flexibility. You can get far more control over your application without it. instead of CFLogin, try something like this pseudo code
<cfcomponent>
<cffunction name = "onRequest" ...>
<cfargument name="targetPage" type="String" required = "true" />
<cfif !structKeyExists(session, "roles") and !findNoCase("loginHandler.cfm",cgi.script_name)>
<!--- notice I prevent the redirect on the form handler, otherwise the ajax will get redirected to the login.cfm page --->
<cfinclude template = "login.cfm">
<cfelse>
<cfinclude template = "#arguments.targetPage#">
</cfif>
</cffunction>
</cfcomponent>
Your login.cfm would then contain your form but your button would fire something like jQuery.post() to "loginHandler.cfm", then depending on the result of the login, your callback function may use jQuery.html() to display the error or window.location.replace / window.location.href if the login was successful. Of course, in the event of a successful login, your ColdFusion page would have to create their session variables and do whatever else you want it to do before sending the result back to your AJAX call.
cffile is giving a head ache now.
My cfm is like this -
`
<cfif session.ismac and session.browsermake eq "firefox">
<cfset size = "55">
</cfif>
<cfset onChange = "document.frmMain.submit1.disabled = true;setdisplayname(this,this.form.dummy);">
<cfif displayname EQ "">
<cfset size = "document.frmMain.submit1.disabled = true;setdisplayname(this,this.form.displayname);">
</cfif>
<cfinput type="file" name="File#thisUploader#" id="File#thisUploader#" size="#size#" onKeyPress="return false;" onchange="#onChange#">
`
and in my cfc the code is like this -
<cffile accept="image/*" action="upload" destination="#application.artworkfilepath#\bulkuploads\#session.loginname#\#form.category#\" filefield="form.File#thisUploader#" nameconflict="makeunique">
and if I dump - <cfoutput>
You uploaded #cffile.ClientFileName#.#cffile.ClientFileExt#
successfully to #cffile.ServerDirectory#.
</cfoutput>
<cfabort>
I get corrct things and no error.
But when i look into the folder there is nothing.
Anyidea? I have added the dump of cffile now. What do you make out of it?
cfform code is like this <cfform id="frmMain" name="frmMain" action="process_multi.cfm" enctype="multipart/form-data" target="_self" method="post">
do a fileExists() directly after the statement and let us know what that says...
you don't have a directorywatcher on the directory do you?
Your cffile nameconfict attribute is set to makeunique, which tells ColdFusion to rename the file to something new when it arrives at the server--if the file already exists.
However, you are using cffile.ClientFileName and cffile.ClientFileExt to refer to the file file--which maps to the unchanged file name as it was received during upload.
Change your code references to cffile.ServerFileName and cffile.ServerFileExt for the final renamed result.
I am using CF-8,windows-XP and IE 5.5.
I am using simple tag namely . but the output i am getting is pure gibberih along witht the text of the file(word document)
upld.cfm
<cffile action="read" file="C:\ColdFusion8\wwwroot\Proj\updl\fileDisk\SOL.doc" variable="fileDisk" >
<cfoutput>#fileDisk#
</cfoutput>
<cfoutput>
<form name="upload" method="post" action="actionUpld.cfm?form_Num=#form_Num#" enctype="multipart/form-data">
<input name="uplForm" id="uplForm" type="file" >
<input type="submit" name="submitUpld" value="Save" onclick="" >
</form>
</cfoutput>
actionUpld.cfm
<cftry>
<cfscript>
newUPL = CreateCFC('cfcs.projDB');
newUPL.Implementation_Num = url.form_Num;
newUPL.uplForm = form.uplForm;
newUPL.putUPL();
</cfscript>
<cfcatch type="any" >
<cfoutput >
<hr>
<h4>Other Error: #cfcatch.Type#</h4>
<li><b>Message:</b> #cfcatch.Message#
<li><b>Detail:</b> #cfcatch.Detail#
<li><b>Error Code:</b> #cfcatch.ErrorCode#
</cfoutput>
</cfcatch>
</cftry>
<cflocation url="upld.cfm??form_Num=#form_Num#" >
How best to use the cffile to output the file ?
Also when i look at the DB, i am getting the file name as
"C:\ColdFusion8\runtime\servers\coldfusion\SERVER-INF\temp\wwwroot-tmp\qeq344.tmp"
How to correct it?
Is there any better way.
Also when i look at the DB, i am
getting the file name as C:\ColdFusion8\runtime\servers\coldfusion\SERVER-INF\temp\wwwroot-tmp\qeq344.tmp
That is a temporary file name assigned to newly uploaded files. On your action page, you need to use cffile action="upload" ... to move that temporary file to the desired location. That will populate a structure called CFFILE with details about the uploaded file, such as CFFILE.serverFile and CFFILE.serverDirectory. (Or use the "result" attribute to output the details to whatever structure name you choose.)
How best to use the cffile to output
the file ?
You cannot display binary files (like *.doc) with cfoutput. To display/download such files in a browser use cfcontent