Custom HTTPRequestHandler for public file upload - wakanda

I'm trying to add a HTTPRequestHandler for a public file upload service to wakanda server. Anybody should be able to POST a file to this service without logging in. Unfortunately I get a "403 Forbidden" error on all POST requests made to the HTTPRequestHandler? GET requests work fine but do not not help much in this case ;-)
The intention is to receive the file, process it, and send it back to the client.
Added my request handler as follows:
application.addHttpRequestHandler('^/fileUpload$', './backend/httpRequestHandler/file-upload.js', 'fileUpload');
Any help on how to solve this problem would be much appreciated.

Finally got it to work myself with cURL. Looks like there was some issue with my Postman setup.
cURL command:
curl --form "fileupload=#test.xml" http://localhost:8081/fileUpload
HTTPRequestHandler:
/**
* file upload handler
* #param request {HTTPRequest} http request
* #param response {HTTPResponse} http response
*/
function fileUpload(request, response) {
try {
var counter = 1;
var nameTemp;
var files = [];
var uploadFolder = Folder('/PROJECT/database/data/tmp/');
var result = [];
var newName;
var myBinaryStream;
// create upload folder if not existing
if (!uploadFolder.exists) {
uploadFolder.create();
}
// create file instances
for (var i = 0; i < request.parts.length; i++) {
files.push(new File(uploadFolder.path + request.parts[i].fileName.replace(/\s/g, '_')));
// create result object
result[i] = {};
result[i].name = request.parts[i].fileName;
result[i].type = request.parts[i].mediaType;
result[i].size = request.parts[i].size;
}
// write file content
for (var i = 0; i < files.length; i++) {
counter = 1;
if (!files[i].exists) {
myBinaryStream = BinaryStream(files[i], 'Write');
myBinaryStream.putBlob(request.parts[i].asBlob);
myBinaryStream.close();
} else {
while (files[i].exists) {
nameTemp = files[i].name.replace(/\s/g, '_');
files[i] = new File(uploadFolder.path + files[i].nameNoExt.replace(/\s/g, '_') + counter + '.' + files[i].extension);
newName = files[i].name;
if (files[i].exists) {
files[i] = new File(uploadFolder.path + nameTemp);
}
counter++;
}
myBinaryStream = BinaryStream(files[i], 'Write');
myBinaryStream.putBlob(request.parts[i].asBlob);
myBinaryStream.close();
result[i].name = newName;
}
}
result = JSON.stringify(result);
// add response header
response.contentType = 'application/json';
return result;
} catch (e) {
console.log(e.stack);
return e;
}
}

Related

Reduce script run time in Google Apps Script?

I created a script that tracks attendance for distance learning. After a while it times out so I think I am having issues with too many calls to the Google Classroom API, however I don't see a way that I can change it to take those calls out of a loop.
The script takes all the Google Classroom classes that my apps script account is a co-teacher on and using timed triggers creates a daily attendance assignment with one question that says 'here'. Students are then supposed to answer the question and then another trigger at night runs the function to 'grade' each assignment and populate my spreadsheet so school secretaries can view it in the morning and record the previous days attendance.
The part that seems to have the bottleneck is my getStudentResponses() function. I tried to reduce time by filtering out students that didn't submit the assignment, but it wasn't enough. Does anyone see any way that I can make this faster? I was reading up on using the Cache Service, but I couldn't figure out how to get that to work. Any help would be appreciated.
var ss = SpreadsheetApp.getActive();
var date = new Date();
/*
creates a button to programmatically create all necessary timed triggers for easy deployment
*/
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Attendance')
.addItem('Create Triggers', 'createTriggers')
.addToUi();
}
/*
auto accepts any co-teacher invites
*/
function acceptInvite() {
try{
var optionalArgs = {
userId: "me"
};
var invites = Classroom.Invitations.list(optionalArgs);
for(var i = 0; i < invites.invitations.length; i++) {
Classroom.Invitations.accept(invites.invitations[i].id);
}
}
catch(e){}
}
/*
populates a spreadsheet with all the classes that the script Google account is a co-teacher of
the sheet has two columns one with the course name and two with the course id
*/
function listCourses() {
var optionalArgs = {courseStates: "ACTIVE"};
var response = Classroom.Courses.list(optionalArgs);
var courses = response.courses;
var classSheet;
try{
classSheet = ss.insertSheet("Classes", 0);
ss.insertSheet("Assignments", 1);
}
catch(e) {
classSheet = ss.getSheetByName("Classes");
}
classSheet.clear();
if (courses && courses.length > 0) {
for (i = 0; i < courses.length; i++) {
var course = courses[i];
classSheet.appendRow([course.name, course.id]);
}
}
}
/*
reads the sheet to get all the classes and creates a new array with all the class IDs
*/
function getCourses() {
var classSheet = ss.getSheetByName("Classes");
var classList = new Array();
var range = classSheet.getDataRange();
var values = range.getValues();
for(var i in values) {
var row = values[i];
var courseId = row[1]+"";
classList.push(Classroom.Courses.get(courseId));
}
createTopics(classList);
}
/*
called immediatly after getCourses, creates topics in each class that will contain the daily attendance assignment
*/
function createTopics(classList) {
for(i = 0; i < classList.length; i++) {
var topic;
var resource = {name: "Daily Online Attendance"};
try {
topic = Classroom.Courses.Topics.create(resource, classList[i].id);
createAssignment(topic,classList[i]);
}
catch(e) {
if(e == "GoogleJsonResponseException: API call to classroom.courses.topics.create failed with error: Requested entity already exists") {
var topics = Classroom.Courses.Topics.list(classList[i].id);
for(j = 0; j < topics.topic.length; j++) {
if(topics.topic[j].name == "Daily Online Attendance") {
createAssignment(topics.topic[j], classList[i]);
}
}
}
}
}
}
/*
creates an assignment in each class, under each topic
each assignment only has one choice that says "here" and is going to be 'graded' each night to track attendance
*/
function createAssignment(topic,course) {
var resource = {
title: "Attendance for "+(date.getMonth()+1)+"/"+date.getDate()+"/2020",
description: "Please fill this assignment out each day for attendance",
topicId: topic.topicId,
state: "PUBLISHED",
workType: "MULTIPLE_CHOICE_QUESTION",
multipleChoiceQuestion: {
"choices": [
"Here"
]
}
};
try {
var assignment = Classroom.Courses.CourseWork.create(resource, course.id);
var sheet = ss.getSheetByName("Assignments");
sheet.appendRow([course.id,assignment.id]);
}
catch(e){}
}
/*
creates a new sheet for each day and logs each assignement
*/
function getStudentResponses() {
var assignmentSheet = ss.getSheetByName("Assignments");
var sheet2;
var response;
assignmentSheet.sort(1, true);
try{
sheet2 = ss.insertSheet("Attendance for "+(date.getMonth()+1)+"/"+date.getDate()+"/2020",(ss.getSheets().length-(ss.getSheets().length-2)));
sheet2.appendRow(["Student Last Name","Student First Name","Grade","Class Name","Assignment Answer"]);
}
catch(e) {
sheet2 = ss.getSheetByName("Attendance for "+(date.getMonth()+1)+"/"+date.getDate()+"/2020");
}
sheet2.setFrozenRows(1);
var range = assignmentSheet.getDataRange();
var values = range.getValues();
for(var i in values) {
var row = values[i];
var courseId = row[0]+"";
var courseWorkId = row[1]+"";
try {
response = Classroom.Courses.CourseWork.StudentSubmissions.list(courseId, courseWorkId);
for(var j in response.studentSubmissions) {
if(response.studentSubmissions[j].state == "TURNED_IN") {
try {
var grade;
var email = Classroom.UserProfiles.get(response.studentSubmissions[j].userId).emailAddress;
sheet2.appendRow([Classroom.UserProfiles.get(response.studentSubmissions[j].userId).name.familyName,Classroom.UserProfiles.get(response.studentSubmissions[j].userId).name.givenName,grade,Classroom.Courses.get(courseId).name,response.studentSubmissions[j].multipleChoiceSubmission.answer]);
}
catch (e) {}
}
}
}
catch(e) {}
}
}
/*
deletes all assignemnts that were created
*/
function deleteAssignments() {
var assignmentSheet = ss.getSheetByName("Assignments");
assignmentSheet.sort(1, true);
var range = assignmentSheet.getDataRange();
var values = range.getValues();
for(var i in values) {
var row = values[i];
var courseId = row[0]+"";
var courseWorkId = row[1]+"";
try {
Classroom.Courses.CourseWork.remove(courseId, courseWorkId);
}
catch(e) {}
assignmentSheet.clear();
}
}
function createTriggers() {
ScriptApp.newTrigger('getCourses')
.timeBased()
.everyDays(1)
.atHour(6)
.create();
ScriptApp.newTrigger('getStudentResponses')
.timeBased()
.everyDays(1)
.atHour(22)
.create();
ScriptApp.newTrigger('deleteAssignments')
.timeBased()
.everyDays(1)
.atHour(23)
.create();
ScriptApp.newTrigger('listCourses')
.timeBased()
.everyDays(1)
.atHour(21)
.create();
ScriptApp.newTrigger('acceptInvite')
.timeBased()
.everyDays(1)
.atHour(20)
.create();
}
appendRow is slow, you should avoid to used it inside a for loop. Instead build an array, then pass the values using a single setValues call.
Resources
Best Practices | Apps Script
Related
Google Script Performance Slow Down
Increase my script performance Google Sheets Script
Very slow execution of for...in loop

Response status code does not indicate success: '400' ('Bad request')

i want to POST data to API in my android xamarin app using refit i've tested the API at Postman and it's working fine but at android app i'm getting exception Bad request.
Here is my android code i added the interface and the model i don't know what is the problem .
public interface RequestAPI
{
[Post("/request")]
Task<create_request> submit([Body] create_request request);
}
requestAPI= RestService.For<RequestAPI>("http://courier-magconsulting.azurewebsites.net/api");
button.Click += async delegate
{
try
{
create_request request = new create_request();
request.PickUpPhone = "7664554";
request.DownPayment = 89;
request.DeliveryFees = 56.8;
request.Note = "i need a help!";
request.RequestID = 88; // replace the value yourself
request.DekiveryLocationLatitude = 2323;
request.DeliveryLocationLongitude = 232;
request.PickUpLocationLatitude = 898;
request.PickUpLocationLongitude = 1123;
BroadcastType type = new BroadcastType();
type.Name = "All";
type.ID = 60; // replace the value yourself
request.BroadcastType = type;
Cargosize size = new Cargosize();
size.Name = "Small";
size.ID = 1; // replace the value yourself
request.Cargosize = size;
Cargoweight weight = new Cargoweight();
weight.Name = "Large";
weight.ID = 2; // replace the value yourself
request.CargoWeight = weight;
Sender sender_ = new Sender();
sender_.Name = "Ahmad";
sender_.SenderID = 1; // replace the value yourself
sender_.Phone = "8788";
sender_.SocialID = "8787";
sender_.RatingAvg = 5;
SenderStatus status = new SenderStatus();
status.ID = 1;
status.Name = "Active";
sender_.Senderstatus = status;
request.Sender = sender_;
create_request result = await requestAPI.submit(request);
Toast.MakeText(this, "Request created", ToastLength.Long).Show();
}
catch(Exception ex)
{
Toast.MakeText(this, ex.Message, ToastLength.Long).Show();
}
};

While Mail body being received, how to fetch the Image from multipart body

My application actually has mail send / receive functionalities to handle.
While receiving the mail, i am unable to view the image which is an inline image being sent from outlook.
Can some one help me how can i catch the image and make available always.
I have java code like below,
try (InputStream stream = new ByteArrayInputStream(Base64
.getMimeDecoder().decode(mail))) {
MimeMessage message = new MimeMessage(null, stream);
Object messageContent = message.getContent();
if (messageContent instanceof String) {
body = (String) messageContent;
} else if (messageContent instanceof MimeMultipart) {
content = (MimeMultipart) messageContent;
for (int i = 0; i < content.getCount(); i++) {
BodyPart bodyPart = content.getBodyPart(i);
String disposition = bodyPart.getDisposition();
if (disposition == null
|| disposition
.equalsIgnoreCase(Part.INLINE)) {
Object object = bodyPart.getContent();
if (object instanceof String) {
body = object.toString();
} else if (object instanceof MimeMultipart) {
MimeMultipart mimeMultipart = (MimeMultipart) object;
String plainBody = null;
String htmlBody = null;
for (int j = 0; j < mimeMultipart.getCount(); j++) {
BodyPart multipartBodyPart = mimeMultipart
.getBodyPart(j);
String multipartDisposition = multipartBodyPart
.getDisposition();
String multipartContentType = multipartBodyPart
.getContentType();
if (multipartDisposition == null
&& multipartContentType != null) {
if (multipartContentType
.contains(MediaType.TEXT_HTML)) {
htmlBody = multipartBodyPart
.getContent().toString();
} else if (multipartContentType
.contains(MediaType.TEXT_PLAIN)) {
plainBody = multipartBodyPart
.getContent().toString();
}
}
}
if (htmlBody != null) {
body = htmlBody;
} else {
body = plainBody;
}
}
}
}
}
Client side i am using CKEditor to handle email body data.
Thanks a lot.
i got a solution from the example shared below
https://www.tutorialspoint.com/javamail_api/javamail_api_fetching_emails.htm
But, this example explains, how to find the image in body and store.
I have also done below to replace src
`
Pattern htmltag = Pattern.compile("]src=\"[^>]>(.?)");
Pattern link = Pattern.compile("src=\"[^>]\">");
String s1 = "";
Matcher tagmatch = htmltag.matcher(s1);
List<String> links = new ArrayList<String>();
while (tagmatch.find()) {
Matcher matcher = link.matcher(tagmatch.group());
matcher.find();
String link1 = matcher.group().replaceFirst("src=\"", "")
.replaceFirst("\">", "")
.replaceFirst("\"[\\s]?target=\"[a-zA-Z_0-9]*", "");
links.add(link1);
s1 = s1.replaceAll(link1, "C:\\//Initiatives_KM\\//image.jpg");
}
`
And on top of this, i gonna do Base64 encoding so that i dont require store in file system.
encodedfileString = Base64.getEncoder().encodeToString(bArray);
With all these i can conclude to say, i got solution for my issue. Thank you.

Catch incoming emails and send them to a web service (rather than just to a mail server)

I would like to catch incoming emails and send them a web service (rather than just to a mail server).
--
After some searching I found a way of getting new emails via polling - see below: This may be of some help to others. Is there a way to receive messages by SMTP? Perhaps by ISAPI ???
using Limilabs.Mail;
using Limilabs.Client.IMAP;
public ActionResult checkIMAPmail()
{
string rval = "not a sausage";
using (Imap imap = new Imap())
{
imap.Connect(<mail server>);
imap.Login(<username>, <password>);
imap.SelectInbox();
List<long> uids = imap.Search(Flag.Unseen);
foreach (long uid in uids)
{
byte[] ourBytes = imap.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(ourBytes);
rval = email.Subject + " [" + email.From + "][" + email.Text + "]";
}
imap.Close();
}
return Content(rval, "text/html");
}
See also http://stackoverflow.com/questions/670183/accessing-imap-in-c-sharp
for other IMAP packages, although note the change to using byte[], above.
Given that Limilabs.Mail is a paid service, I finally used MailKit:
using MailKit;
public int checkIMAPmail()
{
int numEmails = 0;
try {
using (var client = new MailKit.Net.Imap.ImapClient())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(ourSmtpClient);
// disable the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate(ourSmtpAdminUser, ourSmtpAdminUserPwd);
// The Inbox folder is always available on all IMAP servers...
var inboxFolder = client.Inbox;
var savedFolder = client.GetFolder("saved");
inboxFolder.Open(FolderAccess.ReadWrite);
for (int ii = 0; ii < inboxFolder.Count; ii++)
{
var query = MailKit.Search.SearchQuery.NotSeen;
foreach (var uid in inboxFolder.Search(query))
{
var thisMsg = inboxFolder.GetMessage(uid);
string thisDate = notNullString(thisMsg.Date);
string thisSubject = notNullString( thisMsg.Subject);
string thisBody = notNullString(thisMsg.GetTextBody(0)); // plain text
string thisFromName = "";
string thisFromEmail = "";
if ( thisMsg.From != null)
{
// just get the first
foreach( var mb in thisMsg.From.Mailboxes)
{
thisFromName = notNullString( mb.Name);
thisFromEmail = notNullString( mb.Address);
break;
}
}
numEmails += 1;
// move email to saved
inboxFolder.MoveTo(uid, savedFolder);
}
}
client.Disconnect(true);
}
}
catch (Exception exc)
{
log2file("checkIMAPmail Error: " + exc.ToString());
}
return numEmails;
}

how to send multiple variables from servlet as response to ajax post?

I am developing a testing system with jsp and java
At client side i have the following code:
var xmlhttp = new getXmlHttpRequestObject(); //xmlhttp holds the ajax object
function servletPost() {
if(xmlhttp) {
//var txtname = document.getElementById("testForm");
var form = $('#testForm');
xmlhttp.open("POST","servlet/TestingController",true);
xmlhttp.onreadystatechange = handleServletPost;
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhttp.send(form.serialize());
}
}
function handleServletPost() {
//var qComplexity = document.getElementsByName("qComplexity")[0].value;
if (xmlhttp.readyState == 4) {
if(xmlhttp.status == 200) {
var respText = xmlhttp.responseText;
document.getElementById("fullQuestion").innerHTML = respText;
// here i also should change the content of the answer options
// so i should get from servlet multiple variables
// which allows me to change div contents in my jsp like as respText.question or respText.answer[0]
} else {
alert("Ajax calling error");
}
}
}
At server side: (my Servlet)
public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
.........................................................
.........................................................
PrintWriter out = res.getWriter();
String complex = null;
int categ_id = -1;
String asked_by = null;
String Qtext = null;
int qid = -1;
q_numb = 1;
q_numb++;
String sqlSelect = "SELECT * FROM questions WHERE complexity = '" + complexity
+ "'ORDER BY RANDOM() LIMIT 1;";
ResultSet r = myConnection.runQuery( sqlSelect );
session.setAttribute("member", tempMem);
while (r.next()) {
complex = r.getString(5);
categ_id = r.getInt(4);
asked_by = r.getString(3);
Qtext = r.getString(2);
qid = r.getInt(1);
String sqlA = "select * from answers where question_id = '" + qid
+ "' ORDER by RANDOM();";
ResultSet result = myConnection.runQuery( sqlA );
session.setAttribute("member", tempMem); }
So i need to send values of complex, Qtext, qid, categ_id and so on.
Is there any structures to send like from ajax to servlet, but visa versa?
And how to handle sent data in client side?
Thanks in advance!!!!
Use JSON. There are a myriad of free Java JSON marshallers. And JSON is natively supported by JavaScript.

Resources