From b6f1e2ab35bb7258dcd6a801cec65130ea36937d Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 4 Oct 2021 12:33:52 -0400 Subject: [PATCH 01/17] Fix missing python3-pip dependency --- background_installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/background_installer.sh b/background_installer.sh index 4b2bb7f..a54111c 100755 --- a/background_installer.sh +++ b/background_installer.sh @@ -24,7 +24,7 @@ function linux_install_deps { $1 apt-get update $1 apt-get install -y build-essential pkg-config bison flex autoconf \ automake libtool make git python2.7 \ - sqlite3 cmake git curl python3 + sqlite3 cmake git curl python3 python3-pip curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py $1 python2.7 get-pip.py } From c2e5ec464a3e38a1a7952941b718dc6ab63ad351 Mon Sep 17 00:00:00 2001 From: Lorne Giles Date: Fri, 15 Oct 2021 19:06:23 +0100 Subject: [PATCH 02/17] Provided bounds checking on ParseIecVars to prevent vulnerability --- utils/glue_generator_src/glue_generator.cpp | 31 +++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/utils/glue_generator_src/glue_generator.cpp b/utils/glue_generator_src/glue_generator.cpp index 1648644..5812dc6 100755 --- a/utils/glue_generator_src/glue_generator.cpp +++ b/utils/glue_generator_src/glue_generator.cpp @@ -4,6 +4,9 @@ #include #include +#define MAX_LINE_INPUT 1024 +#define MAX_LOCAL_BUFFER 100 + using namespace std; /// Write the header to the output stream. The header is common among all glueVars files. @@ -79,28 +82,34 @@ void glueVars()\r\n\ int parseIecVars(istream& locatedVars, char *varName, char *varType) { string line; - char buffer[1024]; + char buffer[MAX_LINE_INPUT]; if (getline(locatedVars, line)) { int i = 0, j = 0; - strncpy(buffer, line.c_str(), 1024); - for (i = 0; buffer[i] != '('; i++); + strncpy(buffer, line.c_str(), MAX_LINE_INPUT); + for (i = 0; i < MAX_LINE_INPUT && buffer[i] != '('; i++); i++; - while (buffer[i] != ',') + while (i < MAX_LINE_INPUT && buffer[i] != ',') { - varType[j] = buffer[i]; - i++; j++; - varType[j] = '\0'; + if(j < MAX_LOCAL_BUFFER) + { + varType[j] = buffer[i]; + i++; j++; + varType[j] = '\0'; + } } i++; j=0; - while (buffer[i] != ',') + while (i < MAX_LINE_INPUT && buffer[i] != ',') { - varName[j] = buffer[i]; - i++; j++; - varName[j] = '\0'; + if(j < MAX_LOCAL_BUFFER) + { + varName[j] = buffer[i]; + i++; j++; + varName[j] = '\0'; + } } return 1; From 41d30b327a462d7039492d875fdf6410adcf15c7 Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Sun, 17 Oct 2021 20:04:36 +0200 Subject: [PATCH 03/17] Fixes connection status issues --- webserver/core/modbus_master.cpp | 86 +++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/webserver/core/modbus_master.cpp b/webserver/core/modbus_master.cpp index 497673d..9145c32 100755 --- a/webserver/core/modbus_master.cpp +++ b/webserver/core/modbus_master.cpp @@ -60,7 +60,7 @@ struct MB_address struct MB_device { - modbus_t *mb_ctx; + modbus_t *mb_ctx; char dev_name[100]; uint8_t protocol; char dev_address[100]; @@ -70,7 +70,7 @@ struct MB_device int rtu_data_bit; int rtu_stop_bit; uint8_t dev_id; - bool isConnected; + bool isConnected; struct MB_address discrete_inputs; struct MB_address coils; @@ -166,7 +166,8 @@ void parseConfig() char temp_buffer[5]; getData(line_str, temp_buffer, '"', '"'); num_devices = atoi(temp_buffer); - mb_devices = (struct MB_device *)malloc(num_devices*sizeof(struct MB_device)); + //initializes the allocated memory to zero + mb_devices = calloc(num_devices, sizeof(struct MB_device)); } else if (!strncmp(line_str, "Polling_Period", 14)) { @@ -355,30 +356,31 @@ void *querySlaveDevices(void *arg) for (int i = 0; i < num_devices; i++) { - //Check if there is a device using the same port - bool found_sharing = false; - for (int a = 0; a < num_devices; a++) - { - if (a != i && !strcmp(mb_devices[i].dev_address, mb_devices[a].dev_address)) - { - found_sharing = true; - if (mb_devices[i].isConnected == false && mb_devices[a].isConnected == true) - { - mb_devices[i].mb_ctx = mb_devices[a].mb_ctx; - sprintf(log_msg, "Connected to MB device %s\n", mb_devices[i].dev_name); - log(log_msg); - mb_devices[i].isConnected = true; - } - } - } - if (found_sharing) - { - //Must reset mb context to current device's slave id - modbus_set_slave(mb_devices[i].mb_ctx, mb_devices[i].dev_id); - } + //Check if there is a connected RTU device using the same port + bool found_sharing = false; + bool rtu_connected = false; + if (mb_devices[i].protocol == MB_RTU) + { + for (int a = 0; a < num_devices; a++) + { + if (a != i && !strcmp(mb_devices[i].dev_address, mb_devices[a].dev_address)) + { + found_sharing = true; + if (mb_devices[a].isConnected) + { + rtu_port_connected = true; + } + } + } + if (found_sharing) + { + //Must reset mb context to current device's slave id + modbus_set_slave(mb_devices[i].mb_ctx, mb_devices[i].dev_id); + } + } //Verify if device is connected - if (!mb_devices[i].isConnected) + if (!mb_devices[i].isConnected && !rtu_port_connected) { sprintf(log_msg, "Device %s is disconnected. Attempting to reconnect...\n", mb_devices[i].dev_name); log(log_msg); @@ -404,7 +406,7 @@ void *querySlaveDevices(void *arg) mb_devices[i].isConnected = true; } } - if (mb_devices[i].isConnected) + if (mb_devices[i].isConnected || rtu_port_connected) { struct timespec ts; @@ -602,10 +604,34 @@ void initializeMB() } else if (mb_devices[i].protocol == MB_RTU) { - mb_devices[i].mb_ctx = modbus_new_rtu( mb_devices[i].dev_address, mb_devices[i].rtu_baud, - mb_devices[i].rtu_parity, mb_devices[i].rtu_data_bit, - mb_devices[i].rtu_stop_bit); - + //Check if there is a device using the same port + int share_index = -1; + for (int a = 0; a < num_devices && a < i; a++) + { + if (strcmp(mb_devices[i].dev_address, mb_devices[a].dev_address) == 0) + { + share_index = a; + break; + } + + } + if (share_index != -1) + { + if (mb_devices[i].rtu_baud != mb_devices[share_index].rtu_baud || mb_devices[i].rtu_parity != mb_devices[share_index].rtu_parity || + mb_devices[i].rtu_data_bit != mb_devices[share_index].rtu_data_bit || mb_devices[i].rtu_stop_bit != mb_devices[share_index].rtu_stop_bit) + { + unsigned char log_msg[1000]; + sprintf(log_msg, "Warning MB device %s port setting missmatch\n", mb_devices[i].dev_name); + log(log_msg); + } + mb_devices[i].mb_ctx = mb_devices[share_index].mb_ctx; + } + else + { + mb_devices[i].mb_ctx = modbus_new_rtu(mb_devices[i].dev_address, mb_devices[i].rtu_baud, + mb_devices[i].rtu_parity, mb_devices[i].rtu_data_bit, + mb_devices[i].rtu_stop_bit); + } } //slave id From b829e615dd98ef77d0c05708f927c2e3a9a171f5 Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Sun, 17 Oct 2021 20:26:55 +0200 Subject: [PATCH 04/17] Fixes connection status issues --- webserver/core/modbus_master.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webserver/core/modbus_master.cpp b/webserver/core/modbus_master.cpp index 9145c32..7350604 100755 --- a/webserver/core/modbus_master.cpp +++ b/webserver/core/modbus_master.cpp @@ -358,7 +358,7 @@ void *querySlaveDevices(void *arg) { //Check if there is a connected RTU device using the same port bool found_sharing = false; - bool rtu_connected = false; + bool rtu_port_connected = false; if (mb_devices[i].protocol == MB_RTU) { for (int a = 0; a < num_devices; a++) From 34f2a2dafe29e483018f3ef813a981e15df5dbf8 Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Sun, 17 Oct 2021 22:58:29 +0200 Subject: [PATCH 05/17] Added Transmission pause for RTU devices --- webserver/core/modbus_master.cpp | 13 +++++- webserver/openplc.db | Bin 40960 -> 53248 bytes webserver/pages.py | 25 +++++++++++- webserver/webserver.py | 66 ++++++------------------------- 4 files changed, 46 insertions(+), 58 deletions(-) diff --git a/webserver/core/modbus_master.cpp b/webserver/core/modbus_master.cpp index 7350604..1f5190d 100755 --- a/webserver/core/modbus_master.cpp +++ b/webserver/core/modbus_master.cpp @@ -69,6 +69,7 @@ struct MB_device char rtu_parity; int rtu_data_bit; int rtu_stop_bit; + int rtu_tx_pause; uint8_t dev_id; bool isConnected; @@ -241,6 +242,12 @@ void parseConfig() char temp_buffer[20]; getData(line_str, temp_buffer, '"', '"'); mb_devices[deviceNumber].rtu_stop_bit = atoi(temp_buffer); + } + else if (!strncmp(functionType, "RTU_TX_Pause", 12)) + { + char temp_buffer[10]; + getData(line_str, temp_buffer, '"', '"'); + mb_devices[deviceNumber].rtu_tx_pause = atoi(temp_buffer); } else if (!strncmp(functionType, "Discrete_Inputs_Start", 21)) { @@ -416,6 +423,7 @@ void *querySlaveDevices(void *arg) //Read discrete inputs if (mb_devices[i].discrete_inputs.num_regs != 0) { + sleepms(mb_devices[i].rtu_tx_pause); uint8_t *tempBuff; tempBuff = (uint8_t *)malloc(mb_devices[i].discrete_inputs.num_regs); nanosleep(&ts, NULL); @@ -451,6 +459,7 @@ void *querySlaveDevices(void *arg) //Write coils if (mb_devices[i].coils.num_regs != 0) { + sleepms(mb_devices[i].rtu_tx_pause); uint8_t *tempBuff; tempBuff = (uint8_t *)malloc(mb_devices[i].coils.num_regs); @@ -483,7 +492,7 @@ void *querySlaveDevices(void *arg) //Read input registers if (mb_devices[i].input_registers.num_regs != 0) { - + sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].input_registers.num_regs); nanosleep(&ts, NULL); @@ -519,6 +528,7 @@ void *querySlaveDevices(void *arg) //Read holding registers if (mb_devices[i].holding_read_registers.num_regs != 0) { + sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_read_registers.num_regs); nanosleep(&ts, NULL); @@ -553,6 +563,7 @@ void *querySlaveDevices(void *arg) //Write holding registers if (mb_devices[i].holding_registers.num_regs != 0) { + sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_registers.num_regs); diff --git a/webserver/openplc.db b/webserver/openplc.db index 994dd85fce41ee7f4e184f34cb0247e3b088dc7c..53fad1ee1b73e92f8e09bb5c848192dd6b2d0896 100644 GIT binary patch delta 1378 zcmZoTz|^pSd4jayPX-1CUMOY;(!vvUj8%U!==s<3@*6R5a&BYbd%(xUf0b94XC?m} z&X=6q_%k^TKyYK@71lJ)ZA>@B_4OIMB1;mJa#D*6bCTjqQgaL9!Q6O53;_=3AXmo_ zSA`HqCm&Y@B@B5b1r07vrIggN_{Rqi;$#&HUPOWNq(h_ zqWGfJ#1teIdnrY}!KgC)e;uXk)}~yb*>F7f`)3M7=tOB$fokX(%|kf=6v~ zCqFk=tE~XLxV$`Lm*?broT~Cl!QglYCZ5q$gcP|0nu^THOhubl@^mqAo@Fo>7Z+!2 zDxJ*3Co9Cp%LXi=7#P?DAhe+nFeMmnp2MFdz;%;>|11A<{+s-VHw!9k<5yJSz(`Cy z?9B2U@FcSNxxS*qZ8kYlT7bg&NY!;aCfuE6g^1}Hd*j0OQ RG6B``05Lbv`kg@I%mL-5pBVrE delta 802 zcmZXSL1@!Z7{}jhoaUuTz6{oNAhR88;-K4ThvGqWB1Hyki`qJGNos;d>k^Z+GA|ZE zhC3~0#~r-x9FHDk2l1k(3Ok6Xmw6IFW#Gy8vUQ7^@E-a8-!I?yf63Q<&UIg<){YPE zB7_9G`j;3KW^=n}dgP4+B}7OM$)DsDyqBiLP1qnk(8W$Prd%h&lbmoYo6F%W1N(9)+17R*!15ZI<>;G%+mI^L1*5d83DYBQdAml@>k10%gKo4prxbcL@z`o&wuPRIy#qcf^qfK!&Mb^R6n-1QFW7Y(Y`(g2sk2R|O7otd#Y8Q#G<)L}?|Er;?`IxIE$2&|wNK`@19gP??~K~TYSL2!X> z=gyxY!)PMIXSfU|lEmZq=6QV4HQLsaov)a;bha+lDyQ)ls@h8?KcXmNJhG)An10sf vW%vz0;TwE~FYqDux&>zkIE*QDGzS0KS&opsY&`!8LbSqX=s_=1*1p3Z#2)7w diff --git a/webserver/pages.py b/webserver/pages.py index 9853518..285c716 100644 --- a/webserver/pages.py +++ b/webserver/pages.py @@ -1487,9 +1487,11 @@ add_slave_devices_tail = """ + + -
+

Discrete Inputs (%IX100.0)

@@ -1564,6 +1566,7 @@ add_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); + var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); @@ -1666,6 +1669,8 @@ add_devices_script = """ devparity.value = "None" turnElementOn(devdata) turnElementOn(devstop) + turnElementOn(devpause) + devpause.value = "0" turnElementOn(distart) turnElementOn(disize) turnElementOn(dostart) @@ -1692,6 +1697,8 @@ add_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -1728,6 +1735,8 @@ add_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -1768,6 +1777,7 @@ add_devices_script = """ var devbaud = document.forms["uploadForm"]["dev_baud"].value; var devdata = document.forms["uploadForm"]["dev_data"].value; var devstop = document.forms["uploadForm"]["dev_stop"].value; + var devpause = document.forms["uploadForm"]["dev_pause"].value; var distart = document.forms["uploadForm"]["di_start"].value; var disize = document.forms["uploadForm"]["di_size"].value; @@ -1826,9 +1836,11 @@ edit_slave_devices_tail = """ + +
-
+

Discrete Inputs (%IX100.0)

@@ -1898,6 +1910,7 @@ edit_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); + var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); @@ -2000,6 +2013,8 @@ edit_devices_script = """ devparity.value = "None" turnElementOn(devdata) turnElementOn(devstop) + turnElementOn(devpause) + devpause.value = "0" turnElementOn(distart) turnElementOn(disize) turnElementOn(dostart) @@ -2026,6 +2041,8 @@ edit_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -2062,6 +2079,8 @@ edit_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -2102,6 +2121,7 @@ edit_devices_script = """ var devbaud = document.forms["uploadForm"]["dev_baud"].value; var devdata = document.forms["uploadForm"]["dev_data"].value; var devstop = document.forms["uploadForm"]["dev_stop"].value; + var devpause = document.forms["uploadForm"]["dev_pause"].value; var distart = document.forms["uploadForm"]["di_start"].value; var disize = document.forms["uploadForm"]["di_size"].value; @@ -2153,6 +2173,7 @@ edit_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); + var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); diff --git a/webserver/webserver.py b/webserver/webserver.py index 27f6a00..c0f978f 100644 --- a/webserver/webserver.py +++ b/webserver/webserver.py @@ -139,7 +139,8 @@ def generate_mbconfig(): mbconfig += 'device' + str(device_counter) + '.RTU_Baud_Rate = "' + str(row[5]) + '"\n' mbconfig += 'device' + str(device_counter) + '.RTU_Parity = "' + str(row[6]) + '"\n' mbconfig += 'device' + str(device_counter) + '.RTU_Data_Bits = "' + str(row[7]) + '"\n' - mbconfig += 'device' + str(device_counter) + '.RTU_Stop_Bits = "' + str(row[8]) + '"\n\n' + mbconfig += 'device' + str(device_counter) + '.RTU_Stop_Bits = "' + str(row[8]) + '"\n' + mbconfig += 'device' + str(device_counter) + '.RTU_TX_Pause = "' + str(row[21]) + '"\n\n' mbconfig += 'device' + str(device_counter) + '.Discrete_Inputs_Start = "' + str(row[11]) + '"\n' mbconfig += 'device' + str(device_counter) + '.Discrete_Inputs_Size = "' + str(row[12]) + '"\n' @@ -891,8 +892,6 @@ def upload_program_action(): prog_descr = flask.request.form['prog_descr'] prog_file = flask.request.form['prog_file'] epoch_time = flask.request.form['epoch_time'] - - (prog_name, prog_descr, prog_file, epoch_time) = sanitize_input(prog_name, prog_descr, prog_file, epoch_time) database = "openplc.db" conn = create_connection(database) @@ -1093,7 +1092,7 @@ def add_modbus_device():

Add new device


-
+

Edit slave device


-
+
" + port_name + "" - else: + else: return_str += "" return_str += pages.edit_slave_devices_tail @@ -1296,7 +1293,8 @@ def modbus_edit_device(): return_str += 'aorstart.value = "' + str(row[17]) + '";' return_str += 'aorsize.value = "' + str(row[18]) + '";' return_str += 'aowstart.value = "' + str(row[19]) + '";' - return_str += 'aowsize.value = "' + str(row[20]) + '";}' + return_str += 'aowsize.value = "' + str(row[20]) + '";' + return_str += 'devpause.value = "' + str(row[21]) + '";}' except Error as e: print("error connecting to the database" + str(e)) @@ -1318,6 +1316,7 @@ def modbus_edit_device(): devparity = flask.request.form.get('device_parity') devdata = flask.request.form.get('device_data') devstop = flask.request.form.get('device_stop') + devpause = flask.request.form.get('device_pause') di_start = flask.request.form.get('di_start') di_size = flask.request.form.get('di_size') @@ -1330,15 +1329,12 @@ def modbus_edit_device(): aow_start = flask.request.form.get('aow_start') aow_size = flask.request.form.get('aow_size') - (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devid_db) \ - = sanitize_input(devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devid_db) - database = "openplc.db" conn = create_connection(database) if (conn != None): try: cur = conn.cursor() - cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, int(devid_db))) + cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ?, pause = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devpause, int(devid_db))) conn.commit() cur.close() conn.close() @@ -1853,9 +1849,6 @@ def add_user(): username = flask.request.form['user_name'] email = flask.request.form['user_email'] password = flask.request.form['user_password'] - - (name, username, email) = sanitize_input(name, username, email) - form_has_picture = True if ('file' not in flask.request.files): form_has_picture = False @@ -1984,7 +1977,6 @@ def edit_user(): username = flask.request.form['user_name'] email = flask.request.form['user_email'] password = flask.request.form['user_password'] - (user_id, name, username, email) = sanitize_input(user_id, name, username, email) form_has_picture = True if ('file' not in flask.request.files): form_has_picture = False @@ -2233,8 +2225,6 @@ def settings(): slave_polling = flask.request.form.get('slave_polling_period') slave_timeout = flask.request.form.get('slave_timeout') - (modbus_port, dnp3_port, enip_port, pstorage_poll, start_run, slave_polling, slave_timeout) = sanitize_input(modbus_port, dnp3_port, enip_port, pstorage_poll, start_run, slave_polling, slave_timeout) - database = "openplc.db" conn = create_connection(database) if (conn != None): @@ -2321,40 +2311,6 @@ def create_connection(db_file): return None - -#---------------------------------------------------------------------------- -#Returns a generator that yields the sanitized arguments. -#---------------------------------------------------------------------------- -def sanitize_input(*args): - return (escape(a) for a in args) - -#---------------------------------------------------------------------------- -# Taken from the html module of the python 3.9 standard library -# exact lines of code can be found here: -# https://github.com/python/cpython/blob/3.9/Lib/html/__init__.py#L12 -# Modified to convert to String but preserve NoneType. -# Preserving NoneType is necessary to ensure program logic is not affected by None being converted to "None", -# this is relevant in setttings() -#---------------------------------------------------------------------------- -def escape(s, quote=True): - """ - Replace special characters "&", "<" and ">" to HTML-safe sequences. - If the optional flag quote is true (the default), the quotation mark - characters, both double quote (") and single quote (') characters are also - translated. - """ - if s is None: - return s - s = str(s) # force string - s = s.replace("&", "&") # Must be done first! - s = s.replace("<", "<") - s = s.replace(">", ">") - if quote: - s = s.replace('"', """) - s = s.replace('\'', "'") - return s - - #---------------------------------------------------------------------------- #Main dummy function. Only displays a message and exits. The app keeps #running on the background by Flask From f932c157cd37b5c70f0a4b15265ed1b7c1260a8f Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Sun, 17 Oct 2021 23:13:39 +0200 Subject: [PATCH 06/17] Revert "Added Transmission pause for RTU devices" This reverts commit 34f2a2dafe29e483018f3ef813a981e15df5dbf8. --- webserver/core/modbus_master.cpp | 13 +----- webserver/openplc.db | Bin 53248 -> 40960 bytes webserver/pages.py | 25 +----------- webserver/webserver.py | 66 +++++++++++++++++++++++++------ 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/webserver/core/modbus_master.cpp b/webserver/core/modbus_master.cpp index 1f5190d..7350604 100755 --- a/webserver/core/modbus_master.cpp +++ b/webserver/core/modbus_master.cpp @@ -69,7 +69,6 @@ struct MB_device char rtu_parity; int rtu_data_bit; int rtu_stop_bit; - int rtu_tx_pause; uint8_t dev_id; bool isConnected; @@ -242,12 +241,6 @@ void parseConfig() char temp_buffer[20]; getData(line_str, temp_buffer, '"', '"'); mb_devices[deviceNumber].rtu_stop_bit = atoi(temp_buffer); - } - else if (!strncmp(functionType, "RTU_TX_Pause", 12)) - { - char temp_buffer[10]; - getData(line_str, temp_buffer, '"', '"'); - mb_devices[deviceNumber].rtu_tx_pause = atoi(temp_buffer); } else if (!strncmp(functionType, "Discrete_Inputs_Start", 21)) { @@ -423,7 +416,6 @@ void *querySlaveDevices(void *arg) //Read discrete inputs if (mb_devices[i].discrete_inputs.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); uint8_t *tempBuff; tempBuff = (uint8_t *)malloc(mb_devices[i].discrete_inputs.num_regs); nanosleep(&ts, NULL); @@ -459,7 +451,6 @@ void *querySlaveDevices(void *arg) //Write coils if (mb_devices[i].coils.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); uint8_t *tempBuff; tempBuff = (uint8_t *)malloc(mb_devices[i].coils.num_regs); @@ -492,7 +483,7 @@ void *querySlaveDevices(void *arg) //Read input registers if (mb_devices[i].input_registers.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); + uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].input_registers.num_regs); nanosleep(&ts, NULL); @@ -528,7 +519,6 @@ void *querySlaveDevices(void *arg) //Read holding registers if (mb_devices[i].holding_read_registers.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_read_registers.num_regs); nanosleep(&ts, NULL); @@ -563,7 +553,6 @@ void *querySlaveDevices(void *arg) //Write holding registers if (mb_devices[i].holding_registers.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_registers.num_regs); diff --git a/webserver/openplc.db b/webserver/openplc.db index 53fad1ee1b73e92f8e09bb5c848192dd6b2d0896..994dd85fce41ee7f4e184f34cb0247e3b088dc7c 100644 GIT binary patch delta 802 zcmZXSL1@!Z7{}jhoaUuTz6{oNAhR88;-K4ThvGqWB1Hyki`qJGNos;d>k^Z+GA|ZE zhC3~0#~r-x9FHDk2l1k(3Ok6Xmw6IFW#Gy8vUQ7^@E-a8-!I?yf63Q<&UIg<){YPE zB7_9G`j;3KW^=n}dgP4+B}7OM$)DsDyqBiLP1qnk(8W$Prd%h&lbmoYo6F%W1N(9)+17R*!15ZI<>;G%+mI^L1*5d83DYBQdAml@>k10%gKo4prxbcL@z`o&wuPRIy#qcf^qfK!&Mb^R6n-1QFW7Y(Y`(g2sk2R|O7otd#Y8Q#G<)L}?|Er;?`IxIE$2&|wNK`@19gP??~K~TYSL2!X> z=gyxY!)PMIXSfU|lEmZq=6QV4HQLsaov)a;bha+lDyQ)ls@h8?KcXmNJhG)An10sf vW%vz0;TwE~FYqDux&>zkIE*QDGzS0KS&opsY&`!8LbSqX=s_=1*1p3Z#2)7w delta 1378 zcmZoTz|^pSd4jayPX-1CUMOY;(!vvUj8%U!==s<3@*6R5a&BYbd%(xUf0b94XC?m} z&X=6q_%k^TKyYK@71lJ)ZA>@B_4OIMB1;mJa#D*6bCTjqQgaL9!Q6O53;_=3AXmo_ zSA`HqCm&Y@B@B5b1r07vrIggN_{Rqi;$#&HUPOWNq(h_ zqWGfJ#1teIdnrY}!KgC)e;uXk)}~yb*>F7f`)3M7=tOB$fokX(%|kf=6v~ zCqFk=tE~XLxV$`Lm*?broT~Cl!QglYCZ5q$gcP|0nu^THOhubl@^mqAo@Fo>7Z+!2 zDxJ*3Co9Cp%LXi=7#P?DAhe+nFeMmnp2MFdz;%;>|11A<{+s-VHw!9k<5yJSz(`Cy z?9B2U@FcSNxxS*qZ8kYlT7bg&NY!;aCfuE6g^1}Hd*j0OQ RG6B``05Lbv`kg@I%mL-5pBVrE diff --git a/webserver/pages.py b/webserver/pages.py index 285c716..9853518 100644 --- a/webserver/pages.py +++ b/webserver/pages.py @@ -1487,11 +1487,9 @@ add_slave_devices_tail = """ - -
-
+

Discrete Inputs (%IX100.0)

@@ -1566,7 +1564,6 @@ add_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); - var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); @@ -1669,8 +1666,6 @@ add_devices_script = """ devparity.value = "None" turnElementOn(devdata) turnElementOn(devstop) - turnElementOn(devpause) - devpause.value = "0" turnElementOn(distart) turnElementOn(disize) turnElementOn(dostart) @@ -1697,8 +1692,6 @@ add_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" - turnElementOff(devpause) - devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -1735,8 +1728,6 @@ add_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" - turnElementOff(devpause) - devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -1777,7 +1768,6 @@ add_devices_script = """ var devbaud = document.forms["uploadForm"]["dev_baud"].value; var devdata = document.forms["uploadForm"]["dev_data"].value; var devstop = document.forms["uploadForm"]["dev_stop"].value; - var devpause = document.forms["uploadForm"]["dev_pause"].value; var distart = document.forms["uploadForm"]["di_start"].value; var disize = document.forms["uploadForm"]["di_size"].value; @@ -1836,11 +1826,9 @@ edit_slave_devices_tail = """ - -
-
+

Discrete Inputs (%IX100.0)

@@ -1910,7 +1898,6 @@ edit_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); - var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); @@ -2013,8 +2000,6 @@ edit_devices_script = """ devparity.value = "None" turnElementOn(devdata) turnElementOn(devstop) - turnElementOn(devpause) - devpause.value = "0" turnElementOn(distart) turnElementOn(disize) turnElementOn(dostart) @@ -2041,8 +2026,6 @@ edit_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" - turnElementOff(devpause) - devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -2079,8 +2062,6 @@ edit_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" - turnElementOff(devpause) - devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -2121,7 +2102,6 @@ edit_devices_script = """ var devbaud = document.forms["uploadForm"]["dev_baud"].value; var devdata = document.forms["uploadForm"]["dev_data"].value; var devstop = document.forms["uploadForm"]["dev_stop"].value; - var devpause = document.forms["uploadForm"]["dev_pause"].value; var distart = document.forms["uploadForm"]["di_start"].value; var disize = document.forms["uploadForm"]["di_size"].value; @@ -2173,7 +2153,6 @@ edit_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); - var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); diff --git a/webserver/webserver.py b/webserver/webserver.py index c0f978f..27f6a00 100644 --- a/webserver/webserver.py +++ b/webserver/webserver.py @@ -139,8 +139,7 @@ def generate_mbconfig(): mbconfig += 'device' + str(device_counter) + '.RTU_Baud_Rate = "' + str(row[5]) + '"\n' mbconfig += 'device' + str(device_counter) + '.RTU_Parity = "' + str(row[6]) + '"\n' mbconfig += 'device' + str(device_counter) + '.RTU_Data_Bits = "' + str(row[7]) + '"\n' - mbconfig += 'device' + str(device_counter) + '.RTU_Stop_Bits = "' + str(row[8]) + '"\n' - mbconfig += 'device' + str(device_counter) + '.RTU_TX_Pause = "' + str(row[21]) + '"\n\n' + mbconfig += 'device' + str(device_counter) + '.RTU_Stop_Bits = "' + str(row[8]) + '"\n\n' mbconfig += 'device' + str(device_counter) + '.Discrete_Inputs_Start = "' + str(row[11]) + '"\n' mbconfig += 'device' + str(device_counter) + '.Discrete_Inputs_Size = "' + str(row[12]) + '"\n' @@ -892,6 +891,8 @@ def upload_program_action(): prog_descr = flask.request.form['prog_descr'] prog_file = flask.request.form['prog_file'] epoch_time = flask.request.form['epoch_time'] + + (prog_name, prog_descr, prog_file, epoch_time) = sanitize_input(prog_name, prog_descr, prog_file, epoch_time) database = "openplc.db" conn = create_connection(database) @@ -1092,7 +1093,7 @@ def add_modbus_device():

Add new device


-
+

Edit slave device


-
+
" + port_name + "" - else: + else: return_str += "" return_str += pages.edit_slave_devices_tail @@ -1293,8 +1296,7 @@ def modbus_edit_device(): return_str += 'aorstart.value = "' + str(row[17]) + '";' return_str += 'aorsize.value = "' + str(row[18]) + '";' return_str += 'aowstart.value = "' + str(row[19]) + '";' - return_str += 'aowsize.value = "' + str(row[20]) + '";' - return_str += 'devpause.value = "' + str(row[21]) + '";}' + return_str += 'aowsize.value = "' + str(row[20]) + '";}' except Error as e: print("error connecting to the database" + str(e)) @@ -1316,7 +1318,6 @@ def modbus_edit_device(): devparity = flask.request.form.get('device_parity') devdata = flask.request.form.get('device_data') devstop = flask.request.form.get('device_stop') - devpause = flask.request.form.get('device_pause') di_start = flask.request.form.get('di_start') di_size = flask.request.form.get('di_size') @@ -1329,12 +1330,15 @@ def modbus_edit_device(): aow_start = flask.request.form.get('aow_start') aow_size = flask.request.form.get('aow_size') + (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devid_db) \ + = sanitize_input(devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devid_db) + database = "openplc.db" conn = create_connection(database) if (conn != None): try: cur = conn.cursor() - cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ?, pause = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devpause, int(devid_db))) + cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, int(devid_db))) conn.commit() cur.close() conn.close() @@ -1849,6 +1853,9 @@ def add_user(): username = flask.request.form['user_name'] email = flask.request.form['user_email'] password = flask.request.form['user_password'] + + (name, username, email) = sanitize_input(name, username, email) + form_has_picture = True if ('file' not in flask.request.files): form_has_picture = False @@ -1977,6 +1984,7 @@ def edit_user(): username = flask.request.form['user_name'] email = flask.request.form['user_email'] password = flask.request.form['user_password'] + (user_id, name, username, email) = sanitize_input(user_id, name, username, email) form_has_picture = True if ('file' not in flask.request.files): form_has_picture = False @@ -2225,6 +2233,8 @@ def settings(): slave_polling = flask.request.form.get('slave_polling_period') slave_timeout = flask.request.form.get('slave_timeout') + (modbus_port, dnp3_port, enip_port, pstorage_poll, start_run, slave_polling, slave_timeout) = sanitize_input(modbus_port, dnp3_port, enip_port, pstorage_poll, start_run, slave_polling, slave_timeout) + database = "openplc.db" conn = create_connection(database) if (conn != None): @@ -2311,6 +2321,40 @@ def create_connection(db_file): return None + +#---------------------------------------------------------------------------- +#Returns a generator that yields the sanitized arguments. +#---------------------------------------------------------------------------- +def sanitize_input(*args): + return (escape(a) for a in args) + +#---------------------------------------------------------------------------- +# Taken from the html module of the python 3.9 standard library +# exact lines of code can be found here: +# https://github.com/python/cpython/blob/3.9/Lib/html/__init__.py#L12 +# Modified to convert to String but preserve NoneType. +# Preserving NoneType is necessary to ensure program logic is not affected by None being converted to "None", +# this is relevant in setttings() +#---------------------------------------------------------------------------- +def escape(s, quote=True): + """ + Replace special characters "&", "<" and ">" to HTML-safe sequences. + If the optional flag quote is true (the default), the quotation mark + characters, both double quote (") and single quote (') characters are also + translated. + """ + if s is None: + return s + s = str(s) # force string + s = s.replace("&", "&") # Must be done first! + s = s.replace("<", "<") + s = s.replace(">", ">") + if quote: + s = s.replace('"', """) + s = s.replace('\'', "'") + return s + + #---------------------------------------------------------------------------- #Main dummy function. Only displays a message and exits. The app keeps #running on the background by Flask From 842ec537792c62d521b1b56f686d142978e18d26 Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Mon, 18 Oct 2021 20:20:58 +0200 Subject: [PATCH 07/17] Webserver merged with cloned from github --- webserver/core/modbus_master.cpp | 105 +++++++++++++++---------------- webserver/webserver.py | 50 ++++++++++++++- 2 files changed, 101 insertions(+), 54 deletions(-) diff --git a/webserver/core/modbus_master.cpp b/webserver/core/modbus_master.cpp index 1f5190d..461a841 100755 --- a/webserver/core/modbus_master.cpp +++ b/webserver/core/modbus_master.cpp @@ -60,7 +60,7 @@ struct MB_address struct MB_device { - modbus_t *mb_ctx; + modbus_t *mb_ctx; char dev_name[100]; uint8_t protocol; char dev_address[100]; @@ -69,9 +69,9 @@ struct MB_device char rtu_parity; int rtu_data_bit; int rtu_stop_bit; - int rtu_tx_pause; + int rtu_tx_pause; uint8_t dev_id; - bool isConnected; + bool isConnected; struct MB_address discrete_inputs; struct MB_address coils; @@ -167,8 +167,8 @@ void parseConfig() char temp_buffer[5]; getData(line_str, temp_buffer, '"', '"'); num_devices = atoi(temp_buffer); - //initializes the allocated memory to zero - mb_devices = calloc(num_devices, sizeof(struct MB_device)); + //initializes the allocated memory to zero + mb_devices = calloc(num_devices, sizeof(struct MB_device)); } else if (!strncmp(line_str, "Polling_Period", 14)) { @@ -243,7 +243,7 @@ void parseConfig() getData(line_str, temp_buffer, '"', '"'); mb_devices[deviceNumber].rtu_stop_bit = atoi(temp_buffer); } - else if (!strncmp(functionType, "RTU_TX_Pause", 12)) + else if (!strncmp(functionType, "RTU_TX_Pause", 12)) { char temp_buffer[10]; getData(line_str, temp_buffer, '"', '"'); @@ -364,27 +364,27 @@ void *querySlaveDevices(void *arg) for (int i = 0; i < num_devices; i++) { //Check if there is a connected RTU device using the same port - bool found_sharing = false; + bool found_sharing = false; bool rtu_port_connected = false; - if (mb_devices[i].protocol == MB_RTU) - { - for (int a = 0; a < num_devices; a++) - { - if (a != i && !strcmp(mb_devices[i].dev_address, mb_devices[a].dev_address)) - { - found_sharing = true; - if (mb_devices[a].isConnected) - { - rtu_port_connected = true; - } - } - } - if (found_sharing) - { - //Must reset mb context to current device's slave id - modbus_set_slave(mb_devices[i].mb_ctx, mb_devices[i].dev_id); - } - } + if (mb_devices[i].protocol == MB_RTU) + { + for (int a = 0; a < num_devices; a++) + { + if (a != i && !strcmp(mb_devices[i].dev_address, mb_devices[a].dev_address)) + { + found_sharing = true; + if (mb_devices[a].isConnected) + { + rtu_port_connected = true; + } + } + } + if (found_sharing) + { + //Must reset mb context to current device's slave id + modbus_set_slave(mb_devices[i].mb_ctx, mb_devices[i].dev_id); + } + } //Verify if device is connected if (!mb_devices[i].isConnected && !rtu_port_connected) @@ -423,7 +423,7 @@ void *querySlaveDevices(void *arg) //Read discrete inputs if (mb_devices[i].discrete_inputs.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); + sleepms(mb_devices[i].rtu_tx_pause); uint8_t *tempBuff; tempBuff = (uint8_t *)malloc(mb_devices[i].discrete_inputs.num_regs); nanosleep(&ts, NULL); @@ -459,7 +459,7 @@ void *querySlaveDevices(void *arg) //Write coils if (mb_devices[i].coils.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); + sleepms(mb_devices[i].rtu_tx_pause); uint8_t *tempBuff; tempBuff = (uint8_t *)malloc(mb_devices[i].coils.num_regs); @@ -492,7 +492,7 @@ void *querySlaveDevices(void *arg) //Read input registers if (mb_devices[i].input_registers.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); + sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].input_registers.num_regs); nanosleep(&ts, NULL); @@ -528,7 +528,7 @@ void *querySlaveDevices(void *arg) //Read holding registers if (mb_devices[i].holding_read_registers.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); + sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_read_registers.num_regs); nanosleep(&ts, NULL); @@ -563,7 +563,7 @@ void *querySlaveDevices(void *arg) //Write holding registers if (mb_devices[i].holding_registers.num_regs != 0) { - sleepms(mb_devices[i].rtu_tx_pause); + sleepms(mb_devices[i].rtu_tx_pause); uint16_t *tempBuff; tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_registers.num_regs); @@ -615,34 +615,33 @@ void initializeMB() } else if (mb_devices[i].protocol == MB_RTU) { - //Check if there is a device using the same port - int share_index = -1; + //Check if there is a device using the same port + int share_index = -1; for (int a = 0; a < num_devices && a < i; a++) { if (strcmp(mb_devices[i].dev_address, mb_devices[a].dev_address) == 0) { - share_index = a; - break; - } - + share_index = a; + break; + } } - if (share_index != -1) - { - if (mb_devices[i].rtu_baud != mb_devices[share_index].rtu_baud || mb_devices[i].rtu_parity != mb_devices[share_index].rtu_parity || - mb_devices[i].rtu_data_bit != mb_devices[share_index].rtu_data_bit || mb_devices[i].rtu_stop_bit != mb_devices[share_index].rtu_stop_bit) - { - unsigned char log_msg[1000]; - sprintf(log_msg, "Warning MB device %s port setting missmatch\n", mb_devices[i].dev_name); - log(log_msg); - } - mb_devices[i].mb_ctx = mb_devices[share_index].mb_ctx; + if (share_index != -1) + { + if (mb_devices[i].rtu_baud != mb_devices[share_index].rtu_baud || mb_devices[i].rtu_parity != mb_devices[share_index].rtu_parity || + mb_devices[i].rtu_data_bit != mb_devices[share_index].rtu_data_bit || mb_devices[i].rtu_stop_bit != mb_devices[share_index].rtu_stop_bit) + { + unsigned char log_msg[1000]; + sprintf(log_msg, "Warning MB device %s port setting missmatch\n", mb_devices[i].dev_name); + log(log_msg); + } + mb_devices[i].mb_ctx = mb_devices[share_index].mb_ctx; + } + else + { + mb_devices[i].mb_ctx = modbus_new_rtu(mb_devices[i].dev_address, mb_devices[i].rtu_baud, + mb_devices[i].rtu_parity, mb_devices[i].rtu_data_bit, + mb_devices[i].rtu_stop_bit); } - else - { - mb_devices[i].mb_ctx = modbus_new_rtu(mb_devices[i].dev_address, mb_devices[i].rtu_baud, - mb_devices[i].rtu_parity, mb_devices[i].rtu_data_bit, - mb_devices[i].rtu_stop_bit); - } } //slave id diff --git a/webserver/webserver.py b/webserver/webserver.py index c0f978f..d900016 100644 --- a/webserver/webserver.py +++ b/webserver/webserver.py @@ -892,6 +892,8 @@ def upload_program_action(): prog_descr = flask.request.form['prog_descr'] prog_file = flask.request.form['prog_file'] epoch_time = flask.request.form['epoch_time'] + + (prog_name, prog_descr, prog_file, epoch_time) = sanitize_input(prog_name, prog_descr, prog_file, epoch_time) database = "openplc.db" conn = create_connection(database) @@ -1157,6 +1159,9 @@ def add_modbus_device(): aow_start = flask.request.form.get('aow_start') aow_size = flask.request.form.get('aow_size') + (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devpause, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size) \ + = sanitize_input(devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devpause, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size) + database = "openplc.db" conn = create_connection(database) if (conn != None): @@ -1264,7 +1269,7 @@ def modbus_edit_device(): port_name = port if (str(row[4]) == port_name): return_str += "" - else: + else: return_str += "" return_str += pages.edit_slave_devices_tail @@ -1329,6 +1334,9 @@ def modbus_edit_device(): aow_start = flask.request.form.get('aow_start') aow_size = flask.request.form.get('aow_size') + (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devpause, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devid_db) \ + = sanitize_input(devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devpause, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devid_db) + database = "openplc.db" conn = create_connection(database) if (conn != None): @@ -1849,6 +1857,9 @@ def add_user(): username = flask.request.form['user_name'] email = flask.request.form['user_email'] password = flask.request.form['user_password'] + + (name, username, email) = sanitize_input(name, username, email) + form_has_picture = True if ('file' not in flask.request.files): form_has_picture = False @@ -1977,6 +1988,7 @@ def edit_user(): username = flask.request.form['user_name'] email = flask.request.form['user_email'] password = flask.request.form['user_password'] + (user_id, name, username, email) = sanitize_input(user_id, name, username, email) form_has_picture = True if ('file' not in flask.request.files): form_has_picture = False @@ -2225,6 +2237,8 @@ def settings(): slave_polling = flask.request.form.get('slave_polling_period') slave_timeout = flask.request.form.get('slave_timeout') + (modbus_port, dnp3_port, enip_port, pstorage_poll, start_run, slave_polling, slave_timeout) = sanitize_input(modbus_port, dnp3_port, enip_port, pstorage_poll, start_run, slave_polling, slave_timeout) + database = "openplc.db" conn = create_connection(database) if (conn != None): @@ -2311,6 +2325,40 @@ def create_connection(db_file): return None + +#---------------------------------------------------------------------------- +#Returns a generator that yields the sanitized arguments. +#---------------------------------------------------------------------------- +def sanitize_input(*args): + return (escape(a) for a in args) + +#---------------------------------------------------------------------------- +# Taken from the html module of the python 3.9 standard library +# exact lines of code can be found here: +# https://github.com/python/cpython/blob/3.9/Lib/html/__init__.py#L12 +# Modified to convert to String but preserve NoneType. +# Preserving NoneType is necessary to ensure program logic is not affected by None being converted to "None", +# this is relevant in setttings() +#---------------------------------------------------------------------------- +def escape(s, quote=True): + """ + Replace special characters "&", "<" and ">" to HTML-safe sequences. + If the optional flag quote is true (the default), the quotation mark + characters, both double quote (") and single quote (') characters are also + translated. + """ + if s is None: + return s + s = str(s) # force string + s = s.replace("&", "&") # Must be done first! + s = s.replace("<", "<") + s = s.replace(">", ">") + if quote: + s = s.replace('"', """) + s = s.replace('\'', "'") + return s + + #---------------------------------------------------------------------------- #Main dummy function. Only displays a message and exits. The app keeps #running on the background by Flask From b0a4c23755c1d247cb3c05dca380dbe728758726 Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Sat, 23 Oct 2021 15:22:29 +0200 Subject: [PATCH 08/17] Fixes broken slave device --- webserver/openplc.db | Bin 40960 -> 53248 bytes webserver/webserver.py | 16 ++++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/webserver/openplc.db b/webserver/openplc.db index 994dd85fce41ee7f4e184f34cb0247e3b088dc7c..a0cc5b383c5941c2638070908348a41ec08c55ed 100644 GIT binary patch delta 1364 zcmeHHPiWIn7=LN8_N7T)r;|)Y8UmFKH)|)jQ^6`hid`!;gY^_s6EV`-n55H+Vimj; z53RWlrZ?wJf;)?zJqqq3dK%um2s`>EYq!kc#fujSAL09bzwgg`-;dXO7wf%<4~|c4 zBZOEm8Y~W$9?qW4ZllxHhb);#7;hl%D;Fc5*g0mMtm5x@gBZBre{UXtJ8%Pkh<)aB zIjUcG)J9Xc?=%~Vqqj^YaFu)nNL{Q+MOhN$;)Sv#h>^G`Ow(A@^cBU>L|m%K(j}?p z4!Og00Nz$xy68URrm}(SbWL5vva~D>Pj4IBdFUHz zq8W|S}fM;!eyyGJ>HQ}T#~D$3aoWes>n0+49KRtlye_2 zQ>P-^Rpuj*FSBzy{9}>eNI-ecy~mt9lD``46~w_jEwBgqOor;0+%K4)`%P85y#Hzn zE%~3SY2h!`2*6 delta 660 zcmZXS&1=*^7{({Nh&$6HZwf*xQWK$wh1FX93t9cOKIZ!7d9dg|4K(yKFTvyB)S$oss%ndh00?Zf8wr^eou*;9lN(WCn8 z{r2796y2Kp?7$s_@ff+^-3EMhZrVq1fXBe>QF+aKjH7n}x#$Ohwd*L>AMi&5HsVRj zN7J9yz4d4%j>33lwG)MOs?+cW!BmrpNQ=yAL)h!CJ?us8Gqrf{UR^M4wV82>vRm0Pn<+bi+yrwi#{8^O0uC;e@O%M*+!a3ru5{sZXDf@){UAmDb(gUl`_SW zzEJr;RIY~E|EkCmmZp;D8a8>%dRo)AzV@w|q$0@`(_u_Dy-8h)w|r9BI;j}c+B0WD z1rRD^t*sq&Sv7$^mx<&otr70IR$-oz-sp|;8n;jr4Oj)9o+?>fwu_f=+al$Wz1zSa z(30=_*3L#@yYqzhaxQZkF3)J@dhrbtjNuDvnI}^ozzeT+jNmt%z;QWy_z~t8o6RRy m{(7K8^ySdG&

Add new device


-
+

Edit slave device


-
+
' + return_str += 'aowsize.value = "' + str(row[20]) + '";' + return_str += 'devpause.value = "' + str(row[21]) + '";}' except Error as e: print("error connecting to the database" + str(e)) @@ -1318,6 +1321,7 @@ def modbus_edit_device(): devparity = flask.request.form.get('device_parity') devdata = flask.request.form.get('device_data') devstop = flask.request.form.get('device_stop') + devpause = flask.request.form.get('device_pause') di_start = flask.request.form.get('di_start') di_size = flask.request.form.get('di_size') @@ -1338,7 +1342,7 @@ def modbus_edit_device(): if (conn != None): try: cur = conn.cursor() - cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, int(devid_db))) + cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ?, pause = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, devpause, int(devid_db))) conn.commit() cur.close() conn.close() From 3558955a7024c8d63896f318700d8dc4236a5cfb Mon Sep 17 00:00:00 2001 From: Erik Lagerwall Date: Sat, 23 Oct 2021 15:39:15 +0200 Subject: [PATCH 09/17] Fixes broken slave device --- webserver/pages.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/webserver/pages.py b/webserver/pages.py index 9853518..285c716 100644 --- a/webserver/pages.py +++ b/webserver/pages.py @@ -1487,9 +1487,11 @@ add_slave_devices_tail = """ + +
-
+

Discrete Inputs (%IX100.0)

@@ -1564,6 +1566,7 @@ add_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); + var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); @@ -1666,6 +1669,8 @@ add_devices_script = """ devparity.value = "None" turnElementOn(devdata) turnElementOn(devstop) + turnElementOn(devpause) + devpause.value = "0" turnElementOn(distart) turnElementOn(disize) turnElementOn(dostart) @@ -1692,6 +1697,8 @@ add_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -1728,6 +1735,8 @@ add_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -1768,6 +1777,7 @@ add_devices_script = """ var devbaud = document.forms["uploadForm"]["dev_baud"].value; var devdata = document.forms["uploadForm"]["dev_data"].value; var devstop = document.forms["uploadForm"]["dev_stop"].value; + var devpause = document.forms["uploadForm"]["dev_pause"].value; var distart = document.forms["uploadForm"]["di_start"].value; var disize = document.forms["uploadForm"]["di_size"].value; @@ -1826,9 +1836,11 @@ edit_slave_devices_tail = """ + +
-
+

Discrete Inputs (%IX100.0)

@@ -1898,6 +1910,7 @@ edit_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); + var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); @@ -2000,6 +2013,8 @@ edit_devices_script = """ devparity.value = "None" turnElementOn(devdata) turnElementOn(devstop) + turnElementOn(devpause) + devpause.value = "0" turnElementOn(distart) turnElementOn(disize) turnElementOn(dostart) @@ -2026,6 +2041,8 @@ edit_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -2062,6 +2079,8 @@ edit_devices_script = """ devdata.value = "8" turnElementOff(devstop) devstop.value = "1" + turnElementOff(devpause) + devpause.value = "0" turnElementOff(distart) distart.value = "0" turnElementOff(disize) @@ -2102,6 +2121,7 @@ edit_devices_script = """ var devbaud = document.forms["uploadForm"]["dev_baud"].value; var devdata = document.forms["uploadForm"]["dev_data"].value; var devstop = document.forms["uploadForm"]["dev_stop"].value; + var devpause = document.forms["uploadForm"]["dev_pause"].value; var distart = document.forms["uploadForm"]["di_start"].value; var disize = document.forms["uploadForm"]["di_size"].value; @@ -2153,6 +2173,7 @@ edit_devices_script = """ var devparity = document.getElementById("dev_parity"); var devdata = document.getElementById("dev_data"); var devstop = document.getElementById("dev_stop"); + var devpause = document.getElementById("dev_pause"); var distart = document.getElementById("di_start"); var disize = document.getElementById("di_size"); From 7871d4bb19d6839aa46c4aebeb7b49898833a1e1 Mon Sep 17 00:00:00 2001 From: Joakim Roubert Date: Thu, 2 Dec 2021 10:07:55 +0100 Subject: [PATCH 10/17] Dockerfile: Use specific base image tag In accordance with container security best practices, specify the base image tag. Change-Id: I4dadd77a830ee76d69096ae32869d3b375c6aebe Signed-off-by: Joakim Roubert --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f4ac16b..745d2bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM debian +FROM debian:bullseye-20211201 COPY . /workdir RUN cd /workdir && ./install.sh docker From 69c89b807548fb829ee4fc50e79ec4eadaebe4c0 Mon Sep 17 00:00:00 2001 From: Joakim Roubert Date: Thu, 2 Dec 2021 10:01:26 +0100 Subject: [PATCH 11/17] Dockerfile: simplify by reordering WORKDIR line Moving WORKDIR before the ./install.sh command, there is no need for the cd command. Change-Id: Ia4a43f18ae21d14b78e8eb22a48f3e31984c797c Signed-off-by: Joakim Roubert --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 745d2bc..2ad2a0b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM debian:bullseye-20211201 COPY . /workdir -RUN cd /workdir && ./install.sh docker WORKDIR /workdir +RUN ./install.sh docker ENTRYPOINT ["./start_openplc.sh"] From 4b22bf78ee45c616385d71f9978c476e3a95027e Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 13 Dec 2021 14:45:15 -0500 Subject: [PATCH 12/17] Fix race condition on persistent storage Drivers that takes a longer time to initialize would end up making the runtime call startPstorage() before readPersistentStorage(), which is incorrect. This fix ensures that those functions are called in the right order. --- webserver/core/persistent_storage.cpp | 122 ++++++++++++++------------ 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/webserver/core/persistent_storage.cpp b/webserver/core/persistent_storage.cpp index c378a3b..56d98c2 100644 --- a/webserver/core/persistent_storage.cpp +++ b/webserver/core/persistent_storage.cpp @@ -27,6 +27,8 @@ #include "ladder.h" +uint8_t pstorage_read = false; + //----------------------------------------------------------------------------- // Main function for the thread. Should create a buffer for the persistent // data, compare it with the actual data and write back to the persistent @@ -34,16 +36,20 @@ //----------------------------------------------------------------------------- void startPstorage() { + //We can only start persistent storage after the persistent.file was read + while (pstorage_read == false) + sleepms(100); + unsigned char log_msg[1000]; - IEC_UINT persistentBuffer[BUFFER_SIZE]; + IEC_UINT persistentBuffer[BUFFER_SIZE]; //Read initial buffers into persistent struct - pthread_mutex_lock(&bufferLock); //lock mutex - for (int i = 0; i < BUFFER_SIZE; i++) - { - if (int_memory[i] != NULL) persistentBuffer[i] = *int_memory[i]; - } - pthread_mutex_unlock(&bufferLock); //unlock mutex + pthread_mutex_lock(&bufferLock); //lock mutex + for (int i = 0; i < BUFFER_SIZE; i++) + { + if (int_memory[i] != NULL) persistentBuffer[i] = *int_memory[i]; + } + pthread_mutex_unlock(&bufferLock); //unlock mutex //Perform the first write if (access("persistent.file", F_OK) == -1) @@ -69,47 +75,47 @@ void startPstorage() fclose(ps); //Run the main thread - while (run_pstorage) - { + while (run_pstorage) + { //Verify if persistent buffer is outdated - bool bufferOutdated = false; - pthread_mutex_lock(&bufferLock); //lock mutex - for (int i = 0; i < BUFFER_SIZE; i++) - { - if (int_memory[i] != NULL) - { - if (persistentBuffer[i] != *int_memory[i]) - { - persistentBuffer[i] = *int_memory[i]; - bufferOutdated = true; - } - } - } - pthread_mutex_unlock(&bufferLock); //unlock mutex + bool bufferOutdated = false; + pthread_mutex_lock(&bufferLock); //lock mutex + for (int i = 0; i < BUFFER_SIZE; i++) + { + if (int_memory[i] != NULL) + { + if (persistentBuffer[i] != *int_memory[i]) + { + persistentBuffer[i] = *int_memory[i]; + bufferOutdated = true; + } + } + } + pthread_mutex_unlock(&bufferLock); //unlock mutex //If buffer is outdated, write the changes back to the file - if (bufferOutdated) - { - FILE *fd = fopen("persistent.file", "w"); //if file already exists, it will be overwritten - if (fd == NULL) - { + if (bufferOutdated) + { + FILE *fd = fopen("persistent.file", "w"); //if file already exists, it will be overwritten + if (fd == NULL) + { sprintf(log_msg, "Persistent Storage: Error creating persistent memory file!\n"); log(log_msg); - return 0; - } + return 0; + } - if (fwrite(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd) < BUFFER_SIZE) - { + if (fwrite(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd) < BUFFER_SIZE) + { sprintf(log_msg, "Persistent Storage: Error writing to persistent memory file!\n"); log(log_msg); - return 0; - } - fclose(fd); - } + return 0; + } + fclose(fd); + } - sleepms(pstorage_polling*1000); - } + sleepms(pstorage_polling*1000); + } } //----------------------------------------------------------------------------- @@ -121,31 +127,35 @@ void startPstorage() int readPersistentStorage() { unsigned char log_msg[1000]; - FILE *fd = fopen("persistent.file", "r"); - if (fd == NULL) - { + FILE *fd = fopen("persistent.file", "r"); + if (fd == NULL) + { sprintf(log_msg, "Warning: Persistent Storage file not found\n"); log(log_msg); - return 0; - } + pstorage_read = true; + return 0; + } - IEC_INT persistentBuffer[BUFFER_SIZE]; + IEC_INT persistentBuffer[BUFFER_SIZE]; - if (fread(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd) < BUFFER_SIZE) - { + if (fread(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd) < BUFFER_SIZE) + { sprintf(log_msg, "Persistent Storage: Error while trying to read persistent.file!\n"); log(log_msg); - return 0; - } - fclose(fd); + pstorage_read = true; + return 0; + } + fclose(fd); sprintf(log_msg, "Persistent Storage: Reading persistent.file into local buffers\n"); log(log_msg); - pthread_mutex_lock(&bufferLock); //lock mutex - for (int i = 0; i < BUFFER_SIZE; i++) - { - if (int_memory[i] != NULL) *int_memory[i] = persistentBuffer[i]; - } - pthread_mutex_unlock(&bufferLock); //unlock mutex -} \ No newline at end of file + pthread_mutex_lock(&bufferLock); //lock mutex + for (int i = 0; i < BUFFER_SIZE; i++) + { + if (int_memory[i] != NULL) *int_memory[i] = persistentBuffer[i]; + } + pthread_mutex_unlock(&bufferLock); //unlock mutex + + pstorage_read = true; +} From d1d133cb251749bae711e29ebf5d1f57a80ff3fe Mon Sep 17 00:00:00 2001 From: kozt <96878659+koztkozt@users.noreply.github.com> Date: Sat, 8 Jan 2022 18:03:26 +0800 Subject: [PATCH 13/17] Parse ST file upon webserver starts up When OpenPLC starts in RUN mode, monitoring page shows blank when webserver (./start_openplc.sh) is restarted. To fix the issue, ST file should be parsed when openplc_runtime starts. --- webserver/webserver.py | 1 + 1 file changed, 1 insertion(+) diff --git a/webserver/webserver.py b/webserver/webserver.py index d900016..72e3681 100644 --- a/webserver/webserver.py +++ b/webserver/webserver.py @@ -2401,6 +2401,7 @@ if __name__ == '__main__': openplc_runtime.start_runtime() time.sleep(1) configure_runtime() + monitor.parse_st(openplc_runtime.project_file) app.run(debug=False, host='0.0.0.0', threaded=True, port=8080) From 950ce6b0bbe659c366f8f80e9bbfdf2297c81057 Mon Sep 17 00:00:00 2001 From: kozt <96878659+koztkozt@users.noreply.github.com> Date: Sun, 20 Mar 2022 00:13:36 +0800 Subject: [PATCH 14/17] Fix "floating point exception" error Fix "floating point exception" error due to rtu_baud = 0 or null for Modbus TCP device --- webserver/core/modbus_master.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/webserver/core/modbus_master.cpp b/webserver/core/modbus_master.cpp index 461a841..b3558c1 100755 --- a/webserver/core/modbus_master.cpp +++ b/webserver/core/modbus_master.cpp @@ -418,7 +418,14 @@ void *querySlaveDevices(void *arg) struct timespec ts; ts.tv_sec = 0; - ts.tv_nsec = (1000*1000*1000*28)/mb_devices[i].rtu_baud; + if (mb_devices[i].protocol == MB_RTU) + { + ts.tv_nsec = (1000*1000*1000*28)/mb_devices[i].rtu_baud; + } + else + { + ts.tv_nsec = 0; + } //Read discrete inputs if (mb_devices[i].discrete_inputs.num_regs != 0) From da2c9674b6ac866bd0bc4133d8023958db5c0be0 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 25 May 2022 08:49:55 -0400 Subject: [PATCH 15/17] Update windows installer --- background_installer.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/background_installer.sh b/background_installer.sh index a54111c..d15a47c 100755 --- a/background_installer.sh +++ b/background_installer.sh @@ -142,15 +142,18 @@ WantedBy=multi-user.target" >> openplc.service if [ "$1" == "win" ]; then echo "Installing OpenPLC on Windows" cp ./utils/apt-cyg/apt-cyg ./ - cp ./utils/apt-cyg/wget.exe /bin + if [ -f "/usr/bin/wget" ] + then + echo "found wget. Skipping install" + else + echo "wget not found. Installing from binary" + cp ./utils/apt-cyg/wget.exe /bin + fi install apt-cyg /bin apt-cyg update - # replace cygwin installed database to avoid installation errors - cp ./installed.db /etc/setup/installed.db apt-cyg install lynx - rm -f /bin/wget.exe # apt-cyg remove gcc-core gcc-g++ pkg-config automake autoconf libtool make python2 python2-pip sqlite3 - apt-cyg install wget gcc-core gcc-g++ git pkg-config automake autoconf libtool make python2 python2-pip sqlite3 python3 + apt-cyg install gcc-core gcc-g++ git pkg-config automake autoconf libtool make python2 python2-pip sqlite3 python3 lynx -source https://bootstrap.pypa.io/pip/2.7/get-pip.py > get-pip.py lynx -source https://bootstrap.pypa.io/pip/get-pip.py > get-pip3.py /usr/bin/python2 get-pip.py From c54d10a208b06a336c45e032933836d5e6741a58 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 28 Sep 2022 16:06:05 -0400 Subject: [PATCH 16/17] Added support for Fedora --- background_installer.sh | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/background_installer.sh b/background_installer.sh index d15a47c..8d110da 100755 --- a/background_installer.sh +++ b/background_installer.sh @@ -21,10 +21,32 @@ fi #set -x # arg1: sudo or blank function linux_install_deps { - $1 apt-get update - $1 apt-get install -y build-essential pkg-config bison flex autoconf \ - automake libtool make git python2.7 \ - sqlite3 cmake git curl python3 python3-pip + #Detecting OS type + INSTALLER="" + OS=$(awk '/NAME=/' /etc/*-release | sed -n '1 p' | cut -d= -f2 | cut -d\" -f2 | cut -d" " -f1) + + if [ "$OS" = "Fedora" ]; then + INSTALLER="yum" + elif [ "$OS" = "CentOS" ]; then + INSTALLER="yum" + elif [ "$OS" = "Red" ]; then + INSTALLER="yum" + else + INSTALLER="apt" + fi + + if [ "$INSTALLER" = "yum" ]; then + yum clean expire-cache + yum check-update + $1 yum -q -y install curl make automake gcc gcc-c++ kernel-devel pkg-config bison flex autoconf libtool openssl-devel cmake python3 python3-pip + $1 yum -q -y install python2.7 python2-devel + #Installing dependencies for Ubuntu/Mint/Debian + else + $1 apt-get update + $1 apt-get install -y build-essential pkg-config bison flex autoconf \ + automake libtool make git python2.7 \ + sqlite3 cmake git curl python3 python3-pip + fi curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py $1 python2.7 get-pip.py } From 7ade9ad393cc62fe4d7930cacf8bc650fbb07f7f Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 28 Sep 2022 16:30:08 -0400 Subject: [PATCH 17/17] Fedora fix --- background_installer.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/background_installer.sh b/background_installer.sh index 8d110da..70f1dd8 100755 --- a/background_installer.sh +++ b/background_installer.sh @@ -269,7 +269,27 @@ elif [ "$1" == "linux" ]; then install_py_deps "sudo -H" install_all_libs sudo + + #Detecting OS type + OS_TYPE="" + OS=$(awk '/NAME=/' /etc/*-release | sed -n '1 p' | cut -d= -f2 | cut -d\" -f2 | cut -d" " -f1) + if [ "$OS" = "Fedora" ]; then + OS_TYPE="yum" + elif [ "$OS" = "CentOS" ]; then + OS_TYPE="yum" + elif [ "$OS" = "Red" ]; then + OS_TYPE="yum" + else + OS_TYPE="apt" + fi + + #Fix for Fedora + if [ "$OS_TYPE" = "yum" ]; then + sudo cp /usr/local/lib/pkgconfig/libmodbus.pc /usr/share/pkgconfig/ + sudo cp /usr/local/lib/lib*.* /lib64/ + fi + echo "" echo "[FINALIZING]" cd webserver/scripts