Convert string input of linedit() to int for use as an integer variable - oracle

I designed a simple GUI to check Database connectivity. The DB connection parameters such as DB name, Host name, user name, password, port etc will be entered from GUI and the output will be a RED or GREEN image depending upon the connectivity.
I have set up oracle OCI plugin (DB is oracle 10g)
and done the following--
void MainWindow::on_GoButton_clicked()
{
QString HostN = ui->HostNameEdit->text();
QString DatabaseN = ui->DatabaseNameEdit->text();
QString UserN = ui->UserNameEdit->text();
QString PassWD = ui->PasswordEdit->text();
QString PortNO = ui->PortEdit->text();
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
db.setHostName(HostN);
db.setDatabaseName(DatabaseN);
db.setUserName(UserN);
db.setPassword(PassWD);
db.setPort(PortNO);
while(true)
{
if (db.open())
{
// do this
}
else
{
//do that
}
}
}
Now it is showing error--
/home/aj/MY_QT_WORK/DB_connection_test/mainwindow.cpp:19: error: no matching function for call to ‘QSqlDatabase::setPort(QString&)’
Any ideas ???

You could write it as:
db.setPort(PortNO.toInt());
However for much correctness you have to be sure that the PortNO string is really convertible to an integer value. Therefore you can use a flag that will indicate the successful conversion:
bool ok;
int portNumber = PortNO.toInt(&ok);
if (!ok) {
qDebug() << "The port number is incorrect";
// return?
}

Related

Define Bluetooth permissions for a standard Console App in WinRT/C++

I'm working on a WinRT/C++ application that uses Windows APIs to access to RFCOMM Bluetooth and looks for nearby devices. Then I try to create a service in order to create a connection, so I run:
RfcommDeviceService service = RfcommDeviceService::FromIdAsync(currId).get();
However, the FromIdAsync method returns NULL since, according to the documentation:
If a store app has not declared the right capabilities or the user does not grant consent, the method returns a null object.
The solutions I found online all require to add a <Capabilities> tag to the Package.appxmanifest file. However, I do not have such file, since I'm working on a standard Console app.
Is there another way to grant permissions to my app? Alternatively, can I include manually a Package.appxmanifest file so that I can access the Bluetooth? Or I am completely missing the point here and the error is caused by something else?
EDIT: Minimal reproducible example:
// Store all the devices
vector<DeviceInformation> devices;
// Replace targetAddress with Bluetooth address to pair
string targetAddress = "XX:XX:XX:XX:XX:XX";
// AQS string for RFCOMM devices
hstring selectorString = to_hstring("System.Devices.DevObjectType:=5 AND System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\" AND((System.Devices.Aep.IsPaired: = System.StructuredQueryType.Boolean#True OR System.Devices.Aep.IsPaired: = System.StructuredQueryType.Boolean#False) OR System.Devices.Aep.Bluetooth.IssueInquiry: = System.StructuredQueryType.Boolean#False)");
// Create watcher
DeviceWatcher deviceWatcher = DeviceInformation::CreateWatcher(selectorString);
// Callback function for event handling
auto OnAddedDevice = [](DeviceWatcher watcher, DeviceInformation deviceInfo)
{
devices.push_back(deviceInfo);
};
// New Bluetooth device detected -> callback
deviceWatcher.Added(OnAddedDevice);
// Start watcher
deviceWatcher.Start();
std::cout << "Performing device scan...\n" << endl;
Sleep(4000);
// Stop scanning
deviceWatcher.Stop();
// Print results
for (int i = 0; i < devices.size(); i++) {
string name = to_string(devices[i].Name());
string address = getAddress(devices[i]);
std::cout << "(" << address << ")" << "\t" << name << endl;
}
std::cout << endl;
// Look for target device among the scanned ones
for (int i = 0; i < devices.size(); i++) {
string address = getAddress(devices[i]);
// Match found
if (address == targetAddress) {
// Get ID
auto currId = devices[i].Id();
// Create Service [HERE, FROM IDASYNC RETURNS NULL]
RfcommDeviceService service = RfcommDeviceService::FromIdAsync(currId).get();
// Try to get information about the created service [LAUCHES EXCEPTION SINCE service IS NULL]
auto protectionLevel = service.ProtectionLevel();
}
}
Helper function getAddress is used to parse the device ID
string getAddress(DeviceInformation device) {
string id = to_string(device.Id());
string address = "";
for (int i = 37; i < id.length(); i++) {
address += toupper(id[i]);
}
return address;
}

cpp_redis::subscriber -> connect caused exception: connect() failure

When I call "connect" to a Redis publisher, client gets exception "connect() failure" for some of my client/server combinations.
Other clients/servers run smoothly.
I am running Redis version 3.2.100 on windows (this is the newest windows Redis server available).
Using cpp_redis as client.
VisualStudio 2015 is my environment.
cpp_redis::redis_subscriber *subscriber = new cpp_redis::redis_subscriber();
std::string hostIP = 12.0.0.1; // Redis server IP address
int port = 6379;
std::string password = "my_password";
bool isConnected = false;
try
{
subscriber->connect(hostIP, port, nullptr);
if (password != "")
{
subscriber->auth(password,
[this](const cpp_redis::reply& reply)
{
if (!reply.is_error()
{
isConnected = true;
}
}
);
}
else
{
isConnected = true;
}
}
catch (const std::exception& exs)
{
std::cout << exs.what()) << std::endl;
}
works - and for other systems, I get exception on command
-- subscriber->connect(... etc. ?
the exception text is connect() failure
Any insights?
thank you!
mystery solved.
I had a bug in sending the Redis host ip to the clients which could not connect.
this was a really silly bug.

Does the Phoenix framework support Windows authentication?

Our web apps are currently in C# running on Windows and IIS. We rely heavily on the Windows authentication scheme that is included in this environment. With Windows authentication enabled we can detect the identity of the connected user and perform authorization on what screens and operation they are able to use.
If I set up a Phoenix web application will it be possible to detect the identity of the connected user based on their current Windows login? If not is there an easy to use replacement for the Windows authentication?
I just did this over the weekend. Yes, it is possible. You have to use the HttpPlatformHandler add-on for IIS to make it work. HttpPlatformHandler has the forwardWindowsAuthToken configuration setting that you can use to forward the Windows user token for the authenticated user from IIS to your Phoenix application which is running as a child process. You have to use NIFs to process the token and get the Windows username or SID. As you'll note from the docs, you need to call CloseHandle to release the Windows user token for each request.
(I apologize in advance if the code below is not up to best practices. I'm new to Elixir and am actively trying to learn how to write better code. This was also from a hacking session trying to figure out the solution this weekend, so it's also not necessarily polished either.)
To do this, I packaged everything into a custom plug that I could put into the pipeline (I removed Logger statements to compress the size of the example):
defmodule MyApp.WindowsAuthentication do
import Plug.Conn
require Logger
#on_load :load_nifs
def load_nifs do
if match? {:win32, _}, :os.type do
:erlang.load_nif("./priv/windows_authentication", 0)
else
:ok
end
end
def init(options), do: options
def call(conn, _options) do
if match? {:win32, _}, :os.type do
case get_req_header(conn, "x-iis-windowsauthtoken") do
[token_handle_string] ->
# token_handle_string is a hex string
token_handle = String.to_integer(token_handle_string, 16)
case do_get_windows_username(token_handle) do
{:ok, {domain_name, username}} ->
conn = assign(conn, :windows_user, {domain_name, username})
error ->
Logger.error IO.inspect(error)
end
do_close_handle(token_handle)
[] ->
Logger.debug "X-IIS-WindowsAuthToken was not present"
end
end
conn
end
def do_get_windows_username(_token_handle) do
raise "do_get_windows_username/1 is only available on Windows"
end
def do_close_handle(_handle) do
raise "do_close_handle/1 is only available on Windows"
end
end
The C source code for the NIFs is below:
#include <Windows.h>
#include <erl_nif.h>
static const char* error_atom = "error";
static const char* invalid_token_handle_atom = "invalid_token_handle";
static const char* ok_atom = "ok";
static const char* win32_error_atom = "win32_error";
#define MAX_NAME 256
static HANDLE get_user_token(ErlNifEnv *env, ERL_NIF_TERM token) {
HANDLE token_handle;
if (!enif_get_ulong(env, token, (unsigned long *)&token_handle)) {
return NULL;
}
return token_handle;
}
static ERL_NIF_TERM make_win32_error_tuple(ErlNifEnv* env, DWORD error_code) {
return enif_make_tuple2(
env,
enif_make_atom(env, error_atom),
enif_make_ulong(env, error_code)
);
}
static ERL_NIF_TERM make_invalid_token_handle_error(ErlNifEnv* env) {
return enif_make_tuple2(
env,
enif_make_atom(env, error_atom),
enif_make_atom(env, invalid_token_handle_atom)
);
}
static ERL_NIF_TERM do_get_windows_username(ErlNifEnv* env, int argc, ERL_NIF_TERM argv[]) {
HANDLE token_handle;
DWORD token_user_length;
PTOKEN_USER token_user;
DWORD last_error;
WCHAR username[MAX_NAME];
DWORD username_length = MAX_NAME;
WCHAR domain_name[MAX_NAME];
DWORD domain_name_length = MAX_NAME;
size_t converted_chars;
char converted_username[MAX_NAME * 2];
char converted_domain_name[MAX_NAME * 2];
errno_t err;
BOOL succeeded;
SID_NAME_USE sid_name_use;
token_handle = get_user_token(env, argv[0]);
if (!token_handle) {
return make_invalid_token_handle_error(env);
}
if (!GetTokenInformation(token_handle, TokenUser, NULL, 0, &token_user_length)) {
last_error = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER != last_error) {
return make_win32_error_tuple(env, last_error);
}
}
token_user = (PTOKEN_USER)malloc(token_user_length);
if (!GetTokenInformation(token_handle, TokenUser, token_user, token_user_length, &token_user_length)) {
free(token_user);
return make_win32_error_tuple(env, GetLastError());
}
succeeded = LookupAccountSidW(
NULL,
token_user->User.Sid,
username,
&username_length,
domain_name,
&domain_name_length,
&sid_name_use);
if (!succeeded) {
free(token_user);
return make_win32_error_tuple(env, GetLastError());
}
err = wcstombs_s(&converted_chars, converted_username, 512, username, username_length);
err = wcstombs_s(&converted_chars, converted_domain_name, 512, domain_name, domain_name_length);
free(token_user);
return enif_make_tuple2(
env,
enif_make_atom(env, ok_atom),
enif_make_tuple2(
env,
enif_make_string(env, converted_domain_name, ERL_NIF_LATIN1),
enif_make_string(env, converted_username, ERL_NIF_LATIN1)
)
);
}
static ERL_NIF_TERM do_close_handle(ErlNifEnv* env, int argc, ERL_NIF_TERM argv[]) {
HANDLE token_handle;
token_handle = get_user_token(env, argv[0]);
if (!token_handle) {
return make_invalid_token_handle_error(env);
}
if (!CloseHandle(token_handle)) {
return make_win32_error_tuple(env, GetLastError());
}
return enif_make_atom(env, ok_atom);
}
static ErlNifFunc nif_functions[] = {
{ "do_close_handle", 1, do_close_handle },
{ "do_get_windows_username", 1, do_get_windows_username }
};
ERL_NIF_INIT(
Elixir.MyApp.WindowsAuthentication,
nif_functions,
NULL,
NULL,
NULL,
NULL
)
You can compile the C code using the 64-bit Visual Studio C++ tools (open the x64 VS command prompt). I tried this out with the new VS2017 tools. Put the DLL in the priv directory of your application.
cl /LD /I "C:\Program Files\erl-8.2\erts-8.2\include" /DDEBUG windows_authentication.c advapi32.lib
To run the plug, add it to your pipeline in web/router.ex:
pipeline :browser do
plug :accepts, ["html"]
plug MyApp.WindowsAuthentication
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
The end result of this is that conn.assigns.windows_user will contain a tuple of the form {domain_name, username} that has the Windows domain username for the authenticated user.
Note: When I was trying this, I found CPU and memory leak issues from erl.exe when running as a child process of IIS. I'm still trying to figure that out in case you see it. I posted a question about it here.
I'll probably release this as a library on hex.pm when I've cleaned it up and fixed the memory/CPU issue, but for now, here's the code that will let you use Windows authentication with Phoenix.

Print labels via a redirected printer

My task is to print labels via a thermal printer. To this purpose a string of tspl(programming language that the printer understands) commands is generated and sent to the printer. The latter is done in C# with the following method taken from the microsoft example "How to send raw data to a printer by using Visual C# .NET"
public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed.
di.pDocName = "My C#.NET RAW Document";
di.pDataType = "RAW";
// Open the printer.
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
// Start a document.
if (StartDocPrinter(hPrinter, 1, di))
{
// Start a page.
if (StartPagePrinter(hPrinter))
{
// Write your bytes.
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
// If you did not succeed, GetLastError may give more information
// about why not.
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
MessageBox.Show("Error " + dwError);
}
return bSuccess;
}
The actual printer is selected in a PrintDialog
private void button2_Click(object sender, EventArgs e)
{
string s = "CLS\nPRINT 1\n"; // device-dependent string, need a FormFeed?
// Allow the user to select a printer.
PrintDialog pd = new PrintDialog();
pd.PrinterSettings = new PrinterSettings();
if (DialogResult.OK == pd.ShowDialog(this))
{
// Send a printer-specific to the printer.
RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, s);
}
}
In my working environment everything works fine. The environment is a LAN consisting of 3 computers and 1 shared thermal printer:
PC_with_printer - it runs on Windows 7 and has the printer connected to it via USB
PC_aware - it runs on Win 8 and knows about the shared printer
PC_unaware - it runs on WinXP and doens't have the shared printer installed
From PC_aware I connect to PC_unaware via rdp and the printer appears in the list of printers as redirected. Then I run my application , choose the redirected printer and get my empty label printed. So far so good.
Problems begin when I replace PC_unaware with another computer. It runs on Windows Server 2008 R2 and is not in our LAN. Let's call it SERVER. So I carry out the same experiment:
From PC_aware I connect to SERVER via rdp using its public ip address
My thermal printer appears in "Printers and Devices" as "TSC_TDP-244 (redirected 20)"
I go to the printer's properties and click Print Test Page, and it gets printed
I run my app and the printer doesn't print anything.
I have checked return values of all winapi functions that are used in SendBytesToPrinter method (OpenPrinter,StartDocPrinter, StartPagePrinter, WritePrinter,EndPagePrinter,EndDocPrinter, ClosePrinter), and none of them indicates an error. Any idea why it happens and how it may be fixed?
PRINTER_DEFAULTS pd;
pd.DesiredAccess = PRINTER_ACCESS_USE;
pd.pDatatype = NULL;
pd.pDevMode = NULL;
if (!OpenPrinter(szPrinterName, &hPrinter, &pd))
return false;

Serial COM Port Selection by DropDownList in processing

I wrote a program in Processing 2.1.2 to establish a communication via serial Port between two machines. On my laptop, it was working fine but on my desktop where more than one serial ports are available, it is not detecting my functional serial COM port.
So now I want them to appear on Combo Button and I will able to select one from them.
Can you guide me on how do I resolve this issue?
import processing.serial.*;
String input;
Serial port;
void setup() {
size(448, 299,P3D);
println(Serial.list());
port = new Serial(this,Serial.list()[0], 9600);
port.bufferUntil('\n');
}
void draw() {
background(0);
}
void serialEvent(Serial port)
{
input = port.readString();
if(input != null) {
String[] values = split(input, " ");
println(values[0]);
println(values[1]);
println(values[2]);
}
}
As mentioned in the comment, it is possible to use a UI library to display a dropdown. First you have to choose a library, like for example controlP5 which is very popular with Processing. You may choose to use Swing with a native look & feel or G4P. That's totally up to you.
After that it should be a matter of plugging the serial ports list into the dropdown and opening the serial connection on the dropdown listener/callback.
Bellow is a proof of concept sketch based on the controlP5dropdownlist example that comes with the library:
import processing.serial.*;
import controlP5.*;
ControlP5 cp5;
DropdownList serialPortsList;
Serial serialPort;
final int BAUD_RATE = 9600;
void setup() {
size(700, 400,P3D);
String[] portNames = Serial.list();
cp5 = new ControlP5(this);
// create a DropdownList
serialPortsList = cp5.addDropdownList("serial ports").setPosition(10, 10).setWidth(200);
for(int i = 0 ; i < portNames.length; i++) serialPortsList.addItem(portNames[i], i);
}
void controlEvent(ControlEvent theEvent) {
// DropdownList is of type ControlGroup.
// A controlEvent will be triggered from inside the ControlGroup class.
// therefore you need to check the originator of the Event with
// if (theEvent.isGroup())
// to avoid an error message thrown by controlP5.
if (theEvent.isGroup()) {
// check if the Event was triggered from a ControlGroup
println("event from group : "+theEvent.getGroup().getValue()+" from "+theEvent.getGroup());
//check if there's a serial port open already, if so, close it
if(serialPort != null){
serialPort.stop();
serialPort = null;
}
//open the selected core
String portName = serialPortsList.getItem((int)theEvent.getValue()).getName();
try{
serialPort = new Serial(this,portName,BAUD_RATE);
}catch(Exception e){
System.err.println("Error opening serial port " + portName);
e.printStackTrace();
}
}
else if (theEvent.isController()) {
println("event from controller : "+theEvent.getController().getValue()+" from "+theEvent.getController());
}
}
void draw() {
background(128);
}
Also notice any existing connection will be closed when choosing a new serial port and errors handling opening the serial port are handled so the program doesn't crash in case there are issues.
For example, on OSX you get bluetooth serial ports, which may or may not be available or of use:
for processing 3.3.7 doesn't work at all for one string
String portName = serialPortsList.getItem((int)theEvent.getValue()).getName();
So i spent a lot of my neurons and nervs, but my fix is getName change toString();
and
String portName = serialPortsList.getItem((int)theEvent.getValue()).toString();
I don't understand why getName() gives me "The function doesnt exist" but toString works properly. Anybody can explain?
For variable:
String[] portNames = Serial.list();
change to global variable:
String[] portNames;
In:
void setup()
change:
String[] portNames = Serial.list();
to:
portNames = Serial.list();
In code:
String portName = serialPortsList.getItem((int)theEvent.getValue()).toString();
change to:
String portName =portNames.toString();

Resources