 Hey everybody, this is Brian. Welcome to the 119th Qt tutorial with C++ and GUI programming. Be sure to visit my website www.voidrealms.com. You can find tutorials with complete source code, programs, more source code, projects, and you can donate if you feel obligated. Alright, today we're going to be talking a little bit about Pluginbot.net. Now, I can already tell I'm going to get a few hundred hate mails saying, why are you talking about Pluginbot on your C++ channel? Well, because it is written in, you guessed it, C++ and Qt. So, Pluginbot.net, if you're not familiar with it, is a service that runs in the background and it loads plugins. Now, what can this do? This isn't going to be a, like, the sales pitch, mind you. Really, just about anything you can think of. For example, say, plugins. One of the plugins I have, yeah, a telnet server. So, imagine if you will, you have a thousand devices that Pluginbot's installed and the policy's bound to it so that in an instant you can upload this plugin to all 1,000 devices and they're all running a telnet server. Well, huge security vulnerability. You don't want to run the telnet server. This is just proof of concept. What we're going to be covering today is, on GitHub, I have the SDK for plugins, how to actually build a plugin. So, we're going to be covering that a little bit. You can find that at HTTPS, github.com, slash Pluginbot. And from there, you can see, you know, libraries, plugins, policies, and the server version. But we're going to focus on plugins. So, what I've done here is I've just made a simple SDK and it's broken down. So, you have, you know, applications, interfaces, libraries, and the actual plugins themselves. So, we got our little get directory here and we're going to actually clone this. So, we're going to say get clone. I just watched Guardians of the Galaxy. Man, that was a good movie. But now I can't hardly type. It was such a good movie, I can't type. Wow, I really cannot type. So, what we're doing now is we're just doing get and we're cloning it in here. And did I do it in the wrong directory? I did. Darn it. I always forget to do that. What? There we go. Clone that again. See, we all make mistakes. So, now we've got our plugins folder. What do we do with this thing? Well, we're going to open Qt Creator and we're going to go open project. And we're going to say get plugins and open the plugins pro. Allow it to run. It'll do its configuration. Now, this is the reason why I wanted to put this in the Qt tutorials. Because there's a lot of code here that you can actually dig through and use in your own projects. For example, we've done extensive tutorials on Zlib and compression. I actually made a compression library that wraps around Zlib. And this will actually demonstrate how some of that works. Let me back up here. Like I said, I'm tired and I've had a couple days off for first time in a long time. So, we've got applications. We've got a plugin generator. This is something that you would run to upload plugins. And I'm going to compile this, actually. You would upload your plugins to the website. You need to actually generate the plugin first. A plugin tester. If you want to test your plugin and see how it would actually work with the pluginbot.net client, the zip library, and some plugins. I've got the plugin template, which you use as like a starter point for all your projects. And then the telnet server. And this is the same one you see up on pluginbot. Now, let's look at some of this here. If you're on Linux, you'll see this where it's doing this make right here. We're actually building Zlib in the background on Linux, Unix, and Mac. On Windows, it just copies a library. So, there is a lot of goodness going on here. So, let's dig through this project real quick here. We look at the plugins.pro. You see we're just doing subters. I don't think we've really talked about this too much. The project file itself is template subters, meaning we're loading subdirectories. So, you can see here's our subdirectories. And they're ordered, config ordered. That's the order they're going to be compiled in. Notice how it's libs, applications, and then plugins. Libs, applications, plugins. Notice how we're not including interfaces, because those are just the interfaces that get included into the projects themselves. So, what it'll do is it'll jump in and it'll say like libs. And then it loads libs.pro. So, if we go libs, libs.pro, same thing. It's only got one subdirector called zip. We could have just included zip directly. And then we've got this stuff. Now, if you look at some of these, we're adding PRI files or project includes. The config.pri, we're just setting all of our directory structures. And that's loaded in each one of these so that we know and we can use those variables. For example, baseter is print working directory. So, let's jump up here. There's config. So, our base directory is, you know, home, whatever your username or if you're on Windows C, whatever you've got it in, get plugins. So, that's the base directory. And then we're calling these others, like the libdoor is the baseter plus libs. So, this directory plus libs. No rom food or magic going on there. Now, it gets a little tricky when you look at zipconfig.pri or the project include, because you can see what we're doing here is a little bit magical if you're not used to seeing this. You can see we have Unix, which we'll call on Linux and I believe Mac as well. But I don't have a Mac to test that. So, don't send me hate mail. And then Win32. And what we're doing is two distinct build behaviors here. If it's on Windows, we're just sending a command to the command line saying copy this file. Notice how it's a DLL to this path. Now, distr is the path. What is distr? We should back up and look at that. Distr is where the finished application will be placed. So, where's that? If we go up a level, we'll see here's our code compiled directory that Qt made. And then here's this plugin bot SDK. This is where the actual programs got thrown. I do this typically on larger projects so that I don't have to go hunt and unpacking through these things looking for the binaries. I just have everything in a distribution directory and it's good to go. So, you can see we've generated the plugin generator, the plugin tester, and two plugins. Now, if you're on Windows, these will be DLLs. If you're on anything else, they're going to be SOs for system objects. And there's Zlib and then there's our library, the zip compression library. So, now if you're on Linux and Unix and I believe Mac, this is a little bit different. We're actually doing a target Zlib. We're making a command. So, this is a special command. We're going to pump into the command line here. And what we're doing is we're saying, print out the name of the library. If it exists, I'm sorry, if it does not exist, notice that not symbol, then we're going to execute all this. And what we're saying is if it exists, I'm sorry, if it does not exist, then we're going to remove any objects and A files and LOs and SOs that we've already built. And then we're going to rebuild the thing. That way, if you do a build, it's not going to rebuild Zlib. But if that file lib z.so does not exist, it will actually rebuild Zlib. So, we can actually test that here by actually just deleting this. Watch our command or our compile output here. And you can see that GCC. That's actually building Zlib right there. I've done this so many times. I know exactly what it looks like. And voila, Zlib's rebuilt. So, there's just some interesting things you can do with project files. Obviously, I don't have time to go into a whole lot of the code or we'll just be here all night talking. So, we're going to look at, you know, you've got your Zlib wrapper around this zip, which I think we've talked about exhaustingly. And then there's zip config, zip reader, zip writer. You know, I've kind of stolen. I don't want to say stolen. I've borrowed parts of this from Qt itself and always leave, you know, the original authors in there. All right, let's close a lot of these out. So, what's the meat of this thing? What are we really after? Well, this is an SDK and this is pretty typical of most developers. They'll make a SDK or software development kit. So, this SDK in particular, I know like the back of my hand because I wrote it. But what we've got here is you're trying to build a plugin. You want to build your own plugin. So, the structure of a plugin is quite simply you include the interfaces, the iPlugin interface. If you've watched any of my other tutorials, like especially on like C Sharp or Java, we've talked about interfaces before, where an interface is simply a contract between two objects, meaning you will have name, description, long description, author name, etc, etc. If you don't have that, you're violating the contract and it just simply will not compile. So, in order to build a plugin, you have to include this iPlugin interface. Now, parts of this that are interesting, you can put your name, description, long description, your author name, your website, your email, the version. That's how the plugin bot actually determines whether or not it needs to be upgraded. You can start the plugin, stop the plugin, install the plugin and notice how you're giving it a file name. This is called when the plugin's installed and plugin bot will actually send you the file name of your DLL. So, you don't have to guess where you're actually at in the file system. Uninstall, you can remove any files or do any post-processing. You determine whether or not you're in a running state. Typically, what it'll do is it will call install and then it'll immediately call configure. That way, you have the settings that you need. For example, the telnet server needs a port and a password. And then update. Plugin bot updates, I think, once an hour, or you can actually configure that. And then a list of options that the plugin should return. Now, if we look at the template itself, you can see how, and we've got the template header file, you can see how we're actually inheriting the iPlugin interface. That's how we do that. And then you do QInterface's iPlugin. That macro right there, I think we've talked about that before, that will say, hey, you know, you're implementing this iPlugin interface and it'll throw compiler errors if you don't. And then it's just, you know, simple skeleton here. Couple little variables. Sometimes I sound like Bob Ross. Couple little happy trees. But anyways, so inside here, we're immediately saying, no, we're not running. And then we hit the name, the description. I mean, a lot of boring stuff, really. And you would obviously change these with your name and stuff like that. And then you would call your code when you start, when you stop, when you install, when you uninstall, when they want to determine if you're running, when it's updated. And you know how we're doing a QVariant map? Well, QVariant map is because Pluginbot stores a QVariant map in a file. The reason for that is you have all the MIME encoding. So instead of just streaming to a file and saying it's an integer, and then, you know, when you read it back, you're trying to determine what it is, you're actually loading a QVariant, which has all the metadata with it. So you can just say, is it a boolean, is it an integer, whatever. All right. So we're going to scrap the template from now. And I have to kind of watch how long this video gets going. So the telnet server that you actually see on Pluginbot.net, this is actually a full functioning telnet server that loads into the client. I've tested this on Windows and Linux. And you can see, same thing. It's implementing the iPlugin interface. And you can see the interface members there. And then we see some other things like telnet server. So let's look at telnet server. And this is a full functioning telnet server that runs on TCP. And you set whatever port you want. And you can see how it's got start, stop, authenticate, because it takes a password, et cetera, et cetera. Telnet client. That is the, each connection is considered a client. So you're accepting the socket. We've talked about this in our TCP tutorials, but this is a full working TCP server you can actually use. And it shows how to do authentication on top of that. So and we can look at, you know, the server portion. No real magic. We've done TCP servers before. You're seeing, you know, create a new telnet client, you know, accept the connection and away they go. Now the telnet server itself, you can see how we're setting a password and we're setting a port. When this thing loads, that's the first thing it's going to do is look for its properties. So what we're going to do is we're going to load the plugin tester. This program will actually determine how your plugin is going to function inside of the plugin bot software. So this is a, like a dumb down version of the engine. So the first thing we need to do is actually add our plugins. So we're going to add them and you can select that and we're going to select that. You see how they're got a red line? That means they're in an off state. Well, let's look at the telnet server and we can look at the properties here. And these are the properties we're loading from the interface itself. And this is what the website will actually view too. And here are the actual parameters or configuration. We're giving it a password and a port and it has like the, you know, the default, the description, the name and you can see all this in the actual code here. Maybe if I scroll down to it, there we go. So the options function is returning a Q variant map and there's our password. You know, the type is a string, the default password, the description is this is a password. And then we're just basically doing a Q variant map in a Q list and then returning it. Sounds confusing, I know, but it's really not. So what do we actually do with plugins? Well, the first thing that's going to happen is the plugin is going to get installed. That's the first thing plugin bot will do. So it will install the plugin and it'll say warning during a normal install your plugin is decompressed and placed into a special folder and then it is installed and configured. And then it gives you the path that which it pumped out. So that's where we're actually located on the desk. Now when we start, notice how it pops up in the start plugins parameters. These are the actual parameters that are passed to the plugin when it's configured. Notice how port is 1000. We're going to have to change that because we've got app armor, which will block that on Linux. So I'll need to change it to 5000. Now just to prove there's nothing running here, we're going to actually say till net 127 on port 5000. Now 127.001 is just our local loopback or our local machine. Unable connect, remote host connection refused. Now password is password, port is 5000. We can actually add and delete parameters but we're just going to hit okay. And it says, all right, notice how it's getting all this stuff. Let's actually expand this window. Where's it getting all this stuff? Well, this is another example of why I wanted to do this in the Qt tutorials because it's actually getting these from Qt debug messages. We're actually intercepting Qt debug messages. So let's look at this. You can see there's Qt debug, name, option, and value. So where are we grabbing that? Let's look at the plugin tester. And you see how we got this global variable of a Qt text edit pointer to a debug window. Debug window equals UI, text edit, and then we're doing this Q install message handler, Qt message hook. So we look for Qt message hook. Let's see here. Boom. This is where we're actually intercepting it. And you can see we can determine what type it was, whether it was a warning, a debug, a critical, or a fatal. And then we can just print that out. So every debug message that you throw in your plugin, we're going to actually intercept that. And PluginBot actually does this, and that's how it does its logging. You also notice how the state's changed. It shows that it's running. It's got a green arrow. Kind of hard to see. There we go. Where this other one is red. So we can shut that off, turn it on. Now it is running, and it says, started listening on port 5000. So let's test that. We have a password prompt. And we'll just type in some gibberish. Oop. Nope. Didn't authenticate. Nope. Can't spell. And we're authenticated. Now we have full access to this machine. And you can see how we're even intercepting the debug messages inside the plugin itself till that client connected. So I can actually say, you know, ls-l on my root. I've got full root access to this box until that, because PluginBot would run as root, by the way. That's why you don't really want to run a telnet service. It was just proof of concept. Now let's scroll down here. And you can see we're actually intercepting the information right out of the plugin. And if we close this, you can see closing telnet socket 19. So what we're really showing here is that, A, how to build a simple plugin. B, how the plugin interacts with PluginBot.net client. And how to actually go about testing it. You can install it. We're running it. You can update it. Updates occur about once an hour. And this is the information that's typically pumped down during an update. The date it was missing, the date it was updated. That'll almost always be the current date. Your IP address, whether or not it's missing, it'll be a one if it's missing. The name of the device out on the website. The special parameters, password. Port, special parameter from Plugin. We can actually delete those. Status, it is running. And the update interval in minutes. So, and this is a typical update right here. Now why would you want to intercept an update? Typically updates happen because let's say you say, I don't want the password to be password. That's too simple. You want it to be my super admin password. Well, the devices are going to update once an hour. So once an hour they'll pull those settings down and they'll change the password on your telnet server. So it automatically configures the plugins. That's why the plugins have to intercept the update. And of course you can stop the plugin. You see how it's stopped. And it's gone back to a stop state. And ultimately you can uninstall it. And it says warning, during a normal uninstall, your plugin and all associated files will be deleted. That's basically your last chance to say, hey, any configuration files, temp files, open file sockets, anything. Time to close them and get rid of them. That was a mouthful. All right. So let's look at the plugin generator real quick. Plugin generator is actually very simple. You simply, yes, I forgot about that. You simply select a file. And let me cancel that and go back here and show you. You choose a plugin. It'll automatically try to detect your operating system and your CPU architecture. On Windows it's always going to be 32-bit simply because, well, you know, I've only compiled for a 32-bit client. But I'm on Linux 64. Yay, Linux. And notice how it says, boom, debug mode detected. We've detected you've compiled in debug mode. Only, only, only. Repeat after me. Carve it into the desk in front of you. Only submit plugins compiled in. You guessed it. Not debug mode. Release mode. Reason for that is the client's in release mode. So we're going to actually take our plugin server. Notice how it loads all the properties up. And this is what's going to be wrapped in here. And we're just going to hit OK. And we're going to say my plugin.zip. Save that bad boy. And it says the plugin submission was created and any extra files you need to the archive. And here's the actual zip file we created. And if we open this up, you'll see there's your library and then there's a special XML file. This XML file is how we actually communicate with the website plugin bot.net. Really what's going on there is it's just encoding this in a special way that the PHP code can actually read. That's it. So once we've created our zip file, then all we really need to do is go to pluginbot.net and you would log in. And what was my login for this? I think that's one of my demo accounts. Yes. Okay. All right. First thing you would do is go to plugins. And if you don't have the author tools, you'll need to go to account author profile and check this little box show plugin author tools. And then it'd be a good idea to fill in like your name, your email, your website, et cetera, et cetera, and hit save. But anyways, you go to plugins and then you can submit a plugin. And you basically choose the file and upload. And notice how it loads all the information from the plugin. Now one important note, you should set it to public. Reason why it's automatically default to private is because you can make plugins for your own personal use. And if you want the rest of the world to use them, you need to set it to public. And then you have the options and these were just loaded. And this is like your last chance to really modify them. So if you see like it was, you know, the wrong port, you can go, oh no, and then you can, you know, fix that. And then you just hit save when you're done. And so as your plugin information has been saved, you can manage your submissions. And you can see here's the one we just submitted. And usually the other ones, you should give it a description other than telnet server, you can actually say what operating system it's for. And I'm just going to delete that because this was just a demo. Well, that's all for this tutorial. I hope you found this educational entertaining and thank you for watching.