Send filename from JS code to a Rails view - javascript

This is my JavaScript code:
var fullPath = document.getElementById('file').value;
if (fullPath) {
var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
var filename = fullPath.substring(startIndex);
if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
filename = filename.substring(1);
}
}
if(passAll === true){
alert(filename);
}
As the title sugests, how can I send that var filename to a view history (just print it there) obviously after testing that last if? My view is empty so it is free for edit. Another question is if the names are going to be saved or discarded after dropping the server?
And here is my controller history_controller.rb:
class HistoryController < ApplicationController
def historico
end
end

Try running rails routes in the command line of your project directory. Assuming that HistoryController is in routes.rb, it will show the routes available to send or request data from your controller. It should some something like
POST /history history#create. That means you can send your filename via an HTTP POST request {RAILS ROOT URL}/history?filename={THE FILENAME} (if you are developing locally, it will probably be something like http://localhost:3000/history?filename={THE FILENAME}. Then you can access the filename in the create action of your HistoryController with the syntax params[:filename].

Related

How to res.sendFile whilst res.rendering an HTML that uses the sent file in Express.js?

I am trying to create a file server that use node.js and Express. I have the system currently set up so that each user has a file directory. I currently have it set so that the whole file system is hosted using
app.use(express.static(testFolder));
The problem with this approach is that anyone could view anyones files even if they are not logged in. I have looked and other people recommend to not host the whole file system and use res.sendFile(specific file) instead. People also recommend to use middleware to check that the user is authenticated.
My problem with this is that, say for photos, I have a photos route and EJS file set up so that for all photos, the photo that is to be viewed is rendered inside the .ejs file.
How would I res.sendFile() but then have it rendered inside a .ejs file? As just res.sendFile() only shows the photo with a white background and no customisation.
Here is the code for the route:
router.post("/view/photo", function(req, res){
var path = req.body.currentPath
var filename = req.body.fileName
var currentUser = req.body.currentUser
var files = fs.readdirSync(path)
var images = []
var fileExtensions = ['jpg', 'jpeg', 'gif', 'png']
for(var i = 0; i < files.length; i++){
fileExtension = files[i].split(".")[1]
if(fileExtension){
if(fileExtensions.includes(fileExtension.toLowerCase())){
images.push(files[i])
}
}
}
var indexOfFile = images.indexOf(filename)
var next = indexOfFile + 1;
var previous = indexOfFile - 1;
if(next > images.length - 1){
next = next - (images.length)
}
if(previous < 0){
previous = previous + (images.length)
}
path = path.split("/")
path = path.splice(path.indexOf(currentUser, 0), path.length)
path = path.join("/")
finalPath = "../" + path + "/" + filename
var nextFileName = images[next]
var prevFileName = images[previous]
res.sendFile(req.body.currentPath + "/" + filename);
// res.render("showPhoto.ejs", {photoPath: finalPath, filename: filename, currentPath: req.body.currentPath, next: nextFileName, prev:prevFileName });
})
Forget about replacing express.static with sendFile. That's a red herring.
If you want to allow only authenticated users to see an anything, then add middleware that checks to see if they are authenticated on the route that serves up whatever the anything is.
It doesn't matter how the route serves up the anything, only that you authenticate the user before doing do.
If the route uses static to serve up an image file, then add some authentication middleware before it. If the route uses render to generate an HTML document which includes an <img> that points to the previously mentioned static route, then add some authentication middleware before it. etc.
router.post(
"/view/photo",
authenticationMiddleware,
photoPostingEndpointFunction
);
router.use(
"/photos",
authenticationMiddleware,
express.static('path/to/protected/photos)
);

How to send array to nodejs server?

It's my first time working on an android app where I have to use Cordova, Node.js, Express and MongoDB.
My prof gave us some server side script to use.
My problem:
I have to send an array from my app to a URL that I specify to my node server. There is a "sendJSON(req, res)" method in the javascript file I was given and I'm not sure if I have to use this or do something else. This url is a location on my PC.
Here is the sendJSon code in the common.js file:
exports.sendjson = function(res,obj){
var objstr = JSON.stringify(obj);
console.error('SENDJSON:'+objstr);
res.status(200).json(obj);
}
and here is my code at the client side:
//Clear the local storage and array of the user's choice of chicken type
function sendLogs(res){
var server= "my_ipaddress:port_number/chicken/";
clearFields();
var url;
if(chickenNumber == 0)
{
url = server + "Foghorn/log";
common.sendjson(url,{ok:true,list:foghorn_items});
foghorn_items.length = 0;
localStorage.removeItem("foghorn_items");
}
else if(chickenNumber == 1)
{
url = server + "Little/log";
common.sendjson(res,{ok:true,list:little_items});
little_items.length = 0;
localStorage.removeItem("little_items");
}
else if(chickenNumber == 2)
{
url = server + "Tweety/log";
common.sendjson(res,{ok:true,list:tweety_items});
tweety_items.length = 0;
localStorage.removeItem("tweety_items");
}
else if(chickenNumber == 3)
{
url = server + "Hawk/log";
common.sendjson(res,{ok:true,list:hawk_items});
hawk_items.length = 0;
localStorage.removeItem("hawk_items");
}
else if(chickenNumber == 4)
{
url = server + "bertha/log";
common.sendjson(res,{ok:true,list:bertha_items});
bertha_items.length = 0;
localStorage.removeItem("bertha_items");
}
alert("Logs sent");
$.mobile.changePage ("index.html#entry_page", {transition:"slide", reverse:"true"});
}
P.S this is a JQuery Mobile focused application on Android.
Am I sending the array correctly? Do i replace the "res" variable with the "url" variable?
This is what my prof said to do at the client side js:
"Start by defining the URL used to communicate with your node server. This will consists of your computers' IP address and port used to communicate, and then the path /chicken/. The next part will depend on the chicken breed name. Use a case statement to switch based on your chicken breed name. Then concatenate the chicken breed name and "/log" with the URL to complete the URL. When the URL is formed correctly, use the sendjason() function in the examples, to send the chicken items list to this URL. Finally loop through the chicken items and remove them from the list to clear the chicken item list of all items for that breed."

Missing attachment from Outlook JS Api

I'm creating an Outlook add-in and I would like to get each attachment from a mail using JavaScript.
So far, it worked fine with this:
var attch = Office.context.mailbox.item.attachments;
for(i = 0; i < attch.length; i++) {
// Logic here
}
But today, I found that an .msi file was missing from the attch variable. I think that's because this file is an executable and thus is considered as dangerous
As a workaround, I know that I can do an AJAX Request to my ASP.Net webserver and consume Exchange API to get the full attachment list :
var exService = new ExchangeService
{
Url = new Uri(data.EwsURL),
Credentials = new WebCredentials(data.Login, data.Password)
};
var message = EmailMessage.Bind(exService, new ItemId(data.mailId));
var propertySet = new PropertySet(ItemSchema.Attachments);
message.Load(propertySet);
if (message.Attachments.Count == 0 || data.Type == "text" || data.Type == "full") return;
foreach (var attch in message.Attachments.OfType<FileAttachment>().Select(attachment => attachment))
{
// Logic here: returns the attachments info to the webpage
}
Is there a better way to get the full attachments list, using the Office.JS API?

create a template url-routing script

I want to create an url-routing script using javascript as much as possible, but also accepting jQuery in the code. The js file has to change the url path (although I used location.hash instead of location.pathname) and the content of a div with the view id (from external files) accordingly.
Example configuration:
root/index.html
root/tpl/home.html
root/tpl/about.html
home.html content:
<p>This is content of home page</p>
about.html content:
<p>This is the content of the about page </p>
What I have done so far:
'use strict';
var Router = {
root: '/',
routes: [],
urls: [],
titles: [],
navigate: function() {
location.hash = this.root;
return this;
},
add: function(thePath, theUrl, theTitle) {
this.routes.push(thePath);
this.urls.push(theUrl);
this.titles.push(theTitle);
},
loading: function() {
this.navigate();
var r = this.routes;
var u = this.urls;
window.onload = function() {
$("#view").load("tpl/home.html");
};
window.onhashchange = function() {
for (var i = 0; i < r.length; i++) {
if (location.hash == r[i]) {
$("#view").load(u[i]);
}
}
};
}
};
Router.add("#/home", "tpl/home.html", "Home Page");
Router.add("#/about", "tpl/about.html", "About Page");
Router.loading();
Desired type of url:
http://mywebsite.com/
http://mywebsite.com/about
I know there are more than enough libraries that make the routing, like AngularJS and Crossroad, I want to know how this could be done.
To make this URL work - http://mywebsite.com/about - you need a server that knows how to route this request. Since the actual file name is about.html your server must know what to do with extensionless URLs.
Usually, the server uses the file extension as a clue for how to serve up content. For example, if it sees file.php it knows to use the PHP component, for .aspx it knows to use the ASP.NET component, and for .htm or .html it knows to respond with plain HTML (and usually serves the file instead of processing it). Your server must have some rules for what to do with any request, whether it has an extension or not, but without an extension you need to provide an explicit routing rule for that request..
The capabilities for JavaScript to do routing are limited because it requires the user to already be on your site. You can do some interesting things if you parse the URL parameters or use hashes and use them for routing, but that still requires requesting a page from your site as the first step.
For example: the server is already doing some level of "extensionless routing" when you give it this request:
http://mywebsite.com/
The parts of the URL are:
http - protocol
(port 80 is implied because it is default HTTP port)
mywebsite.com - domain AKA host
/ the path
The server sees / and uses what IIS calls a "default document" (I think apache calls it "default index" or "default page"). The server has been configured to return a file such as "index.html" or "default.htm" in this case. So when you request http://mywebsite.com/ you actually may get back the equivalent of http://mywebsite.com/index.html
When the server sees http://mywebsite.com/about it may first look for a folder named about and next for a file named about, but since your file is actually named about.html and is in a different folder (/tpl) the server needs some help to know how to translate http://mywebsite.com/about into the appropriate request - which for you would be http://mywebsite.com/#/about so that it requests the routing page (assuming it is the default document in the web app root folder) so that the browser can parse and execute the JavaScript that does the routing. Capisce?
You might be interested by frontexpress.
My library fix your case like below:
// Front-end application
const app = frontexpress();
const homeMiddleware = (req, res) => {
document.querySelector('#view').innerHTML = '<p>This is content of home page</p>';
}
app.get('/', homeMiddleware);
app.get('/home', homeMiddleware);
app.get('/about', (req, res) => {
document.querySelector('#view').innerHTML = '<p>This is the content of the about page </p>';
});
Obviously, you can get the template files from the server.
The #view will be feeded as below:
document.querySelector('#view').innerHTML = res.responseText;
More detailed sample in this gist
I have worked with what your answers and I have build the following Router. The only issue remains that it still uses location.hash
(function() {
var Router = {
root: '#/',
routes: [],
urls: [],
titles: [],
add: function(thePath, theUrl, theTitle) {
this.routes.push(thePath);
this.urls.push(theUrl);
this.titles.push(theTitle);
},
navigate: function() {
var routes = this.routes,
urls = this.urls,
root = this.root;
function loading() {
var a = $.inArray(location.hash, routes),
template = urls[a];
if (a === -1) {
location.hash = root;
$("#view").load(urls[0]);
}
else {
$("#view").load(template);
if (a === 0) {
window.scrollTo(0, 0);
}
else {
window.scrollTo(0, 90);
}
}
}
window.onload = loading;
window.onhashchange = loading;
}
};
Router.add("#/", "tpl/home.html", "Home Page");
Router.add("#/about", "tpl/about.html", "About Page");
Router.add("#/licence", "tpl/licence.html", "MIIT Licence");
Router.add("#/cabala", "tpl/cabala.html", "Cabala Checker");
Router.add("#/articles/esp", "tpl/article1.html", "ESP");
Router.add("#/fanfics/the-chupacabra-case", "tpl/article2.html", "The Chupacabra Case");
Router.navigate();
})();
Your request reads like what you're attempting to do is to add a "path+file" ("/tpl/about.html") to a base url ("www.myhost.com"). If that's the case, then you need to dynamically extract the host name from your current document and then append the new URL to the existing base. You can get the existing host name by executing the following commands in javascript:
var _location = document.location.toString();
var serverNameIndex = _location.indexOf('/', _location.indexOf('://') + 3);
var serverName = _location.substring(0, serverNameIndex) + '/';
This will return a string like: "http://www.myhost.com/" to which you can now append your new URL. All of this can be done in javascript prior to sending to the server.
If you only want the server name, without the leading http or https, then change the last line to be:
var serverName = _location.substring(_location.indexOf('://') + 3, serverNameIndex) + '/';
Lets break your code down a little bit:
function loading() {
"location.hash" is set based on the URL most recently clicked (www.myhost.home/#about). One essential question is, is this the action that you want, or do you want to pass in a value from the html for the onClick operation? It seems like that would be a more effective approach for you.
var a = $.inArray(location.hash, routes),
template = urls[a];
var a will be set to either -1 or the location of "location.hash" in the "routes array. If location.hash does not exist in routes, then a==-1 and the script will fail, because you're setting template = urls[-1]. You may want to move setting template to inside the "else" statement.
if (a === -1) {
location.hash = root;
$("#view").load(urls[0]);
}
else {yada yada yada
}
You could use a sequence in your html analogous to:
<a onclick="loading('#about')">Go to About Page</a>

Batch File > Javascript > WinSCP > Check if file exists

I have a batch file that will launch a .js file which, via WinSCP, checks if a file exists and returns to the batch file if it does or not.
The problem IS: It always returns not found, and I cannot figure out why. I am unsure how to use a wildcard in this scenario.
The batch file looks like this:
cscript /nologo file.js
if errorlevel 1 goto notfound
exit
:notfound
(another script to copy a file over)
Only one file can exist on the server at once. So every ten min, this batch file will run, check if there is a file, if not, copy one over.
The file.js:
// Configuration
// Remote file search for
var FILEPATH = "../filepath/TSS*";
// Session to connect to
var SESSION = "mysession#someplace.come";
// Path to winscp.com
var WINSCP = "c:\\program files (x86)\\winscp\\winscp.com";
var filesys = WScript.CreateObject("Scripting.FileSystemObject");
var shell = WScript.CreateObject("WScript.Shell");
var logfilepath = filesys.GetSpecialFolder(2) + "\\" + filesys.GetTempName() + ".xml";
var p = FILEPATH.lastIndexOf('/');
var path = FILEPATH.substring(0, p);
var filename = FILEPATH.substring(p + 1);
var exec;
// run winscp to check for file existence
exec = shell.Exec("\"" + WINSCP + "\" /log=\"" + logfilepath + "\"");
exec.StdIn.Write(
"option batch abort\n" +
"open \"" + SESSION + "\"\n" +
"ls \"" + path + "\"\n" +
"exit\n");
// wait until the script finishes
while (exec.Status == 0)
{
WScript.Sleep(100);
WScript.Echo(exec.StdOut.ReadAll());
}
if (exec.ExitCode != 0)
{
WScript.Echo("Error checking for file existence");
WScript.Quit(1);
}
// look for log file
var logfile = filesys.GetFile(logfilepath);
if (logfile == null)
{
WScript.Echo("Cannot find log file");
WScript.Quit(1);
}
// parse XML log file
var doc = new ActiveXObject("MSXML2.DOMDocument");
doc.async = false;
doc.load(logfilepath);
doc.setProperty("SelectionNamespaces",
"xmlns:w='http://winscp.net/schema/session/1.0'");
var nodes = doc.selectNodes("//w:file/w:filename[#value='" + filename + "']");
if (nodes.length > 0)
{
WScript.Echo("File found");
// signalize file existence to calling process;
// you can also continue with processing (e.g. downloading the file)
// directly from the script here
WScript.Quit(0);
}
else
{
WScript.Echo("File not found");
WScript.Quit(1);
}
On line 4 it says:
var FILEPATH = "../filepath/TSS*";
That star is what is giving me issues, i think. I need to look for a file which STARTS WITH TSS, but will have a time stamp tacked on the end. So i need to just use a wildcard after TSS.
So what i need help with is: Making this process return true if any file exists with TSS*
Any help would be much appreciated.
EDIT:
var nodes = doc.selectNodes("//w:file/w:filename[starts-with(#value, 'TSS')]");
This code seems to not work. If this code worked, it seems like it would solve all my problems.
You need to correct xpath expression in var nodes... line.
Try something like this:
doc.setProperty("SelectionLanguage", "XPath"); //added in edit
var nodes = doc.selectNodes("//w:file/w:filename[starts-with(#value, '" + filename + "')]");
and delete asterisk from FILEPATH.
Note: first line is required in order to use XPath as the query language, not default (and old) XSLPattern which doesn't support methods such as starts-with or contains.
SelectionLanguage Property (MDSN).
You can use the stat command. You can even inline the WinSCP script into the batch file:
#echo off
set REMOTE_PATH=/home/user/test.txt
winscp.com /command ^
"option batch abort" ^
"open mysession" ^
"stat %REMOTE_PATH%" ^
"exit"
if errorlevel 1 goto error
echo File %REMOTE_PATH% exists
rem Do something
exit 0
:error
echo Error or file %REMOTE_PATH% not exists
exit 1
An alternative is using the Session.FileExists from WinSCP .NET assembly.
For further details, see the WinSCP article Checking file existence.

Categories