I'd like to create a launcher for a Java game I'm developing that will require the user to log in before the game itself can be downloaded. My idea was to have the launcher send the credentials to my webserver, and the webserver would output the location of a temporary file given the credentials were correct. However, this would be a bit tricky/inefficient, given:
The server would need to copy the game file every time someone updates, and
The webserver wouldn't know when the file was finished downloading.
Perhaps the launcher could send a request to a separate script to delete a file of the given temporary name? The problem with that is that the launcher could easily be decompiled and modified to not send the request, defeating the purpose of creating a new file.
Any suggestions as to this idea and its issues?
I would use a database, like this:
urlgenerator.php
<?php
// generate code
$code = uniqid();
// save code to database
db_save($code);
// write link
echo 'Download';
download.php
<?php
// get code from url
$single_use_code = $_GET['code'];
// check if the code is in the db
if(db_get_code($single_use_code)) {
// remove code from database as it is single use only
db_remove($single_use_code);
// start download
start_download();
} else {
// the code is not valid
die('BAD code');
}
Try something like this:
// Define a random key
$key = 'kgjiowtjiohgjiut09ig90im09yig90mi903i490ti209tgwgt';
$secondsValid = 300;
if($_GET['action'] == 'download')
{
$time = $_GET['time'];
if(time() - $time > $secondsValid)
die('Code has expired, please try again');
if($_GET['validation'] != md5($time.$key))
die('Invalid validation code');
DownloadFile();
die;
}
elseif(CredentialsAreCorrect())
{
$time = time();
header('Location: '.$_SERVER['REQUEST_URI'].'?action=download&time='.$time.'&validation='.md5($time.$key));
die;
}
else
die('Invalid credentials');
This is an easy way to give a validated user a timebombed URL (valid for 5 minutes in this case) without any nasty copying/symlinking/whatever involved, no databases, just using basic facilities that cannot be hacked as long as the key is secure. Just make sure your key has enough entropy (40+ random keypresses should do it) so no rainbow table or brute force attack is feasible.
Simple workaround: on a unix system, you can remove a file while it's in use without affecting currently-open file handles on that file. so
user requests download
script makes a symlink in the documentroot somewhere that points at wherever the file is really stored (somewhere outside of the document root)
URL to the symlink is send out as a parameter to the user.
User clicks on the donwload link, e.g. http://example.com?get=path/of/symlink
The download script fopen()'s the symlink and starts dishing out the file's contents
script REMOVES the symlink after it's been fopen()'d
Now the symlink is gone and can't be reused anymore, but the download script will still be sending data to the user because it opened the symlink/file before it was removed.
Related
I want to set up only one instance of the CHM file when clicking on "Help" in the menubar and stopping it from opening twice when clicked again - therefore how do I code it?
I've tried to use it with process.isAlive(), but after I close it I want a counter set to zero, which only opens another CHM file when the counter is 0.
helpMenu.addMouseListener(new MouseAdapter() {
// do this after clicked
openCHM();
});
So MouseEvent is fired once.
openCHM() {
Process p;
if(cnt == 0) {
p = Runtime.getRuntime().exec("hh.exe Help.chm");
cnt++;
if(!p.isAlive()) {
cnt = 0;
}
}
I expected the counter to be 0, but then came to the conclusion that MouseEvent already fired once and the code got already executed, therefore it never goes to the second if-statement and sets my counter to 0.
EDIT
There is no correct answer how to open a CHM file once, but there is a workaround that makes it possible, we just need to look if the file is renamable or not.
protected void openCHM() {
try {
File file = new File("YOURNAME.chm");
boolean renamable = file.renameTo(file); // can't rename if file is already open, returns true if renaming is possible
if(renamable) {
Runtime.getRuntime().exec("hh.exe YOURNAME.chm");
} else if(!file.exists() ){
// message: file doesn't exist (in path)
} else {
// file is already open
}
} catch () {
}
}
I'm not a Java programmer but the short story - not possible (AFAIK).
You know, hh.exe is the HTMLHelp executable and associated with *.CHM files. It's just a shell that uses the HTML Help API and is really just hosting a browser window.
HH.EXE is not single instance, if you open a CHM or another file three times using HH.EXE, then three help windows will appear. Try it using PowerShell:
PS D:\_working> hh.exe C:\Windows\Help\htmlhelp.chm
Several client-side command line switches are available to help authors that are part of the HTML Help executable program (hh.exe) and therefore work when HTML Help Workshop is not set up.
KeyHH.exe was running years ago with special parameters.
If you call the HH API directly from your application, and not via a second helper program like HH.EXE or KEYHH.EXE, then you MUST close any open help windows before shutting down the application or you will probably crash Windows.
For some information related to the problem you maybe interested in Open CHM File Once.
Some quoted info from the link above:
When you do that you are just calling the help viewer again and again from the command line, you're not using the HTML Help API which is what you need to access the CHM once it is open. You need to check whether your flavors of Java and Smalltalk support calls to the HTML Help API. This API is documented in detail in the help file of Microsoft HTML Help Workshop, which is the compiler package you installed to be able to generate CHMs.
i am trying to make a project where the user inputs a couple of brands and receives feedback of their mentioned times in twitter.. so far i ve made/found/tweaked the basic frontend in java, the php scripts for consuming the twitter streaming api plus a database to save the incoming tweets,, the last two in a xaamp server locally. Its working perfectly but i must run the scripts manually through my browser.
what i need is
php scripts to run in the backround (as their creator insists )
start and stop scripts at will to change and renew requested keywords
and i need this to be done from my frontend.
i thought of this..
since in the first place i send user inputs to the scripts through my database (java arrayOfBrands => db table => php requests and gets a column as array ) i could do smth like a flag in mysql database changable by my frontend and critical in the execution of my script.
then i looked at this question
Starting / Stopping php script running in background from browser
but the guy here proposes to do it as a cronjob... the other guy who made the scripts says about a thousand times in the instructions "DONT DO IT AS A CRONJOB" but as a procedure in the backround... and they both seem good and pro(Adam Green 140dev and Aziz Saleh 1763 fame here ) and i dont know which way to go..
here is "my" code
<?php
/**
* get_tweets.php
* Collect tweets from the Twitter streaming API
* This must be run as a continuous background process
* Latest copy of this code: http://140dev.com/free-twitter-api-source-code-library/
* #author Adam Green <140dev#gmail.com>
* #license GNU Public License
* #version BETA 0.30
*/
ini_set('display_errors', true);
require_once('140dev_config.php');
require_once('brands.php');
require_once('../libraries/phirehose/Phirehose.php');
require_once('../libraries/phirehose/OauthPhirehose.php');
class Consumer extends OauthPhirehose
{
// A database connection is established at launch and kept open permanently
public $oDB;
public function db_connect() {
require_once('db_lib.php');
$this->oDB = new db;
}
// This function is called automatically by the Phirehose class
// when a new tweet is received with the JSON data in $status
public function enqueueStatus($status) {
$tweet_object = json_decode($status);
// Ignore tweets without a properly formed tweet id value
if (!(isset($tweet_object->id_str))) { return;}
$tweet_id = $tweet_object->id_str;
// If there's a ", ', :, or ; in object elements, serialize() gets corrupted
// You should also use base64_encode() before saving this
$raw_tweet = base64_encode(serialize($tweet_object));
$field_values = 'raw_tweet = "' . $raw_tweet . '", ' .
'tweet_id = ' . $tweet_id;
$this->oDB->insert('json_cache',$field_values);
}
}
// Open a persistent connection to the Twitter streaming API
$stream = new Consumer(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_FILTER);
// Establish a MySQL database connection
$stream->db_connect();
// The keywords for tweet collection are entered here as an array
// More keywords can be added as array elements
// For example: array('recipe','food','cook','restaurant','great meal')
$stream->setTrack($mybrands);
// Start collecting tweets
// Automatically call enqueueStatus($status) with each tweet's JSON data
$stream->consume();
this is the script i need to run/not run
plz help me in any way possible either code or advice or just a tip are valuable for me.
thanks in advance.
I found online google drive script that sends an email with the changes on the prices of Amazon products that I insert.
This is the file
I couldn't make it work for 100%.. It work sometimes only for some of the products, and I cant find the reason.
Please help me to understand what is wrong.
Also, I wanted to know if I could modify the script so it will send me an alert twice a day and not only once, as it is now.
Configuring Email Notification Intervals
The email notifications are configured as Google Apps Scripts triggers invoking the priceEmail function. They're randomly assigned when you initialize the spreadsheet (refer to the Start_Tracking implementation).
To configure email notifications manually – e.g. adding a second daily email – open the Copy of Amazon Price Tracker by ctrlq.org script associated with the spreadsheet (via the spreadsheet Tools > Script editor... menu command). Then proceed to opening the triggers dialog (Resources > Current project's triggers menu command) and add a new time-driven trigger for the priceEmail hook.
Script Errors
By default, the priceEmail function handles all errors silently. There's not much clue to what would cause the script to not work 100% of the time. If you'd like to be notified of the errors, either remove the exception handling in the current implementation or update the priceEmail body.
I'd advice making the following modifications (again via the spreadsheet Tools > Script editor... menu command):
function priceEmail() {
var sheet, data, page, table="";
sheet = SpreadsheetApp.getActiveSheet();
data = sheet.getRange(2, 2, 21, 2).getValues(); // Note that the script will only look at the first 20 rows.
try {
for (i in data) {
if (data[i][0] !== "") {
page = UrlFetchApp.fetch(
"http://ctrlq.org/aws/lookup/", {
"method": "post", "payload": {"url":data[i][0]}
}).getContentText();
table = table + tableRow(page);
}
}
} catch (e) {
Logger.log(e.toString());
// Following line inserted to include any error messages in your daily email(s).
table += "<tr><td><strong>Error:</strong></td><td>" + e + " (url: \"" + data[i][0] + "\")</td></tr>";
}
// ...
Is there any method to create a file in java that cannot be deleted.
I have googled it and found processes involving the cmd.
However, I require a pure "java" way that can be done on any platform.
Thanks in advance.
Thank you for your help.
I finally got it right.
I used the following code to deny access to user
public static void main() throws IOException
{
Path file = Paths.get("c:/b.txt");
AclFileAttributeView aclAttr = Files.getFileAttributeView(file, AclFileAttributeView.class);
//System.out.println();
UserPrincipalLookupService upls = file.getFileSystem().getUserPrincipalLookupService();
UserPrincipal user = upls.lookupPrincipalByName(System.getProperty("user.name"));
AclEntry.Builder builder = AclEntry.newBuilder();
builder.setPermissions(EnumSet.of(AclEntryPermission.APPEND_DATA, AclEntryPermission.DELETE, AclEntryPermission.DELETE_CHILD, AclEntryPermission.EXECUTE, AclEntryPermission.READ_ACL, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.READ_DATA, AclEntryPermission.READ_NAMED_ATTRS, AclEntryPermission.SYNCHRONIZE, AclEntryPermission.WRITE_ACL, AclEntryPermission.WRITE_ATTRIBUTES, AclEntryPermission.WRITE_DATA, AclEntryPermission.WRITE_NAMED_ATTRS, AclEntryPermission.WRITE_OWNER));
builder.setPrincipal(user);
builder.setType(AclEntryType.DENY);
aclAttr.setAcl(Collections.singletonList(builder.build()));
}
Try the method setPosixFilePermissions() and set the permissions to read only for all the classes of users. Refer this - http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#setPosixFilePermissions%28java.nio.file.Path,%20java.util.Set%29
If you want to create a file that can't be accidentally overwritten, then look at the various answers to this: How do i programmatically change file permissions?
If you want to create a file that the current program cannot delete at all (but a privileged one could), it might be possible by setting permissions appropriately on the parent directory, or possibly using SELinux Mandatory Access Control cleverness.
If you want to create a truly undeleteable file, then you are out of luck. I am not aware of any operating system that supports creation of files that can never be deleted. It would be an "anti-feature".
I would also agree with #Teifi's comment. Create a file that cannot ever be deleted on the user's machine is not acceptable ... unless done by, or with the authorization of the system's administrators. I would call any software that did that "malicious" too.
I am writing an attendance program in Java for use in class; my goal is to be able to have the students download the class file to their accounts (we'll be working on the same network) and then run them with their usernames and a password that will change daily. My program works fine, but I've run into a bug that I can't seem to overcome.
When it's run for the first time in any given day, attend.java will create a new text file in a specified directory on my account and then append the username of whoever ran the program to the file (currently it just appends the first argument of the program to the file, but I hope to modify it so it is more accurate and no one can give a false username), thereby compiling a list of students.
For example, running:
>> java attend desadams cheesecake
will take the given password "cheesecake" and if it matches the day's password either create a new textfile called "(today's date).txt" and write the username "desadams" to it (if it is being run for the first time that day) or else simply append the username "desadams" to the preexisting "(today's date).txt" file.
I wrote my own createFile() method that utilizes the java.nio.file package to create a file with custom permissions:
public static void createFile(File file) throws IOException{
Path newFile = file.toPath();
//create new file and set permissions
/* For the purposes of this program, the new file (the attendance list) must readable and writable to everbody
* in order for this program to work properly when run from their user, because this program both reads and modif\
ies.
*/
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxrw-rw-");
Files.createFile(newFile);
Files.setPosixFilePermissions(newFile, perms);
//set owner
UserPrincipal owner = newFile.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByName("desadams");
Files.setOwner(newFile, owner);
//set group
GroupPrincipal group = newFile.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByGroupName("studen\
ts");
Files.getFileAttributeView(newFile, PosixFileAttributeView.class).setGroup(group);
}
I could not create the file and set the permissions at the same time, because the umask of the account would get in the way, so I did it in two steps and it works fine.
Now we get to my problem: I can compile and run this program just fine from my own account, but in anticipation of running it from other accounts, I changed the setOwner() method to use an arbitrary username instead of my own to better simulate the conditions of running the program from a different account. And it failed. Attempting to set the owner to anyone other than the person running the program results in an "operation not permitted" error.
I already knew that the UNIX command chown would not work because none of the network accounts have access to the root account, but I didn't expect it to prevent Java from doing the same thing, though I suppose it does make sense.
Is there anyway at all to get around this? The simplest way, of course, would be to run the program myself prior to anyone else each day, so that the attendance file is created in my own username and then I wouldn't have to worry about making sure to set the owner to my username within the program itself; it will always find the attendance file and thus not have to create it with the proper file attributes. However, though that may be exactly what I do, I would like to know if anyone has a solution that suggests how to set the owner within the program itself.
Thanks, and sorry this was a long post.
If the users are sudoers on your system, you could have them do sudo java attend desadams cheesecake. However, I expect they are not sudoers, and therefore your solution where you create the file first is probably the best one.