Connectng to remote database in Adobe AIR - actionscript-3

I am developing an AIR mobile application. I am using Sqlite as my local database. Now I have to maintain some datas in a centralised database which has located in remote server ie., i have to push some data to remote database from my mobile application as well as retreieve.
My questions are
Can I use sqlite as centralised database?
How can I connect to the database located in server.
Thanks in Advance.

I'll try to sum up the answer for this question. SQLite is not designed to be a service and therefore can not be used as a remote database, unless you only need to read from it.
If you only need it for reading data you can download it from the server, save as a file and then use it as a local database. This method is better explained here: Link
But if you want to use it for writing as well as reading you'll have a lot of problems with concurrency and data usage, so using a SQLite database is not an option here. Better explained here: Link
The correct way of doing this is having a backend (server script or server program), which listens to your requests and acts according to them.
For example if you want to authenticate user you can send something like this to the server:
username: "Gio"
password: "123"
action: "login"
In Actionscript 3 call would look like this:
import flash.net.URLVariables;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.IOErrorEvent;
import flash.events.Event;
import flash.net.URLRequestMethod;
// create a URLLoader to POST data to the server
var loader:URLLoader = new URLLoader();
// server address where your script is listening
var request:URLRequest = new URLRequest("http://example.com");
// create and set the variables passed to the server script
var params:URLVariables = new URLVariables();
params.username = "Gio";
params.password = "123";
params.action = "login";
request.data = params;
// set the request type to POST as it's more secure and can hold more data
request.method = URLRequestMethod.POST;
loader.addEventListener(Event.COMPLETE, onPostComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, onPostFailed);
loader.load(request);
function onPostFailed(e:Event):void
{
// happens if the server is unreachable
trace("I/O Error when sending a POST request");
}
function onPostComplete(e:Event):void
{
// loader.data will hold the response received from the server
trace(e.target.data);
}
On the server side I'd recommend using PHP as it's easier to learn, simple and works great with MySQL.
In PHP you'd have something like this to handle the request:
<?php
$host="localhost"; // Host name
$username=""; // Mysql username
$password=""; // Mysql password
$db_name="test"; // Database name
$tbl_name="members"; // Table name
// Connect to server and select databse.
mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");
// username and password sent from form
if($_POST['action'] == "login")
{
$receivedUsername=$_POST['username'];
$receivedPassword=$_POST['password'];
$sql="SELECT * FROM $tbl_name WHERE username='$receivedUsername' and password='$receivedPassword'";
$result=mysql_query($sql);
// Mysql_num_row is counting table row
$count=mysql_num_rows($result);
// If result matched $receivedUsername and $receivedPassword, table row must be 1 row
if($count==1){
echo "Authentication success";
}
else {
echo "Wrong Username or Password";
}
}
?>
This will seem a little complicated at first, but it's not of a big deal actually. You'll have to read more on PHP and how to setup it as I can't fit all the details in this post.

I using AMFPHP in serverside.
In Flash You call service on server:
_net_connection = new NetConnection();
_net_connection.addEventListener(NetStatusEvent.NET_STATUS, connectionStatusHandler);
_net_connection.connect(_server_url);
_responder = new Responder(loginResult, null);
_net_connection.call("userSerivce2/login", _responder, _user_login, _user_passwword);
private function loginResult(result_object:Object):void {
save_log('loginResult (' + result_object.status + ")");
//rest of code
}
responder - is function in AS3 you will execute after call
userSerivce2/login - class userSerivce2, method login
you add responder (_responder) and additional arguments like _user_login, _user_passwword, in this case.
server PHP:
public function login($user_name, $user_password) {
//SELECT blablabla
try {
if ($logged) {
$this->call_result['status'] = 0;
throw new mysqli_sql_exception("Pomyślnie zalogowano.");
} else {
$this->call_result['status'] = 3;
throw new mysqli_sql_exception("Błąd logowania. Wprowadź poprawny login, oraz hasło.");
}
} catch(Exception $e) {
$this->call_result['error_message'] = $e->getMessage();
return $this->call_result;
}
return $this->call_result; //method will return object
}

Related

Connect to MySQL Database using sockets

I am following up from my last question, where I was suggested to use sockets for a real time chat application using MySQL database. I have been researching some information about the usage of sockets in flutter, after trying several times and several different codes and failing, I clicked inside another stackoverflow question about sockets and found out this code snippet:
import 'dart:io';
import 'dart:async';
Socket socket;
void main() {
Socket.connect("localhost", 4567).then((Socket sock) {
socket = sock;
socket.listen(dataHandler,
onError: errorHandler,
onDone: doneHandler,
cancelOnError: false);
}).catchError((AsyncError e) {
print("Unable to connect: $e");
});
//Connect standard in to the socket
stdin.listen((data) => socket.write(new String.fromCharCodes(data).trim() + '\n'));
}
void dataHandler(data){
print(new String.fromCharCodes(data).trim());
}
void errorHandler(error, StackTrace trace){
print(error);
}
void doneHandler(){
socket.destroy();
}
I may be wrong but I think this may be the way to connect to my database, if it is not please help me out, I would appreciate it. But I can't find a way to write in the database name, username and password in order to access the data from a specific MySQL database.

Database logon failed while using mysql azure

I am trying to print crystal report in PDF format , and on my local machine it’s working fine. But when I publish application to the server, it’s giving me the following error on Print button.
Exception Details: System.Runtime.InteropServices.COMException: Database logon failed.
Below is my code in my controller
public ActionResult Export(int Id)
{
ReportDocument rd = new ReportDocument();
rd.Load(Path.Combine(Server.MapPath("~/Reports/GcReport.rpt")));
var query = rLAService.GetGeneralConsignmentById(Id);
var querylist = new List<GeneralConsignmentDto> { query };
rd.SetDataSource(querylist);
rd.SetParameterValue("Id", Id);
//rd.SetDataSource(rLAService.GetGeneralConsignmentById(Id));
Response.Buffer = false;
Response.ClearContent();
Response.ClearHeaders();
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/pdf", "GC Report.pdf");
}
Edit
Ok, after digging throuh the problem, i found that error is table name generalconsignment1 does not found. But problem is it is taking automatically instead of generalconsignment.now how to handle this situation?

What's the best way to migrate to ServiceStack authentication framework when stuck with my_aspnet_* tables

I'm not quite ready to change up all my user/auth tables from the MySQL user/roles/profile provider format, but am moving off of MVC to ServiceStack.
Is there a pre-built IUserAuthRespository and/or CredentialsAuthProvider somewhere that can be used, or do I need to build one to provide this mapping?
If I need to build one, I assume implementing at the IUserAuthRepository level is the cleanest? Is there a minimum set of methods required to implement basic login/logout (and administrative "switch user" impersonation) functionality?
I tried implementing a custom CredentialsAuthProvider, which seems to work, but I'm unable to get local posts for impersonation to use the proper provider. Looking for a solution to that, I realized that maybe its better to implement the repository instead.
EDIT:
My current registration of the custom auth provider is:
Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[]
{
container.Resolve<MySqlCredentialsAuthProvider>() //HTML Form post of UserName/Password credentials
}));
And calling code for the local post to the AuthenticateService is:
[RequiredRole(SystemRoles.Administrator)]
public object Any(ImpersonateUser request)
{
using (var service = base.ResolveService<AuthenticateService>()) //In Process
{
//lets us login without a password if we call it internally
var result = service.Post(new Authenticate
{
provider = AuthenticateService.CredentialsProvider,
UserName = request.Username,
//Password = "should-not-matter-since-we-are-posting-locally"
});
return result;
}
}
Integrating with existing User Auth tables
If you want to use your existing User/Auth tables, the easiest solution is to ignore the UserAuth repositories and implement a Custom CredentialsAuthProvider that looks at your existing database tables to return whether their Authentication attempt was successful.
Implement OnAuthenticated() to populate the rest of your typed IAuthSession from your database, e.g:
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService,
string userName, string password)
{
//Add here your custom auth logic (database calls etc)
//Return true if credentials are valid, otherwise false
}
public override IHttpResult OnAuthenticated(IServiceBase authService,
IAuthSession session, IAuthTokens tokens,
Dictionary<string, string> authInfo)
{
//Fill IAuthSession with data you want to retrieve in the app eg:
session.FirstName = "some_firstname_from_db";
//...
//Call base method to Save Session and fire Auth/Session callbacks:
return base.OnAuthenticated(authService, session, tokens, authInfo);
//Alternatively avoid built-in behavior and explicitly save session with
//authService.SaveSession(session, SessionExpiry);
//return null;
}
}
Importing existing User Auth tables
If you want to import them into an OrmLite User Auth tables, you would configure to use the OrmLiteAuthRepository in your AppHost:
//Register to use MySql Dialect Provider
container.Register<IDbConnectionFactory>(
new OrmLiteConnectionFactory(dbConnString, MySqlDialect.Provider));
Plugins.Add(new AuthFeature(
() => new CustomUserSession(), //Use your own typed Custom UserSession type
new IAuthProvider[] {
//HTML Form post of UserName/Password credentials
new CredentialsAuthProvider()
}));
//Tell ServiceStack you want to persist User Info in the registered MySql DB above
container.Register<IUserAuthRepository>(c =>
new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
//Resolve instance of configured IUserAuthRepository
var userAuth = container.Resolve<IUserAuthRepository>();
//Create any missing UserAuth RDBMS tables
authRepo.InitSchema();
Then to import your data you can use the above MySQL DB connection to select from your existing tables then use the IUserAuthRepository to create new Users.
// Open DB Connection to RDBMS
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
//Example of fetching old Users out of a custom table (use your table instead)
var oldUsers = db.Select<OldUserInfo>();
// Clear existing UserAuth tables if you want to replay this import
//db.DeleteAll<UserAuthDetails>();
//db.DeleteAll<UserAuth>();
//Go through and create new User Accounts using Old User Info
foreach (var oldUser in oldUsers)
{
//Create New User Info from Old Info
var newUser = new UserAuth {
UserName = oldUser.UserName,
Email = oldUser.Email,
//...
};
//Create New User Account with oldUser Password
authRepo.CreateUserAuth(newUser, oldUser.Password);
}
}
After this you'll have new User Accounts from your old User Info which you can sign in with.

Can't connect to MySQL/MariaDB database from vibed app

All work fine if I use custom main ( void main() instead of shared static this() ).
With default main I am getting "Access Violation" error. It's look like MySQL not allow connecting to it from localhost, but in my.ini I added string:
bind-address = 127.0.0.1
code, if it's help:
import std.stdio;
import std.path;
import std.file;
import std.string;
import dini;
import vibe.d;
import colorize;
import ddbc.all;
shared static this()
{
auto settings = new HTTPServerSettings;
settings.port = 8080;
settings.bindAddresses = ["::1", "127.0.0.1"];
listenHTTP(settings, &hello);
auto parseconfig = new ParseConfig();
auto db = new DBConnect(parseconfig);
}
void hello(HTTPServerRequest req, HTTPServerResponse res)
{
res.writeBody("Hello, World!");
}
class ParseConfig
{
string dbname;
string dbuser;
string dbpass;
string dbhost;
string dbport;
this()
{
try
{
//getcwd do not return correct path if run from task shoulder
string confpath = buildPath((thisExePath[0..((thisExePath.lastIndexOf("\\"))+1)]), "config.ini");
//writefln(thisExePath[0..((thisExePath.lastIndexOf("\\"))+1)]); // get path without extention +1 is for getting last slash
//string confpath = buildPath(thisExePath, "config.ini");
if (!exists(confpath))
{
writeln("ERROR: config.ini do not exists");
}
auto config = Ini.Parse(confpath);
try
{
this.dbname = config.getKey("dbname");
this.dbuser = config.getKey("dbuser");
this.dbpass = config.getKey("dbpass");
this.dbhost = config.getKey("dbhost");
this.dbport = config.getKey("dbport");
}
catch (Exception msg)
{
cwritefln("ERROR: Can't parse config: %s".color(fg.red), msg.msg);
}
}
catch(Exception msg)
{
cwriteln(msg.msg.color(fg.red));
core.thread.Thread.sleep( dur!("msecs")(1000));
}
}
}
class DBConnect
{
Statement stmt;
ParseConfig parseconfig;
this(ParseConfig parseconfig)
{
try
{
this.parseconfig = parseconfig;
MySQLDriver driver = new MySQLDriver();
string url = MySQLDriver.generateUrl(parseconfig.dbhost, to!short(parseconfig.dbport), parseconfig.dbname);
string[string] params = MySQLDriver.setUserAndPassword(parseconfig.dbuser, parseconfig.dbpass);
DataSource ds = new ConnectionPoolDataSourceImpl(driver, url, params);
auto conn = ds.getConnection();
scope(exit) conn.close();
stmt = conn.createStatement();
writefln("\n[Database connection OK]");
}
catch (Exception ex)
{
writefln(ex.msg);
writeln("Could not connect to DB. Please check settings");
}
}
}
Also I run next command:
GRANT ALL PRIVILEGES ON *.* TO 'root'#'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
also I tried different bind-address like: 0.0.0.0 and localhost but without result. After every new binding I did restart of MySQL service.
I am using this driver http://code.dlang.org/packages/ddbc
What's wrong?
To continue on my comment ( Can't connect to MySQL/MariaDB database from vibed app ).
I just tested, and it's definitely the event loop ;)
Instead of:
auto parseconfig = new ParseConfig();
auto db = new DBConnect(parseconfig);
Just do:
runTask({
auto parseconfig = new ParseConfig();
auto db = new DBConnect(parseconfig);
});
Worked for me (DMD 2.067.0 / Vibe 0.7.23 / ddbc 0.2.24 / colorize & dini master).
To answer your comment ( Can't connect to MySQL/MariaDB database from vibed app) : the event loop starts inside the main function.
What happens when you launch a D application ? The entry point is a C main inside the runtime, which initialize it (the runtime), including module constructor, run the unittest (if you've compiled with -unittest), then call your main (which name is "_Dmain" - useful to know if you want to set a breakpoint with GDB).
When Vibe.d's main is called, it parses command line argument, an optional config file, and finally, starts the event loop. Any code that wish to run once the event loop has started should use runTask and similar, or createTimer. They should not call the code directly from the static constructor (it's actually one of the most common mistake when starting with Vibe.d).
I ran into an issue that could be related while developing mysql-lited, an alternative MySQL/MariaDB driver.
The issue I think is related to a module initialization order bug in phobos/SHA1, which I believe is still open in 2.067.1. The suggested work-around is to use VibeCustomMain instead, and define your own main(). You can just copy the defaul main() from appmain.d and use that.
Alternatively you could try mysql-lited and see if that works better for you.

JavaMail SMTPSendFailedException

I am writing a bulk email program using the JavaMail api. I have a Microsoft Exhange server which I am trying to send the emails in to. When I run my program I get the following error:
**com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057)
at com.sun.mail.smtp.SMTPTransport.finishData(SMTPTransport.java:1862)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1100)
at javax.mail.Transport.send0(Transport.java:195)
at javax.mail.Transport.send(Transport.java:124)
at SendEmail.postMail(SendEmail.java:100)
at EmailGenerator.main(EmailGenerator.java:52)**
The part of my code trying to send the message is as follows:
Properties props = new Properties();
props.put("mail.smtp.host", email_server);
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", true);
class EmailAuthenticator extends Authenticator {
String user;
String pw;
EmailAuthenticator (String FROM, String PASSWORD)
{
super();
this.user = FROM;
this.pw = PASSWORD;
}
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, pw);
}
}
Session session = Session.getInstance(props, new EmailAuthenticator(USER, PASSWORD));
session.setDebug(debug);
System.out.println("Session created");
.. CREATED MESSAGE HERE...
Transport transport = session.getTransport("smtp");
transport.connect(exchange_server,user,password);
transport.send(msg);
transport.close();
I wonder am I missing some configuration on the Exchange server side, or is an issue with my code?
OK I figured out where I was going wrong here and am posting up the answer incase anybody else can get some value out of it. I had the following line of code:
props.put("mail.smtp.auth", true);
This was telling my application that it needed to authenticate to the SMTP server, when in fact it didnt. This was causing my application from logging into the SMTP server and sending the email and thus producing the error message. Setting this property to false or not having this line of code fixed the issue for me. This line of code is only necessary for SMTP servers that require you to login, which my Exchange server didnt.