Upgrading to version 8.0.0

pull/74/head
mbusb 8 years ago
commit 2c33ed73de

93
.gitignore vendored

@ -0,0 +1,93 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
.venv/
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
# Created by PyCharm
.idea

@ -0,0 +1,137 @@
Version - 8.0.0
---------------
* This version is written in python 3
* GUI toolkit moved to pyqt5
* Upgraded isodump.py to support python 3 (Thanks to LiQiong Lee)
* Option to choose the desired persistence size using slide
* Introduces command line option (install and uninstall distros as of now and will be extended later)
* Progress can be monitered when running from terminal
* Multibootusb should be started with admin/ root privilage under Linux
* Fixed the bug which causing USB disk to set read only
* Fixed 'Undef symbol FAIL: __syslinux_debug_enabled' error for gparted, clonezilla and some other (Thsnks to yurikhan for pointing to right direction)
* Fixed the bug which crashes multibootusb when non-ascii charecters are present in the ISO link
* Fixed the bug which prevent multibootusb not to install syslinux
* Now debain installer can be installed
* Updated dependency packages stddeb, pyinstaller and pyudev to latest version
* Fixed hiren's boot cd bug (but user has to avoid "'" in the path)
* Updated install.py script to include all missing dependencies
* pkexec is required now undaining Linux for obtaining admin permission
* Fixed dban not supported error
* Fixed AVG rescue disk not supported error
* Added Offline Windows Password and registry editor (latest version)
* Added F4UBCD iso
* Fixed the crash when mountpath contain space
* Dropped udisk version 1 for obtaining details of USB disks
* Now the GUI responds smoothly when using ISO Imager option (dd)
* Fixed superficial duplicate devices on Refresh USB under ISO Imager tab
* Corrected some typo errors
* version bumped to 8.0.0 as it is a major upgrade
* Added support for bl-Hydrogen Linux
* Many other improvements and bug fixes...
Version - 7.5.0
---------------
* Introducing "ISO Imager". Now you can write ISO images directly to USB and it is cross platform too.
* util-linux is required now under Linux.
* Most of the reported bugs has been fixed.
* Inclusion of 64 bit syslinux (except version 5 as I could not find any) under Linux.
* Added alphine Linux and memtest
* Included missing install.py, uninstall.py and dd directory to source package.
Version - 7.4.0
---------------
* Portion of the code has been rewritten.
* Added support for ext2/3/4 and Btrf filesystem.
* Corrected wrong naming of persistence files.
* Bug fix for PartedMagic update script.
* Few typo has been corrected.
* Included doc strings.
* Now install and uninstall script is written in python.
* Upgraded the debian build script (stdeb) to latest version.
* Lot of other minor bug fixes.
* GUI is slightly larger now.
* Generic way to remove files outside multibootusb directory.
* Various improvements to build script.
Version - 7.3.0
---------------
* Rewrite of the source code. It is easier to read source code now.
* UDisks2 has been added for detecting and getting USB details under Linux.
* Patch for ubuntu 14.10 and above which uses isolinux version 6.
* Added persistence for ubuntu and its derivatives. Maximum persistence can be up to 4GB.
* No USB label error has been solved. It now works with USB drives even without names.
* Corrected wait time to 30 sec.
* Updating GUI is now handled by QThread
* Added following distros:-
- Trinity Rescue Kit
- DBan
* Check for QEMU installation before doing any QEMU related operations.
* Feedback after installing syslinux (under syslinux tab).
* psutil dependency has been dropped.
Version - 7.2.0
---------------
* Updated syslinux version from 6.0.2 to 6.0.3
* Added background image for syslinux.
* Increased timeout time to 30 sec.
* Added following distros:-
- CentOS minimal.
- Ubuntu Server.
* Patch from kbytesys to fix systemrescueCD menu items and other string manupulations.
* Fix for few other bugs.
Version - 7.1.0
---------------
* ISO extraction is much faster than previous releases.
* Included pyudev for better detection of USB drives under Linux.
* Included install.sh for installing multibootusb under Linux.
* Included setup.py for installing directly from source.
* Improved USB detection under Linux.
* Lot of important bug fix and minor improvements.
Version - 7.0.0
---------------
* 7Zip is no more used for extracting ISO files. Thanks to contibution by LiQiong Lee for isodump.py script.
* Improved ISO extraction speed on certain distros.
* Added solydx, antix and fixed puppy bug.
* ISO integrity check is much faster than previos releases.
* QEMU feature is back on both Linux and Windows.
* Fixed OpenSuse uninstall issue.
* Check if any running process while exiting.
* Added PCLinuxOS.
* Various other major and minor improvements to all scripts.
* Changed version numbering to three digit.
Version -7.0 Beta2
------------------
* Now multibootusb installs correct version of syslinux shipped with distro.
* Various optimization for installation of syslinux.
* Extensive test has been done to make sure to fix bugs.
* Able to uninstall distros properly under windows.
* Greater attention is given to ensure that correct version of syslinux is installed in distro directory.
* Various code optimization.
* Copying iso files under windows is faster now.
* Added follwing distros:-
- Wifislax
- PcLinuxOS
- Salix live/install
- Slackel live/install
- Zenwalk live/install
* Few other distros which I dont remember
* Size of windows executable has been reduced (using upx)
* Added refresh usb button. So that restarting of application is not required to detect USB.
* Added new lable space to indicate progress of the process.
* Various other smaller improvements.
Version -7.0 Beta
-----------------
* Code base is now in python 2.7
* Code is hosted at github so that anybody can view the progress of the development.
* Various bugs present in the older version (6.4.1) has been fixed
* Stand alone for windows and Linux.
* PyQt choosen as GUI toolkit.
* Official website is up and running at and you are viewing it now :-)
* New logo.
* Single code base for Linux and windows
* other improvements which i dont remember exactly :-)

@ -0,0 +1,998 @@
GNU GENERAL PUBLIC LICENSE
<<<<<<< HEAD
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
=======
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
<<<<<<< HEAD
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
=======
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
<<<<<<< HEAD
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
=======
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5
The precise terms and conditions for copying, distribution and
modification follow.
<<<<<<< HEAD
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
=======
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
<<<<<<< HEAD
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
=======
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
<<<<<<< HEAD
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
=======
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
<<<<<<< HEAD
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
=======
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
>>>>>>> f69e8b932e01aa3691f02e1ad3ebd67a3174cbe5

@ -0,0 +1,65 @@
####User guide is located here http://multibootusb.org/page_guide/
What is multibootusb?
---------------------
MultiBootUSB is a cross platform* software/utility to create multi boot live Linux on a removable media i.e USB disk.
It is similar to unetbootin but many distros can be installed, provided you have enough space on the disk.
MultiBootUSB also provides an option to uninstall distro(s) at any time, if you wish.
* Only works on windows and linux
How to install?
---------------
The install.py script provided with multibootusb should take care of all dependency and install multibootusb.
Assume that you have downloaded the package named "multibootusb.tar.gz" in to your home directory.
Issue the following commands to install multibootusb:-
```
tar -xf ./multibootusb.tar.gz
cd multibootusb
chmod +x ./install.py
sudo ./install.py
```
That is it. You can find multibootusb under system menu or simply launch from terminal by typing "multibootusb".
If "install.py" script fails to install multibootusb successfully then manually install following packages and rerun the install.py script:-
* mtools util-linux parted python3-qt5 python-dbus pkexec
NOTE: install.py currently supports only distros based on apt-get, yum, zypper, pacman.
You can add more if you use other package manager system and email to me for adding into upstream.
The above how to is only for linux. Windows users may download pre compiled standalone binaries/ .exe from
https://sourceforge.net/projects/multibootusb/files/
How to uninstall?
-----------------
You can uninstall multibootusb at any time using the "uninstall.py" script provided with multibootusb.
```
cd multibootusb
chmod +x ./uninstall.py
sudo ./uninstall.py
```
Website:
--------
www.multibootusb.org
Development:
-----------
https://github.com/mbusb/multibootusb
Help:
-----
Mail me at feedback.multibootusb@gmail.com for query, help, bug report or feature request.
Contributor(s)
--------------
LiQiong Lee
Ian Bruce
and many others who have given their valuable bug report/ feedback.
Author(s)
---------
MultiBootUSB is brought to you by Sundar and co-authored by Ian Bruce.

@ -0,0 +1,270 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: build_pkg
# Purpose: Module to create package, executable, source archieve and upload to sourceforge site.
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
"""
This is an internal script to make automation of building binary/ source packages and uploading to Sourceforge.
This may not work for you without modification in to variables and paths. Please amend wherever required.
Originally written for cryptully and modified by me for multibootusb.
Released under General Public Licence (GPL).
Author: Sundar
"""
import os
import shutil
import subprocess
import sys
import platform
####################################################################################################
# Change the below variables to suit your needs.
if platform.system() == "Windows":
# pyinstaller_path = "F:\Documents\PyInstaller-3.2\pyinstaller.py"
# pyinstaller_path = "I:\home\sundar\Documents\pyInstaller\pyinstaller.py"
pyinstaller_path = 'D:\multibootusb\pyinstaller\pyinstaller.py'
# release_dir = os.path.join("D:", "multibootusb", "release")
release_dir = 'D:\\multibootusb\\release'
else:
from os.path import expanduser
home = expanduser("~")
pyinstaller_path = "/home/sundar/Documents/pyInstaller/pyinstaller.py"
release_dir = "/media/sundar/Data/multibootusb/release"
sourceforge_release_path = "multibootusb@frs.sourceforge.net:/home/frs/project/multibootusb/"
####################################################################################################
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
class pkg():
def __init__(self, name):
self.pkg_name = name
self.version = open(os.path.join("data", "version.txt"), 'r').read().strip()
self.release_upload_dir = os.path.join(release_dir, self.version)
def build_package(self):
self.clean_dir()
if not os.path.exists(self.release_upload_dir):
os.mkdir(self.release_upload_dir)
if not os.path.exists(os.path.join(self.release_upload_dir, "Linux")):
os.mkdir(os.path.join(self.release_upload_dir, "Linux"))
elif not os.path.exists(os.path.join(self.release_upload_dir, "Windows")):
os.mkdir(os.path.join(self.release_upload_dir, "Windows"))
elif not os.path.exists(os.path.join(self.release_upload_dir, "Source")):
os.mkdir(os.path.join(self.release_upload_dir, "Source"))
if self.pkg_name == "deb":
print("Ensure thta you have python-stdeb package installed!")
stdcfg = ("[DEFAULT]\n"
"Package: multibootusb\n"
"Depends: python3-pyqt5, parted, util-linux, mtools, python-dbus, pkexec\n"
"Build-Depends: python3-all\n"
"Section: system\n"
"XS-Python-Version: = 3.5\n"
"Debian-Version: 1")
with open("stdeb.cfg", "w") as f:
f.write(stdcfg)
if subprocess.call('python3 setup.py --command-packages=stdeb.command bdist_deb', shell=True) == 0 and \
os.path.exists(os.path.join("deb_dist", "python3-multibootusb_" + self.version + "-1_all.deb")):
try:
shutil.copy2(os.path.join("deb_dist", "python3-multibootusb_" + self.version + "-1_all.deb"),
os.path.join(self.release_upload_dir, "Linux"), follow_symlinks=True) #,follow_symlinks=False
except:
os.system('cp -rf ' + os.path.join("deb_dist", "python3-multibootusb_" + self.version + "-1_all.deb") + ' ' +
os.path.join(self.release_upload_dir, "Linux"))
if os.path.exists("stdeb.cfg"):
os.remove("stdeb.cfg")
print("\n\n\nDebian package has been created and can be found here::")
print((os.path.join("deb_dist", "python3-multibootusb_" + self.version + "-1_all.deb\n\n\n")))
result = True
elif self.pkg_name == 'rpm' or self.pkg_name == 'suse' or self.pkg_name == 'mageia':
if self.pkg_name == 'suse' or self.pkg_name == 'mageia':
require = "python3-qt5, parted, util-linux, pkexec, mtools"
else:
require = "PyQt5, parted, util-linux, mtools"
setup_cfg = ("[bdist_rpm]\n"
"Group = Applications/System\n"
"Vendor = Sundar <feedback.multibootusb@gmail.com>\n"
"Requires = " + require)
with open("setup.cfg", "w") as f:
f.write(setup_cfg)
if subprocess.call('python3 setup.py bdist_rpm', shell=True) == 0 and \
os.path.exists(os.path.join("dist", "multibootusb-" + self.version + "-1.noarch.rpm")):
if self.pkg_name == 'suse':
package = "multibootusb-" + self.version + "-1suse.noarch.rpm"
elif self.pkg_name == 'mageia':
package = "multibootusb-" + self.version + "-1mageia.noarch.rpm"
else:
package = "multibootusb-" + self.version + "-1.noarch.rpm"
try:
shutil.copy2(os.path.join("dist", "multibootusb-" + self.version + "-1.noarch.rpm"),
os.path.join(self.release_upload_dir, "Linux", package))
except:
os.system('cp -rf ' + os.path.join("dist", "multibootusb-" + self.version + "-1.noarch.rpm") + ' ' +
os.path.join(self.release_upload_dir, "Linux", package))
if os.path.exists("setup.cfg"):
os.remove("setup.cfg")
print("\n\n\nRPM package has been created and can be found here::")
print((os.path.join("dist", "multibootusb-" + self.version + "-1.noarch.rpm\n\n\n")))
result = True
elif self.pkg_name == "exe":
if not platform.system() == "Windows":
print("You can generate windows executable from windows host only.")
else:
# subprocess.call('python ' + pyinstaller_path + ' --upx-dir C:\\upx multibootusb.spec', shell=True) == 0 and \
# os.path.exists(os.path.join("dist", 'multibootusb-' + self.version + ".exe")):
if subprocess.call('python ' + pyinstaller_path + ' --windowed multibootusb.spec', shell=True) == 0 and \
os.path.exists(os.path.join("dist", 'multibootusb-' + self.version + ".exe")):
shutil.copy2(os.path.join("dist", 'multibootusb-' + self.version + ".exe"),
os.path.join(self.release_upload_dir, "Windows"))
print("\n\n\nWindows binary has been created and can be found here::")
print((os.path.join("dist", "multibootusb-" + self.version + ".exe\n\n\n")))
result = True
elif self.pkg_name == 'install':
if subprocess.call("python3", "install.py", shell=True) == 0:
print("Installation is successful.")
result = True
elif self.pkg_name == 'src':
package = "multibootusb-" + self.version + ".tar.gz"
if subprocess.call('python3 setup.py sdist', shell=True) == 0 and \
os.path.exists(os.path.join("dist", "multibootusb-" + self.version + ".tar.gz")):
try:
shutil.copy2(os.path.join("dist", "multibootusb-" + self.version + ".tar.gz"),
os.path.join(self.release_upload_dir, "Source"), follow_symlinks=False)
except:
os.system('cp -rf ' + os.path.join("dist", package) + ' ' + os.path.join(self.release_upload_dir, "Source", package))
print("\n\n\nSource package has been created and can be found here::")
print((os.path.join("dist", "multibootusb-" + self.version + ".tar.gz\n\n\n")))
result = True
elif self.pkg_name == 'run':
subprocess.call(['python3', 'multibootusb'])
elif self.pkg_name == 'clean':
self.clean_dir()
elif self.pkg_name == "upload":
self.upload()
else:
print("Option not found.")
usage()
'''
if result:
return result
'''
def upload(self):
if platform.system() == "Windows":
print("You can upload to SF only from Linux as it needs rsync.")
else:
print("Uploading files...")
cmd = "rsync --rsh=ssh -l -p -r -t -z --stats /media/sundar/Data/multibootusb/release/" + self.version + " " + sourceforge_release_path
if os.system(cmd) == 0:
print((bcolors.OKGREEN + "\n\nVersion " + self.version + " has been successfully uploaded to SF.\n\n" + bcolors.ENDC))
else:
print((bcolors.FAIL + "\n\n\nError while uploading to SF.\n\n\n" + bcolors.ENDC))
def clean_dir(self):
if not os.path.exists('build') and not os.path.exists('dist') and not os.path.exists('deb_dist'):
print("Already clean. Nothing to do.")
else:
dir_list = ["build", "dist", "deb_dist"]
if os.path.exists('MANIFEST'):
self.deleteFile('MANIFEST')
for directory in dir_list:
if os.path.exists(directory):
shutil.rmtree(directory)
print("Cleaning pthon byte files...")
for path, subdirs, files in os.walk(os.curdir):
# print subdirs
for name in files:
if name.endswith('.pyc'):
print(("Cleaning " + os.path.join(path, name)))
os.chmod(os.path.join(path, name), 0o777)
os.unlink(os.path.join(path, name))
# os.remove(os.path.join(path,name))
def deleteDirectory(self, path):
try:
for files in os.listdir(path):
if os.path.isdir(os.path.join(path, files)):
# print (os.path.join(path, files))
os.chmod(os.path.join(path, files), 0o777)
shutil.rmtree(os.path.join(path, files))
else:
# print (os.path.join(path, files))
os.chmod(os.path.join(path, files), 0o777)
os.unlink(os.path.join(path, files))
os.remove(os.path.join(path, files))
if os.path.exists(path):
print("Path exist.")
os.rmdir(path)
shutil.rmtree(path)
else:
print("Path exist.")
except OSError as ose:
# Ignore 'no such file or directory' errors
if ose.errno != 2:
print("OS Error.")
# Useful to delete files.
def deleteFile(self, path):
try:
os.unlink(path)
except OSError as ose:
if ose.errno != 2:
print(ose)
def usage():
""" Prompt users how to use """
print ("Invalid option(s)\n"
"Possible options are ::\n"
"\033[94mexe\033[0m <-- For making Windows/ Linux standalone executable using pyinstaller\n"
"\033[94mdeb\033[0m <-- For making creating package for debian/ubuntu\n"
"\033[94mrpm\033[0m <-- For creating package for fedora/redhat/centos\n"
"\033[94msuse\033[0m <-- For creating package for OpenSuse\n"
"\033[94mmageia\033[0m <-- For creating package for mageia/mandriva\n"
"\033[94msrc\033[0m <-- For creating source package for other distributions\n"
"\033[94mall\033[0m <-- For creating package for all distros\n"
"\033[94mclean\033[0m <-- For Cleaning dist, build directory and other temp/python byte files\n"
"\033[94minstall\033[0m <-- Directly install from source package\n"
"\033[94mrun\033[0m <-- Directly run multibootusb from source package\n"
"\033[92mupload\033[0m <-- Upload package directory to SourceForge")
sys.exit(-1)
if __name__ == '__main__':
argv = sys.argv
if not os.path.exists(release_dir):
print("Release directory does not exist.\nPlease mount and rerun the script.")
sys.exit(1)
elif not os.path.exists(pyinstaller_path):
print("Pyinstaller path does not exist.\nPlease correct the path and rerun the script.")
sys.exit(1)
if len(argv) == 1:
usage()
else:
argv = argv[1]
if argv == "all":
all_arug = ["clean", "exe", "deb", "rpm", "suse", "mageia", "src"]
for package_name in all_arug:
print(("Creating package for argument " + package_name))
build = pkg(package_name)
build.build_package()
else:
build = pkg(argv)
build.build_package()

@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Name=multibootusb
Comment=Install multiple Linux Operating System on USB
Icon=multibootusb.png
Exec=multibootusb-pkexec
Categories=System;
StartupNotify=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,35 @@
# This file is created by MultiBootUSB.
default vesamenu.c32
prompt 0
menu title MultiBootUSB
MENU BACKGROUND /multibootusb/bg.png
TIMEOUT 300
MENU WIDTH 80
MENU MARGIN 10
MENU PASSWORDMARGIN 3
MENU ROWS 12
MENU TABMSGROW 18
MENU CMDLINEROW 18
MENU ENDROW -1
MENU PASSWORDROW 11
MENU TIMEOUTROW 20
MENU HELPMSGROW 22
MENU HELPMSGENDROW -1
MENU HIDDENROW -2
MENU HSHIFT 0
MENU VSHIFT 0
MENU COLOR border 30;44 #40ffffff #a0000000 std
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
MENU COLOR help 37;40 #c0ffffff #a0000000 std
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
label Boot from Hard Drive
MENU LABEL Boot from Hard Disk
KERNEL chain.c32
APPEND hd1
MENU DEFAULT

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,98 @@
# generated from XKB map ar
include common
map 0x401
exclam 0x02 shift
at 0x03 shift
numbersign 0x04 shift
dollar 0x05 shift
percent 0x06 shift
asciicircum 0x07 shift
ampersand 0x08 shift
asterisk 0x09 shift
parenleft 0x0a shift
parenright 0x0b shift
minus 0x0c
underscore 0x0c shift
equal 0x0d
plus 0x0d shift
Arabic_dad 0x10 altgr
Arabic_fatha 0x10 shift altgr
Arabic_sad 0x11 altgr
Arabic_fathatan 0x11 shift altgr
Arabic_theh 0x12 altgr
Arabic_damma 0x12 shift altgr
Arabic_qaf 0x13 altgr
Arabic_dammatan 0x13 shift altgr
Arabic_feh 0x14 altgr
UFEF9 0x14 shift altgr
Arabic_ghain 0x15 altgr
Arabic_hamzaunderalef 0x15 shift altgr
Arabic_ain 0x16 altgr
grave 0x16 shift altgr
Arabic_ha 0x17 altgr
division 0x17 shift altgr
Arabic_khah 0x18 altgr
multiply 0x18 shift altgr
Arabic_hah 0x19 altgr
Arabic_semicolon 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
Arabic_jeem 0x1a altgr
bracketright 0x1b
braceright 0x1b shift
Arabic_dal 0x1b altgr
Arabic_sheen 0x1e altgr
backslash 0x1e shift altgr
Arabic_seen 0x1f altgr
Arabic_yeh 0x20 altgr
bracketleft 0x20 shift altgr
Arabic_beh 0x21 altgr
bracketright 0x21 shift altgr
Arabic_lam 0x22 altgr
UFEF7 0x22 shift altgr
Arabic_alef 0x23 altgr
Arabic_hamzaonalef 0x23 shift altgr
Arabic_teh 0x24 altgr
Arabic_tatweel 0x24 shift altgr
Arabic_noon 0x25 altgr
Arabic_comma 0x25 shift altgr
Arabic_meem 0x26 altgr
slash 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
Arabic_kaf 0x27 altgr
apostrophe 0x28
quotedbl 0x28 shift
Arabic_tah 0x28 altgr
grave 0x29
asciitilde 0x29 shift
Arabic_thal 0x29 altgr
Arabic_shadda 0x29 shift altgr
backslash 0x2b
bar 0x2b shift
less 0x2b altgr
greater 0x2b shift altgr
Arabic_hamzaonyeh 0x2c altgr
asciitilde 0x2c shift altgr
Arabic_hamza 0x2d altgr
Arabic_sukun 0x2d shift altgr
Arabic_hamzaonwaw 0x2e altgr
Arabic_kasra 0x2e shift altgr
Arabic_ra 0x2f altgr
Arabic_kasratan 0x2f shift altgr
UFEFB 0x30 altgr
UFEF5 0x30 shift altgr
Arabic_alefmaksura 0x31 altgr
Arabic_maddaonalef 0x31 shift altgr
Arabic_tehmarbuta 0x32 altgr
apostrophe 0x32 shift altgr
comma 0x33
less 0x33 shift
Arabic_waw 0x33 altgr
period 0x34
greater 0x34 shift
Arabic_zain 0x34 altgr
slash 0x35
question 0x35 shift
Arabic_zah 0x35 altgr
Arabic_question_mark 0x35 shift altgr

@ -0,0 +1,157 @@
include modifiers
#
# Top row
#
1 0x2
2 0x3
3 0x4
4 0x5
5 0x6
6 0x7
7 0x8
8 0x9
9 0xa
0 0xb
BackSpace 0xe
#
# QWERTY first row
#
Tab 0xf localstate
ISO_Left_Tab 0xf shift
q 0x10 addupper
w 0x11 addupper
e 0x12 addupper
r 0x13 addupper
t 0x14 addupper
y 0x15 addupper
u 0x16 addupper
i 0x17 addupper
o 0x18 addupper
p 0x19 addupper
#
# QWERTY second row
#
a 0x1e addupper
s 0x1f addupper
d 0x20 addupper
f 0x21 addupper
g 0x22 addupper
h 0x23 addupper
j 0x24 addupper
k 0x25 addupper
l 0x26 addupper
Return 0x1c localstate
#
# QWERTY third row
#
z 0x2c addupper
x 0x2d addupper
c 0x2e addupper
v 0x2f addupper
b 0x30 addupper
n 0x31 addupper
m 0x32 addupper
space 0x39 localstate
less 0x56
greater 0x56 shift
bar 0x56 altgr
brokenbar 0x56 shift altgr
#
# Esc and Function keys
#
Escape 0x1 localstate
F1 0x3b localstate
F2 0x3c localstate
F3 0x3d localstate
F4 0x3e localstate
F5 0x3f localstate
F6 0x40 localstate
F7 0x41 localstate
F8 0x42 localstate
F9 0x43 localstate
F10 0x44 localstate
F11 0x57 localstate
F12 0x58 localstate
# Printscreen, Scrollock and Pause
# Printscreen really requires four scancodes (0xe0, 0x2a, 0xe0, 0x37),
# but (0xe0, 0x37) seems to work.
Print 0xb7 localstate
Sys_Req 0xb7 localstate
Execute 0xb7 localstate
Scroll_Lock 0x46
#
# Insert - PgDown
#
Insert 0xd2 localstate
Delete 0xd3 localstate
Home 0xc7 localstate
End 0xcf localstate
Page_Up 0xc9 localstate
Page_Down 0xd1 localstate
#
# Arrow keys
#
Left 0xcb localstate
Up 0xc8 localstate
Down 0xd0 localstate
Right 0xcd localstate
#
# Numpad
#
Num_Lock 0x45
KP_Divide 0xb5
KP_Multiply 0x37
KP_Subtract 0x4a
KP_Add 0x4e
KP_Enter 0x9c
KP_Decimal 0x53 numlock
KP_Separator 0x53 numlock
KP_Delete 0x53
KP_0 0x52 numlock
KP_Insert 0x52
KP_1 0x4f numlock
KP_End 0x4f
KP_2 0x50 numlock
KP_Down 0x50
KP_3 0x51 numlock
KP_Next 0x51
KP_4 0x4b numlock
KP_Left 0x4b
KP_5 0x4c numlock
KP_Begin 0x4c
KP_6 0x4d numlock
KP_Right 0x4d
KP_7 0x47 numlock
KP_Home 0x47
KP_8 0x48 numlock
KP_Up 0x48
KP_9 0x49 numlock
KP_Prior 0x49
Caps_Lock 0x3a
#
# Inhibited keys
#
Multi_key 0x0 inhibit

@ -0,0 +1,120 @@
# generated from XKB map dk
include common
map 0x406
exclam 0x02 shift
exclamdown 0x02 altgr
onesuperior 0x02 shift altgr
quotedbl 0x03 shift
at 0x03 altgr
twosuperior 0x03 shift altgr
numbersign 0x04 shift
sterling 0x04 altgr
threesuperior 0x04 shift altgr
currency 0x05 shift
dollar 0x05 altgr
onequarter 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
cent 0x06 shift altgr
ampersand 0x07 shift
yen 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
division 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
guillemotleft 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
guillemotright 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
plus 0x0c
question 0x0c shift
plusminus 0x0c altgr
questiondown 0x0c shift altgr
dead_acute 0x0d
dead_grave 0x0d shift
bar 0x0d altgr
brokenbar 0x0d shift altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
cent 0x12 shift altgr
registered 0x13 altgr
thorn 0x14 altgr
THORN 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oe 0x18 altgr
OE 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
aring 0x1a
Aring 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
dead_diaeresis 0x1b
dead_circumflex 0x1b shift
dead_tilde 0x1b altgr
dead_caron 0x1b shift altgr
ordfeminine 0x1e altgr
masculine 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
ae 0x27
AE 0x27 shift
oslash 0x28
Ooblique 0x28 shift
dead_caron 0x28 shift altgr
onehalf 0x29
section 0x29 shift
threequarters 0x29 altgr
paragraph 0x29 shift altgr
apostrophe 0x2b
asterisk 0x2b shift
dead_doubleacute 0x2b altgr
multiply 0x2b shift altgr
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
copyright 0x2e altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
dead_cedilla 0x33 altgr
dead_ogonek 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
dead_abovedot 0x34 shift altgr
minus 0x35
underscore 0x35 shift
hyphen 0x35 altgr
macron 0x35 shift altgr
nobreakspace 0x39 altgr
less 0x56
greater 0x56 shift
backslash 0x56 altgr
notsign 0x56 shift altgr

@ -0,0 +1,114 @@
# generated from XKB map de
include common
map 0x407
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
quotedbl 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
section 0x04 shift
threesuperior 0x04 altgr
sterling 0x04 shift altgr
dollar 0x05 shift
onequarter 0x05 altgr
currency 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
ssharp 0x0c
question 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
acute 0x0d
dead_acute 0x0d
grave 0x0d shift
dead_grave 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
z 0x15 addupper
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
udiaeresis 0x1a
Udiaeresis 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
plus 0x1b
asterisk 0x1b shift
asciitilde 0x1b altgr
dead_tilde 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
odiaeresis 0x27
Odiaeresis 0x27 shift
dead_doubleacute 0x27 altgr
adiaeresis 0x28
Adiaeresis 0x28 shift
dead_caron 0x28 shift altgr
asciicircum 0x29
dead_circumflex 0x29
degree 0x29 shift
notsign 0x29 altgr
numbersign 0x2b
apostrophe 0x2b shift
dead_breve 0x2b shift altgr
y 0x2c addupper
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,169 @@
# rdesktop Swiss-German (de-ch) keymap file
# 2003-06-03 by noldi@tristar.ch
#
include common
map 0x00000807
#
# Scan Code 1
section 0x29
degree 0x29 shift
notsign 0x29 altgr inhibit
#
# Scan Code 2
plus 0x2 shift
brokenbar 0x02 altgr
#
# Scan Code 3
quotedbl 0x03 shift
at 0x03 altgr
#
# Scan Code 4
asterisk 0x04 shift
numbersign 0x04 altgr
#
# Scan Code 5
ccedilla 0x05 shift
onequarter 0x05 altgr inhibit
#
# Scan Code 6
percent 0x06 shift
onehalf 0x06 altgr inhibit
#
# Scan Code 7
ampersand 0x07 shift
notsign 0x07 altgr
#
# Scan Code 8
slash 0x08 shift
bar 0x08 altgr
#
# Scan Code 9
parenleft 0x09 shift
cent 0x09 altgr
#
# Scan Code 10
parenright 0x0a shift
#
# Scan Code 11
equal 0x0b shift
braceright 0x0b altgr inhibit
#
# Scan Code 12
apostrophe 0x0c
question 0x0c shift
dead_acute 0x0c altgr
#
# Scan Code 13
dead_circumflex 0x0d
dead_grave 0x0d shift
dead_tilde 0x0d altgr
#
# Scan Code 19
EuroSign 0x12 altgr
#
# Scan Code 22
z 0x15 addupper
#
# Scan Code 27
udiaeresis 0x1a
egrave 0x1a shift
bracketleft 0x1a altgr
#
# Scan Code 28
dead_diaeresis 0x1b
exclam 0x1b shift
bracketright 0x1b altgr
#
# Scan Code 40
odiaeresis 0x27
eacute 0x27 shift
#
# Scan Code 41
adiaeresis 0x28
agrave 0x28 shift
braceleft 0x28 altgr
#
# Scan Code 42 (only on international keyboards)
dollar 0x2b
sterling 0x2b shift
braceright 0x2b altgr
#
# Scan Code 45 (only on international keyboards)
backslash 0x56 altgr
#
# Scan Code 46
y 0x2c addupper
#
# Scan Code 53
comma 0x33
semicolon 0x33 shift
#
# Scan Code 54
period 0x34
colon 0x34 shift
#
# Scan Code 55
minus 0x35
underscore 0x35 shift
#
# Suppress Windows unsupported AltGr keys
#
# Scan Code 17
paragraph 0x10 altgr inhibit
#
# Scan Code 21
tslash 0x14 altgr inhibit
#
# Scan Code 22
leftarrow 0x15 altgr inhibit
#
# Scan Code 23
downarrow 0x16 altgr inhibit
#
# Scan Code 24
rightarrow 0x17 altgr inhibit
#
# Scan Code 25
oslash 0x18 altgr inhibit
#
# Scan Code 26
thorn 0x19 altgr inhibit
#
# Scan Code 31
ae 0x1e altgr inhibit
#
# Scan Code 32
ssharp 0x1f altgr inhibit
#
# Scan Code 33
eth 0x20 altgr inhibit
#
# Scan Code 34
dstroke 0x21 altgr inhibit
#
# Scan Code 35
eng 0x22 altgr inhibit
#
# Scan Code 36
hstroke 0x23 altgr inhibit
#
# Scan Code 38
kra 0x25 altgr inhibit
#
# Scan Code 39
lstroke 0x26 altgr inhibit
#
# Scan Code 46
guillemotleft 0x2c altgr inhibit
#
# Scan Code 47
guillemotright 0x2d altgr inhibit
#
# Scan Code 49
leftdoublequotemark 0x2f altgr inhibit
#
# Scan Code 50
rightdoublequotemark 0x30 altgr inhibit
#
# Scan Code 52
mu 0x32 altgr inhibit

@ -0,0 +1,119 @@
# generated from XKB map gb
include common
map 0x809
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
quotedbl 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
sterling 0x04 shift
threesuperior 0x04 altgr
dollar 0x05 shift
EuroSign 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
asciicircum 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
ampersand 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
asterisk 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenleft 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
parenright 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
minus 0x0c
underscore 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
equal 0x0d
plus 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
bracketright 0x1b
braceright 0x1b shift
dead_tilde 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
dead_acute 0x27 altgr
dead_doubleacute 0x27 shift altgr
apostrophe 0x28
at 0x28 shift
dead_circumflex 0x28 altgr
dead_caron 0x28 shift altgr
grave 0x29
notsign 0x29 shift
bar 0x29 altgr
numbersign 0x2b
asciitilde 0x2b shift
dead_grave 0x2b altgr
dead_breve 0x2b shift altgr
guillemotleft 0x2c altgr
less 0x2c shift altgr
guillemotright 0x2d altgr
greater 0x2d shift altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
less 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
greater 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
slash 0x35
question 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr
backslash 0x56
bar 0x56 shift

@ -0,0 +1,35 @@
# generated from XKB map us
include common
map 0x409
exclam 0x02 shift
at 0x03 shift
numbersign 0x04 shift
dollar 0x05 shift
percent 0x06 shift
asciicircum 0x07 shift
ampersand 0x08 shift
asterisk 0x09 shift
parenleft 0x0a shift
parenright 0x0b shift
minus 0x0c
underscore 0x0c shift
equal 0x0d
plus 0x0d shift
bracketleft 0x1a
braceleft 0x1a shift
bracketright 0x1b
braceright 0x1b shift
semicolon 0x27
colon 0x27 shift
apostrophe 0x28
quotedbl 0x28 shift
grave 0x29
asciitilde 0x29 shift
backslash 0x2b
bar 0x2b shift
comma 0x33
less 0x33 shift
period 0x34
greater 0x34 shift
slash 0x35
question 0x35 shift

@ -0,0 +1,105 @@
# generated from XKB map es
include common
map 0x40a
exclam 0x02 shift
bar 0x02 altgr
quotedbl 0x03 shift
at 0x03 altgr
oneeighth 0x03 shift altgr
periodcentered 0x04 shift
numbersign 0x04 altgr
sterling 0x04 shift altgr
dollar 0x05 shift
asciitilde 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
notsign 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
seveneighths 0x08 shift altgr
parenleft 0x09 shift
trademark 0x09 shift altgr
parenright 0x0a shift
plusminus 0x0a shift altgr
equal 0x0b shift
degree 0x0b shift altgr
apostrophe 0x0c
question 0x0c shift
exclamdown 0x0d
questiondown 0x0d shift
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
dead_grave 0x1a
dead_circumflex 0x1a shift
bracketleft 0x1a altgr
dead_abovering 0x1a shift altgr
plus 0x1b
asterisk 0x1b shift
bracketright 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
ntilde 0x27
Ntilde 0x27 shift
dead_doubleacute 0x27 shift altgr
dead_acute 0x28
dead_diaeresis 0x28 shift
braceleft 0x28 altgr
masculine 0x29
ordfeminine 0x29 shift
backslash 0x29 altgr
ccedilla 0x2b
Ccedilla 0x2b shift
braceright 0x2b altgr
dead_breve 0x2b shift altgr
guillemotleft 0x2c altgr
less 0x56
greater 0x56 shift
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
division 0x34 shift altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,86 @@
map 0x00000425
include common
#
# Top row
#
dead_caron 0x29
dead_tilde 0x29 shift
# 1
exclam 0x2 shift
# 2
quotedbl 0x3 shift
at 0x3 altgr
# 3
numbersign 0x4 shift
sterling 0x4 altgr
# 4
currency 0x5 shift
dollar 0x5 altgr
# 5
percent 0x6 shift
# 6
ampersand 0x7 shift
# 7
slash 0x8 shift
braceleft 0x8 altgr
# 8
parenleft 0x9 shift
bracketleft 0x9 altgr
# 9
parenright 0xa shift
bracketright 0xa altgr
# 0
equal 0xb shift
braceright 0xb altgr
plus 0xc
question 0xc shift
backslash 0xc altgr
acute 0xd
dead_acute 0xd
grave 0xd shift
dead_grave 0xd shift
#
# QWERTY first row
#
EuroSign 0x12 altgr
udiaeresis 0x1a
Udiaeresis 0x1a shift
otilde 0x1b
Otilde 0x1b shift
section 0x1b altgr
#
# QWERTY second row
#
scaron 0x1f altgr
Scaron 0x1f altgr shift
odiaeresis 0x27
Odiaeresis 0x27 shift
adiaeresis 0x28
Adiaeresis 0x28 shift
asciicircum 0x28 altgr
apostrophe 0x2b
asterisk 0x2b shift
onehalf 0x2b altgr
#
# QWERTY third row
#
less 0x56
greater 0x56 shift
bar 0x56 altgr
zcaron 0x2c altgr
Zcaron 0x2c altgr shift
comma 0x33
semicolon 0x33 shift
period 0x34
colon 0x34 shift
minus 0x35
underscore 0x35 shift

@ -0,0 +1,124 @@
# generated from XKB map se_FI
include common
map 0x40b
exclam 0x02 shift
exclamdown 0x02 altgr
onesuperior 0x02 shift altgr
quotedbl 0x03 shift
at 0x03 altgr
twosuperior 0x03 shift altgr
numbersign 0x04 shift
sterling 0x04 altgr
threesuperior 0x04 shift altgr
currency 0x05 shift
dollar 0x05 altgr
onequarter 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
cent 0x06 shift altgr
ampersand 0x07 shift
yen 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
division 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
guillemotleft 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
guillemotright 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
plus 0x0c
question 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
dead_acute 0x0d
dead_grave 0x0d shift
plusminus 0x0d altgr
notsign 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
cent 0x12 shift altgr
registered 0x13 altgr
thorn 0x14 altgr
THORN 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oe 0x18 altgr
OE 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
aring 0x1a
Aring 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
dead_diaeresis 0x1b
dead_circumflex 0x1b shift
dead_tilde 0x1b altgr
dead_caron 0x1b shift altgr
ordfeminine 0x1e altgr
masculine 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
ampersand 0x25 shift altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
odiaeresis 0x27
Odiaeresis 0x27 shift
oslash 0x27 altgr
Ooblique 0x27 shift altgr
adiaeresis 0x28
Adiaeresis 0x28 shift
ae 0x28 altgr
AE 0x28 shift altgr
section 0x29
onehalf 0x29 shift
paragraph 0x29 altgr
threequarters 0x29 shift altgr
apostrophe 0x2b
asterisk 0x2b shift
acute 0x2b altgr
multiply 0x2b shift altgr
guillemotleft 0x2c altgr
less 0x2c shift altgr
guillemotright 0x2d altgr
greater 0x2d shift altgr
copyright 0x2e altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
apostrophe 0x30 shift altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
dead_cedilla 0x33 altgr
dead_ogonek 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
dead_abovedot 0x34 shift altgr
minus 0x35
underscore 0x35 shift
hyphen 0x35 altgr
macron 0x35 shift altgr
nobreakspace 0x39 altgr

@ -0,0 +1,77 @@
map 0x438
include common
#
# Top row
#
onehalf 0x29
section 0x29 shift
# 1
exclam 0x2 shift
# 2
quotedbl 0x3 shift
at 0x3 altgr
# 3
numbersign 0x4 shift
sterling 0x4 altgr
# 4
currency 0x5 shift
dollar 0x5 altgr
# 5
percent 0x6 shift
# 6
ampersand 0x7 shift
# 7
slash 0x8 shift
braceleft 0x8 altgr
# 8
parenleft 0x9 shift
bracketleft 0x9 altgr
# 9
parenright 0xa shift
bracketright 0xa altgr
# 0
equal 0xb shift
braceright 0xb altgr
plus 0xc
question 0xc shift
plusminus 0xc altgr
bar 0xd altgr
dead_acute 0xd
#
# QWERTY first row
#
EuroSign 0x12 altgr
aring 0x1a
Aring 0x1a shift
eth 0x1b addupper
asciitilde 0x1b altgr
#
# QWERTY second row
#
ae 0x27 addupper
oslash 0x28
Ooblique 0x28 shift
apostrophe 0x2b
asterisk 0x2b shift
#
# QWERTY third row
#
less 0x56
greater 0x56 shift
backslash 0x56 altgr
comma 0x33
semicolon 0x33 shift
period 0x34
colon 0x34 shift
minus 0x35
underscore 0x35 shift

@ -0,0 +1,181 @@
include common
map 0x40c
#
# Top row
#
twosuperior 0x29
notsign 0x29 altgr
ampersand 0x02
1 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
eacute 0x03
2 0x03 shift
asciitilde 0x03 altgr
oneeighth 0x03 shift altgr
quotedbl 0x04
3 0x04 shift
numbersign 0x04 altgr
apostrophe 0x05
4 0x05 shift
braceleft 0x05 altgr
parenleft 0x06
5 0x06 shift
bracketleft 0x06 altgr
threeeighths 0x06 shift altgr
minus 0x07
6 0x07 shift
bar 0x07 altgr
fiveeighths 0x07 shift altgr
egrave 0x08
7 0x08 shift
grave 0x08 altgr
seveneighths 0x08 shift altgr
underscore 0x09
8 0x09 shift
backslash 0x09 altgr
trademark 0x09 shift altgr
ccedilla 0x0a
9 0x0a shift
asciicircum 0x0a altgr
plusminus 0x0a shift altgr
agrave 0x0b
0 0x0b shift
at 0x0b altgr
parenright 0x0c
degree 0x0c shift
bracketright 0x0c altgr
questiondown 0x0c shift altgr
equal 0x0d
plus 0x0d shift
braceright 0x0d altgr
dead_ogonek 0x0d shift altgr
#
# AZERTY first row
#
a 0x10 addupper
ae 0x10 altgr
AE 0x10 shift altgr
z 0x11 addupper
guillemotleft 0x11 altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
dead_circumflex 0x1a
dead_diaeresis 0x1a shift
dead_abovering 0x1a shift altgr
dollar 0x1b
sterling 0x1b shift
currency 0x1b altgr
dead_macron 0x1b shift altgr
#
# AZERTY second row
#
q 0x1e addupper
Greek_OMEGA 0x1e shift altgr
ssharp 0x1f altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
m 0x27 addupper
masculine 0x27 shift altgr
ugrave 0x28
percent 0x28 shift
dead_caron 0x28 shift altgr
asterisk 0x2b
mu 0x2b shift
dead_grave 0x2b altgr
dead_breve 0x2b shift altgr
#
# AZERTY third row
#
less 0x56
greater 0x56 shift
w 0x2c addupper
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
rightdoublequotemark 0x30 altgr
comma 0x32
question 0x32 shift
dead_acute 0x32 altgr
dead_doubleacute 0x32 shift altgr
semicolon 0x33
period 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
colon 0x34
slash 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
exclam 0x35
section 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,140 @@
# generated from XKB map be
include common
map 0x80c
ampersand 0x02
1 0x02 shift
bar 0x02 altgr
exclamdown 0x02 shift altgr
eacute 0x03
2 0x03 shift
at 0x03 altgr
oneeighth 0x03 shift altgr
quotedbl 0x04
3 0x04 shift
numbersign 0x04 altgr
sterling 0x04 shift altgr
apostrophe 0x05
4 0x05 shift
onequarter 0x05 altgr
dollar 0x05 shift altgr
parenleft 0x06
5 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
section 0x07
6 0x07 shift
asciicircum 0x07 altgr
fiveeighths 0x07 shift altgr
egrave 0x08
7 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
exclam 0x09
8 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
ccedilla 0x0a
9 0x0a shift
braceleft 0x0a altgr
plusminus 0x0a shift altgr
agrave 0x0b
0 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
parenright 0x0c
degree 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
minus 0x0d
underscore 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
a 0x10 addupper
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
z 0x11 addupper
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
cent 0x12 shift altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
dead_circumflex 0x1a
dead_diaeresis 0x1a shift
bracketleft 0x1a altgr
dead_abovering 0x1a shift altgr
dollar 0x1b
asterisk 0x1b shift
bracketright 0x1b altgr
dead_macron 0x1b shift altgr
q 0x1e addupper
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
ampersand 0x25 shift altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
m 0x27 addupper
dead_acute 0x27 altgr
dead_doubleacute 0x27 shift altgr
ugrave 0x28
percent 0x28 shift
dead_acute 0x28 altgr
dead_caron 0x28 shift altgr
twosuperior 0x29
threesuperior 0x29 shift
notsign 0x29 altgr
mu 0x2b
sterling 0x2b shift
dead_grave 0x2b altgr
dead_breve 0x2b shift altgr
w 0x2c addupper
guillemotleft 0x2c altgr
less 0x2c shift altgr
guillemotright 0x2d altgr
greater 0x2d shift altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
apostrophe 0x30 shift altgr
comma 0x32
question 0x32 shift
dead_cedilla 0x32 altgr
masculine 0x32 shift altgr
semicolon 0x33
period 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
colon 0x34
slash 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
equal 0x35
plus 0x35 shift
dead_tilde 0x35 altgr
dead_abovedot 0x35 shift altgr
backslash 0x56 altgr

@ -0,0 +1,50 @@
# Canadian French
# By Simon Germain
include common
map 0xc0c
backslash 0x29 altgr
plusminus 0x2 altgr
at 0x3 altgr
sterling 0x4 altgr
cent 0x5 altgr
currency 0x6 altgr
notsign 0x7 altgr
bar 0x29 shift
twosuperior 0x9 altgr
threesuperior 0xa altgr
onequarter 0xb altgr
onehalf 0xc altgr
threequarters 0xd altgr
section 0x18 altgr
paragraph 0x19 altgr
bracketleft 0x1a altgr
bracketright 0x1b altgr
asciitilde 0x27 altgr
braceleft 0x28 altgr
braceright 0x2b altgr
less 0x2b
greater 0x2b shift
guillemotleft 0x56
guillemotright 0x56 shift
degree 0x56 altgr
mu 0x32 altgr
eacute 0x35
dead_acute 0x35 altgr
dead_grave 0x28
dead_circumflex 0x1a
dead_circumflex 0x1a shift
dead_cedilla 0x1b
dead_diaeresis 0x1b shift
exclam 0x2 shift
quotedbl 0x3 shift
slash 0x4 shift
dollar 0x5 shift
percent 0x6 shift
question 0x7 shift
ampersand 0x8 shift
asterisk 0x9 shift
parenleft 0xa shift
parenright 0xb shift
underscore 0xc shift
plus 0xd shift

@ -0,0 +1,114 @@
# generated from XKB map fr_CH
include common
map 0x100c
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
quotedbl 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
section 0x04 shift
threesuperior 0x04 altgr
sterling 0x04 shift altgr
dollar 0x05 shift
onequarter 0x05 altgr
currency 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
ssharp 0x0c
question 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
acute 0x0d
dead_acute 0x0d
grave 0x0d shift
dead_grave 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
z 0x15 addupper
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
udiaeresis 0x1a
Udiaeresis 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
plus 0x1b
asterisk 0x1b shift
asciitilde 0x1b altgr
dead_tilde 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
odiaeresis 0x27
Odiaeresis 0x27 shift
dead_doubleacute 0x27 altgr
adiaeresis 0x28
Adiaeresis 0x28 shift
dead_caron 0x28 shift altgr
asciicircum 0x29
dead_circumflex 0x29
degree 0x29 shift
notsign 0x29 altgr
numbersign 0x2b
apostrophe 0x2b shift
dead_breve 0x2b shift altgr
y 0x2c addupper
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,125 @@
# generated from XKB map hr
include common
map 0x41a
exclam 0x02 shift
asciitilde 0x02 altgr
dead_tilde 0x02 shift altgr
quotedbl 0x03 shift
dead_caron 0x03 altgr
caron 0x03 shift altgr
numbersign 0x04 shift
asciicircum 0x04 altgr
dead_circumflex 0x04 shift altgr
dollar 0x05 shift
dead_breve 0x05 altgr
breve 0x05 shift altgr
percent 0x06 shift
degree 0x06 altgr
dead_abovering 0x06 shift altgr
ampersand 0x07 shift
dead_ogonek 0x07 altgr
ogonek 0x07 shift altgr
slash 0x08 shift
grave 0x08 altgr
dead_grave 0x08 shift altgr
parenleft 0x09 shift
dead_abovedot 0x09 altgr
abovedot 0x09 shift altgr
parenright 0x0a shift
dead_acute 0x0a altgr
apostrophe 0x0a shift altgr
equal 0x0b shift
dead_doubleacute 0x0b altgr
doubleacute 0x0b shift altgr
apostrophe 0x0c
question 0x0c shift
dead_diaeresis 0x0c altgr
diaeresis 0x0c shift altgr
plus 0x0d
asterisk 0x0d shift
dead_cedilla 0x0d altgr
cedilla 0x0d shift altgr
backslash 0x10 altgr
Greek_OMEGA 0x10 shift altgr
bar 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
z 0x15 addupper
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
scaron 0x1a
Scaron 0x1a shift
division 0x1a altgr
dead_abovering 0x1a shift altgr
dstroke 0x1b
Dstroke 0x1b shift
multiply 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
bracketleft 0x21 altgr
ordfeminine 0x21 shift altgr
bracketright 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
lstroke 0x25 altgr
ampersand 0x25 shift altgr
Lstroke 0x26 altgr
ccaron 0x27
Ccaron 0x27 shift
dead_acute 0x27 altgr
dead_doubleacute 0x27 shift altgr
cacute 0x28
Cacute 0x28 shift
ssharp 0x28 altgr
dead_caron 0x28 shift altgr
dead_cedilla 0x29
dead_diaeresis 0x29 shift
notsign 0x29 altgr
zcaron 0x2b
Zcaron 0x2b shift
currency 0x2b altgr
dead_breve 0x2b shift altgr
y 0x2c addupper
guillemotleft 0x2c altgr
less 0x2c shift altgr
guillemotright 0x2d altgr
greater 0x2d shift altgr
cent 0x2e altgr
copyright 0x2e shift altgr
at 0x2f altgr
grave 0x2f shift altgr
braceleft 0x30 altgr
apostrophe 0x30 shift altgr
braceright 0x31 altgr
section 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,115 @@
# Hungarian keyboard layout (QWERTZ)
# Created by: The NeverGone <never@delfin.klte.hu>
include common
map 0x40e
# AltGr keys:
notsign 0x29 altgr
asciitilde 0x02 altgr
caron 0x03 altgr
asciicircum 0x04 altgr
breve 0x05 altgr
degree 0x06 altgr
ogonek 0x07 altgr
grave 0x08 altgr
abovedot 0x09 altgr
acute 0x0a altgr
doubleacute 0x0b altgr
diaeresis 0x0c altgr
cedilla 0x0d altgr
backslash 0x10 altgr
bar 0x11 altgr
EuroSign 0x12 altgr
Iacute 0x17 altgr
division 0x1a altgr
multiply 0x1b altgr
dstroke 0x1f altgr
Dstroke 0x20 altgr
bracketleft 0x21 altgr
bracketright 0x22 altgr
iacute 0x24 altgr
lstroke 0x25 altgr
Lstroke 0x26 altgr
dollar 0x27 altgr
ssharp 0x28 altgr
currency 0x2b altgr
less 0x56 altgr
greater 0x2c altgr
numbersign 0x2d altgr
ampersand 0x2e altgr
at 0x2f altgr
braceleft 0x30 altgr
braceright 0x31 altgr
semicolon 0x33 altgr
asterisk 0x35 altgr
# Shift keys:
section 0x29 shift
apostrophe 0x02 shift
quotedbl 0x03 shift
plus 0x04 shift
exclam 0x05 shift
percent 0x06 shift
slash 0x07 shift
equal 0x08 shift
parenleft 0x09 shift
parenright 0x0a shift
Odiaeresis 0x0b shift
Udiaeresis 0x0c shift
Oacute 0x0d shift
Z 0x15 shift
Odoubleacute 0x1a shift
Uacute 0x1b shift
Eacute 0x27 shift
Aacute 0x28 shift
Udoubleacute 0x2b shift
Y 0x2c shift
question 0x33 shift
colon 0x34 shift
underscore 0x35 shift
F13 0x3b shift
F14 0x3c shift
F15 0x3d shift
F16 0x3e shift
F17 0x3f shift
F18 0x40 shift
F19 0x41 shift
F20 0x42 shift
F21 0x43 shift
F22 0x44 shift
F23 0x57 shift
F24 0x58 shift
# Ctrl keys:
F25 0x3b ctrl
F26 0x3c ctrl
F27 0x3d ctrl
F28 0x3e ctrl
F29 0x3f ctrl
F30 0x40 ctrl
F31 0x41 ctrl
F32 0x42 ctrl
F33 0x43 ctrl
F34 0x44 ctrl
F35 0x57 ctrl
#NoSymbol 0x58 ctrl
0 0x29
odiaeresis 0x0b
udiaeresis 0x0c
oacute 0x0d
z 0x15
odoubleacute 0x1a
uacute 0x1b
eacute 0x27
aacute 0x28
udoubleacute 0x2b
y 0x2c
comma 0x33
period 0x34
minus 0x35

@ -0,0 +1,140 @@
# 2004-03-16 Halldór Guðmundsson and Morten Lange
# Keyboard definition file for the Icelandic keyboard
# to be used in rdesktop 1.3.x ( See rdesktop.org)
# generated from XKB map de, and changed manually
# Location for example /usr/local/share/rdesktop/keymaps/is
include common
map 0x40f
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
quotedbl 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
#section 0x04 shift
numbersign 0x04 shift
threesuperior 0x04 altgr
sterling 0x04 shift altgr
dollar 0x05 shift
onequarter 0x05 altgr
currency 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
#ssharp 0x0c
odiaeresis 0x0c
#question 0x0c shift
Odiaeresis 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
#acute 0x0d
minus 0x0d
#dead_acute 0x0d
#grave 0x0d shift
#dead_grave 0x0d shift
underscore 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
#z 0x15 addupper
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
#thorn 0x19 altgr
#THORN 0x19 shift altgr
#udiaeresis 0x1a
#Udiaeresis 0x1a shift
#dead_diaeresis 0x1a altgr
#dead_abovering 0x1a shift altgr
eth 0x1a
ETH 0x1a shift
apostrophe 0x1b
question 0x1b shift
#plus 0x1b
#asterisk 0x1b shift
asciitilde 0x1b altgr
#grave 0x1b altgr
#dead_tilde 0x1b altgr
#dead_macron 0x1b shift altgr
#ae 0x1e altgr
#AE 0x1e shift altgr
#eth 0x20 altgr
#eth 0x20
#ETH 0x20 shift altgr
#ETH 0x20 shift
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
#adiaeresis 0x27
#Adiaeresis 0x27 shift
ae 0x27
AE 0x27 shift
dead_doubleacute 0x27 altgr
#adiaeresis 0x28
#Adiaeresis 0x28 shift
#dead_caron 0x28 shift altgr
#asciicircum 0x29
acute 0x28
dead_acute 0x28
#dead_circumflex 0x29
#degree 0x29 shift
#notsign 0x29 altgr
plus 0x2b
asterisk 0x2b shift
grave 0x2b altgr
#numbersign 0x2b
#apostrophe 0x2b shift
#dead_breve 0x2b shift altgr
#y 0x2c addupper
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
#minus 0x35
#underscore 0x35 shift
thorn 0x35
THORN 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,115 @@
# generated from XKB map it
include common
map 0x410
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
quotedbl 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
sterling 0x04 shift
threesuperior 0x04 altgr
dollar 0x05 shift
onequarter 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
parenleft 0x09 shift
trademark 0x09 shift altgr
parenright 0x0a shift
plusminus 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
apostrophe 0x0c
question 0x0c shift
grave 0x0c altgr
questiondown 0x0c shift altgr
igrave 0x0d
asciicircum 0x0d shift
asciitilde 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
cent 0x12 shift altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
egrave 0x1a
eacute 0x1a shift
bracketleft 0x1a altgr
dead_abovering 0x1a shift altgr
plus 0x1b
asterisk 0x1b shift
bracketright 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
ograve 0x27
ccedilla 0x27 shift
at 0x27 altgr
dead_doubleacute 0x27 shift altgr
agrave 0x28
degree 0x28 shift
numbersign 0x28 altgr
backslash 0x29
bar 0x29 shift
notsign 0x29 altgr
ugrave 0x2b
section 0x2b shift
dead_grave 0x2b altgr
dead_breve 0x2b shift altgr
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,108 @@
# generated from XKB map jp106
include common
map 0x411
exclam 0x02 shift
kana_NU 0x02 altgr
quotedbl 0x03 shift
kana_FU 0x03 altgr
numbersign 0x04 shift
kana_A 0x04 altgr
kana_a 0x04 shift altgr
dollar 0x05 shift
kana_U 0x05 altgr
kana_u 0x05 shift altgr
percent 0x06 shift
kana_E 0x06 altgr
kana_e 0x06 shift altgr
ampersand 0x07 shift
kana_O 0x07 altgr
kana_o 0x07 shift altgr
apostrophe 0x08 shift
kana_YA 0x08 altgr
kana_ya 0x08 shift altgr
parenleft 0x09 shift
kana_YU 0x09 altgr
kana_yu 0x09 shift altgr
parenright 0x0a shift
kana_YO 0x0a altgr
kana_yo 0x0a shift altgr
asciitilde 0x0b shift
kana_WA 0x0b altgr
kana_WO 0x0b shift altgr
minus 0x0c
equal 0x0c shift
kana_HO 0x0c altgr
asciicircum 0x0d
asciitilde 0x0d shift
kana_HE 0x0d altgr
kana_TA 0x10 altgr
kana_TE 0x11 altgr
kana_I 0x12 altgr
kana_i 0x12 shift altgr
kana_SU 0x13 altgr
kana_KA 0x14 altgr
kana_N 0x15 altgr
kana_NA 0x16 altgr
kana_NI 0x17 altgr
kana_RA 0x18 altgr
kana_SE 0x19 altgr
at 0x1a
grave 0x1a shift
voicedsound 0x1a altgr
bracketleft 0x1b
braceleft 0x1b shift
semivoicedsound 0x1b altgr
kana_openingbracket 0x1b shift altgr
kana_CHI 0x1e altgr
kana_TO 0x1f altgr
kana_SHI 0x20 altgr
kana_HA 0x21 altgr
kana_KI 0x22 altgr
kana_KU 0x23 altgr
kana_MA 0x24 altgr
kana_NO 0x25 altgr
kana_RI 0x26 altgr
semicolon 0x27
plus 0x27 shift
kana_RE 0x27 altgr
colon 0x28
asterisk 0x28 shift
kana_KE 0x28 altgr
Zenkaku_Hankaku 0x29
bracketright 0x2b
braceright 0x2b shift
kana_MU 0x2b altgr
kana_closingbracket 0x2b shift altgr
kana_TSU 0x2c altgr
kana_tsu 0x2c shift altgr
kana_SA 0x2d altgr
kana_SO 0x2e altgr
kana_HI 0x2f altgr
kana_KO 0x30 altgr
kana_MI 0x31 altgr
kana_MO 0x32 altgr
comma 0x33
less 0x33 shift
kana_NE 0x33 altgr
kana_comma 0x33 shift altgr
period 0x34
greater 0x34 shift
kana_RU 0x34 altgr
kana_fullstop 0x34 shift altgr
slash 0x35
question 0x35 shift
kana_ME 0x35 altgr
kana_conjunctive 0x35 shift altgr
Eisu_toggle 0x3a shift
Execute 0x54 shift
Kanji 0x70
backslash 0x73
yen 0x7d
bar 0x7d shift
underscore 0x73 shift
Henkan_Mode 0x79
Katakana 0x70
Muhenkan 0x7b
Henkan_Mode_Real 0x79
Henkan_Mode_Ultra 0x79
backslash_ja 0x73

@ -0,0 +1,57 @@
# generated from XKB map lt
include common
map 0x427
exclam 0x02 shift
aogonek 0x02 altgr
Aogonek 0x02 shift altgr
at 0x03 shift
ccaron 0x03 altgr
Ccaron 0x03 shift altgr
numbersign 0x04 shift
eogonek 0x04 altgr
Eogonek 0x04 shift altgr
dollar 0x05 shift
eabovedot 0x05 altgr
Eabovedot 0x05 shift altgr
percent 0x06 shift
iogonek 0x06 altgr
Iogonek 0x06 shift altgr
asciicircum 0x07 shift
scaron 0x07 altgr
Scaron 0x07 shift altgr
ampersand 0x08 shift
uogonek 0x08 altgr
Uogonek 0x08 shift altgr
asterisk 0x09 shift
umacron 0x09 altgr
Umacron 0x09 shift altgr
parenleft 0x0a shift
doublelowquotemark 0x0a altgr
parenright 0x0b shift
leftdoublequotemark 0x0b altgr
minus 0x0c
underscore 0x0c shift
equal 0x0d
plus 0x0d shift
zcaron 0x0d altgr
Zcaron 0x0d shift altgr
bracketleft 0x1a
braceleft 0x1a shift
bracketright 0x1b
braceright 0x1b shift
semicolon 0x27
colon 0x27 shift
apostrophe 0x28
quotedbl 0x28 shift
grave 0x29
asciitilde 0x29 shift
backslash 0x2b
bar 0x2b shift
comma 0x33
less 0x33 shift
period 0x34
greater 0x34 shift
slash 0x35
question 0x35 shift
endash 0x56
EuroSign 0x56 shift

@ -0,0 +1,128 @@
# generated from XKB map lv
include common
map 0x426
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
at 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
numbersign 0x04 shift
threesuperior 0x04 altgr
sterling 0x04 shift altgr
dollar 0x05 shift
EuroSign 0x05 altgr
cent 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
asciicircum 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
ampersand 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
asterisk 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenleft 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
parenright 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
minus 0x0c
underscore 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
equal 0x0d
plus 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
emacron 0x12 altgr
Emacron 0x12 shift altgr
rcedilla 0x13 altgr
Rcedilla 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
umacron 0x16 altgr
Umacron 0x16 shift altgr
imacron 0x17 altgr
Imacron 0x17 shift altgr
omacron 0x18 altgr
Omacron 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
bracketright 0x1b
braceright 0x1b shift
dead_tilde 0x1b altgr
dead_macron 0x1b shift altgr
ISO_Next_Group 0x1c shift
amacron 0x1e altgr
Amacron 0x1e shift altgr
scaron 0x1f altgr
Scaron 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
gcedilla 0x22 altgr
Gcedilla 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kcedilla 0x25 altgr
Kcedilla 0x25 shift altgr
lcedilla 0x26 altgr
Lcedilla 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
dead_acute 0x27 altgr
dead_doubleacute 0x27 shift altgr
apostrophe 0x28
quotedbl 0x28 shift
leftdoublequotemark 0x28 altgr
doublelowquotemark 0x28 shift altgr
grave 0x29
asciitilde 0x29 shift
notsign 0x29 altgr
backslash 0x2b
bar 0x2b shift
dead_grave 0x2b altgr
dead_breve 0x2b shift altgr
zcaron 0x2c altgr
Zcaron 0x2c shift altgr
guillemotright 0x2d altgr
greater 0x2d shift altgr
ccaron 0x2e altgr
Ccaron 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
apostrophe 0x30 shift altgr
ncedilla 0x31 altgr
Ncedilla 0x31 shift altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
less 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
greater 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
slash 0x35
question 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr
nobreakspace 0x39 altgr

@ -0,0 +1,101 @@
# generated from XKB map mk
include common
map 0x42f
exclam 0x02 shift
at 0x03 shift
doublelowquotemark 0x03 shift altgr
numbersign 0x04 shift
leftdoublequotemark 0x04 shift altgr
dollar 0x05 shift
percent 0x06 shift
asciicircum 0x07 shift
ampersand 0x08 shift
asterisk 0x09 shift
parenleft 0x0a shift
parenright 0x0b shift
minus 0x0c
underscore 0x0c shift
equal 0x0d
plus 0x0d shift
Cyrillic_lje 0x10 altgr
Cyrillic_LJE 0x10 shift altgr
Cyrillic_nje 0x11 altgr
Cyrillic_NJE 0x11 shift altgr
Cyrillic_ie 0x12 altgr
Cyrillic_IE 0x12 shift altgr
Cyrillic_er 0x13 altgr
Cyrillic_ER 0x13 shift altgr
Cyrillic_te 0x14 altgr
Cyrillic_TE 0x14 shift altgr
Macedonia_dse 0x15 altgr
Macedonia_DSE 0x15 shift altgr
Cyrillic_u 0x16 altgr
Cyrillic_U 0x16 shift altgr
Cyrillic_i 0x17 altgr
Cyrillic_I 0x17 shift altgr
Cyrillic_o 0x18 altgr
Cyrillic_O 0x18 shift altgr
Cyrillic_pe 0x19 altgr
Cyrillic_PE 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
Cyrillic_sha 0x1a altgr
Cyrillic_SHA 0x1a shift altgr
bracketright 0x1b
braceright 0x1b shift
Macedonia_gje 0x1b altgr
Macedonia_GJE 0x1b shift altgr
Cyrillic_a 0x1e altgr
Cyrillic_A 0x1e shift altgr
Cyrillic_es 0x1f altgr
Cyrillic_ES 0x1f shift altgr
Cyrillic_de 0x20 altgr
Cyrillic_DE 0x20 shift altgr
Cyrillic_ef 0x21 altgr
Cyrillic_EF 0x21 shift altgr
Cyrillic_ghe 0x22 altgr
Cyrillic_GHE 0x22 shift altgr
Cyrillic_ha 0x23 altgr
Cyrillic_HA 0x23 shift altgr
Cyrillic_je 0x24 altgr
Cyrillic_JE 0x24 shift altgr
Cyrillic_ka 0x25 altgr
Cyrillic_KA 0x25 shift altgr
Cyrillic_el 0x26 altgr
Cyrillic_EL 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
Cyrillic_che 0x27 altgr
Cyrillic_CHE 0x27 shift altgr
apostrophe 0x28
quotedbl 0x28 shift
Macedonia_kje 0x28 altgr
Macedonia_KJE 0x28 shift altgr
grave 0x29
asciitilde 0x29 shift
backslash 0x2b
bar 0x2b shift
Cyrillic_zhe 0x2b altgr
Cyrillic_ZHE 0x2b shift altgr
Cyrillic_ze 0x2c altgr
Cyrillic_ZE 0x2c shift altgr
Cyrillic_dzhe 0x2d altgr
Cyrillic_DZHE 0x2d shift altgr
Cyrillic_tse 0x2e altgr
Cyrillic_TSE 0x2e shift altgr
Cyrillic_ve 0x2f altgr
Cyrillic_VE 0x2f shift altgr
Cyrillic_be 0x30 altgr
Cyrillic_BE 0x30 shift altgr
Cyrillic_en 0x31 altgr
Cyrillic_EN 0x31 shift altgr
Cyrillic_em 0x32 altgr
Cyrillic_EM 0x32 shift altgr
comma 0x33
less 0x33 shift
semicolon 0x33 shift altgr
period 0x34
greater 0x34 shift
colon 0x34 shift altgr
slash 0x35
question 0x35 shift

@ -0,0 +1,17 @@
Shift_R 0x36
Shift_L 0x2a
Alt_R 0xb8
Mode_switch 0xb8
Alt_L 0x38
Control_R 0x9d
Control_L 0x1d
# Translate Super to Windows keys.
# This is hardcoded. See documentation for details.
Super_R 0xdb
Super_L 0xdc
# Translate Menu to the Windows Application key.
Menu 0xdd

@ -0,0 +1,60 @@
# Dutch (Netherlands)
include common
map 0x413
exclam 0x02 shift
onesuperior 0x02 altgr
quotebl 0x03 shift
twosuperior 0x03 altgr
numbersign 0x04 shift
threesuperior 0x04 altgr
dollar 0x05 shift
onequarter 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
ampersand 0x07 shift
threequarters 0x07 altgr
underscore 0x08 shift
sterling 0x08 altgr
parenleft 0x09 shift
braceleft 0x09 altgr
parenright 0x0a shift
braceright 0x0a altgr
apostrophe 0x0b shift
slash 0x0c
question 0x0c shift
backslash 0x0c altgr
degree 0x0d
dead_tilde 0x0d shift
dead_cedilla 0x0d altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
dead_diaeresis 0x1a
dead_circumflex 0x1a shift
asterisk 0x1b
bar 0x1b shift
ssharp 0x1f altgr
plus 0x27
plusminus 0x27 shift
dead_acute 0x28
dead_grave 0x28 shift
at 0x29
section 0x29 shift
notsign 0x29 altgr
less 0x2b
greater 0x2b shift
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
copyright 0x2e altgr
mu 0x32 altgr
comma 0x33
semicolon 0x33 shift
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
hyphen 0x35
equal 0x35 shift
bracketright 0x56
bracketleft 0x56 shift
brokenbar 0x56 altgr

@ -0,0 +1,3 @@
# Dutch (Belgium)
map 0x813
include common

@ -0,0 +1,119 @@
# generated from XKB map no
include common
map 0x414
exclam 0x02 shift
exclamdown 0x02 altgr
onesuperior 0x02 shift altgr
quotedbl 0x03 shift
at 0x03 altgr
twosuperior 0x03 shift altgr
numbersign 0x04 shift
sterling 0x04 altgr
threesuperior 0x04 shift altgr
currency 0x05 shift
dollar 0x05 altgr
onequarter 0x05 shift altgr
percent 0x06 shift
onehalf 0x06 altgr
cent 0x06 shift altgr
ampersand 0x07 shift
yen 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
division 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
guillemotleft 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
guillemotright 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
plus 0x0c
question 0x0c shift
plusminus 0x0c altgr
questiondown 0x0c shift altgr
backslash 0x0d
dead_grave 0x0d shift
dead_acute 0x0d altgr
notsign 0x0d shift altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
cent 0x12 shift altgr
registered 0x13 altgr
thorn 0x14 altgr
THORN 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oe 0x18 altgr
OE 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
aring 0x1a
Aring 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
dead_diaeresis 0x1b
dead_circumflex 0x1b shift
asciicircum 0x01b shift
dead_tilde 0x1b altgr
asciitilde 0x1b altgr
dead_caron 0x1b shift altgr
ordfeminine 0x1e altgr
masculine 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
oslash 0x27
Ooblique 0x27 shift
dead_doubleacute 0x27 shift altgr
ae 0x28
AE 0x28 shift
dead_caron 0x28 shift altgr
bar 0x29
section 0x29 shift
brokenbar 0x29 altgr
paragraph 0x29 shift altgr
apostrophe 0x2b
asterisk 0x2b shift
multiply 0x2b shift altgr
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
copyright 0x2e altgr
leftdoublequotemark 0x2f altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
dead_cedilla 0x33 altgr
dead_ogonek 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
dead_abovedot 0x34 shift altgr
minus 0x35
underscore 0x35 shift
hyphen 0x35 altgr
macron 0x35 shift altgr
nobreakspace 0x39 altgr
onehalf 0x56 altgr
threequarters 0x56 shift altgr

@ -0,0 +1,122 @@
# generated from XKB map pl
include common
map 0x415
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
at 0x03 shift
twosuperior 0x03 altgr
oneeighth 0x03 shift altgr
numbersign 0x04 shift
threesuperior 0x04 altgr
sterling 0x04 shift altgr
dollar 0x05 shift
onequarter 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
asciicircum 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
ampersand 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
asterisk 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenleft 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
parenright 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
minus 0x0c
underscore 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
equal 0x0d
plus 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
eogonek 0x12 altgr
Eogonek 0x12 shift altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
EuroSign 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oacute 0x18 altgr
Oacute 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
bracketright 0x1b
braceright 0x1b shift
dead_tilde 0x1b altgr
dead_macron 0x1b shift altgr
aogonek 0x1e altgr
Aogonek 0x1e shift altgr
sacute 0x1f altgr
Sacute 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
dead_acute 0x27 altgr
dead_doubleacute 0x27 shift altgr
apostrophe 0x28
quotedbl 0x28 shift
dead_circumflex 0x28 altgr
dead_caron 0x28 shift altgr
grave 0x29
asciitilde 0x29 shift
notsign 0x29 altgr
backslash 0x2b
bar 0x2b shift
dead_grave 0x2b altgr
dead_breve 0x2b shift altgr
zabovedot 0x2c altgr
Zabovedot 0x2c shift altgr
zacute 0x2d altgr
Zacute 0x2d shift altgr
cacute 0x2e altgr
Cacute 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
nacute 0x31 altgr
Nacute 0x31 shift altgr
mu 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
less 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
greater 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
slash 0x35
question 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,113 @@
# generated from XKB map pt
include common
map 0x816
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
quotedbl 0x03 shift
at 0x03 altgr
oneeighth 0x03 shift altgr
numbersign 0x04 shift
sterling 0x04 altgr
dollar 0x05 shift
section 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
threequarters 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
apostrophe 0x0c
question 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
guillemotleft 0x0d
guillemotright 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
cent 0x12 shift altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
plus 0x1a
asterisk 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
dead_acute 0x1b
dead_grave 0x1b shift
dead_tilde 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
ccedilla 0x27
Ccedilla 0x27 shift
dead_doubleacute 0x27 shift altgr
masculine 0x28
ordfeminine 0x28 shift
dead_circumflex 0x28 altgr
dead_caron 0x28 shift altgr
backslash 0x29
bar 0x29 shift
notsign 0x29 altgr
dead_tilde 0x2b
dead_circumflex 0x2b shift
dead_breve 0x2b shift altgr
less 0x56
greater 0x56 shift
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
mu 0x32 altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
multiply 0x33 shift altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
division 0x34 shift altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

@ -0,0 +1,69 @@
# generated from XKB map br
include common
map 0x416
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
at 0x03 shift
twosuperior 0x03 altgr
onehalf 0x03 shift altgr
numbersign 0x04 shift
threesuperior 0x04 altgr
threequarters 0x04 shift altgr
dollar 0x05 shift
sterling 0x05 altgr
onequarter 0x05 shift altgr
percent 0x06 shift
cent 0x06 altgr
dead_diaeresis 0x07 shift
notsign 0x07 altgr
diaeresis 0x07 shift altgr
ampersand 0x08 shift
braceleft 0x08 altgr
asterisk 0x09 shift
bracketleft 0x09 altgr
parenleft 0x0a shift
bracketright 0x0a altgr
parenright 0x0b shift
braceright 0x0b altgr
minus 0x0c
underscore 0x0c shift
backslash 0x0c altgr
equal 0x0d
plus 0x0d shift
section 0x0d altgr
EuroSign 0x12 altgr
registered 0x13 altgr
dead_acute 0x1a
dead_grave 0x1a shift
acute 0x1a altgr
grave 0x1a shift altgr
bracketleft 0x1b
braceleft 0x1b shift
ordfeminine 0x1b altgr
ccedilla 0x27
Ccedilla 0x27 shift
dead_tilde 0x28
dead_circumflex 0x28 shift
asciitilde 0x28 altgr
asciicircum 0x28 shift altgr
apostrophe 0x29
quotedbl 0x29 shift
bracketright 0x2b
braceright 0x2b shift
masculine 0x2b altgr
copyright 0x2e altgr
mu 0x32 altgr
comma 0x33
less 0x33 shift
period 0x34
greater 0x34 shift
semicolon 0x35
colon 0x35 shift
comma 0x53 numlock
backslash 0x56
bar 0x56 shift
slash 0x73
question 0x73 shift
degree 0x73 altgr
KP_Decimal 0x34

@ -0,0 +1,109 @@
# generated from XKB map ru
include common
map 0x419
exclam 0x02 shift
at 0x03 shift
quotedbl 0x03 shift altgr
numbersign 0x04 shift
dollar 0x05 shift
asterisk 0x05 shift altgr
percent 0x06 shift
colon 0x06 shift altgr
asciicircum 0x07 shift
comma 0x07 shift altgr
ampersand 0x08 shift
period 0x08 shift altgr
asterisk 0x09 shift
semicolon 0x09 shift altgr
parenleft 0x0a shift
parenright 0x0b shift
minus 0x0c
underscore 0x0c shift
equal 0x0d
plus 0x0d shift
Cyrillic_shorti 0x10 altgr
Cyrillic_SHORTI 0x10 shift altgr
Cyrillic_tse 0x11 altgr
Cyrillic_TSE 0x11 shift altgr
Cyrillic_u 0x12 altgr
Cyrillic_U 0x12 shift altgr
Cyrillic_ka 0x13 altgr
Cyrillic_KA 0x13 shift altgr
Cyrillic_ie 0x14 altgr
Cyrillic_IE 0x14 shift altgr
Cyrillic_en 0x15 altgr
Cyrillic_EN 0x15 shift altgr
Cyrillic_ghe 0x16 altgr
Cyrillic_GHE 0x16 shift altgr
Cyrillic_sha 0x17 altgr
Cyrillic_SHA 0x17 shift altgr
Cyrillic_shcha 0x18 altgr
Cyrillic_SHCHA 0x18 shift altgr
Cyrillic_ze 0x19 altgr
Cyrillic_ZE 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
Cyrillic_ha 0x1a altgr
Cyrillic_HA 0x1a shift altgr
bracketright 0x1b
braceright 0x1b shift
Cyrillic_hardsign 0x1b altgr
Cyrillic_HARDSIGN 0x1b shift altgr
Cyrillic_ef 0x1e altgr
Cyrillic_EF 0x1e shift altgr
Cyrillic_yeru 0x1f altgr
Cyrillic_YERU 0x1f shift altgr
Cyrillic_ve 0x20 altgr
Cyrillic_VE 0x20 shift altgr
Cyrillic_a 0x21 altgr
Cyrillic_A 0x21 shift altgr
Cyrillic_pe 0x22 altgr
Cyrillic_PE 0x22 shift altgr
Cyrillic_er 0x23 altgr
Cyrillic_ER 0x23 shift altgr
Cyrillic_o 0x24 altgr
Cyrillic_O 0x24 shift altgr
Cyrillic_el 0x25 altgr
Cyrillic_EL 0x25 shift altgr
Cyrillic_de 0x26 altgr
Cyrillic_DE 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
Cyrillic_zhe 0x27 altgr
Cyrillic_ZHE 0x27 shift altgr
apostrophe 0x28
quotedbl 0x28 shift
Cyrillic_e 0x28 altgr
Cyrillic_E 0x28 shift altgr
grave 0x29
asciitilde 0x29 shift
Cyrillic_io 0x29 altgr
Cyrillic_IO 0x29 shift altgr
backslash 0x2b
bar 0x2b shift
Cyrillic_ya 0x2c altgr
Cyrillic_YA 0x2c shift altgr
Cyrillic_che 0x2d altgr
Cyrillic_CHE 0x2d shift altgr
Cyrillic_es 0x2e altgr
Cyrillic_ES 0x2e shift altgr
Cyrillic_em 0x2f altgr
Cyrillic_EM 0x2f shift altgr
Cyrillic_i 0x30 altgr
Cyrillic_I 0x30 shift altgr
Cyrillic_te 0x31 altgr
Cyrillic_TE 0x31 shift altgr
Cyrillic_softsign 0x32 altgr
Cyrillic_SOFTSIGN 0x32 shift altgr
comma 0x33
less 0x33 shift
Cyrillic_be 0x33 altgr
Cyrillic_BE 0x33 shift altgr
period 0x34
greater 0x34 shift
Cyrillic_yu 0x34 altgr
Cyrillic_YU 0x34 shift altgr
slash 0x35
question 0x35 shift
slash 0x56 altgr
bar 0x56 shift altgr

@ -0,0 +1,110 @@
# generated from XKB map sl
include common
map 0x424
exclam 0x02 shift
asciitilde 0x02 altgr
dead_tilde 0x02 shift altgr
quotedbl 0x03 shift
dead_caron 0x03 altgr
caron 0x03 shift altgr
numbersign 0x04 shift
asciicircum 0x04 altgr
dead_circumflex 0x04 shift altgr
dollar 0x05 shift
dead_breve 0x05 altgr
breve 0x05 shift altgr
percent 0x06 shift
degree 0x06 altgr
dead_abovering 0x06 shift altgr
ampersand 0x07 shift
dead_ogonek 0x07 altgr
ogonek 0x07 shift altgr
slash 0x08 shift
grave 0x08 altgr
dead_grave 0x08 shift altgr
parenleft 0x09 shift
dead_abovedot 0x09 altgr
abovedot 0x09 shift altgr
parenright 0x0a shift
dead_acute 0x0a altgr
equal 0x0b shift
dead_doubleacute 0x0b altgr
doubleacute 0x0b shift altgr
apostrophe 0x0c
question 0x0c shift
dead_diaeresis 0x0c altgr
diaeresis 0x0c shift altgr
plus 0x0d
asterisk 0x0d shift
dead_cedilla 0x0d altgr
cedilla 0x0d shift altgr
backslash 0x10 altgr
Greek_OMEGA 0x10 shift altgr
bar 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
z 0x15 addupper
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
rightarrow 0x17 altgr
idotless 0x17 shift altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
scaron 0x1a
Scaron 0x1a shift
division 0x1a altgr
dstroke 0x1b
Dstroke 0x1b shift
multiply 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
bracketleft 0x21 altgr
ordfeminine 0x21 shift altgr
bracketright 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
lstroke 0x25 altgr
Lstroke 0x26 altgr
ccaron 0x27
Ccaron 0x27 shift
cacute 0x28
Cacute 0x28 shift
ssharp 0x28 altgr
dead_cedilla 0x29
notsign 0x29 altgr
zcaron 0x2b
Zcaron 0x2b shift
currency 0x2b altgr
y 0x2c addupper
guillemotleft 0x2c altgr
guillemotright 0x2d altgr
cent 0x2e altgr
copyright 0x2e shift altgr
at 0x2f altgr
braceleft 0x30 altgr
braceright 0x31 altgr
section 0x32 altgr
masculine 0x32 shift altgr
comma 0x33
semicolon 0x33 shift
horizconnector 0x33 altgr
period 0x34
colon 0x34 shift
periodcentered 0x34 altgr
minus 0x35
underscore 0x35 shift
dead_belowdot 0x35 altgr

@ -0,0 +1,82 @@
map 0x0000041d
include common
#
# Top row
#
section 0x29
onehalf 0x29 shift
# 1
exclam 0x2 shift
# 2
quotedbl 0x3 shift
at 0x3 altgr
# 3
numbersign 0x4 shift
sterling 0x4 altgr
# 4
currency 0x5 shift
dollar 0x5 altgr
# 5
percent 0x6 shift
# 6
ampersand 0x7 shift
# 7
slash 0x8 shift
braceleft 0x8 altgr
# 8
parenleft 0x9 shift
bracketleft 0x9 altgr
# 9
parenright 0xa shift
bracketright 0xa altgr
# 0
equal 0xb shift
braceright 0xb altgr
plus 0xc
question 0xc shift
backslash 0xc altgr
acute 0xd
dead_acute 0xd
grave 0xd shift
dead_grave 0xd shift
#
# QWERTY first row
#
EuroSign 0x12 altgr
aring 0x1a
Aring 0x1a shift
dead_diaeresis 0x1b
dead_circumflex 0x1b shift
dead_tilde 0x1b altgr
#
# QWERTY second row
#
odiaeresis 0x27
Odiaeresis 0x27 shift
adiaeresis 0x28
Adiaeresis 0x28 shift
apostrophe 0x2b
asterisk 0x2b shift
#
# QWERTY third row
#
less 0x56
greater 0x56 shift
bar 0x56 altgr
mu 0x32 altgr
comma 0x33
semicolon 0x33 shift
period 0x34
colon 0x34 shift
minus 0x35
underscore 0x35 shift

@ -0,0 +1,131 @@
# generated from XKB map th
include common
map 0x41e
exclam 0x02 shift
Thai_lakkhangyao 0x02 altgr
plus 0x02 shift altgr
at 0x03 shift
slash 0x03 altgr
Thai_leknung 0x03 shift altgr
numbersign 0x04 shift
minus 0x04 altgr
Thai_leksong 0x04 shift altgr
dollar 0x05 shift
Thai_phosamphao 0x05 altgr
Thai_leksam 0x05 shift altgr
percent 0x06 shift
Thai_thothung 0x06 altgr
Thai_leksi 0x06 shift altgr
asciicircum 0x07 shift
Thai_sarau 0x07 altgr
Thai_sarauu 0x07 shift altgr
ampersand 0x08 shift
Thai_saraue 0x08 altgr
Thai_baht 0x08 shift altgr
asterisk 0x09 shift
Thai_khokhwai 0x09 altgr
Thai_lekha 0x09 shift altgr
parenleft 0x0a shift
Thai_totao 0x0a altgr
Thai_lekhok 0x0a shift altgr
parenright 0x0b shift
Thai_chochan 0x0b altgr
Thai_lekchet 0x0b shift altgr
minus 0x0c
underscore 0x0c shift
Thai_khokhai 0x0c altgr
Thai_lekpaet 0x0c shift altgr
equal 0x0d
plus 0x0d shift
Thai_chochang 0x0d altgr
Thai_lekkao 0x0d shift altgr
Thai_maiyamok 0x10 altgr
Thai_leksun 0x10 shift altgr
Thai_saraaimaimalai 0x11 altgr
quotedbl 0x11 shift altgr
Thai_saraam 0x12 altgr
Thai_dochada 0x12 shift altgr
Thai_phophan 0x13 altgr
Thai_thonangmontho 0x13 shift altgr
Thai_saraa 0x14 altgr
Thai_thothong 0x14 shift altgr
Thai_maihanakat 0x15 altgr
Thai_nikhahit 0x15 shift altgr
Thai_saraii 0x16 altgr
Thai_maitri 0x16 shift altgr
Thai_rorua 0x17 altgr
Thai_nonen 0x17 shift altgr
Thai_nonu 0x18 altgr
Thai_paiyannoi 0x18 shift altgr
Thai_yoyak 0x19 altgr
Thai_yoying 0x19 shift altgr
bracketleft 0x1a
braceleft 0x1a shift
Thai_bobaimai 0x1a altgr
Thai_thothan 0x1a shift altgr
bracketright 0x1b
braceright 0x1b shift
Thai_loling 0x1b altgr
comma 0x1b shift altgr
Thai_fofan 0x1e altgr
Thai_ru 0x1e shift altgr
Thai_hohip 0x1f altgr
Thai_khorakhang 0x1f shift altgr
Thai_kokai 0x20 altgr
Thai_topatak 0x20 shift altgr
Thai_dodek 0x21 altgr
Thai_sarao 0x21 shift altgr
Thai_sarae 0x22 altgr
Thai_chochoe 0x22 shift altgr
Thai_maitho 0x23 altgr
Thai_maitaikhu 0x23 shift altgr
Thai_maiek 0x24 altgr
Thai_maichattawa 0x24 shift altgr
Thai_saraaa 0x25 altgr
Thai_sorusi 0x25 shift altgr
Thai_sosua 0x26 altgr
Thai_sosala 0x26 shift altgr
semicolon 0x27
colon 0x27 shift
Thai_wowaen 0x27 altgr
Thai_soso 0x27 shift altgr
apostrophe 0x28
quotedbl 0x28 shift
Thai_ngongu 0x28 altgr
period 0x28 shift altgr
grave 0x29
asciitilde 0x29 shift
underscore 0x29 altgr
percent 0x29 shift altgr
ISO_First_Group 0x2a shift
backslash 0x2b
bar 0x2b shift
Thai_khokhuat 0x2b altgr
Thai_khokhon 0x2b shift altgr
Thai_phophung 0x2c altgr
parenleft 0x2c shift altgr
Thai_popla 0x2d altgr
parenright 0x2d shift altgr
Thai_saraae 0x2e altgr
Thai_choching 0x2e shift altgr
Thai_oang 0x2f altgr
Thai_honokhuk 0x2f shift altgr
Thai_sarai 0x30 altgr
Thai_phinthu 0x30 shift altgr
Thai_sarauee 0x31 altgr
Thai_thanthakhat 0x31 shift altgr
Thai_thothahan 0x32 altgr
question 0x32 shift altgr
comma 0x33
less 0x33 shift
Thai_moma 0x33 altgr
Thai_thophuthao 0x33 shift altgr
period 0x34
greater 0x34 shift
Thai_saraaimaimuan 0x34 altgr
Thai_lochula 0x34 shift altgr
slash 0x35
question 0x35 shift
Thai_fofa 0x35 altgr
Thai_lu 0x35 shift altgr
ISO_Last_Group 0x36 shift

@ -0,0 +1,123 @@
# generated from XKB map tr
include common
map 0x41f
exclam 0x02 shift
onesuperior 0x02 altgr
exclamdown 0x02 shift altgr
apostrophe 0x03 shift
at 0x03 altgr
oneeighth 0x03 shift altgr
dead_circumflex 0x04 shift
numbersign 0x04 altgr
sterling 0x04 shift altgr
plus 0x05 shift
dollar 0x05 altgr
percent 0x06 shift
onehalf 0x06 altgr
threeeighths 0x06 shift altgr
ampersand 0x07 shift
asciicircum 0x07 altgr
fiveeighths 0x07 shift altgr
slash 0x08 shift
braceleft 0x08 altgr
seveneighths 0x08 shift altgr
parenleft 0x09 shift
bracketleft 0x09 altgr
trademark 0x09 shift altgr
parenright 0x0a shift
bracketright 0x0a altgr
plusminus 0x0a shift altgr
equal 0x0b shift
braceright 0x0b altgr
degree 0x0b shift altgr
asterisk 0x0c
question 0x0c shift
backslash 0x0c altgr
questiondown 0x0c shift altgr
minus 0x0d
underscore 0x0d shift
dead_cedilla 0x0d altgr
dead_ogonek 0x0d shift altgr
at 0x10 altgr
Greek_OMEGA 0x10 shift altgr
lstroke 0x11 altgr
Lstroke 0x11 shift altgr
EuroSign 0x12 altgr
paragraph 0x13 altgr
registered 0x13 shift altgr
tslash 0x14 altgr
Tslash 0x14 shift altgr
leftarrow 0x15 altgr
yen 0x15 shift altgr
downarrow 0x16 altgr
uparrow 0x16 shift altgr
idotless 0x17
I 0x17 shift
rightarrow 0x17 altgr
oslash 0x18 altgr
Ooblique 0x18 shift altgr
thorn 0x19 altgr
THORN 0x19 shift altgr
gbreve 0x1a
Gbreve 0x1a shift
dead_diaeresis 0x1a altgr
dead_abovering 0x1a shift altgr
udiaeresis 0x1b
Udiaeresis 0x1b shift
asciitilde 0x1b altgr
dead_macron 0x1b shift altgr
ae 0x1e altgr
AE 0x1e shift altgr
ssharp 0x1f altgr
section 0x1f shift altgr
eth 0x20 altgr
ETH 0x20 shift altgr
dstroke 0x21 altgr
ordfeminine 0x21 shift altgr
eng 0x22 altgr
ENG 0x22 shift altgr
hstroke 0x23 altgr
Hstroke 0x23 shift altgr
kra 0x25 altgr
ampersand 0x25 shift altgr
lstroke 0x26 altgr
Lstroke 0x26 shift altgr
scedilla 0x27
Scedilla 0x27 shift
dead_acute 0x27 altgr
dead_doubleacute 0x27 shift altgr
i 0x28
Iabovedot 0x28 shift
dead_circumflex 0x28 altgr
dead_caron 0x28 shift altgr
backslash 0x29
quotedbl 0x29 shift
asciitilde 0x29 altgr
comma 0x2b
semicolon 0x2b shift
bar 0x2b altgr
dead_breve 0x2b shift altgr
guillemotleft 0x2c altgr
less 0x2c shift altgr
guillemotright 0x2d altgr
greater 0x2d shift altgr
cent 0x2e altgr
copyright 0x2e shift altgr
leftdoublequotemark 0x2f altgr
grave 0x2f shift altgr
rightdoublequotemark 0x30 altgr
apostrophe 0x30 shift altgr
mu 0x32 altgr
masculine 0x32 shift altgr
odiaeresis 0x33
Odiaeresis 0x33 shift
less 0x33 altgr
multiply 0x33 shift altgr
ccedilla 0x34
Ccedilla 0x34 shift
greater 0x34 altgr
division 0x34 shift altgr
period 0x35
colon 0x35 shift
dead_belowdot 0x35 altgr
dead_abovedot 0x35 shift altgr

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,107 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: install.py
# Purpose: Script to install multibootusb from source on different linux distros. This also pulls in dependencies.
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import os
import sys
import urllib.request, urllib.error, urllib.parse
import subprocess
if not os.getuid() == 0:
print("You must run this file with admin privilege.")
print("Try sudo ./install.py")
sys.exit(0)
class Install():
def mbusb(self):
try:
from PyQt5 import QtGui
if subprocess.call("python3 setup.py install --record ./.install_files.txt", shell=True) == 0:
print("Installation finished.")
print("Find multibootusb under system menu or run from terminal using the following command...")
print("\nmultibootusb\n")
print("You can uninstall multibootusb at any time using follwing command (with root/sudo previlage)")
print("\n./uninstall.sh\n")
except:
print("Installing missing package.")
if self.supported_pac_manager() is not True:
print("Unsupported package manager.")
print("Please install parted, util-linux and python3-pyqt5/PyQt5, mtools and python3-dbus\n"
"Whatever the package name is applicable to your distro and rerun this script.")
sys.exit(0)
elif self.internet_on() is False:
print("Unable to connect to internet.")
print("Please install parted, util-linux and python3-pyqt5/PyQt5, pkexec, mtools and python3-dbus \n"
"Whatever the package name is applicable to your distro and rerun this script.")
sys.exit(0)
elif self.internet_on() is True:
if self.install_dependency_package() is not True:
print("Error installing dependency packages.")
else:
if subprocess.call("python3 setup.py install --record ./.install_files.txt", shell=True) == 0:
print("Installation finished.")
print("Find multibootusb under system menu or run from terminal using the following command...")
print("\nmultibootusb\n")
print("You can uninstall multibootusb at any time using follwing command (with root/sudo previlage)")
print("\nsudo ./uninstall.sh\n")
def internet_on(self):
try:
ret = urllib.request.urlopen('https://www.google.com', timeout=1)
print("Interconnection exist.")
result = True
except urllib.error.URLError:
print("Interconnection does not exist.")
result = False
return result
def supported_pac_manager(self):
pac_managers = ["pacman", "yum", "apt-get", "zypper", "urpmi"]
result = "0"
for pac_man in pac_managers:
if subprocess.call("which " + pac_man, shell=True) == 0:
result = "1"
return True
if not result == "1":
return False
def install_dependency_package(self):
if subprocess.call("which pacman", shell=True) == 0:
subprocess.call("pacman -Sy --noconfirm", shell=True)
if subprocess.call("pacman -S --needed --noconfirm python-pyqt5 pkexec mtools parted util-linux python-dbus") == 0: # Thank you Neitsab for "--needed" argument.
result = True
elif subprocess.call("which yum", shell=True) == 0:
subprocess.call("yum check-update", shell=True)
if subprocess.call("yum install mtools PyQt5 pkexec util-linux parted python3-dbus -y", shell=True) == 0:
result = True
elif subprocess.call("which apt-get", shell=True) == 0:
subprocess.call("apt-get -q update", shell=True)
if subprocess.call("apt-get -q -y install python3-pyqt5 pkexec parted util-linux mtools python3-dbus", shell=True) == 0:
result = True
elif subprocess.call("which zypper", shell=True) == 0:
subprocess.call("zypper refresh", shell=True)
if subprocess.call("zypper install -y mtools python3-qt5 pkexec util-linux parted", shell=True) == 0:
result = True
elif subprocess.call("which urpmi", shell=True) == 0:
subprocess.call("urpmi.update -a", shell=True)
if subprocess.call("urpmi install -auto mtools util-linux pkexec parted python3-qt5", shell=True) == 0:
result = True
if result is not True:
return False
else:
result
install = Install()
install.mbusb()

@ -0,0 +1,98 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name: multibootusb
# Purpose: Main file which will determine if cli or gui is to be opened
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import getopt
import sys
import os
import platform
# Had trouble in importing scripts directory. Had to add few lines below to ensure it works on source as well as
# post install
try:
from scripts.mbusb_cli import *
from scripts import admin
except:
try:
from .scripts.mbusb_cli import *
from .scripts import admin
except:
import scripts
gui = True
iso_link = None
usb_disk = None
uninstall = False
def usage():
print('\nAn advanced multi boot live usb creator using command line.')
print('\nUsage: python3 multibootusb -c -i /path/to/iso [option(s)] -t /path/to/device\n')
print('[option(s)] are :\n')
print(' -h or --help : Print this help message and exit')
print(' -i or --iso : Path to ISO file')
print(' -t or --target : Path to target USB device partition (example /dev/sdb1)\n')
print(' -c or --command : This option is must for invoking multibootusb from command line\n')
print(' -u or --uninstall : List and uninstall distro from USB disk')
print(' Command line example for making a bootable USB from command line should look like this:-\n')
print(' python3 multibootusb -c -i ../../favourite.iso -t /dev/sdb1\n')
exit(2)
def start_gui():
print('Starting multibootusb GUI...')
from scripts import mbusb_gui
mbusb_gui.main_gui()
if __name__ == '__main__':
if platform.system() == 'Windows':
if not admin.isUserAdmin():
admin.runAsAdmin()
sys.exit(0)
try:
opts, args = getopt.getopt(sys.argv[1:], 'i:t:vhcu',
['iso=', 'target=', 'version', 'help', 'command', 'uninstall'])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ('-h', '--help'):
usage()
sys.exit(2)
elif opt in ('-v', '--version'):
print_version()
sys.exit()
elif opt in ('-i', '--iso'):
config.iso_link = arg
elif opt in ('-t', '--target'):
config.usb_disk = arg
elif opt in ('-c', '--command'):
gui = False
elif opt in ('-u', '--uninstall'):
uninstall = True
else:
gui = True
#start_gui()
'''
usage()
sys.exit()
'''
if gui is False:
if uninstall is True and config.usb_disk is not None:
cli_uninstall_distro()
elif config.iso_link is None and config.usb_disk is None:
usage()
elif config.iso_link is None or config.usb_disk is None:
print('\nOptions \'-i\' and \'t\' must be supplied together. See the usage below.')
usage()
else:
cli_install_distro()
elif gui is True:
start_gui()

Binary file not shown.

@ -0,0 +1,6 @@
#!/bin/bash
if [ $(which pkexec) ]; then
pkexec --disable-internal-agent "/usr/bin/multibootusb" "$@"
else
/usr/bin/multibootusb "$@"
fi

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
<action id="org.debian.pkexec.run-multibootusb">
<description>Run the multibootusb program</description>
<message>Authentication is required to run the multibootusb</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/multibootusb</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>

@ -0,0 +1,10 @@
# Author(s) information
__authors__ = ['Sundar']
__author__ = ','.join(__authors__)
__credits__ = ['Ian Bruce', 'Lee']
__copyright__ = 'Copyright (c) 2014'
__license__ = 'GPL'
# Maintanence information
__maintainer__ = 'Sundar'
__email__ = 'feedback.multibootusb@gmail.com'

@ -0,0 +1,166 @@
#!/usr/bin/env python3
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# Name: admin.py
# Purpose: Module to ask for admin rights under Linux and Windows
# Authors: Originally developed by Preston Landers (for windows) and modified for multibootusb by Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of the same license as Python 2.6.5
##
## (C) COPYRIGHT © Preston Landers 2010
## Released under the same license as Python 2.6.5
##
"""
User Access Control for Microsoft Windows Vista and higher. This is
only for the Windows platform.
This will relaunch either the current script - with all the same command
line parameters - or else you can provide a different script/program to
run. If the current user doesn't normally have admin rights, he'll be
prompted for an admin password. Otherwise he just gets the UAC prompt.
This is meant to be used something like this::
if not pyuac.isUserAdmin():
return pyuac.runAsAdmin()
# otherwise carry on doing whatever...
See L{runAsAdmin} for the main interface.
"""
import os
import traceback
import types
import platform
import sys
import subprocess
from PyQt5 import QtWidgets
def isUserAdmin():
"""
@return: True if the current user is an 'Admin' whatever that means
(root on Unix), otherwise False.
Warning: The inner function fails unless you have Windows XP SP2 or
higher. The failure causes a traceback to be printed and this
function to return False.
"""
if platform.system() == "Windows":
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print("Admin check failed, assuming not an admin.")
return False
elif platform.system() == "Linux":
return os.getuid() == 0
else:
raise RuntimeError("Unsupported operating system for this module: %s" % (os.name,))
def runAsAdmin(cmdLine=None, wait=True):
"""
Attempt to relaunch the current script as an admin using the same
command line parameters. Pass cmdLine in to override and set a new
command. It must be a list of [command, arg1, arg2...] format.
Set wait to False to avoid waiting for the sub-process to finish. You
will not be able to fetch the exit code of the process if wait is
False.
Returns the sub-process return code, unless wait is False in which
case it returns None.
@WARNING: this function only works on Windows.
"""
#if os.name == 'nt':
# raise RuntimeError, "This function is only implemented on Windows."
if platform.system() == "Windows":
import win32api, win32con, win32event, win32process
from win32com.shell.shell import ShellExecuteEx
from win32com.shell import shellcon
python_exe = sys.executable
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif type(cmdLine) not in (types.TupleType, types.ListType):
raise ValueError("cmdLine is not a sequence.")
cmd = '"%s"' % (cmdLine[0],)
# XXX TODO: isn't there a function or something we can call to massage command line params?
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
cmdDir = ''
showCmd = win32con.SW_SHOWNORMAL
#showCmd = win32con.SW_HIDE
lpVerb = 'runas' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn't seem to allow us to fetch the PID or handle
# of the process, so we can't get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo['hProcess']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = None
return rc
def adminCmd(cmd, fork=False, gui=False):
"""
This simple function checks for a sudo command and runs a command using it.
This function tries to launch given script with root access using pkexec/gksu/gksudo/kdesu/kdesudo,
if one of them is already installed.
PyQt4 is used as GUI.
Author : sundar
"""
sudo_cmd = ''
if os.getuid() == 0:
sudo_cmd = cmd
else:
if os.system('which pkexec') == 0:
if gui:
cmd = ['export DISPLAY=$DISPLAY; export XAUTHORITY=$XAUTHORITY; '] + cmd # By default, pkexec disallows X11 apps. Restore DISPLAY & XAUTHORITY to allow it. man 1 pkexec/"SECURITY NOTES" section
sudo_cmd = ['pkexec', '/bin/sh', '-c']
elif os.system('which gksudo') == 0:
sudo_cmd = ["gksudo", "--", "/bin/sh", "-c"]
elif os.system('which gksu') == 0:
sudo_cmd = ["gksu"]
elif os.system('which kdesudo') == 0:
sudo_cmd = ["kdesudo", "-t", "-c"] # http://www.unix.com/man-page/debian/1/kdesudo/
elif os.system('which kdesu') == 0:
sudo_cmd = ["kdesu", "-t", "-c"] # http://linux.die.net/man/1/kdesu
else:
QtWidgets.QMessageBox.information('No root...',
'Could not find any of: pkexec, sudo, gksu, kdesu, gksudo, or kdesudo. Please install one then restart multibootusb.')
sys.exit(0)
final_cmd = ' '.join(sudo_cmd + ['"' + ' '.join(cmd).replace('"', '\\"') + '"'])
print("Executing ==> " + final_cmd)
if fork:
return subprocess.Popen(final_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, shell=True)
else:
ret = subprocess.call(final_cmd, shell=True)
print("Process returned ==> " + str(ret))
return ret

@ -0,0 +1,32 @@
#!/usr/bin/env python3
# Name: config.py
# Purpose: Module to share important variables between various modules. Mainly included so as not to call many
# functions again and again
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
iso_link = ""
usb_disk = ""
usb_mount = ""
persistence = 0
distro = ""
status_text = ""
percentage = 0
syslinux_version = ''
uninstall_distro_dir_name = ""
uninstall_distro_dir_path = ""
iso_file_list = ''
imager_iso_link = ""
imager_usb_disk_selected = ""
imager_lock = ""
imager_percentage = ""
imager_status_text = ""
install_size = ""
editors_linux = ["gedit", "kate", "kwrite"]
editors_win = ["notepad++.exe", "notepad.exe"]
imager_usb_disk = []

@ -0,0 +1,160 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: distro.py
# Purpose: Module to detect if distro types supported by multibootusb (by extracting specific files)
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import os
import string
import platform
import re
from .iso import *
from .isodump3 import ISO9660
from .gen import *
from . import config
def distro(iso_cfg_ext_dir, iso_link):
"""
Detect if distro is supported by multibootusb.
:param iso_cfg_ext_dir: Directory where *.cfg files are extracted.
:return: Detected distro name as string.
"""
iso9660fs = ISO9660(iso_link)
iso_file_list = iso9660fs.readDir("/")
if platform.system() == "Linux" or platform.system() == "Windows":
for path, subdirs, files in os.walk(iso_cfg_ext_dir):
for name in files:
if name.endswith('.cfg') or name.endswith('.CFG') or name.endswith('.txt') or name.endswith('.TXT'):
try:
# errors='ignore' is required as some files also contain non utf character
string = open(os.path.join(path, name), errors='ignore').read()
except IOError:
return "Read Error."
else:
if any("f4ubcd" in s.lower() for s in iso_file_list):
return "f4ubcd"
if re.search(r'ubcd', string, re.I):
return "ubcd"
elif re.search(r'Super Grub Disk', string, re.I):
return None
elif re.search(r'hbcd', string, re.I):
return "hbcd"
elif re.search(r'systemrescuecd', string, re.I):
return "systemrescuecd"
elif re.search(r'pmagic|partedmagic', string, re.I) and isolinux_bin_exist(iso_link):
return "parted-magic"
elif re.search(r'mgalive', string, re.I): # mounting fat filesystem hard coded in to initrd.
# Can be modified only under linux.
return "mageialive"
elif re.search(r'archisolabel|misolabel', string, re.I):
return "arch"
elif re.search(r'chakraisolabel', string, re.I):
return "chakra"
elif re.search(r'boot=live', string, re.I) and isolinux_bin_exist(iso_link):
return "debian"
elif re.search(r'debian-installer', string, re.I) and isolinux_bin_exist(iso_link):
return "debian-install"
elif re.search(r'solydx', string, re.I):
return "solydx"
elif re.search(r'knoppix', string, re.I):
return "knoppix"
elif re.search(r'root=live', string, re.I):
return "fedora"
elif re.search(r'redhat', string, re.I):
return "redhat"
# elif re.search(r'suse', string, re.I):
# return "suse"
elif re.search(r'opensuse', string,
re.I):
return "opensuse"
elif re.search(
r'slitaz|dban|ophcrack|tinycore|rescue.cpi|xpud|untangle|4mlinux|partition wizard|'
r'riplinux|lebel dummy|http://pogostick.net/~pnh/ntpasswd/|AVG Rescue CD', string, re.I):
return "slitaz"
elif re.search(r'boot=casper', string, re.I):
return "ubuntu"
elif re.search(r'wifislax', string, re.I):
return "wifislax"
elif re.search(r'slax', string, re.I):
return "slax"
elif re.search(r'sms|vector|autoexec', string, re.I):
return "sms"
elif re.search(r'antix', string, re.I):
return "antix"
elif re.search(r'porteus', string, re.I):
return "porteus"
elif re.search(r'livecd=livecd|PCLinuxOS', string, re.I):
return "pclinuxos"
elif re.search(r'looptype=squashfs', string, re.I):
return "gentoo"
elif re.search(r'finnix', string, re.I):
return "finnix"
elif re.search(r'wifiway', string, re.I):
return "wifiway"
elif re.search(r'puppy|quirky', string, re.I):
return "puppy"
elif re.search(r'ipcop', string, re.I):
return "ipcop"
elif re.search(r'ipfire', string, re.I):
return "ipfire"
elif re.search(r'zenwalk|slack|salix', string, re.I) and re.search(r'live', string, re.I):
return "salix-live"
elif re.search(r'zenwalk|slack|salix', string, re.I):
return "zenwalk"
elif re.search(r'ubuntu server', string, re.I):
return "ubuntu-server"
elif re.search(r'Welcome to CentOS', string, re.I):
return "centos-net-minimal"
elif re.search(r'Trinity Rescue Kit', string, re.I):
return "trinity-rescue"
elif re.search(r'alpine', string, re.I):
return "alpine"
elif re.search(r'http://support.kaspersky.com', string, re.I):
return "kaspersky"
distro = detect_iso_from_file_list(iso_link)
if distro:
return distro
# FIXME: See the below comments.
'''
else:
# FIXME: The idea of detecting as generic is to work like a unetbootin if other methods fails.
# This simply extracts distro to root of the USB and install syslinux on isolinux.bin directory.
# All works fine but unable to boot the distro successfully. Also, see the generic section from
# syslinux, update_cfg and install_distro modules.
if self.isolinux_bin_exist():
return "generic"
'''
else:
return None
def detect_iso_from_file_list(iso_link):
"""
Fallback detection script from the content of an ISO.
:return:
"""
if os.path.exists(iso_link):
iso9660fs = ISO9660(iso_link)
iso_file_list = iso9660fs.readDir("/")
if any("sources" in s.lower() for s in iso_file_list):
return "Windows"
elif any("config.isoclient" in s.lower() for s in iso_file_list):
return "opensuse"
elif any("dban" in s.lower() for s in iso_file_list):
return "slitaz"
elif any("memtest.img" in s.lower() for s in iso_file_list):
return "mentest"
else:
print(iso_file_list)
if __name__ == '__main__':
iso_cfg_ext_dir = os.path.join(multibootusb_host_dir(), "iso_cfg_ext_dir")
#iso_link = '../../../DISTROS/2016/debian-live-8.3.0-amd64-lxde-desktop.iso'
iso_link = '/media/sundar/Data/DISTROS/ubuntu_14_04_backup/Downloads/clonezilla-live-2.4.2-32-amd64.iso'
iso_extract_file(iso_link, iso_cfg_ext_dir, 'cfg')
print(distro(iso_cfg_ext_dir))

@ -0,0 +1,285 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*
# Name: gen.py
# Purpose: This 'general' module contain many functions required to be called at many places
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import sys
import os
import platform
import shutil
import string
import zipfile
def scripts_dir_path():
return os.path.dirname(os.path.realpath(__file__))
def resource_path(relativePath):
"""
Function to detect the correct path of file when working with sourcecode/install or binary.
:param relativePath: Path to file/data.
:return: Modified path to file/data.
"""
try:
basePath = sys._MEIPASS # Try if we are running as standalone executable
# print('Running stand alone executable.')
except:
basePath = '/usr/share/multibootusb' # Check if we run in installed environment
#if os.path.exists('/usr/share/multibootusb'):
#print('Running from installed machine.')
if not os.path.exists(basePath):
#basePath = os.path.abspath(".")
basePath = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
if os.path.exists(os.path.join(basePath, relativePath)):
path = os.path.join(basePath, relativePath)
return path
elif not os.path.exists(os.path.join(basePath, relativePath)):
if os.path.exists(os.path.join(os.path.abspath("."), relativePath)):
basePath = os.path.abspath(".")
elif os.path.exists(os.path.join(os.path.abspath(".."), relativePath)):
basePath = os.path.abspath("..")
path = os.path.join(basePath, relativePath)
return path
def print_version():
"""
Simple print the version number of the multibootusb application
:return:
"""
print('multibootusb version : ', mbusb_version())
def quote(text):
"""
Function to quote the input word or sentence.
:param text: Any word or sentence.
:return: Quoted text or sentence. If already quoted the same text is returned.
"""
if not is_quoted(text):
return '"' + text + '"'
else:
return text
def is_quoted(text):
"""
Function to check if word is quoted.
:param text: Any word or sentence with or without quote.
:return: True if text is quoted else False.
"""
if text.startswith("""") and text.endswith("""):
return True
else:
return False
def has_digit(word):
"""
Useful function to detect if input word contain digit.
:param word: Any alphanumeric word.
:return: True if the word has a digit else False.
"""
return any(char.isdigit() for char in word)
def sys_64bits():
"""
Detect if the host system is 64 bit.
:return: True if system is 64 bit.
"""
return sys.maxsize > 2**32
def multibootusb_host_dir():
"""
Cross platform way to detect multibootusb directory on host system.
:return: Path to multibootusb directory of host system.
"""
import tempfile
if platform.system() == "Linux":
home_dir = os.path.expanduser('~')
mbusb_dir = os.path.join(home_dir, ".multibootusb")
elif platform.system() == "Windows":
mbusb_dir = os.path.join(tempfile.gettempdir(), "multibootusb")
return mbusb_dir
def iso_cfg_ext_dir():
"""
Function to return the path to ISO configuration file extraction directory.
:return: Path to directory where ISO config files will be extracted.
"""
return os.path.join(multibootusb_host_dir(), 'iso_cfg_ext_dir')
def clean_iso_cfg_ext_dir(iso_cfg_ext_dir):
"""
Clean old ISO config files extracted by previous use of multibootusb.
:param iso_cfg_ext_dir: Path to config extract directory.
:return:
"""
if os.path.exists(iso_cfg_ext_dir):
filelist = [f for f in os.listdir(iso_cfg_ext_dir)]
for f in filelist:
if os.path.isdir(os.path.join(iso_cfg_ext_dir, f)):
shutil.rmtree(os.path.join(iso_cfg_ext_dir, f))
else:
os.remove(os.path.join(iso_cfg_ext_dir, f))
else:
print('iso_cfg_ext_dir directory does not exist.')
def copy_mbusb_dir_usb(usb_disk):
"""
Copy the multibootusb directory to USB mount path.
:param usb_mount_path: Path to USB mount.
:return:
"""
from .iso import iso_size
from .usb import details
usb_details = details(usb_disk)
usb_mount_path = usb_details['mount_point']
if not os.path.exists(os.path.join(usb_mount_path, "multibootusb")):
try:
print('Copying multibootusb directory to', usb_mount_path)
shutil.copytree(resource_path(os.path.join("data", "multibootusb")), os.path.join(usb_mount_path, "multibootusb"))
return True
except:
return False
else:
print('multibootus directory already exist. Not copying.')
def read_input_yes():
"""
List option and read user input
:return: True if user selected yes or else false
"""
yes_list = ['Y', 'y', 'Yes', 'yes', 'YES']
no_list = ['N', 'n', 'No', 'no', 'NO']
response = input("Please enter the option listed above : ")
if response in yes_list:
return True
elif response in no_list:
return False
def strings(file_path):
"""
Similar to strings command in Linux.
:param file_path: Path to file as string.
:return: All printable character of a file.
"""
import re
nonprintable = re.compile(b'[^%s]+' % re.escape(string.printable.encode('ascii')))
with open(file_path, "rb") as f:
for result in nonprintable.split(f.read()):
if result:
yield result.decode('ASCII')
def size_not_enough(iso_link, usb_disk):
from .iso import iso_size
from .usb import details
isoSize = iso_size(iso_link)
usb_details = details(usb_disk)
usb_size = usb_details['size_free']
if isoSize > usb_size:
return True
else:
return False
def mbusb_version():
version = open(resource_path(os.path.join("data", "version.txt")), 'r').read().strip()
return version
def prepare_mbusb_host_dir():
"""
Prepare multibootusb host directory and extract data files for use.
:return:
"""
home = multibootusb_host_dir()
if not os.path.exists(home):
os.makedirs(home)
else:
print("Cleaning old multibootusb directory...")
shutil.rmtree(home)
os.makedirs(home)
if not os.path.exists(os.path.join(home, "preference")):
os.makedirs(os.path.join(home, "preference"))
if not os.path.exists(os.path.join(home, "iso_cfg_ext_dir")):
os.makedirs(os.path.join(home, "iso_cfg_ext_dir"))
if os.path.exists(os.path.join(home, "syslinux", "bin", "syslinux4")):
print("Syslinux exist in multibootusb directory...")
else:
print("Extracting syslinux to multibootusb directory...")
if platform.system() == "Linux":
if sys_64bits() is True:
print('Host OS is 64 bit...')
print("Extracting syslinux 64 bit...")
# print(resource_path(os.path.join("data", "tools", "syslinux", "syslinux_linux_64.zip")))
with zipfile.ZipFile(resource_path(os.path.join("data", "tools", "syslinux", "syslinux_linux_64.zip")), "r") as z:
z.extractall(home)
else:
print("Extracting syslinux 32 bit...")
with zipfile.ZipFile(resource_path(os.path.join("data", "tools", "syslinux", "syslinux_linux.zip")), "r") as z:
z.extractall(home)
else:
with zipfile.ZipFile(resource_path(os.path.join("data", "tools", "syslinux", "syslinux_windows.zip")), "r") as z:
z.extractall(home)
print("Extracting syslinux modules to multibootusb directory...")
with zipfile.ZipFile(resource_path(os.path.join("data", "tools", "syslinux", "syslinux_modules.zip")), "r") as z:
z.extractall(os.path.join(home, "syslinux"))
'''
if not os.path.exists(os.path.join(home, "persistence_data")):
print("Copying persistence data to multibootusb directory...")
shutil.copytree(resource_path(os.path.join("data", "tools", "persistence_data")),
os.path.join(home, "persistence_data"))
'''
if platform.system() == "Windows":
if not os.path.exists(os.path.join(home, "dd")):
print("Copying dd to multibootusb directory.")
shutil.copytree(resource_path(os.path.join("data", "tools", "dd")),
os.path.join(home, "dd"))
if os.listdir(os.path.join(home, "iso_cfg_ext_dir")):
print(os.listdir(os.path.join(home, "iso_cfg_ext_dir")))
print("iso extract directory is not empty.")
print("Removing junk files...")
for files in os.listdir(os.path.join(home, "iso_cfg_ext_dir")):
if os.path.isdir(os.path.join(os.path.join(home, "iso_cfg_ext_dir", files))):
print (os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)))
os.chmod(os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)), 0o777)
shutil.rmtree(os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)))
else:
try:
print (os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)))
os.chmod(os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)), 0o777)
os.unlink(os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)))
os.remove(os.path.join(os.path.join(home, "iso_cfg_ext_dir", files)))
except OSError:
print("Can't remove the file. Skip it.")
if __name__ == '__main__':
print(quote("""Test-string"""))
print(has_digit("test-string-with-01-digit"))
print(sys_64bits())
print(multibootusb_host_dir())
print(iso_cfg_ext_dir())
strings_test = strings('../../text-stings.bin')
print(strings_test)

@ -0,0 +1,820 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>644</width>
<height>516</height>
</rect>
</property>
<property name="windowTitle">
<string>multibootusb</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>MultiBootUSB</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="2">
<widget class="QLabel" name="label_persistence_value">
<property name="text">
<string>0 MB</string>
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="QLabel" name="labelstep3">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Step 3&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSlider" name="slider_persistence">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Choose Persistence size. Not all distros supports persistence...</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBothSides</enum>
</property>
<property name="tickInterval">
<number>0</number>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QPushButton" name="close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item row="1" column="3" colspan="2">
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Detect USB</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QPushButton" name="detect_usb">
<property name="text">
<string>Refresh USB</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="0" column="5">
<widget class="QLabel" name="labelstep1">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Step 1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLabel" name="labelstep2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Step 2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QPushButton" name="create">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item row="0" column="3" colspan="2">
<widget class="QComboBox" name="comboBox"/>
</item>
<item row="3" column="3" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Uninstall (Optional)</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QPushButton" name="uninstall">
<property name="text">
<string>Uninstall Distro</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="browse_iso">
<property name="text">
<string>Browse ISO</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_persistence">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Persistence&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="4" colspan="3">
<widget class="QListWidget" name="listWidget"/>
</item>
<item row="7" column="0" colspan="6">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="6" column="0" colspan="6">
<widget class="QLabel" name="status">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="4">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="2" column="3" colspan="3">
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>USB Details</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="usb_dev">
<property name="text">
<string>Drive ::</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="usb_vendor">
<property name="text">
<string>Vendor ::</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="usb_model">
<property name="text">
<string>Model::</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="usb_size">
<property name="text">
<string>Size ::</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="usb_mount">
<property name="text">
<string>Mount ::</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="imager">
<attribute name="title">
<string>ISO Imager</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<layout class="QGridLayout" name="gridLayout_9">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Imager</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QGridLayout" name="gridLayout_11">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>-------------- USB details -------------------</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QComboBox" name="comboBox_2"/>
</item>
<item>
<widget class="QPushButton" name="pushbtn_imager_refreshusb">
<property name="text">
<string>Refresh USB</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="imager_disk_label">
<property name="text">
<string>Disk Label ::</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="imager_total_size">
<property name="text">
<string>Disk Size</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="imager_uuid">
<property name="text">
<string>Disk Label ::</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_10">
<property name="title">
<string>------------------------------ ISO details ----------------------------------</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Browse ISO</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_3"/>
</item>
<item>
<widget class="QLabel" name="imager_bootable">
<property name="text">
<string>Bootable ISO</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="imager_iso_size">
<property name="text">
<string>ISO Size</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>Imager Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QLabel" name="imager_label_status">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_12">
<item row="2" column="2">
<widget class="QPushButton" name="imager_write">
<property name="text">
<string>Write/Create</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="imager_close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; color:#ff0000;&quot;&gt;WARNING&lt;/span&gt; : Any bootable USB made using&lt;span style=&quot; font-weight:600;&quot;&gt; ISO Imager will destroy all data &lt;/span&gt;on the selected USB disk. &lt;/p&gt;&lt;p&gt;Use it at your own risk. Developers are not responsile for loss of any data.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QProgressBar" name="imager_progressbar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="syslinux_ab">
<attribute name="title">
<string>Syslinux</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="title">
<string>Install Syslinux</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1">
<widget class="QPushButton" name="install_syslinux">
<property name="text">
<string>Install</string>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<widget class="QRadioButton" name="install_sys_all">
<property name="text">
<string>Install syslinux and copy all required files.</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="install_sys_only">
<property name="text">
<string>Install only syslinux (existing configurations will not be altred).</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Edit syslinux.cfg</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="1">
<widget class="QPushButton" name="edit_syslinux">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;Using this option user can edit syslinux.cfg file directly. It directly uses &lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;default editor of host system. Be careful while editing syslinux.cfg file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>QEMU</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Boot ISO</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="gridLayout_7">
<item row="4" column="4">
<widget class="QRadioButton" name="ram_iso_2048">
<property name="text">
<string>2048 MB</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QRadioButton" name="ram_iso_1024">
<property name="text">
<string>1024 MB</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QRadioButton" name="ram_iso_256">
<property name="text">
<string>256 MB</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QPushButton" name="browse_iso_qemu">
<property name="text">
<string>Browse ISO</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="5">
<widget class="QLabel" name="label_7">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Best way to test your downloaded ISOs. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QRadioButton" name="ram_iso_512">
<property name="text">
<string>512 MB</string>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="boot_iso_qemu">
<property name="text">
<string>Boot ISO</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QRadioButton" name="ram_iso_768">
<property name="text">
<string>768 MB</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QLineEdit" name="lineEdit_2"/>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="0" colspan="4">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Choose desired RAM and click on Boot ISO button.</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_9">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Boot USB</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout_8">
<item row="2" column="2">
<widget class="QRadioButton" name="ram_usb_768">
<property name="text">
<string>768 MB</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="ram_usb_256">
<property name="text">
<string>256 MB</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="5">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;Use this option if you want to check USB installation without reboot.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QRadioButton" name="ram_usb_1024">
<property name="text">
<string>1024 MB</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="4">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Choose desired RAM and click on Boot USB button.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="ram_usb_512">
<property name="text">
<string>512 MB</string>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="boot_usb_qemu">
<property name="text">
<string>Boot USB</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QRadioButton" name="ram_usb_2048">
<property name="text">
<string>2048 MB</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="2">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>About</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="1">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>30</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;An advanced bootable usb creator with option to install/uninstall &lt;/p&gt;&lt;p align=&quot;center&quot;&gt;multiple distros. This software is written in python and pyqt. &lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Copyright 2010-2016 Sundar&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Author(s)&lt;/span&gt;: Sundar, Ian Bruce, Lee&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Licence:&lt;/span&gt; GPL version 2 or later&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Home page&lt;/span&gt;: &lt;a href=&quot; http://multibootusb.org&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://multibootusb.org&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Help/Email:&lt;/span&gt; feedback.multibootusb@gmail.com&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Source Code:&lt;/span&gt;&lt;span style=&quot; font-weight:600;&quot;/&gt;&lt;a href=&quot;https://github.com/mbusb/multibootusb&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/mbusb/multibootusb&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

@ -0,0 +1,445 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'scripts/gui/multibootusb.ui'
#
# Created by: PyQt5 UI code generator 5.5.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(644, 516)
self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog)
self.horizontalLayout.setObjectName("horizontalLayout")
self.tabWidget = QtWidgets.QTabWidget(Dialog)
self.tabWidget.setObjectName("tabWidget")
self.tab_3 = QtWidgets.QWidget()
self.tab_3.setObjectName("tab_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.tab_3)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label_persistence_value = QtWidgets.QLabel(self.tab_3)
self.label_persistence_value.setObjectName("label_persistence_value")
self.gridLayout.addWidget(self.label_persistence_value, 5, 2, 1, 1)
self.labelstep3 = QtWidgets.QLabel(self.tab_3)
self.labelstep3.setObjectName("labelstep3")
self.gridLayout.addWidget(self.labelstep3, 5, 5, 1, 1)
self.slider_persistence = QtWidgets.QSlider(self.tab_3)
self.slider_persistence.setEnabled(False)
self.slider_persistence.setAutoFillBackground(False)
self.slider_persistence.setOrientation(QtCore.Qt.Horizontal)
self.slider_persistence.setTickPosition(QtWidgets.QSlider.TicksBothSides)
self.slider_persistence.setTickInterval(0)
self.slider_persistence.setObjectName("slider_persistence")
self.gridLayout.addWidget(self.slider_persistence, 5, 1, 1, 1)
self.close = QtWidgets.QPushButton(self.tab_3)
self.close.setObjectName("close")
self.gridLayout.addWidget(self.close, 5, 3, 1, 1)
self.verticalLayout_11 = QtWidgets.QVBoxLayout()
self.verticalLayout_11.setObjectName("verticalLayout_11")
self.groupBox_11 = QtWidgets.QGroupBox(self.tab_3)
self.groupBox_11.setObjectName("groupBox_11")
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.groupBox_11)
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.detect_usb = QtWidgets.QPushButton(self.groupBox_11)
self.detect_usb.setObjectName("detect_usb")
self.horizontalLayout_8.addWidget(self.detect_usb)
self.verticalLayout_11.addWidget(self.groupBox_11)
self.gridLayout.addLayout(self.verticalLayout_11, 1, 3, 1, 2)
self.labelstep1 = QtWidgets.QLabel(self.tab_3)
self.labelstep1.setObjectName("labelstep1")
self.gridLayout.addWidget(self.labelstep1, 0, 5, 1, 1)
self.labelstep2 = QtWidgets.QLabel(self.tab_3)
self.labelstep2.setObjectName("labelstep2")
self.gridLayout.addWidget(self.labelstep2, 4, 5, 1, 1)
self.create = QtWidgets.QPushButton(self.tab_3)
self.create.setObjectName("create")
self.gridLayout.addWidget(self.create, 5, 4, 1, 1)
self.comboBox = QtWidgets.QComboBox(self.tab_3)
self.comboBox.setObjectName("comboBox")
self.gridLayout.addWidget(self.comboBox, 0, 3, 1, 2)
self.groupBox = QtWidgets.QGroupBox(self.tab_3)
self.groupBox.setObjectName("groupBox")
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout_5 = QtWidgets.QGridLayout()
self.gridLayout_5.setObjectName("gridLayout_5")
self.uninstall = QtWidgets.QPushButton(self.groupBox)
self.uninstall.setObjectName("uninstall")
self.gridLayout_5.addWidget(self.uninstall, 0, 0, 1, 1)
self.verticalLayout.addLayout(self.gridLayout_5)
self.gridLayout.addWidget(self.groupBox, 3, 3, 1, 2)
self.browse_iso = QtWidgets.QPushButton(self.tab_3)
self.browse_iso.setObjectName("browse_iso")
self.gridLayout.addWidget(self.browse_iso, 4, 4, 1, 1)
self.label_persistence = QtWidgets.QLabel(self.tab_3)
self.label_persistence.setObjectName("label_persistence")
self.gridLayout.addWidget(self.label_persistence, 5, 0, 1, 1)
self.listWidget = QtWidgets.QListWidget(self.tab_3)
self.listWidget.setObjectName("listWidget")
self.gridLayout.addWidget(self.listWidget, 0, 0, 4, 3)
self.progressBar = QtWidgets.QProgressBar(self.tab_3)
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.gridLayout.addWidget(self.progressBar, 7, 0, 1, 6)
self.status = QtWidgets.QLabel(self.tab_3)
self.status.setMinimumSize(QtCore.QSize(0, 0))
self.status.setAcceptDrops(False)
self.status.setAutoFillBackground(False)
self.status.setFrameShadow(QtWidgets.QFrame.Plain)
self.status.setText("")
self.status.setScaledContents(False)
self.status.setObjectName("status")
self.gridLayout.addWidget(self.status, 6, 0, 1, 6)
self.lineEdit = QtWidgets.QLineEdit(self.tab_3)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 4, 0, 1, 4)
self.groupBox_6 = QtWidgets.QGroupBox(self.tab_3)
self.groupBox_6.setObjectName("groupBox_6")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_6)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.usb_dev = QtWidgets.QLabel(self.groupBox_6)
self.usb_dev.setObjectName("usb_dev")
self.verticalLayout_5.addWidget(self.usb_dev)
self.usb_vendor = QtWidgets.QLabel(self.groupBox_6)
self.usb_vendor.setObjectName("usb_vendor")
self.verticalLayout_5.addWidget(self.usb_vendor)
self.usb_model = QtWidgets.QLabel(self.groupBox_6)
self.usb_model.setObjectName("usb_model")
self.verticalLayout_5.addWidget(self.usb_model)
self.usb_size = QtWidgets.QLabel(self.groupBox_6)
self.usb_size.setObjectName("usb_size")
self.verticalLayout_5.addWidget(self.usb_size)
self.usb_mount = QtWidgets.QLabel(self.groupBox_6)
self.usb_mount.setObjectName("usb_mount")
self.verticalLayout_5.addWidget(self.usb_mount)
self.gridLayout.addWidget(self.groupBox_6, 2, 3, 1, 3)
self.horizontalLayout_2.addLayout(self.gridLayout)
self.tabWidget.addTab(self.tab_3, "")
self.imager = QtWidgets.QWidget()
self.imager.setObjectName("imager")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.imager)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.gridLayout_9 = QtWidgets.QGridLayout()
self.gridLayout_9.setObjectName("gridLayout_9")
self.groupBox_7 = QtWidgets.QGroupBox(self.imager)
self.groupBox_7.setObjectName("groupBox_7")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupBox_7)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.gridLayout_11 = QtWidgets.QGridLayout()
self.gridLayout_11.setObjectName("gridLayout_11")
self.groupBox_9 = QtWidgets.QGroupBox(self.groupBox_7)
self.groupBox_9.setObjectName("groupBox_9")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.groupBox_9)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.comboBox_2 = QtWidgets.QComboBox(self.groupBox_9)
self.comboBox_2.setObjectName("comboBox_2")
self.verticalLayout_8.addWidget(self.comboBox_2)
self.pushbtn_imager_refreshusb = QtWidgets.QPushButton(self.groupBox_9)
self.pushbtn_imager_refreshusb.setObjectName("pushbtn_imager_refreshusb")
self.verticalLayout_8.addWidget(self.pushbtn_imager_refreshusb)
self.imager_disk_label = QtWidgets.QLabel(self.groupBox_9)
self.imager_disk_label.setObjectName("imager_disk_label")
self.verticalLayout_8.addWidget(self.imager_disk_label)
self.imager_total_size = QtWidgets.QLabel(self.groupBox_9)
self.imager_total_size.setObjectName("imager_total_size")
self.verticalLayout_8.addWidget(self.imager_total_size)
self.imager_uuid = QtWidgets.QLabel(self.groupBox_9)
self.imager_uuid.setObjectName("imager_uuid")
self.verticalLayout_8.addWidget(self.imager_uuid)
self.gridLayout_11.addWidget(self.groupBox_9, 0, 0, 1, 1)
self.groupBox_10 = QtWidgets.QGroupBox(self.groupBox_7)
self.groupBox_10.setObjectName("groupBox_10")
self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.groupBox_10)
self.verticalLayout_9.setObjectName("verticalLayout_9")
self.pushButton = QtWidgets.QPushButton(self.groupBox_10)
self.pushButton.setObjectName("pushButton")
self.verticalLayout_9.addWidget(self.pushButton)
self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox_10)
self.lineEdit_3.setObjectName("lineEdit_3")
self.verticalLayout_9.addWidget(self.lineEdit_3)
self.imager_bootable = QtWidgets.QLabel(self.groupBox_10)
self.imager_bootable.setObjectName("imager_bootable")
self.verticalLayout_9.addWidget(self.imager_bootable)
self.imager_iso_size = QtWidgets.QLabel(self.groupBox_10)
self.imager_iso_size.setObjectName("imager_iso_size")
self.verticalLayout_9.addWidget(self.imager_iso_size)
self.gridLayout_11.addWidget(self.groupBox_10, 0, 1, 1, 1)
self.verticalLayout_6.addLayout(self.gridLayout_11)
self.gridLayout_9.addWidget(self.groupBox_7, 1, 0, 1, 1)
self.groupBox_8 = QtWidgets.QGroupBox(self.imager)
self.groupBox_8.setObjectName("groupBox_8")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.groupBox_8)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.imager_label_status = QtWidgets.QLabel(self.groupBox_8)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.imager_label_status.sizePolicy().hasHeightForWidth())
self.imager_label_status.setSizePolicy(sizePolicy)
self.imager_label_status.setText("")
self.imager_label_status.setObjectName("imager_label_status")
self.verticalLayout_7.addWidget(self.imager_label_status)
self.gridLayout_12 = QtWidgets.QGridLayout()
self.gridLayout_12.setObjectName("gridLayout_12")
self.imager_write = QtWidgets.QPushButton(self.groupBox_8)
self.imager_write.setObjectName("imager_write")
self.gridLayout_12.addWidget(self.imager_write, 2, 2, 1, 1)
self.imager_close = QtWidgets.QPushButton(self.groupBox_8)
self.imager_close.setObjectName("imager_close")
self.gridLayout_12.addWidget(self.imager_close, 2, 1, 1, 1)
self.label_10 = QtWidgets.QLabel(self.groupBox_8)
self.label_10.setObjectName("label_10")
self.gridLayout_12.addWidget(self.label_10, 1, 0, 1, 3)
self.imager_progressbar = QtWidgets.QProgressBar(self.groupBox_8)
self.imager_progressbar.setProperty("value", 0)
self.imager_progressbar.setObjectName("imager_progressbar")
self.gridLayout_12.addWidget(self.imager_progressbar, 0, 0, 1, 3)
self.verticalLayout_7.addLayout(self.gridLayout_12)
self.gridLayout_9.addWidget(self.groupBox_8, 2, 0, 1, 1)
self.horizontalLayout_7.addLayout(self.gridLayout_9)
self.tabWidget.addTab(self.imager, "")
self.syslinux_ab = QtWidgets.QWidget()
self.syslinux_ab.setObjectName("syslinux_ab")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.syslinux_ab)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.gridLayout_2 = QtWidgets.QGridLayout()
self.gridLayout_2.setObjectName("gridLayout_2")
self.groupBox_2 = QtWidgets.QGroupBox(self.syslinux_ab)
self.groupBox_2.setAutoFillBackground(False)
self.groupBox_2.setObjectName("groupBox_2")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_2)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.gridLayout_3 = QtWidgets.QGridLayout()
self.gridLayout_3.setObjectName("gridLayout_3")
self.install_syslinux = QtWidgets.QPushButton(self.groupBox_2)
self.install_syslinux.setObjectName("install_syslinux")
self.gridLayout_3.addWidget(self.install_syslinux, 2, 1, 1, 1)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem, 2, 0, 1, 1)
self.install_sys_all = QtWidgets.QRadioButton(self.groupBox_2)
self.install_sys_all.setObjectName("install_sys_all")
self.gridLayout_3.addWidget(self.install_sys_all, 1, 0, 1, 2)
self.install_sys_only = QtWidgets.QRadioButton(self.groupBox_2)
self.install_sys_only.setObjectName("install_sys_only")
self.gridLayout_3.addWidget(self.install_sys_only, 0, 0, 1, 2)
self.horizontalLayout_4.addLayout(self.gridLayout_3)
self.gridLayout_2.addWidget(self.groupBox_2, 0, 0, 1, 1)
self.groupBox_3 = QtWidgets.QGroupBox(self.syslinux_ab)
self.groupBox_3.setObjectName("groupBox_3")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_3)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.gridLayout_4 = QtWidgets.QGridLayout()
self.gridLayout_4.setObjectName("gridLayout_4")
self.edit_syslinux = QtWidgets.QPushButton(self.groupBox_3)
self.edit_syslinux.setObjectName("edit_syslinux")
self.gridLayout_4.addWidget(self.edit_syslinux, 1, 1, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_4.addItem(spacerItem1, 1, 0, 1, 1)
self.label_2 = QtWidgets.QLabel(self.groupBox_3)
self.label_2.setObjectName("label_2")
self.gridLayout_4.addWidget(self.label_2, 0, 0, 1, 2)
self.horizontalLayout_5.addLayout(self.gridLayout_4)
self.gridLayout_2.addWidget(self.groupBox_3, 1, 0, 1, 1)
self.horizontalLayout_3.addLayout(self.gridLayout_2)
self.tabWidget.addTab(self.syslinux_ab, "")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.groupBox_5 = QtWidgets.QGroupBox(self.tab)
self.groupBox_5.setObjectName("groupBox_5")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_5)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.gridLayout_7 = QtWidgets.QGridLayout()
self.gridLayout_7.setObjectName("gridLayout_7")
self.ram_iso_2048 = QtWidgets.QRadioButton(self.groupBox_5)
self.ram_iso_2048.setObjectName("ram_iso_2048")
self.gridLayout_7.addWidget(self.ram_iso_2048, 4, 4, 1, 1)
self.ram_iso_1024 = QtWidgets.QRadioButton(self.groupBox_5)
self.ram_iso_1024.setObjectName("ram_iso_1024")
self.gridLayout_7.addWidget(self.ram_iso_1024, 4, 3, 1, 1)
self.ram_iso_256 = QtWidgets.QRadioButton(self.groupBox_5)
self.ram_iso_256.setObjectName("ram_iso_256")
self.gridLayout_7.addWidget(self.ram_iso_256, 4, 0, 1, 1)
self.browse_iso_qemu = QtWidgets.QPushButton(self.groupBox_5)
self.browse_iso_qemu.setObjectName("browse_iso_qemu")
self.gridLayout_7.addWidget(self.browse_iso_qemu, 2, 4, 1, 1)
self.label_7 = QtWidgets.QLabel(self.groupBox_5)
self.label_7.setObjectName("label_7")
self.gridLayout_7.addWidget(self.label_7, 0, 0, 1, 5)
self.ram_iso_512 = QtWidgets.QRadioButton(self.groupBox_5)
self.ram_iso_512.setObjectName("ram_iso_512")
self.gridLayout_7.addWidget(self.ram_iso_512, 4, 1, 1, 1)
self.boot_iso_qemu = QtWidgets.QPushButton(self.groupBox_5)
self.boot_iso_qemu.setObjectName("boot_iso_qemu")
self.gridLayout_7.addWidget(self.boot_iso_qemu, 6, 4, 1, 1)
self.ram_iso_768 = QtWidgets.QRadioButton(self.groupBox_5)
self.ram_iso_768.setObjectName("ram_iso_768")
self.gridLayout_7.addWidget(self.ram_iso_768, 4, 2, 1, 1)
self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_5)
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout_7.addWidget(self.lineEdit_2, 2, 0, 1, 4)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_7.addItem(spacerItem2, 3, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(self.groupBox_5)
self.label_3.setObjectName("label_3")
self.gridLayout_7.addWidget(self.label_3, 6, 0, 1, 4)
spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_7.addItem(spacerItem3, 5, 0, 1, 1)
spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_7.addItem(spacerItem4, 1, 0, 1, 1)
self.verticalLayout_3.addLayout(self.gridLayout_7)
self.verticalLayout_2.addWidget(self.groupBox_5)
spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem5)
self.gridLayout_6 = QtWidgets.QGridLayout()
self.gridLayout_6.setObjectName("gridLayout_6")
self.groupBox_4 = QtWidgets.QGroupBox(self.tab)
self.groupBox_4.setObjectName("groupBox_4")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_4)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.gridLayout_8 = QtWidgets.QGridLayout()
self.gridLayout_8.setObjectName("gridLayout_8")
self.ram_usb_768 = QtWidgets.QRadioButton(self.groupBox_4)
self.ram_usb_768.setObjectName("ram_usb_768")
self.gridLayout_8.addWidget(self.ram_usb_768, 2, 2, 1, 1)
self.ram_usb_256 = QtWidgets.QRadioButton(self.groupBox_4)
self.ram_usb_256.setObjectName("ram_usb_256")
self.gridLayout_8.addWidget(self.ram_usb_256, 2, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(self.groupBox_4)
self.label_6.setObjectName("label_6")
self.gridLayout_8.addWidget(self.label_6, 0, 0, 1, 5)
self.ram_usb_1024 = QtWidgets.QRadioButton(self.groupBox_4)
self.ram_usb_1024.setObjectName("ram_usb_1024")
self.gridLayout_8.addWidget(self.ram_usb_1024, 2, 3, 1, 1)
self.label_4 = QtWidgets.QLabel(self.groupBox_4)
self.label_4.setObjectName("label_4")
self.gridLayout_8.addWidget(self.label_4, 4, 0, 1, 4)
self.ram_usb_512 = QtWidgets.QRadioButton(self.groupBox_4)
self.ram_usb_512.setObjectName("ram_usb_512")
self.gridLayout_8.addWidget(self.ram_usb_512, 2, 1, 1, 1)
self.boot_usb_qemu = QtWidgets.QPushButton(self.groupBox_4)
self.boot_usb_qemu.setObjectName("boot_usb_qemu")
self.gridLayout_8.addWidget(self.boot_usb_qemu, 4, 4, 1, 1)
self.ram_usb_2048 = QtWidgets.QRadioButton(self.groupBox_4)
self.ram_usb_2048.setObjectName("ram_usb_2048")
self.gridLayout_8.addWidget(self.ram_usb_2048, 2, 4, 1, 1)
spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_8.addItem(spacerItem6, 1, 1, 1, 1)
spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_8.addItem(spacerItem7, 3, 2, 1, 1)
spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_8.addItem(spacerItem8, 5, 0, 1, 1)
self.verticalLayout_4.addLayout(self.gridLayout_8)
self.gridLayout_6.addWidget(self.groupBox_4, 0, 0, 1, 1)
self.verticalLayout_2.addLayout(self.gridLayout_6)
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.tab_2)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.gridLayout_10 = QtWidgets.QGridLayout()
self.gridLayout_10.setObjectName("gridLayout_10")
spacerItem9 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_10.addItem(spacerItem9, 0, 1, 1, 1)
spacerItem10 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_10.addItem(spacerItem10, 1, 0, 1, 1)
spacerItem11 = QtWidgets.QSpacerItem(20, 30, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_10.addItem(spacerItem11, 2, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(self.tab_2)
self.label_5.setObjectName("label_5")
self.gridLayout_10.addWidget(self.label_5, 1, 1, 1, 1)
spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_10.addItem(spacerItem12, 1, 2, 1, 1)
self.horizontalLayout_6.addLayout(self.gridLayout_10)
self.tabWidget.addTab(self.tab_2, "")
self.horizontalLayout.addWidget(self.tabWidget)
self.retranslateUi(Dialog)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "multibootusb"))
self.label_persistence_value.setText(_translate("Dialog", "0 MB"))
self.labelstep3.setText(_translate("Dialog", "<html><head/><body><p align=\"center\"><span style=\" font-weight:600;\">Step 3</span></p></body></html>"))
self.slider_persistence.setToolTip(_translate("Dialog", "Choose Persistence size. Not all distros supports persistence..."))
self.close.setText(_translate("Dialog", "Close"))
self.groupBox_11.setTitle(_translate("Dialog", "Detect USB"))
self.detect_usb.setText(_translate("Dialog", "Refresh USB"))
self.labelstep1.setText(_translate("Dialog", "<html><head/><body><p align=\"center\"><span style=\" font-weight:600;\">Step 1</span></p></body></html>"))
self.labelstep2.setText(_translate("Dialog", "<html><head/><body><p align=\"center\"><span style=\" font-weight:600;\">Step 2</span></p></body></html>"))
self.create.setText(_translate("Dialog", "Create"))
self.groupBox.setTitle(_translate("Dialog", "Uninstall (Optional)"))
self.uninstall.setText(_translate("Dialog", "Uninstall Distro"))
self.browse_iso.setText(_translate("Dialog", "Browse ISO"))
self.label_persistence.setText(_translate("Dialog", "<html><head/><body><p><span style=\" font-weight:600;\">Persistence</span></p></body></html>"))
self.groupBox_6.setTitle(_translate("Dialog", "USB Details"))
self.usb_dev.setText(_translate("Dialog", "Drive ::"))
self.usb_vendor.setText(_translate("Dialog", "Vendor ::"))
self.usb_model.setText(_translate("Dialog", "Model::"))
self.usb_size.setText(_translate("Dialog", "Size ::"))
self.usb_mount.setText(_translate("Dialog", "Mount ::"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("Dialog", "MultiBootUSB"))
self.groupBox_7.setTitle(_translate("Dialog", "Imager"))
self.groupBox_9.setTitle(_translate("Dialog", "-------------- USB details -------------------"))
self.pushbtn_imager_refreshusb.setText(_translate("Dialog", "Refresh USB"))
self.imager_disk_label.setText(_translate("Dialog", "Disk Label ::"))
self.imager_total_size.setText(_translate("Dialog", "Disk Size"))
self.imager_uuid.setText(_translate("Dialog", "Disk Label ::"))
self.groupBox_10.setTitle(_translate("Dialog", "------------------------------ ISO details ----------------------------------"))
self.pushButton.setText(_translate("Dialog", "Browse ISO"))
self.imager_bootable.setText(_translate("Dialog", "Bootable ISO"))
self.imager_iso_size.setText(_translate("Dialog", "ISO Size"))
self.groupBox_8.setTitle(_translate("Dialog", "Imager Progress"))
self.imager_write.setText(_translate("Dialog", "Write/Create"))
self.imager_close.setText(_translate("Dialog", "Close"))
self.label_10.setText(_translate("Dialog", "<html><head/><body><p><span style=\" font-weight:600; color:#ff0000;\">WARNING</span> : Any bootable USB made using<span style=\" font-weight:600;\"> ISO Imager will destroy all data </span>on the selected USB disk. </p><p>Use it at your own risk. Developers are not responsile for loss of any data.</p></body></html>"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.imager), _translate("Dialog", "ISO Imager"))
self.groupBox_2.setTitle(_translate("Dialog", "Install Syslinux"))
self.install_syslinux.setText(_translate("Dialog", "Install"))
self.install_sys_all.setText(_translate("Dialog", "Install syslinux and copy all required files."))
self.install_sys_only.setText(_translate("Dialog", "Install only syslinux (existing configurations will not be altred)."))
self.groupBox_3.setTitle(_translate("Dialog", "Edit syslinux.cfg"))
self.edit_syslinux.setText(_translate("Dialog", "Edit"))
self.label_2.setText(_translate("Dialog", "<html><head/><body><p align=\"justify\">Using this option user can edit syslinux.cfg file directly. It directly uses </p><p align=\"justify\">default editor of host system. Be careful while editing syslinux.cfg file.</p></body></html>"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.syslinux_ab), _translate("Dialog", "Syslinux"))
self.groupBox_5.setTitle(_translate("Dialog", "Boot ISO"))
self.ram_iso_2048.setText(_translate("Dialog", "2048 MB"))
self.ram_iso_1024.setText(_translate("Dialog", "1024 MB"))
self.ram_iso_256.setText(_translate("Dialog", "256 MB"))
self.browse_iso_qemu.setText(_translate("Dialog", "Browse ISO"))
self.label_7.setText(_translate("Dialog", "<html><head/><body><p>Best way to test your downloaded ISOs. </p></body></html>"))
self.ram_iso_512.setText(_translate("Dialog", "512 MB"))
self.boot_iso_qemu.setText(_translate("Dialog", "Boot ISO"))
self.ram_iso_768.setText(_translate("Dialog", "768 MB"))
self.label_3.setText(_translate("Dialog", "Choose desired RAM and click on Boot ISO button."))
self.groupBox_4.setTitle(_translate("Dialog", "Boot USB"))
self.ram_usb_768.setText(_translate("Dialog", "768 MB"))
self.ram_usb_256.setText(_translate("Dialog", "256 MB"))
self.label_6.setText(_translate("Dialog", "<html><head/><body><p align=\"justify\">Use this option if you want to check USB installation without reboot.</p></body></html>"))
self.ram_usb_1024.setText(_translate("Dialog", "1024 MB"))
self.label_4.setText(_translate("Dialog", "Choose desired RAM and click on Boot USB button."))
self.ram_usb_512.setText(_translate("Dialog", "512 MB"))
self.boot_usb_qemu.setText(_translate("Dialog", "Boot USB"))
self.ram_usb_2048.setText(_translate("Dialog", "2048 MB"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Dialog", "QEMU"))
self.label_5.setText(_translate("Dialog", "<html><head/><body><p align=\"center\">An advanced bootable usb creator with option to install/uninstall </p><p align=\"center\">multiple distros. This software is written in python and pyqt. </p><p align=\"center\">Copyright 2010-2016 Sundar</p><p align=\"center\"><span style=\" font-weight:600; text-decoration: underline;\">Author(s)</span>: Sundar, Ian Bruce, Lee</p><p align=\"center\"><span style=\" font-weight:600; text-decoration: underline;\">Licence:</span> GPL version 2 or later</p><p align=\"center\"><span style=\" font-weight:600; text-decoration: underline;\">Home page</span>: <a href=\" http://multibootusb.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://multibootusb.org</span></a></p><p align=\"center\"><span style=\" font-weight:600; text-decoration: underline;\">Help/Email:</span> feedback.multibootusb@gmail.com</p><p align=\"center\"><span style=\" font-weight:600; text-decoration: underline;\">Source Code:</span><span style=\" font-weight:600;\"/><a href=\"https://github.com/mbusb/multibootusb\"><span style=\" text-decoration: underline; color:#0000ff;\">https://github.com/mbusb/multibootusb</span></a></p><p><br/></p></body></html>"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Dialog", "About"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())

@ -0,0 +1,227 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: imager.py
# Purpose: Module to write ISO image to selected USB disk. Uses dd as backend.
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
# WARNING : Any boot-able USB made using this module will destroy data stored on USB disk.
import os
import subprocess
import collections
import platform
import signal
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from .gui.ui_multibootusb import Ui_Dialog
from .gen import *
from . import iso
from . import usb
from . import config
from . import progressbar
if platform.system() == "Windows":
import win32com.client
def dd_linux():
import time
input = "if=" + config.imager_iso_link
in_file_size = float(os.path.getsize(config.imager_iso_link))
output = "of=" + config.imager_usb_disk
os.system("umount " + config.imager_usb_disk + "1")
command = ['dd', input, output, "bs=1M"]
print("Executing ==> ", command)
dd_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
pbar = progressbar.ProgressBar(maxval=100).start() # bar = progressbar.ProgressBar(redirect_stdout=True)
while dd_process.poll() is None:
time.sleep(.1) # If this time delay is not given, the Popen does not execute the actual command
dd_process.send_signal(signal.SIGUSR1)
dd_process.stderr.flush()
while True:
out_error = dd_process.stderr.readline().decode()
if out_error:
if 'bytes' in out_error:
copied = int(out_error.split(' ', 1)[0])
config.imager_percentage = round((float(copied) / float(in_file_size) * 100))
pbar.update(config.imager_percentage)
break
if dd_process.poll() is not None:
print("Executing ==> sync")
os.system("sync")
print("ISO has been written to USB disk...")
return
def dd_win():
windd = resource_path(os.path.join("data", "tools", "dd", "dd.exe"))
if os.path.exists(resource_path(os.path.join("data", "tools", "dd", "dd.exe"))):
print("dd exist")
input = "if=" + config.imager_iso_link
in_file_size = float(os.path.getsize(config.imager_iso_link) / 1024 / 1024)
output = "of=\\\.\\" + config.imager_usb_disk
command = [windd, input, output, "bs=1M", "--progress"]
print("Executing ==> ", command)
dd_process = subprocess.Popen(command, universal_newlines=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
shell=False)
while dd_process.poll() is None:
for line in iter(dd_process.stderr.readline, ''):
line = line.strip()
if 'error' in line.lower() or 'invalid' in line.lower():
print("Error writing to disk...")
break
if line and line[-1] == 'M':
copied = float(line.strip('M').replace(',', ''))
config.imager_percentage = round((copied / float(in_file_size) * 100))
print("ISO has been written to USB disk...")
return
class Imager(QtWidgets.QDialog, Ui_Dialog):
"""
Raw write to USB disk using dd.
"""
def __init__(self):
QtWidgets.QDialog.__init__(self)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
def on_Imager_Browse_iso_Click(self):
"""
Browse and choose an ISO.
:return:
"""
self.ui.lineEdit_3.clear()
config.imager_iso_link = QtWidgets.QFileDialog.getOpenFileName(self, 'Select an iso...', "", "ISO Files (*.iso)")[0]
if config.imager_iso_link:
if platform.system() == "Windows":
if "/" in config.imager_iso_link:
config.imager_iso_link = config.imager_iso_link.strip().replace("/", "\\")
self.ui.lineEdit_3.insert(str(config.imager_iso_link))
self.add_iso_gui_label_text()
else:
print("File not selected...")
def add_iso_gui_label_text(self):
"""
Simple function to add text label to GUI widgets.
:return:
"""
print("Testing ISO...")
if iso.is_bootable(config.imager_iso_link) is True:
self.ui.imager_bootable.setText("Bootable ISO :: Yes")
print("ISO is bootable.")
else:
self.ui.imager_bootable.setText("Bootable ISO :: No")
print("ISO is not bootable.")
if os.path.exists(config.imager_iso_link):
print("Path " + config.imager_iso_link + " is exist...")
self.iso_size = str(round(os.path.getsize(config.imager_iso_link) / 1024 / 1024))
self.ui.imager_iso_size.setText("ISO Size :: " + self.iso_size + " MB")
print("ISO Size is ", self.iso_size, " MB")
def onImagerComboChange(self):
config.imager_usb_disk = str(self.ui.comboBox_2.currentText())
if bool(config.imager_usb_disk):
self.ui.imager_disk_label.setText("Disk Type :: " + self.imager_usb_detail(config.imager_usb_disk,
partition=0).usb_type)
self.ui.imager_total_size.setText("Disk Size :: " + usb.bytes2human(int(self.imager_usb_detail
(config.imager_usb_disk,
partition=0).total_size)))
if platform.system() == "Linux":
self.ui.imager_uuid.setText("Disk Model :: " + str(self.imager_usb_detail(config.imager_usb_disk,
partition=0).model))
else:
self.ui.imager_uuid.setText("Disk Label :: " + self.imager_usb_detail(config.imager_usb_disk,
partition=0).model)
def imager_list_usb(self, partition=1):
"""
Function to detect whole USB disk. It uses lsblk package on Linux.
:param partition: What to return. By default partition is set.
:return: USB disk/partition as list
"""
disk = []
if platform.system() == "Linux":
output = subprocess.check_output("lsblk -i", shell=True)
if not partition == 1:
for line in output.splitlines():
line = line.split()
if (line[2].strip()) == b'1' and (line[5].strip()) == b'disk':
disk.append(str("/dev/" + str(line[0].strip().decode())))
elif partition == 1:
for line in output.splitlines():
line = line.split()
if (line[2].strip()) == b'1' and line[5].strip() == b'part':
disk.append(str("/dev/" + str(line[0].strip()[2:])))
else:
if partition == 1 or not partition == 1:
oFS = win32com.client.Dispatch("Scripting.FileSystemObject")
oDrives = oFS.Drives
for drive in oDrives:
if drive.DriveType == 1 and drive.IsReady:
disk.append(drive)
return disk
def imager_usb_detail(self, usb_disk, partition=1):
"""
Function to detect details of USB disk using lsblk
:param usb_disk: path to usb disk
:param partition: by default partition is set (but yet to code for it)
:return: details of size, type and model as tuples
"""
_ntuple_diskusage = collections.namedtuple('usage', 'total_size usb_type model')
if platform.system() == "Linux":
output = subprocess.check_output("lsblk -ib " + usb_disk, shell=True)
for line in output.splitlines():
line = line.split()
if not partition == 1:
if line[2].strip() == b'1' and line[5].strip() == b'disk':
total_size = line[3]
if not total_size:
total_size = "Unknown"
usb_type = "Removable"
model = subprocess.check_output("lsblk -in -f -o MODEL " + usb_disk, shell=True).decode()
if not model:
model = "Unknown"
else:
try:
selected_usb_part = str(usb_disk)
oFS = win32com.client.Dispatch("Scripting.FileSystemObject")
d = oFS.GetDrive(oFS.GetDriveName(oFS.GetAbsolutePathName(selected_usb_part)))
selected_usb_device = d.DriveLetter
label = (d.VolumeName).strip()
if not label.strip():
label = "No label."
total_size = d.TotalSize
usb_type = "Removable"
model = label
except:
print("Error detecting USB details.")
return _ntuple_diskusage(total_size, usb_type, model)
def get_usb_size(self, usb_disk):
"""
Function to detect USB disk space. Useful but not used in multibootusb as of now.
:param usb_disk: USB disk like "/dev/sdb"
:return: Size of the disk as integer
"""
if platform.system() == "Linux":
cat_output = subprocess.check_output("cat /proc/partitions | grep " + usb_disk[5:], shell=True)
usb_size = int(cat_output.split()[2]) * 1024
print(usb_size)
return usb_size
else:
usb_size = self.usb.disk_usage(self.usb.get_usb(usb_disk).mount).total
return usb_size

@ -0,0 +1,169 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: install.py
# Purpose: This module contain functions to install ISO files to USB disk non destructively.
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import os
import shutil
import sys
import platform
import threading
import subprocess
from .usb import *
from .gen import *
from .iso import *
from scripts.update_cfg_file import *
from . import config
from . import persistence
def install_distro():
"""
Install selected ISO to USB disk.
:return:
"""
usb_details = details(config.usb_disk)
usb_mount = usb_details['mount_point']
install_dir = os.path.join(usb_mount, "multibootusb", iso_basename(config.iso_link))
_iso_file_list = iso_file_list(config.iso_link)
if not os.path.exists(os.path.join(usb_mount, "multibootusb")):
print("Copying multibootusb directory to ", usb_mount)
shutil.copytree(resource_path(os.path.join("data", "tools", "multibootusb")),
os.path.join(config.usb_mount, "multibootusb"))
if not os.path.exists(install_dir):
os.makedirs(install_dir)
with open(os.path.join(install_dir, "multibootusb.cfg"), "w") as f:
f.write(config.distro)
with open(os.path.join(install_dir, "iso_file_list.cfg"), 'w') as f:
for file_path in _iso_file_list:
f.write(file_path + "\n")
print("Installing ", iso_name(config.iso_link), "on", install_dir)
if config.distro == "opensuse":
iso_extract_file(config.iso_link, install_dir, 'boot')
status_text = "Copying ISO..."
if platform.system() == "Windows":
subprocess.call(["xcopy", config.iso_link, usb_mount], shell=True) # Have to use xcopy as python file copy is dead slow.
elif platform.system() == "Linux":
print(config.iso_link, usb_mount)
shutil.copy(config.iso_link, usb_mount)
elif config.distro == "Windows":
print("Extracting iso to " + usb_mount)
iso_extract_full(config.iso_link, install_dir)
elif config.distro == "trinity-rescue":
iso_extract_file(config.iso_link, usb_mount, 'trk3')
elif config.distro == "ipfire":
iso_extract_file(config.iso_link, usb_mount, '.tlz')
iso_extract_file(config.iso_link, usb_mount, 'distro.img')
iso_extract_file(config.iso_link, install_dir, 'boot')
elif config.distro == "alpine":
iso_extract_full(config.iso_link, usb_mount)
elif config.distro == "zenwalk":
iso_extract_file(config.iso_link, install_dir, "kernel")
if platform.system() == "Windows":
subprocess.call(["xcopy", config.iso_link, install_dir], shell=True)
elif platform.system() == "Linux":
shutil.copy(config.iso_link, install_dir)
elif config.distro == "salix-live":
iso_extract_file(config.iso_link, install_dir, "boot")
config.status_text = "Copying ISO..."
if platform.system() == "Windows":
subprocess.call("xcopy " + config.iso_link + " " + install_dir, shell=True)
elif platform.system() == "Linux":
shutil.copy(config.iso_link, install_dir)
elif config.distro == "generic":
with open(os.path.join(install_dir, "generic.cfg"), "w") as f:
f.write(os.path.join(isolinux_bin_dir(config.iso_link), "generic") + ".bs")
iso_extract_full(config.iso_link, usb_mount)
else:
iso_extract_full(config.iso_link, install_dir)
if platform.system() == 'Linux':
print('ISO extracted successfully. Sync is in progress...')
os.system('sync')
if config.persistence != 0:
config.status_text = 'Creating Persistence...'
persistence.create_persistence()
install_patch()
def install_progress():
"""
Function to calculate progress percentage of install.
:return:
"""
from . import progressbar
usb_details = details(config.usb_disk)
usb_mount = usb_details['mount_point']
usb_size_used = usb_details['size_used']
thrd = threading.Thread(target=install_distro, name="install_progress")
# thrd.daemon()
# install_size = usb_size_used / 1024
install_size = iso_size(config.iso_link) / 1024
final_size = (usb_size_used + iso_size(config.iso_link)) + config.persistence
thrd.start()
pbar = progressbar.ProgressBar(maxval=100).start() # bar = progressbar.ProgressBar(redirect_stdout=True)
while thrd.is_alive():
current_size = details(config.usb_disk)['size_used']
percentage = int((current_size / final_size) * 100)
if percentage > 100:
percentage = 100
config.percentage = percentage
pbar.update(percentage)
def install_patch():
if config.distro == 'debian':
if platform.system() == 'Linux':
os.system('sync')
iso_cfg_ext_dir = os.path.join(multibootusb_host_dir(), "iso_cfg_ext_dir")
isolinux_path = os.path.join(iso_cfg_ext_dir, isolinux_bin_path(config.iso_link)[1:])
iso_linux_bin_dir = isolinux_bin_dir(config.iso_link)
config.syslinux_version = isolinux_version(isolinux_path)
iso9660fs = ISO9660(config.iso_link)
iso_file_list = iso9660fs.readDir("/")
os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link), isolinux_bin_dir(config.iso_link)[1:])
if any("makeboot.sh" in s.lower() for s in iso_file_list):
for module in os.listdir(os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link),
isolinux_bin_dir(config.iso_link)[1:])):
if module.endswith(".c32"):
if os.path.exists(os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link),
isolinux_bin_dir(config.iso_link)[1:], module)):
try:
#os.chmod(os.path.join(config.usb_mount, "multibootusb",
# iso_basename(config.iso_link), isolinux_bin_dir(config.iso_link)[1:], module), 0o777)
#os.unlink(os.path.join(config.usb_mount, "multibootusb",
# iso_basename(config.iso_link), isolinux_bin_dir(config.iso_link)[1:], module))
os.remove(os.path.join(config.usb_mount, "multibootusb",
iso_basename(config.iso_link), isolinux_bin_dir(config.iso_link)[1:], module))
print("Copying ", module)
print((resource_path(
os.path.join(multibootusb_host_dir(), "syslinux", "modules", config.syslinux_version, module)),
os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link),
isolinux_bin_dir(config.iso_link)[1:], module)))
shutil.copy(resource_path(
os.path.join(multibootusb_host_dir(), "syslinux", "modules", config.syslinux_version, module)),
os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link),
isolinux_bin_dir(config.iso_link)[1:], module))
except Exception as err:
print(err)
print("Could not copy ", module)
else:
print('Patch not required...')
if __name__ == '__main__':
config.iso_link = '../../../DISTROS/2016/slitaz-4.0.iso'
install_distro()

@ -0,0 +1,209 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*
# Name: iso.py
# Purpose: Module to manupulate ISO file
# Authors: Sundar
# Depends: isodump3.py (Authored by Johni Lee for MultiBootUSB)
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import sys
import os
import string
import platform
import re
from .gen import *
from .isodump3 import ISO9660
_iso_cfg_ext_dir = iso_cfg_ext_dir()
def iso_name(iso_link):
"""
Find the name of an ISO.
:return: Name of an ISO (with extension) as string. Returns If not returns None.
"""
if os.path.exists(iso_link):
try:
name = os.path.basename(str(iso_link))
except:
name = None
else:
name = None
return name
def iso_basename(iso_link):
"""
Find the base name of an ISO.
:return: Base name (without extension) of a selected ISO as string. If not returns None.
"""
try:
dir_name = str(os.path.splitext(os.path.basename(str(iso_link)))[0])
except:
dir_name = None
return dir_name
def isolinux_bin_exist(iso_link):
"""
Check if an "isolinux.bin" file exist.
:return: True if "isolinux.bin" file exist of False if not.
"""
if os.path.exists(iso_link):
iso9660fs = ISO9660(iso_link)
iso_file_list = iso9660fs.readDir("/")
if any("isolinux.bin" in s.lower() for s in iso_file_list):
return True
else:
return False
def iso_size(iso_link):
return os.path.getsize(iso_link)
def is_bootable(iso_link):
"""
Check if an ISO has the ability to boot.
:return: True if ISO is bootable and False if not.
"""
iso9660fs = ISO9660(iso_link)
isBootable = iso9660fs.checkISOBootable()
if isBootable:
return True
else:
return False
def isolinux_bin_dir(iso_link):
"""
Detects "isolinux.bin" directory.
:return: path of "isolinux.bin" directory as string.
"""
iso9660fs = ISO9660(iso_link)
if os.path.exists(iso_link):
bin_dir = False
iso_file_list = iso9660fs.readDir("/")
if any("isolinux.bin" in s.lower() for s in iso_file_list):
for f in iso_file_list:
if 'isolinux.bin' in f.lower():
bin_dir = os.path.dirname(f)
break
return bin_dir
def isolinux_bin_path(iso_link):
"""
Detects pat to "isolinux.bin".
:return: path of "isolinux.bin" directory as string.
"""
iso_bin_path = False
if isolinux_bin_exist(iso_link) is not False:
iso9660fs = ISO9660(iso_link)
iso_file_list = iso9660fs.readDir("/")
for f in iso_file_list:
if 'isolinux.bin' in f.lower():
iso_bin_path = f
break
return iso_bin_path
def integrity(iso_link):
"""
Check the integrity of an ISO.
:return: True if integrity passes or False if it fails.
"""
if os.path.exists(iso_link):
iso9660fs = ISO9660(iso_link)
if iso9660fs.checkIntegrity():
return True
else:
return False
def iso_file_list(iso_link):
"""
Function to return the content of an ISO.
:return: List of files of an ISO as list.
"""
iso9660fs = ISO9660(iso_link)
iso_file_list = iso9660fs.readDir("/")
return iso_file_list
def isolinux_version(isolinux_bin_path):
"""
Detect isolinux version shipped by distros.
:param isolinux_path: Path to "isolinux.bin"
:return: Version number as string.
"""
version = ["3", "4", "5", "6"]
if isolinux_bin_path is not None:
sl = list(strings(isolinux_bin_path))
for strin in sl:
if re.search(r'isolinux ', strin, re.I):
for number in version:
if re.search(r'isolinux ' + number, strin, re.I):
print("\n\nFound syslinux version " + number + "\n\n")
return str(number)
def iso_extract_file(iso_link, dest_dir, filter):
"""
Extract the specific file(s) from an ISO
:param dest_dir: Path to destination directory.
:param filter: Filter to extract particular file(s)
:return: Extract file(s) to destination.
"""
if os.path.exists(iso_link) and os.path.exists(dest_dir):
iso9660fs = ISO9660(iso_link)
iso9660fs.writeDir("/", dest_dir, filter)
def extract_cfg_file(iso_link):
iso_extract_file(iso_link, _iso_cfg_ext_dir, '.cfg')
iso_extract_file(iso_link, _iso_cfg_ext_dir, '.CFG')
iso_extract_file(iso_link, _iso_cfg_ext_dir, '.TXT')
iso_extract_file(iso_link, _iso_cfg_ext_dir, '.txt')
iso_extract_file(iso_link, _iso_cfg_ext_dir, 'isolinux.bin')
iso_extract_file(iso_link, _iso_cfg_ext_dir, 'ISOLINUX.BIN')
def iso_extract_full(iso_link, dest_dir):
"""
Extract an ISO to destination directory
:param dest_dir: Destination path as string.
:return: False if it fails or extract ISO files to destination directory.
"""
iso9660fs = ISO9660(iso_link)
try:
iso9660fs.writeDir("/", dest_dir)
except:
print("ISO extraction failed.")
return False
if __name__ == '__main__':
#iso_path = '../../../DISTROS/2016/debian-live-8.3.0-amd64-lxde-desktop.iso'
iso_path = '../../../DISTROS/2015/super_grub2_disk_hybrid_2.02s3.iso'
test_iso_bin_path = os.path.join('test', 'isolinux', 'isolinux.bin')
print('iso_name(iso_path) : ', iso_name(iso_path))
print('iso_basename(iso_path) : ', iso_basename(iso_path))
print('Integrity of ISO is : ', integrity(iso_path))
f_list = (iso_file_list(iso_path))
if f_list:
for f in f_list:
print(f)
print('isolinux_bin_exist(iso_path) : ', isolinux_bin_exist(iso_path))
#print('is_bootable : ', is_bootable(iso_path))
print('isolinux_bin_dir() : ', isolinux_bin_dir(iso_path))
print('isolinux_bin_path(iso_path) : ', isolinux_bin_path(iso_path))
iso_extract_full(iso_path, 'test')
iso_extract_file(iso_path, 'test', 'isolinux.bin')
print(isolinux_version(test_iso_bin_path))

@ -0,0 +1,805 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*
# Name: isodump3.py
# Purpose: Module to list and extract iso files.
# Authors: LiQiong Lee (written exclusively for multibootusb)
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License version 3
# Credit : I am grateful to LiQiong Lee. He not only wrote this module for multibootusb, but also extended the same
# to python3 within short time after request.
""" ISO9660fs
Dump raw meta data of iso9660 file system.
Extract directories and files.
"""
##
## Extract directory or file from iso.
## Support RRIP.
##
# Author : joni <joni.kartore.lee@gmail.com>
# version : 1.0
import sys
import struct
import os
import re
import stat
from ctypes import *
from . import config
BLOCK_SIZE = 2048
S_IFSOCKET = 0o140000
S_IFLINK = 0o120000
S_IFREG = 0o100000
S_IFBLK = 0o060000
S_IFCHR = 0o020000
S_IFDIR = 0o040000
S_IFIFO = 0o010000
E_SUCCESS = 0
E_FAILURE = -1
E_DEVICEFILE = -2 # can't write device file
class PrimaryVolume(Structure):
def __init__(self):
self.sysIdentifier = ""
self.volIdentifier = ""
self.volSize = 0
self.volSeq = 0
self.blockSize = 0
self.ptSize = 0
self.ptLRd = 0
self.fsVer = 0
self.rootLoc = 0
self.rootTotal = 0
class Rrip(Structure):
def __init__(self):
self.offset = -1
self.altname = ""
self.devH = 0
self.devL = 0
self.fMode = 0
class DirRecord(Structure):
def __init__(self):
self.lenDr = 0
self.lenEattr = 0
self.locExtent= 0
self.lenData = 0
self.dtYear = 0
self.dtMonth = 0
self.dtHour = 0
self.dtMinute = 0
self.dtSecond = 0
self.dtOffset = 0
self.fFlag = 0
self.fUnitSize= 0
self.gapSize = 0
self.volSeqNr = 0
self.lenFi = 0
self.fIdentifier = ""
self.sysUseStar = 0
self.suspBuf = ""
self.rrip = None
class PathTabelItem(Structure):
def __init__(self):
self.lenDi = 0
self.lenEattr = 0
self.locExtenti = 0
self.pdirNr = 0
self.fIdentifier = ""
class ISO9660:
"""
This class can dump iso9660 file system meta data and extract files.
Support:
RRIP extension.
"""
def __init__(self, isofile):
try:
f = open(isofile, 'rb')
except(IOError):
sys.stderr.write("can't open {0}".format(isofile))
sys.exit(-1)
self.isoFile = f
self.priVol = None
self.rootDir = None
self.rripOffset = -1
desc_nr = 0
while True:
desc_nr = desc_nr + 1
try:
self.isoFile.seek(BLOCK_SIZE*(15+desc_nr))
volume_dsc = self.isoFile.read(BLOCK_SIZE)
flag = struct.unpack('B',volume_dsc[0:1])[0]
if flag == 1:
self.__readPrimaryVolume__(volume_dsc)
continue
if flag == 255:
break
except Exception as e:
print("Got exception when init iso file:", sys.exc_info()[0])
self.priVol = None
self.rootDir = None
break
def __del__(self):
self.isoFile.close()
def __readPrimaryVolume__(self, volume_dsc):
""" Dump primary volume descriptor """
global BLOCK_SIZE
priVol = PrimaryVolume()
priVol.sysIdentifier = volume_dsc[8:40]
priVol.volIdentifier = volume_dsc[40:72]
priVol.volSize = struct.unpack('<L',volume_dsc[80:84])[0]
priVol.volSeq = struct.unpack('<H',volume_dsc[124:126])[0]
priVol.blockSize = struct.unpack('<H',volume_dsc[128:130])[0]
priVol.ptSize = struct.unpack('<L',volume_dsc[132:136])[0]
priVol.ptLRd = struct.unpack('<L',volume_dsc[140:144])[0]
priVol.fsVer = struct.unpack('B', volume_dsc[881:882])[0]
dirRec = self.readDirrecord(volume_dsc[156:190])
priVol.rootLoc = dirRec.locExtent
priVol.rootTotal = dirRec.lenData
BLOCK_SIZE = priVol.blockSize
# Check RRIP
#print ("loc extent(%d)"%(dirRec.locExtent))
self.priVol = priVol # readDirItems will use self.priVol
root_dir = self.readDirItems(dirRec.locExtent, priVol.rootTotal)[0]
rripNode = self.__rripLoop__(root_dir.suspBuf, root_dir.lenDr-root_dir.sysUseStar)
if rripNode.offset != -1:
self.rripOffset = rripNode.offset
#print ("RRIP: rrip_offset %d"%(self.rripOffset))
else:
print (" This disc don't support RRIP")
self.rootDir = root_dir
# Rrip extension
def __rripLoop__(self, desc_buf, len_buf):
if self.rripOffset > 0:
entry_buf = desc_buf[self.rripOffset:]
print ("__rripLoop__ offset:%d"%(self.rripOffset))
else:
entry_buf = desc_buf
rr = Rrip()
while True:
ce_blk = 0
ce_len = 0
ce_off = 0
head = 0
len_entry = 0
while True:
#print (("\n%d, %d\n")%(len_buf, head))
head += len_entry
if len_buf - head < 4: # less than one entry
break
entry_buf = entry_buf[len_entry:]
sig1 = struct.unpack("B", entry_buf[0:1])[0]
sig2 = struct.unpack("B", entry_buf[1:2])[0]
len_entry = struct.unpack("B", entry_buf[2:3])[0]
ver = struct.unpack("B", entry_buf[3:4])[0]
#if len_entry == 0:
# print "Got a entry in __rripLoop__ (%c,%c) of SUSP with length:(%d),version:(%d)-->"%(sig1,sig2,len_entry, ver),
if len_entry == 0:
break;
if sig1 == ord('S') and sig2 == ord('P'):
ck1 = struct.unpack("B", entry_buf[4:5])[0]
ck2 = struct.unpack("B", entry_buf[5:6])[0]
skip = struct.unpack("B", entry_buf[6:7])[0]
#print "-->(0x%x==0xBE,0x%x==EF,%d)" %(ck1, ck2, skip)
if ck1 == 0xBE and ck2 == 0xEF:
rr.offset = skip
continue
if sig1 == ord('C') and sig2 == ord('E'):
ce_blk = struct.unpack("<L", entry_buf[4:8])[0]
ce_off = struct.unpack("<L", entry_buf[12:16])[0]
ce_len = struct.unpack("<L", entry_buf[20:24])[0]
#print "-->(%d,%d,%d)" %(ce_blk, ce_off, ce_len)
continue
if sig1 == ord('N') and sig2 == ord('M'):
flag = struct.unpack("B", entry_buf[4:5])[0]
#print "-->(flag:(0x%x), name:(%s))" %(flag, entry_buf[5:len_entry])
if flag == 0x02: # FLAG_CURRENT
rr.altname += "."
elif flag == 0x04: # FLAG_PARENT
rr.altname += ".."
elif flag == 0x01 or flag ==0: # 1:FLAG_CONTINUE
rr.altname += entry_buf[5:len_entry].decode()
continue
if sig1 == ord('P') and sig2 == ord('N'):
rr.devH = struct.unpack("<L", entry_buf[4:8])[0]
rr.devL = struct.unpack("<L", entry_buf[12:16])[0]
continue
if sig1 == ord('E') and sig2 == ord('R'):
len_id = struct.unpack("B", entry_buf[4:5])[0]
len_des = struct.unpack("B", entry_buf[5:6])[0]
len_src = struct.unpack("B", entry_buf[6:7])[0]
ext_ver = struct.unpack("B", entry_buf[7:8])[0]
continue
if sig1 == ord('P') and sig2 == ord('X'):
rr.fMode = struct.unpack("<L", entry_buf[4:8])[0]
s_link = struct.unpack("<L", entry_buf[12:16])[0]
uid = struct.unpack("<L", entry_buf[20:24])[0]
gid = struct.unpack("<L", entry_buf[28:32])[0]
continue
if sig1 == ord('S') and sig2 == ord('T'):
return rr
#print "\n"
# while (True) end #
if ce_len > 0:
#print " Read CE block, (%d, %d, %d)"%(ce_blk, ce_len, ce_off)
self.isoFile.seek(ce_blk*BLOCK_SIZE + ce_off)
entry_buf = self.isoFile.read(ce_len)
len_buf = ce_len
else:
break
# while (True) end #
return rr
def checkISOBootable(self):
""" Struct of a classical generic MBR.
0x0000 Bootstrap Code area
-----------------------------------------
0x01BE
.. Partition table
0x01EE
------------------------------------------
0x01FE 55h
Boot signature
0x01FF AAh
"""
self.isoFile.seek(0x01FE)
h = self.isoFile.read(2)
s1 = struct.unpack('B', h[0:1])[0]
s2 = struct.unpack('B', h[1:2])[0]
#print "-->(0x%x,0x%x)" %(s1, s2)
if (s1 == 0x55) and (s2 == 0xAA):
result = True # "Bootable"
else:
result = False # "Not bootable"
return result
def searchDir(self, path):
# /root/abc/ - ['', 'root', 'abc', '']
# /root/abc - ['', 'root', 'abc']
# / - ['', '']
dircomps = path.split('/')
if dircomps[-1] == '':
dircomps.pop()
if dircomps == []:
return
if self.priVol == None:
return
if len(dircomps) == 1:
return self.rootDir
pdir_loc = self.priVol.rootLoc
pdir_len = self.priVol.rootTotal
i_dircomp = 1
while True:
found = False
dirs = self.readDirItems(pdir_loc, pdir_len)
for item in dirs:
if item.fIdentifier == dircomps[i_dircomp]:
pdir_loc = item.locExtent
pdir_len = item.lenData
found = True
#print "found (%s)"%(dircomps[i_dircomp])
break
if found: # advacne
if i_dircomp < len(dircomps)-1:
i_dircomp = i_dircomp + 1
else:
return item
else:
print ("can't find " + dircomps[i_dircomp])
return None
def readDirrecord(self, desc_buf):
""" Dump file dirctory record
Return a directory record reading from a Directory Descriptors.
"""
dirRec = DirRecord()
try:
dirRec.lenDr = struct.unpack("B", desc_buf[0:1])[0]
if dirRec.lenDr == 0:
return None
except:
return None
dirRec.lenEattr = struct.unpack("B", desc_buf[1:2])[0]
dirRec.locExtent = struct.unpack("<L", desc_buf[2:6])[0]
dirRec.lenData = struct.unpack("<L", desc_buf[10:14])[0]
dirRec.fFlag = struct.unpack("B", desc_buf[25:26])[0]
dirRec.fUnitSize = struct.unpack("B", desc_buf[26:27])[0]
dirRec.gapSize = struct.unpack("B", desc_buf[27:28])[0]
dirRec.volSeqNr = struct.unpack("<H", desc_buf[28:30])[0]
dirRec.lenFi = struct.unpack("B", desc_buf[32:33])[0]
dirRec.fIdentifier = ""
if dirRec.lenFi == 1:
dirRec.fIdentifier = struct.unpack("B", desc_buf[33:34])[0]
if dirRec.fIdentifier == 0:
dirRec.fIdentifier = "."
elif dirRec.fIdentifier == 1:
dirRec.fIdentifier = ".."
else:
dirRec.fIdentifier = desc_buf[33:33+dirRec.lenFi].decode()
idx = dirRec.fIdentifier.rfind(";")
if idx != -1:
dirRec.fIdentifier = dirRec.fIdentifier[0:idx]
dirRec.suspBuf = ""
dirRec.sysUseStar = 34 + dirRec.lenFi -1
if dirRec.lenFi % 2 == 0:
dirRec.sysUseStar += 1
# Extension Attribute
if dirRec.lenDr > dirRec.sysUseStar+4:
if dirRec.locExtent == self.priVol.rootLoc:
dirRec.suspBuf = desc_buf[dirRec.sysUseStar:dirRec.lenDr]
suspBuf = desc_buf[dirRec.sysUseStar:dirRec.lenDr]
if self.rripOffset != -1:
rripNode = self.__rripLoop__(suspBuf, dirRec.lenDr-dirRec.sysUseStar)
dirRec.rrip = rripNode
if rripNode != None:
if rripNode.altname != "":
dirRec.fIdentifier = rripNode.altname
dirRec.lenFi = len(rripNode.altname)
#print "rrip_altname: %s"%(dirRec.fIdentifier)
# if rripNode end #
# if self.rripOffset != -1 end #
# if dirRec.lenDr > .. end #
return dirRec
def readDirItems(self, block_nr=None, total=None):
""" Read file dirctory records
Read dirctory records from 'block_nr' with a length of 'total'.
Return a list containing directory records(DirRecord).
"""
dirs = []
total_blk = (total+BLOCK_SIZE-1)//BLOCK_SIZE
i_blk = 0
while i_blk < total_blk:
self.isoFile.seek((block_nr+i_blk)*BLOCK_SIZE)
desc_buf = self.isoFile.read(BLOCK_SIZE)
i_blk = i_blk + 1
while True:
dirItem = self.readDirrecord(desc_buf)
if dirItem == None:
break
dirs.append(dirItem)
if desc_buf.__len__() > dirItem.lenDr:
desc_buf = desc_buf[dirItem.lenDr:]
else:
break
return dirs
def readPathtableL(self):
""" Read path table of L typde """
if self.priVol == None:
return
block_nr = self.priVol.ptLRd
total = self.priVol.ptSize
path_table = []
self.isoFile.seek(block_nr*BLOCK_SIZE)
ptbuf = self.isoFile.read((BLOCK_SIZE * ((total+BLOCK_SIZE-1)//BLOCK_SIZE)))
i = 0
r_size = 0
while True :
i = i+1
t = PathTabelItem()
t.lenDi = struct.unpack('B', ptbuf[0:1])[0]
t.lenEattr = struct.unpack('B', ptbuf[1:2])[0]
t.locExtent = struct.unpack('<L', ptbuf[2:6])[0]
t.pdirNr = struct.unpack('<H', ptbuf[6:8])[0]
t.fIdentifier = ptbuf[8:8+t.lenDi].decode()
path_table.append(t)
if t.lenDi % 2 :
len_pd = 1
else:
len_pd = 0
r_size += 9+t.lenDi-1+len_pd
if r_size >= total:
break
ptbuf = ptbuf[9+t.lenDi-1+len_pd:]
# while True
return path_table
# @path -- path within iso file system.
# @output -- what local path you want write to.
# @pattern -- regular expression.
# @r -- recursion flag, write the whole sub-directories or not.
# @all_type -- which file type should be writed.
# False: Write regular type files only.
# True: Wirte all types files (regular, device file, link, socket, etc)
def writeDir(self, path, output, pattern="", r=True, all_type=False):
""" Extract a directory
Return 0 means success otherwise failure.
"""
d = self.searchDir(path)
if d != None:
if output.endswith("/"):
output = output[0:-1]
# Try to make target directory.
if not os.path.exists(output):
try:
os.makedirs(output)
except(OSError):
sys.stderr.write("can't make dirs({0})\n".format(output))
return E_FAILURE
pp = None
if pattern != "":
p = r'{0}'.format(pattern)
pp = re.compile(p)
#print "writeDir: flag(%x)"%(d.fFlag)
if d.fFlag & 0x02 == 0x02:
# Check if a clean directory.
#try:
# if len(os.listdir(output)) > 0:
# sys.stderr.write("The target directory is not empty\n")
# return E_FAILURE
#except(OSError):
# sys.stderr.write("can't access dirs({0})\n".format(p))
# return E_FAILURE
self.writeDir_r(output, d, pp, r, all_type)
return E_SUCCESS
else:
return self.writeFile(d, output+path, all_type)
else:
return E_FAILURE
def writeDir_r(self, det_dir, dire, pp, r, all_type):
#print "writeDir_r:(%s)"%(det_dir)
dirs = self.readDirItems(dire.locExtent, dire.lenData)
for d in dirs:
if not d.fIdentifier in [".", ".."]:
if (pp != None) and (pp.search(d.fIdentifier) == None):
match = False
else:
match = True
#print "mathing %s, %s, (%x)"%(match, d.fIdentifier, d.fFlag)
p = det_dir + "/" + d.fIdentifier
if d.fFlag & 0x02 == 0x02:
if not os.path.exists(p):
os.makedirs(p, 0o777)
if r:
if match:
self.writeDir_r(p, d, None, r, all_type) # Don't need to match subdirectory.
else:
self.writeDir_r(p, d, pp, r, all_type)
elif match:
self.writeFile(d, p, all_type)
# if not d.fIdentifier end #
# for d in dirs end #
def writeFile(self, dirRec, detFile, all_type):
""" Write a file to detFile
Return 0 means success otherwise failure.
"""
global file_out
if detFile == "" or dirRec == None:
sys.stderr.write("can't write file\n")
return E_FAILURE
#print "write file (%s)"%(detFile)
config.status_text = detFile
dirname = os.path.dirname(detFile)
if not os.path.exists(dirname):
try:
os.makedirs(dirname, 0o777)
except(OSError):
sys.stderr.write("can't makedirs\n")
return E_FAILURE
if all_type == True:
# device file
if dirRec.rrip != None and (dirRec.rrip.devH != 0 or dirRec.rrip.devL != 0):
#fFlag == 0
high = dirRec.rrip.devH
low = dirRec.rrip.devL
if high == 0:
device = os.makedev(os.major(low), os.minor(low))
else:
device = os.makedev(high, os.minor(low))
try:
mode = dirRec.rrip.fMode & 0o770000
if mode == S_IFCHR:
os.mknod(detFile, 0o777|stat.S_IFCHR, device)
elif mode == S_IFBLK:
os.mknod(detFile, 0o777|stat.S_IFBLK, device)
except(OSError):
sys.stderr.write("can't mknode, maybe no permission\n")
return E_DEVICEFILE
return E_SUCCESS
loc = dirRec.locExtent
length = dirRec.lenData
self.isoFile.seek(BLOCK_SIZE * loc)
#print "file length(%d)"%(length)
r_size = BLOCK_SIZE*1024*50 #100M cache
try:
f_output = open(detFile, 'wb', r_size)
except(IOError):
sys.stderr.write("can't open{0} for write\n".format(detFile))
return E_FAILURE
while True:
if length == 0:
break
elif length <= r_size:
r_size = length
length = 0
else:
length = length - r_size
buf = self.isoFile.read(r_size)
f_output.write(buf)
f_output.flush()
# while True end.
f_output.close()
return E_SUCCESS
def readDir(self, dir_path, r=True):
file_list = []
d = self.searchDir(dir_path)
if d != None:
if (d.fFlag & 0x02) == 0x02:
#print "readDir (%x, %x)"%(d.locExtent, d.lenData)
if dir_path.endswith("/"):
dir_path = dir_path[0:-1]
self.readDir_r(file_list, dir_path, d, r)
# if (d.fFlag & 0x02) == 0x02: #
# if d != None:
return file_list
def readDir_r(self, file_list, dir_path, dire, r):
if (dire.fFlag & 0x02) != 0x02:
return
dirs = self.readDirItems(dire.locExtent, dire.lenData)
for d in dirs:
if not d.fIdentifier in [".", ".."]:
p = dir_path + "/" + d.fIdentifier
file_list.append(p)
if r:
self.readDir_r(file_list, p, d, r)
# if not d.fIdentifier #
# for d in dirs: #
def checkIntegrity(self):
if self.priVol == None: # no primary volume
return False
if self.priVol.ptSize == 0: # empty ?
return True
path_table = self.readPathtableL()
if path_table == []: # pathtable record is broken.
return False
# find last file item to check
for dr in reversed(path_table):
#print dr.fIdentifier
dirs = self.readDirItems(dr.locExtent, BLOCK_SIZE)
if len(dirs) > 2:
dot = dirs[0]
dirs2 = self.readDirItems(dot.locExtent, dot.lenData) # get the whole items.
for dr2 in reversed(dirs2): # search last file item.
if dr2.fFlag == 0:
#print "get last file(%s)"%(dr2.fIdentifier)
try:
#self.isoFile.seek(BLOCK_SIZE * dr2.locExtent+dr2.lenData)
lastfile_end = BLOCK_SIZE * dr2.locExtent + dr2.lenData
self.isoFile.seek(0, os.SEEK_END)
iso_end = self.isoFile.tell()
#print ("%d-->%d")%(lastfile_end, iso_end)
if iso_end >= lastfile_end:
return True
else:
return False
except(IOError):
#print "exception when seek. iso is broken"
return False
elif len(dirs) < 2: # Dir record is broken. At least, should have two entries.
return False
return True
###########################################################################
def dump_dir_record(dirs):
""" Dump all the file dirctory records contained in desc_buf """
print("Dump file/deirectory record")
print("===========================", end="\n")
if dirs != None:
for f in dirs:
print("length of directory record:(0x%x), length of extend attribute:(%d), \
location of record:(%d)BLOCK->(0x%x), data length(%d) size of file unit:(%d), \
interleave gap size:(%d), file flag:(0x%x),name length:(%d) identify:(%s)\n" \
%(f.lenDr, f.lenEattr, f.locExtent, f.locExtent*BLOCK_SIZE,f.lenData, \
f.fUnitSize, f.gapSize, f.fFlag, f.lenFi, f.fIdentifier))
def dump_pathtable_L(path_table):
""" Dump path table of L typde """
print("Dump path table")
print("================", end="\n")
#path_table = readPathtableL()
i = 0
for t in path_table:
i = i + 1
if t.lenDi == 1:
if t.fIdentifier in [0, 1]:
print("is a root directory(%d)" %(is_root))
print("%d->length of identify:(%d), length of extend attribute:(%d), \
local:(%d)->(0x%x), parent dir number:(%d), identify:(%s)\n" \
%(i, t.lenDi, t.lenEattr, t.locExtent, t.locExtent*BLOCK_SIZE, t.pdirNr, t.fIdentifier))
def dump_primary_volume(privol=None):
""" Dump primary volume descriptor """
if privol == None:
print("Can't dump, maybe iso is broken")
return
print("===== Dump primary volume descriptor ==")
print("System Identifier:(%s)" %(privol.sysIdentifier.decode()))
print("Volume Identifier:(%s)" %privol.volIdentifier.decode())
print("Volume Space size:(0x%x)BLOCKS(2kB)" %privol.volSize)
print("Volume sequence number:(%d)" %(privol.volSeq))
print("logic block size:(0x%x)" %(privol.blockSize))
print("Volume path talbe L's BLOCK number is :(0x%x-->0x%x), size(%d)" %(privol.ptLRd, privol.ptLRd*BLOCK_SIZE, privol.ptSize))
# print "Abstract File Identifier: (%s)" %(volume_dsc[739:776])
# print "Bibliographic File Identifier: (%s)" %(volume_dsc[776:813])
print("pathtable locate (%d)" %(privol.ptLRd))
print("File Structure Version:(%d)" %(privol.fsVer))
print("Root directory is at (%d)block, have(0x%x)bytes" %(privol.rootLoc, privol.rootTotal))
# dump_dir_record(None, 23, 1)
def dump_boot_record(volume_dsc):
""" Dump boot record """
print("===== Dump boot record ==")
std_identifier = volume_dsc[1:6]
print("Standard Identifier:(%s)" %std_identifier)
vol_ver = struct.unpack('B', volume_dsc[6])
print("Volume descriptor version:(%d)" %vol_ver)
bootsys_identifier = volume_dsc[7:39]
print("boot system identifier(%s)" %bootsys_identifier)
boot_identifier = volume_dsc[39:71]
print("boot identifier(%s)" %boot_identifier)
def usage():
""" Prompt user how to use """
print("""
Usage: isodump dump-what [options] iso-file
[dump-what]
-----------
boot - Dump boot record.
primary-volume - Dump primary volume.
pathtable - Dump path table.
dir-record [block number] [length] - Dump a raw data of a Directory Record
iso:/dir [-r] [-o output] [-p pattern] - Dump a dirctory or file to [output]
-r recursively visit directory.
-p spcify a Regular expression pattern for re.search(pattern,).
isodump xx.iso - Dump the root directory
isodump pathtable xx.iso - Dump the path table record.
isodump iso:/ -r xx.iso
-- Dump the root directory of xx.iso recursively.
isodump iso:/ -r -o /tmp/iso xx.iso
-- Extract the iso to /tmp/iso/.
isodump iso:/boot -o /tmp/iso/boot xx.iso
-- Extract the /boot directory of xx.iso to /tmp/iso/boot.
isodump iso:/boot/grup.cfg -o /tmp/grub.cfg xx.iso
-- Extract the file "grup.cfg" to "/tmp/grub.cfg"
isodump iso:/boot -r -o /tmp/iso -p "*.cfg" xx.iso
-- Extract any files or directories under /boot maching "*.cfg" to /tmp/iso/.
""")
sys.exit(-1)
if __name__ == '__main__':
argv = sys.argv
if len(argv) < 3:
usage()
iso9660fs = ISO9660(argv[-1])
integrity = iso9660fs.checkIntegrity()
if integrity == False:
print("iso file is broken")
sys.exit(-1)
dump_what = argv[1]
if dump_what == "primary-volume":
dump_primary_volume(iso9660fs.priVol)
elif dump_what == "pathtable":
path_table = iso9660fs.readPathtableL()
dump_pathtable_L(path_table)
if dump_what == "dir-record":
if len(argv) == 5:
print("dump dir-record (%s, %s)"%(argv[2], argv[3]))
dirs = iso9660fs.readDirItems(int(argv[2]), int(argv[3]))
dump_dir_record(dirs)
else:
usage()
elif dump_what.startswith("iso:"):
o_path = ""
r = False
o = False
p = False
pattern = ""
for arg in argv[2:-1]:
if arg == "-r":
r = True
o = False
p = False
elif arg == "-o":
o = True
p = False
elif arg == "-p":
o = False
p = True
elif o == True:
o_path = arg
o = False
elif p == True:
pattern = arg
p = False
isodir = dump_what[4:]
if o_path == "":
print("dump_dir(%s)"%(isodir))
filelist = iso9660fs.readDir(isodir, r)
if filelist == []:
print("can't read any file from (%s)"%(isodir))
else:
for f in filelist:
print(f)
else:
print("writeDir(%s)->(%s) with pattern(%s)"%(isodir, o_path, pattern))
sys.exit(iso9660fs.writeDir(isodir, o_path, pattern, r, True))

@ -0,0 +1,23 @@
import iso
import source
def parse(path_or_url, cache_content=False, min_fetch=16):
"""
Returns an :class:`ISO` object for the given filesystem path or URL.
cache_content:
Whether to store sectors backing file content in the sector cache. If true, this will
cause memory usage to grow to the size of the ISO as more file content get accessed.
Even if false (default), an individual Record object will cache its own file content
for the lifetime of the Record, once accessed.
min_fetch:
The smallest number of sectors to fetch in a single operation, to speed up sequential
accesses, e.g. for directory traversal. Defaults to 16 sectors, or 32 KiB.
"""
if path_or_url.startswith("http"):
src = source.HTTPSource(path_or_url, cache_content=cache_content, min_fetch=min_fetch)
else:
src = source.FileSource(path_or_url, cache_content=cache_content, min_fetch=min_fetch)
return iso.ISO(src)

@ -0,0 +1,56 @@
class ISO(object):
def __init__(self, source):
self._source = source
# Unpack volume descriptors
self.volume_descriptors = {}
sector = 16
while True:
self._source.seek(sector)
sector += 1
vd = self._source.unpack_volume_descriptor()
self.volume_descriptors[vd.name] = vd
if vd.name == "terminator":
break
# Unpack the path table
self._source.seek(
self.volume_descriptors['primary'].path_table_l_loc,
self.volume_descriptors['primary'].path_table_size)
self.path_table = self._source.unpack_path_table()
# Save a reference to the root record
self.root = self.volume_descriptors['primary'].root_record
def record(self, *path):
"""
Retrieves a record for the given path.
"""
path = [part.upper() for part in path]
record = None
pivot = len(path)
# Resolve as much of the path as possible via the path table
while pivot > 0:
try:
record = self.path_table.record(*path[:pivot])
except KeyError:
pivot -= 1
else:
break
if record is None:
record = self.root
# Resolve the remainder of the path by walking record children
for part in path[pivot:]:
for child in record.children_unsafe:
if child.name == part:
record = child
break
else:
raise KeyError(part)
return record

@ -0,0 +1,31 @@
import record
class PathTable(object):
def __init__(self, source):
self._source = source
self.paths = {}
paths_list = []
while len(source) > 0:
name_length = source.unpack('B')
_ = source.unpack('B')
location = source.unpack('<I')
parent_idx = source.unpack('<H') - 1
name = source.unpack_string(name_length)
_ = source.unpack_raw(name_length % 2)
path = []
if len(paths_list) > 0:
path.extend(paths_list[parent_idx])
if name != "\x00":
path.append(name)
paths_list.append(path)
self.paths[tuple(path)] = location
def record(self, *path):
location = self.paths[path]
self._source.seek(location)
return self._source.unpack_record()

@ -0,0 +1,70 @@
class Record(object):
def __init__(self, source, length):
self._source = source
self._content = None
target = source.cursor + length
_ = source.unpack('B') # TODO: extended attributes length
self.location = source.unpack_both('I')
self.length = source.unpack_both('I')
self.datetime = source.unpack_dir_datetime()
flags = source.unpack('B')
self.is_hidden = flags & 1
self.is_directory = flags & 2
# TODO: other flags
_ = source.unpack('B') # TODO: interleave unit size
_ = source.unpack('B') # TODO: interleave gap size
_ = source.unpack_both('h') # TODO: volume sequence
name_length = source.unpack('B')
self.name = source.unpack_string(name_length).split(';')[0]
if self.name == "\x00":
self.name = ""
# TODO: extended attributes
source.unpack_raw(target - source.cursor)
def __repr__(self):
return "<Record (%s) name=%r>" % (
"directory" if self.is_directory else "file",
self.name)
@property
def children_unsafe(self):
"""
Assuming this is a directory record, this generator yields a record for each child. Use
with caution: at each iteration, the generator assumes that the source cursor has not moved
since the previous child was yielded. For safer behaviour, use :func:`children`.
"""
assert self.is_directory
self._source.seek(self.location, self.length)
_ = self._source.unpack_record() # current directory
_ = self._source.unpack_record() # parent directory
while len(self._source) > 0:
record = self._source.unpack_record()
if record is None:
self._source.unpack_boundary()
continue
yield record
@property
def children(self):
"""
Assuming this is a directory record, this property contains records for its children.
"""
return list(self.children_unsafe)
@property
def content(self):
"""
Assuming this is a file record, this property contains the file's contents
"""
assert not self.is_directory
if self._content is None:
self._source.seek(self.location, self.length, is_content=True)
self._content = self._source.unpack_all()
return self._content

@ -0,0 +1,165 @@
import datetime
import struct
import urllib
import path_table
import record
import volume_descriptors
SECTOR_LENGTH = 2048
class SourceError(Exception):
pass
class Source(object):
def __init__(self, cache_content=False, min_fetch=16):
self._buff = None
self._sectors = {}
self.cursor = None
self.cache_content = cache_content
self.min_fetch = min_fetch
def __len__(self):
return len(self._buff) - self.cursor
def unpack_raw(self, l):
if l > len(self):
raise SourceError("Source buffer under-run")
data = self._buff[self.cursor:self.cursor + l]
self.cursor += l
return data
def unpack_all(self):
return self.unpack_raw(len(self))
def unpack_boundary(self):
return self.unpack_raw(SECTOR_LENGTH - (self.cursor % SECTOR_LENGTH))
def unpack_both(self, st):
a = self.unpack('<'+st)
b = self.unpack('>'+st)
if a != b:
raise SourceError("Both-endian value mismatch")
return a
def unpack_string(self, l):
return self.unpack_raw(l).rstrip(' ')
def unpack(self, st):
if st[0] not in '<>':
st = '<' + st
d = struct.unpack(st, self.unpack_raw(struct.calcsize(st)))
if len(st) == 2:
return d[0]
else:
return d
def unpack_vd_datetime(self):
return self.unpack_raw(17) # TODO
def unpack_dir_datetime(self):
epoch = datetime.datetime(1970, 1, 1)
date = self.unpack_raw(7)
t = [struct.unpack('<B', i)[0] for i in date[:-1]]
t.append(struct.unpack('<b', date[-1])[0])
t[0] += 1900
t_offset = t.pop(-1) * 15 * 60. # Offset from GMT in 15min intervals, converted to secs
t_timestamp = (datetime.datetime(*t) - epoch).total_seconds() - t_offset
t_datetime = datetime.datetime.fromtimestamp(t_timestamp)
t_readable = t_datetime.strftime('%Y-%m-%d %H:%M:%S')
return t_readable
def unpack_volume_descriptor(self):
ty = self.unpack('B')
identifier = self.unpack_string(5)
version = self.unpack('B')
if identifier != "CD001":
raise SourceError("Wrong volume descriptor identifier")
if version != 1:
raise SourceError("Wrong volume descriptor version")
if ty == 0:
vd = volume_descriptors.BootVD(self)
elif ty == 1:
vd = volume_descriptors.PrimaryVD(self)
elif ty == 2:
vd = volume_descriptors.SupplementaryVD(self)
elif ty == 3:
vd = volume_descriptors.PartitionVD(self)
elif ty == 255:
vd = volume_descriptors.TerminatorVD(self)
else:
raise SourceError("Unknown volume descriptor type: %d" % ty)
return vd
def unpack_path_table(self):
return path_table.PathTable(self)
def unpack_record(self):
length = self.unpack('B')
if length == 0:
return None
return record.Record(self, length-1)
def seek(self, start_sector, length=SECTOR_LENGTH, is_content=False):
self.cursor = 0
self._buff = ""
do_caching = (not is_content or self.cache_content)
n_sectors = 1 + (length - 1) // SECTOR_LENGTH
fetch_sectors = max(self.min_fetch, n_sectors) if do_caching else n_sectors
need_start = None
def fetch_needed(need_count):
data = self._fetch(need_start, need_count)
self._buff += data
if do_caching:
for sector_idx in xrange(need_count):
self._sectors[need_start + sector_idx] = data[sector_idx*SECTOR_LENGTH:(sector_idx+1)*SECTOR_LENGTH]
for sector in xrange(start_sector, start_sector + fetch_sectors):
if sector in self._sectors:
if need_start is not None:
fetch_needed(sector - need_start)
need_start = None
# If we've gotten past the sectors we actually need, don't continue to fetch
if sector >= start_sector + n_sectors:
break
self._buff += self._sectors[sector]
elif need_start is None:
need_start = sector
if need_start is not None:
fetch_needed(start_sector + fetch_sectors - need_start)
self._buff = self._buff[:length]
def _fetch(self, sector, count=1):
raise NotImplementedError
class FileSource(Source):
def __init__(self, path, **kwargs):
super(FileSource, self).__init__(**kwargs)
self._file = open(path, 'rb')
def _fetch(self, sector, count=1):
self._file.seek(sector*SECTOR_LENGTH)
return self._file.read(SECTOR_LENGTH*count)
class HTTPSource(Source):
def __init__(self, url, **kwargs):
super(HTTPSource, self).__init__(**kwargs)
self._url = url
def _fetch(self, sector, count=1):
opener = urllib.FancyURLopener()
opener.http_error_206 = lambda *a, **k: None
opener.addheader("Range", "bytes=%d-%d" % (
SECTOR_LENGTH * sector,
SECTOR_LENGTH * (sector + count) - 1))
return opener.open(self._url).read()

@ -0,0 +1,59 @@
class VolumeDescriptor(object):
name = None
def __init__(self, source):
pass
def __repr__(self):
return "<VolumeDescriptor name=%r>" % self.name
class BootVD(VolumeDescriptor):
name = "boot"
class PrimaryVD(VolumeDescriptor):
name = "primary"
def __init__(self, source):
super(PrimaryVD, self).__init__(source)
_ = source.unpack_raw(1) # unused
self.system_identifier = source.unpack_string(32)
self.volume_identifier = source.unpack_string(32)
_ = source.unpack_raw(8) # unused
self.volume_space_size = source.unpack_both('i')
_ = source.unpack_raw(32) # unused
self.volume_set_size = source.unpack_both('h')
self.volume_seq_num = source.unpack_both('h')
self.logical_block_size = source.unpack_both('h')
self.path_table_size = source.unpack_both('i')
self.path_table_l_loc = source.unpack('<i')
self.path_table_opt_l_loc = source.unpack('<i')
self.path_table_m_loc = source.unpack('>i')
self.path_table_opt_m_loc = source.unpack('>i')
self.root_record = source.unpack_record()
self.volume_set_identifier = source.unpack_string(128)
self.publisher_identifier = source.unpack_string(128)
self.data_preparer_identifier = source.unpack_string(128)
self.application_identifier = source.unpack_string(128)
self.copyright_file_identifier = source.unpack_string(38)
self.abstract_file_identifier = source.unpack_string(36)
self.bibliographic_file_identifier = source.unpack_string(37)
self.volume_datetime_created = source.unpack_vd_datetime()
self.volume_datetime_modified = source.unpack_vd_datetime()
self.volume_datetime_expires = source.unpack_vd_datetime()
self.volume_datetime_effective = source.unpack_vd_datetime()
self.file_structure_version = source.unpack('B')
class SupplementaryVD(VolumeDescriptor):
name = "supplementary"
class PartitionVD(VolumeDescriptor):
name = "partition"
class TerminatorVD(VolumeDescriptor):
name = "terminator"

@ -0,0 +1,85 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: mbusb_cli.py
# Purpose: Module to handle command line options of multibootusb
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import os
import re
import shutil
from . import usb
from . import gen
from .iso import *
from .uninstall_distro import *
from .distro import *
from .syslinux import *
from .install import *
def read_input_uninstall():
response = False
try:
response = int(input("Please enter the number against the distro you need to uninstall: "))
except ValueError:
print('\nPlease provide valid integer from the above list.\n')
return response
def cli_install_distro():
'''
if platform.system() == 'Linux':
if os.getuid() != 0:
exit("You need to have root privileges to run this script.\nPlease try again using 'sudo'. Exiting.")
elif platform.system() == 'Windows':
if admin.isUserAdmin():
admin.elevate()
'''
print('Starting multibootusb from Command line...')
if usb.is_block(config.usb_disk) is False:
print(config.usb_disk, 'is not a valid device partition...')
exit(1)
elif integrity(config.iso_link) is not True:
print(config.iso_link, ' failed to pass integrity check...')
exit(1)
elif size_not_enough(config.iso_link, config.usb_disk) is True:
print(config.usb_disk, 'does not have enough space...')
else:
prepare_mbusb_host_dir()
extract_cfg_file(config.iso_link)
_distro = distro(iso_cfg_ext_dir(), config.iso_link)
print('Detected distro type is', _distro)
if _distro is not None:
print('\nSelected ISO is :', quote(iso_name(config.iso_link)))
print('Selected target device is:', quote(config.usb_disk), '\n')
print('Please confirm the option.')
print('Y/y/Yes/yes/YES or N/n/No/no/NO')
if read_input_yes() is True:
config.distro = _distro
copy_mbusb_dir_usb(config.usb_disk)
install_progress()
syslinux_distro_dir(config.usb_disk, config.iso_link, _distro)
syslinux_default(config.usb_disk)
update_distro_cfg_files(config.iso_link, config.usb_disk, _distro)
else:
print('Sorry', iso_name(config.iso_link), 'is not supported at the moment\n'
'Please report tissue at https://github.com/mbusb/multibootusb/issues')
def cli_uninstall_distro():
distro_list = install_distro_list()
if distro_list is not None:
for index, _distro_dir in enumerate(distro_list):
print(index, '--->>', _distro_dir)
user_input = read_input_uninstall()
if user_input is not False:
for index, _distro_dir in enumerate(distro_list):
if index == user_input:
config.uninstall_distro_dir_name = _distro_dir
unin_distro()
else:
print('No distro installed on', config.usb_disk)

@ -0,0 +1,594 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: mbusb_gui.py
# Purpose: Module to handle multibootusb through gui
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import os
import platform
import sys
import signal
from PyQt5 import QtCore, QtGui, QtWidgets
import subprocess
import time
from scripts.gui.ui_multibootusb import Ui_Dialog
from . import usb
from .gen import *
from .install import *
from .uninstall_distro import *
from .syslinux import *
from .distro import *
from .iso import *
from .imager import Imager, dd_linux, dd_win
from . import persistence
from . import config
from . import admin
from . import qemu
from .update_cfg_file import update_distro_cfg_files
class AppGui(qemu.Qemu, Imager, QtWidgets.QDialog, Ui_Dialog):
"""
Main multibootusb GUI manipulation class.
"""
def __init__(self):
QtWidgets.QDialog.__init__(self)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# Main Tab
self.ui.detect_usb.clicked.connect(self.onRefereshClick)
self.ui.close.clicked.connect(self.on_close_Click)
self.ui.browse_iso.clicked.connect(self.browse_iso)
self.ui.comboBox.activated[str].connect(self.onComboChange)
# self.ui.create.clicked.connect(self.update_progress)
self.ui.create.clicked.connect(self.onCreateClick)
self.ui.slider_persistence.valueChanged.connect(self.update_slider_text)
self.ui.uninstall.clicked.connect(self.OnUninstallClick)
# ISO Imager Tab
self.ui.pushButton.clicked.connect(self.on_Imager_Browse_iso_Click)
self.ui.comboBox_2.activated[str].connect(self.onImagerComboChange)
self.ui.pushbtn_imager_refreshusb.clicked.connect(self.onRefereshClick)
self.ui.imager_close.clicked.connect(self.on_close_Click)
self.ui.imager_write.clicked.connect(self.dd_write)
# Syslinux Tab
self.ui.install_syslinux.clicked.connect(self.onInstall_syslinuxClick)
self.ui.edit_syslinux.clicked.connect(self.onedit_syslinux)
# QEMU Tab
self.ui.browse_iso_qemu.clicked.connect(self.on_Qemu_Browse_iso_Click)
self.ui.boot_iso_qemu.clicked.connect(self.on_Qemu_Boot_iso_Click)
self.ui.boot_usb_qemu.clicked.connect(lambda: self.on_Qemu_Boot_usb_Click(str(self.ui.comboBox.currentText())))
# self.ui.tabWidget.removeTab(3)
# Update progressbar and status (Main ISO install)
self.progress_thread_install = GuiInstallProgress()
self.progress_thread_install.finished.connect(self.install_syslinux)
self.progress_thread_install.update.connect(self.ui.progressBar.setValue)
self.progress_thread_install.status.connect(self.ui.status.setText)
# Update progressbar and status (Uninstall from previous install)
self.progress_thread_uninstall = GuiUninstallProgress()
self.progress_thread_uninstall.finished.connect(self.uninstall_sys_file_update)
self.progress_thread_uninstall.update.connect(self.ui.progressBar.setValue)
self.progress_thread_uninstall.status.connect(self.ui.status.setText)
# Update progressbar and status (dd ISO)
self.progress_thread_dd = DD_Progress()
self.progress_thread_dd.update.connect(self.ui.imager_progressbar.setValue)
self.progress_thread_dd.finished.connect(self.dd_finished)
self.progress_thread_dd.status.connect(self.ui.imager_label_status.setText)
self.add_device()
prepare_mbusb_host_dir()
def add_device(self):
"""
Adds list of available USB devices to GUI combobox.
:return:
"""
detected_device = usb.list()
if bool(detected_device):
for device in detected_device:
self.ui.comboBox.addItem(str(device))
if self.ui.comboBox.currentText():
self.onComboChange()
imager_detected_device = self.imager_list_usb(partition=0)
if bool(imager_detected_device):
for disk in imager_detected_device:
self.ui.comboBox_2.addItem(str(disk))
self.onImagerComboChange()
def onComboChange(self):
"""
Detects and updates GUI with populated USB device details.
:return:
"""
self.ui.listWidget.clear()
config.usb_disk = str(self.ui.comboBox.currentText())
config.imager_usb_disk = str(self.ui.comboBox_2.currentText())
if bool(config.usb_disk):
self.update_gui_oncombobox(config.usb_disk)
else:
print("No USB disk found...")
def onRefereshClick(self):
"""
Calls function to detect USB devices.
:return:
"""
self.ui.comboBox.clear()
self.ui.comboBox_2.clear()
self.add_device()
def update_gui_oncombobox(self, usb_disk):
self.usb_details = usb.details(usb_disk)
config.usb_mount = self.usb_details['mount_point']
self.ui.usb_dev.setText("Drive :: " + usb_disk)
# self.label.setFont(QtGui.QFont("Times",weight=QtGui.QFont.Bold))
self.ui.usb_vendor.setText("Vendor :: " + self.usb_details['vendor'])
self.ui.usb_model.setText("Model :: " + self.usb_details['model'])
self.ui.usb_size.setText("Total Size :: " + str(usb.bytes2human(self.usb_details['size_total'])))
self.ui.usb_mount.setText("Mount :: " + self.usb_details['mount_point'])
self.update_list_box(usb_disk)
def update_list_box(self, usb_disk):
"""
Updates listbox with installed distros on selected USB disk.
:param usb_mount: Selected USB disk from combobox.
:return:
"""
distro_list = install_distro_list()
#sys_cfg_file = os.path.join(str(usb_mount), "multibootusb", "syslinux.cfg")
if distro_list is not None:
self.ui.listWidget.clear()
for name in distro_list:
self.ui.listWidget.addItem(name)
else:
if config.usb_mount == 'No_Mount':
print("UBS disk is not mounted and can't update list widget...")
#QtWidgets.QMessageBox.information(self, 'No Install...',
# 'syslinux.cfg does not exist for updating list widget.')
def browse_iso(self):
if str(self.ui.lineEdit.text()):
self.ui.lineEdit.clear()
config.iso_link = QtWidgets.QFileDialog.getOpenFileName(self, 'Select an iso...', '', 'ISO Files (*.iso)')[0]
if config.iso_link:
if platform.system() == "Windows":
if "/" in config.iso_link:
config.iso_link = config.iso_link.strip().replace("/", "\\")
self.ui.lineEdit.insert(str(config.iso_link))
if os.path.exists(config.iso_link):
clean_iso_cfg_ext_dir(
os.path.join(multibootusb_host_dir(), "iso_cfg_ext_dir")) # Need to be cleaned.
extract_cfg_file(config.iso_link)
if integrity(config.iso_link) is True:
config.distro = distro(iso_cfg_ext_dir(), config.iso_link)
else:
QtWidgets.QMessageBox.warning(self, 'ISO Error.', "ISO integrity failed.\n\n"
"Please check the downloaded ISO.")
if config.distro:
per_availability = persistence.persistence_distro(config.distro, config.usb_disk, config.iso_link)[0]
per_max_size = persistence.persistence_distro(config.distro, config.usb_disk, config.iso_link)[1]
if per_availability is not None:
self.ui.slider_persistence.setEnabled(True)
self.ui.slider_persistence.setTickInterval(10)
self.ui.slider_persistence.setSingleStep(10)
ui_per_max_size = per_max_size / 1024 / 1024
config.persistence = per_max_size
self.ui.slider_persistence.setMaximum(ui_per_max_size)
print('Persistence Max Size: ', bytes2human(per_max_size))
else:
print('Persistence is not available for', iso_name(config.iso_link))
else:
print("File not selected...")
def update_slider_text(self):
slide_value = self.ui.slider_persistence.value() * 1024 * 1024
self.ui.label_persistence_value.setText(bytes2human(slide_value))
config.persistence = slide_value
def install_syslinux(self):
"""
Function to install syslinux on distro directory and on selected USB disks.
:return:
"""
self.ui.status.setText(str("Installing Syslinux..."))
syslinux_distro_dir(config.usb_disk, config.iso_link, config.distro)
syslinux_default(config.usb_disk)
update_distro_cfg_files(config.iso_link, config.usb_disk, config.distro, config.persistence)
self.update_list_box(config.usb_disk)
if sys.platform.startswith("linux"):
self.ui.status.setText("Sync is in progress...")
os.system('sync')
self.ui.status.clear()
QtWidgets.QMessageBox.information(self, 'Finished...', iso_name(config.iso_link) + ' has been successfully installed.')
def onInstall_syslinuxClick(self):
"""
Function to install syslinux/extlinux on selected USB disk.
:return:
"""
if platform.system() == "Linux" or platform.system() == "Windows":
if self.ui.install_sys_all.isChecked() or self.ui.install_sys_only.isChecked():
print("Installing default syslinux on ", config.usb_disk)
ret = syslinux_default(config.usb_disk)
if ret is True:
if self.ui.install_sys_all.isChecked():
print("Copying multibootusb directory to " + config.usb_mount)
for dirpath, dirnames, filenames in os.walk(resource_path(os.path.join("tools", "multibootusb"))):
for f in filenames:
print("Copying " + f)
shutil.copy(resource_path(os.path.join(dirpath, f)), os.path.join(self.usb.get_usb(config.usb_disk).mount, "multibootusb"))
QtWidgets.QMessageBox.information(self, 'Install Success...',
'Syslinux installed successfully on ' + config.usb_disk)
elif ret is False:
QtWidgets.QMessageBox.information(self, 'Install error...',
'Sorry. Syslinux failed to install on ' + config.usb_disk)
else:
QtWidgets.QMessageBox.information(self, 'No selection...',
'Please select one of the option from above.')
def onedit_syslinux(self):
"""
Function to edit main syslinux.cfg file.
:return:
"""
# Function to edit syslinux.cfg file on editors like gedit, notepad etc.
# Suggest me more editor which can be included in to this function.
sys_cfg_file = os.path.join(config.usb_mount, "multibootusb", "syslinux.cfg")
print("Locating " + sys_cfg_file)
editor = ''
if not os.path.exists(sys_cfg_file):
print("syslinux.cfg file not found...")
QtWidgets.QMessageBox.information(self, 'File not found...', 'Sorry. Unable to locate syslinux.cfg file.\n'
'You can only edit syslinux.cfg file generated by multibootusb.')
else:
if platform.system() == "Linux":
for e in config.editors_linux:
if subprocess.call('which ' + e, shell=True) == 0:
print("Editor found is " + e)
editor = e
break
elif platform.system() == "Windows":
for e in config.editors_win:
if not shutil.which(e) is None:
print("Editor found is " + e)
editor = e
break
if not editor:
QtWidgets.QMessageBox.information(self, 'Editor not found...',
'Sorry. Installed editor is not supported by multibootusb\n'
'Edit ' + sys_cfg_file + ' manually.\n')
else:
try:
subprocess.Popen(editor + " '" + sys_cfg_file + "'", shell=True).pid
except OSError:
QtWidgets.QMessageBox.warning(self, 'Error...',
'Failed to open syslinux.cfg file.\n'
'Edit syslinux.cfg file manually.\n')
def OnUninstallClick(self):
"""
Triggers a function to uninstall a selected distro.
:return:
"""
if self.ui.listWidget.currentItem() is None:
print("Please select a distro from the list.")
QtWidgets.QMessageBox.information(self, 'No selection.', 'Please select a distro from the list.')
else:
config.uninstall_distro_dir_name = str(self.ui.listWidget.currentItem().text()).strip()
reply = QtWidgets.QMessageBox.question(self, "Review selection...",
"Are you sure to uninstall " + config.uninstall_distro_dir_name,
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
if not os.path.exists(os.path.join(config.usb_mount, 'multibootusb', config.uninstall_distro_dir_name)):
print("Distro install directory not found. Just updating syslinux.cfg file.")
update_sys_cfg_file()
#self.uninstall.update_sys_cfg_file()
else:
self.progress_thread_uninstall.start()
def uninstall_sys_file_update(self):
"""
Function to remove and update uninstall distro text.
:return:
"""
update_sys_cfg_file()
self.update_list_box(config.usb_mount)
if sys.platform.startswith("linux"):
self.ui.status.setText("Sync is in progress...")
os.system('sync')
self.ui.status.clear()
QtWidgets.QMessageBox.information(self, 'Uninstall Complete...',
config.uninstall_distro_dir_name + ' has been successfully removed.')
def onCreateClick(self):
"""
Main function to create bootable USB disk.
:param usb_disk: ComboBox text as detected USB disk.
:param iso_link: LineEdit text as selected ISO link.
:return:
"""
if not config.usb_disk:
QtWidgets.QMessageBox.information(self, "No Device...",
"No USB device found.\n\nInsert USB and use Refresh USB button to detect USB.")
elif not config.iso_link:
QtWidgets.QMessageBox.information(self, "No ISO...", "No ISO found.\n\nPlease use step 2 to choose an ISO.")
elif usb.details(config.usb_disk)['mount_point'] == 'No_Mount':
QtWidgets.QMessageBox.information(self, "No Mount...", "USB disk is not mounted.\n"
"Please mount USB disk and press refresh USB button.")
else:
if not integrity(config.iso_link) is True:
QtWidgets.QMessageBox.information(self, "Integrity...",
"ISO integrity failed.\n\nPlease check the downloaded ISO.")
else:
if os.path.exists(config.iso_link):
self.ui.lineEdit.clear()
if config.distro:
print("Distro type detected is ", config.distro)
copy_mbusb_dir_usb(config.usb_disk)
if not os.path.exists(os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link))):
install_size = iso_size(config.iso_link) + config.persistence
# print("Persistence choosen is " + str(persistence_size) + " MB")
if install_size >= disk_usage(config.usb_mount).free:
QtWidgets.QMessageBox.information(self, "No Space.", "No space available on " +
config.usb_disk)
else:
reply = QtWidgets.QMessageBox.question(self, 'Review selection...',
'Selected USB disk:: %s\n' % config.usb_disk +
'USB mount point:: %s\n' % config.usb_mount +
'Selected distro:: %s\n\n' % iso_name(config.iso_link) +
'Would you like to proceed for installation?',
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
self.ui.slider_persistence.setEnabled(False)
self.progress_thread_install.start()
else:
QtWidgets.QMessageBox.information(self, 'Already Exist...',
os.path.basename(config.iso_link) + ' is already installed.')
else:
QtWidgets.QMessageBox.information(self, 'No support...',
'Sorry.\n' + os.path.basename(config.iso_link) +
' is not supported at the moment\n'
'Please email this issue to feedback.multibootusb@gmail.com')
# Added to refresh usb disk remaining size after distro installation
# self.update_gui_usb_info()
def dd_finished(self):
"""
Re-enable the blocked widgets for newer use.
:return:
"""
self.ui.imager_progressbar.setValue(0)
self.ui.imager_label_status.clear()
self.ui.comboBox_2.setEnabled(True)
self.ui.pushButton.setEnabled(True)
self.ui.imager_bootable.setText("Bootable ISO :: ")
self.ui.imager_iso_size.setText("ISO Size :: ")
QtWidgets.QMessageBox.information(self, 'Finished...', 'ISO has been written to USB disk.\nPlease reboot your '
'system to boot from USB.')
def dd_start(self):
"""
Function to block the widgets under ISO Imager tab...
:return:
"""
self.ui.imager_progressbar.setValue(0)
self.ui.imager_label_status.clear()
self.ui.lineEdit_3.clear()
self.ui.pushButton.setEnabled(False)
self.ui.comboBox_2.setEnabled(False)
self.ui.pushbtn_imager_refreshusb.setEnabled(False)
status_text = ("<b>Writing " + os.path.basename(config.imager_iso_link) + "</b>" + " to " + "<b>" +
config.imager_usb_disk_selected + "</b>")
self.ui.imager_label_status.setText(status_text)
def dd_quit(self):
self.ui.imager_progressbar.setValue(0)
self.ui.imager_label_status.clear()
self.ui.comboBox_2.setEnabled(True)
self.ui.pushButton.setEnabled(True)
QtWidgets.QMessageBox.information(self, 'Failed!', 'Writing ISO failed.')
def dd_write(self):
if not config.imager_usb_disk:
QtWidgets.QMessageBox.information(self, 'No USB...', 'Please Insert USB disk and rerun multibootusb.')
elif not config.imager_iso_link:
QtWidgets.QMessageBox.information(self, 'No ISO...', 'Please select an ISO.')
else:
usb_disk_size = int(self.imager_usb_detail(config.imager_usb_disk, partition=0).total_size)
self.iso_size = os.path.getsize(config.imager_iso_link)
if self.iso_size >= usb_disk_size:
QtWidgets.QMessageBox.information(self, "No Space.", os.path.basename(config.imager_iso_link) +
" size is larger than the size of " + config.imager_usb_disk)
else:
reply = QtWidgets.QMessageBox.question \
(self, 'Review selection...',
'Selected USB disk:: %s\n' % config.imager_usb_disk +
'Selected distro:: %s\n\n' % os.path.basename(config.imager_iso_link) +
'Would you like to proceed for installation?',
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
self.dd_start()
self.progress_thread_dd.start()
def on_close_Click(self):
"""
Closes main GUI.
:return:
"""
self.close()
def closeEvent(self, event):
"""
To capture the main close event.
:param event: Close event.
:return:
"""
reply = QtWidgets.QMessageBox.question(self, 'Exit MultiBootUSB...',
"Do you really want to quit multibootusb?", QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
print("Closing multibootusb...")
event.accept()
sys.exit(0)
else:
print("Close event cancelled.")
event.ignore()
class GuiInstallProgress(QtCore.QThread):
"""
Update GUI thread during install.
"""
update = QtCore.pyqtSignal(int)
status = QtCore.pyqtSignal(str)
finished = QtCore.pyqtSignal()
def __init__(self):
QtCore.QThread.__init__(self)
def __del__(self):
self.wait()
def run(self):
install_dir = os.path.join(config.usb_mount, "multibootusb", iso_basename(config.iso_link))
self.thread = GenericThread(install_progress)
status_text = ""
self.thread.start()
while self.thread.isRunning():
if config.status_text.strip():
config.status_text = config.status_text.replace(install_dir + "/", "Extracting ")
self.update.emit(config.percentage)
self.status.emit(config.status_text)
if not self.thread.isFinished() and config.percentage == 100:
config.status_text = ""
self.status.emit("Please wait...")
self.update.emit(100)
self.update.emit(0)
self.status.emit("Installing boot loader...")
if self.thread.isFinished():
config.status_text = ""
self.finished.emit()
print("Distro extraction completed...")
return
class GuiUninstallProgress(QtCore.QThread):
"""
Update GUI thread during uninstall.
"""
update = QtCore.pyqtSignal(int)
status = QtCore.pyqtSignal(str)
finished = QtCore.pyqtSignal()
def __init__(self):
QtCore.QThread.__init__(self)
self.thread = GenericThread(uninstall_progress)
def __del__(self):
self.wait()
def run(self):
self.thread.start()
while self.thread.isRunning():
self.update.emit(config.percentage)
self.status.emit(config.status_text)
if not self.thread.isFinished() and config.percentage == 100:
config.status_text = "Please wait..."
self.update.emit(100)
self.update.emit(0)
config.percentage = 0
self.status.emit("Updating syslinux.cfg file...")
if self.thread.isFinished():
config.status_text = ""
self.finished.emit()
print("Distro uninstall is complete...")
return
class DD_Progress(QtCore.QThread):
"""
Update GUI progress bar without blocking rest of GUI element when dd process is in progress.
"""
update = QtCore.pyqtSignal(int)
status = QtCore.pyqtSignal(str)
finished = QtCore.pyqtSignal()
def __init__(self):
QtCore.QThread.__init__(self)
if platform.system() == 'Linux':
self.thread = GenericThread(dd_linux)
elif platform.system() == 'Windows':
self.thread = GenericThread(dd_win)
def __del__(self):
self.wait()
def run(self):
self.thread.start()
while self.thread.isRunning():
if config.imager_percentage:
self.update.emit(config.imager_percentage)
if not self.thread.isFinished() and config.percentage == 100:
config.imager_status_text = ""
self.status.emit("Please wait...")
self.update.emit(100)
self.update.emit(0)
if self.thread.isFinished():
config.status_text = ""
self.finished.emit()
return
class GenericThread(QtCore.QThread):
def __init__(self, function, *args, **kwargs):
QtCore.QThread.__init__(self)
self.function = function
self.args = args
self.kwargs = kwargs
def __del__(self):
self.wait()
def run(self):
self.function(*self.args, **self.kwargs)
return
def main_gui():
app = QtWidgets.QApplication(sys.argv)
window = AppGui()
ui = Ui_Dialog()
window.show()
window.setWindowTitle("MultiBootUSB - " + mbusb_version())
window.setWindowIcon(QtGui.QIcon(resource_path(os.path.join("data", "tools", "multibootusb.png"))))
sys.exit(app.exec_())

@ -0,0 +1,102 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# Name: persistence.py
# Purpose: Module to deal with persistence of a selected distro.
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import sys
import os
import platform
import tarfile
import subprocess
from . import usb
from . import iso
from . import gen
from . import config
def persistence_distro(distro, usb_disk, iso_link):
"""
Function to detect if distro can have persistence option.
:param distro: Detected distro name.
:return: Distro name as string or None otherwise.
"""
iso_size = iso.iso_size(iso_link)
fat_max_size = (4096 * 1024 * 1024)
usb_details = usb.details(usb_disk)
usb_sf = usb_details['file_system']
usb_free_size = usb_details['size_free']
if usb_sf == 'vfat' or 'FAT32':
if usb_free_size > fat_max_size:
_max_size = fat_max_size
else:
_max_size = usb_free_size
else:
_max_size = usb_free_size
if distro == "ubuntu":
print("Persistence option is available.")
return "ubuntu", _max_size
else:
return None, None
# FIXME to get debian and fedora persistence workable...
# Able to add successfully but unable to keep persistence data.
'''
elif distro == "debian":
print "Persistence option is available."
return "debian"
elif distro == "fedora":
print "Persistence option is available."
return "fedora"
'''
def create_persistence():
if config.distro == "ubuntu":
fs_name = 'casper-rw'
elif config.distro == 'debian':
fs_name = 'live-rw'
persistence = config.persistence / 1024 / 1024
if platform.system() == 'Linux':
mkfs = 'mkfs.ext3'
dd = 'dd'
persistence_mkfs_cmd = mkfs + ' -F ' + os.path.join(config.usb_mount, 'multibootusb',
iso.iso_basename(config.iso_link),
fs_name)
elif platform.system() == 'Windows':
mkfs = gen.resource_path(os.path.join("data", "tools", "mkfs", "mke2fs.exe"))
dd = gen.resource_path(os.path.join("data", "tools", "dd", "dd.exe"))
persistence_mkfs_cmd = 'echo y|' + mkfs + ' -b 1024 -L ' + fs_name + ' ' + os.path.join(config.usb_mount, 'multibootusb',
iso.iso_basename(config.iso_link), fs_name)
persistence_dd_cmd = dd + ' if=/dev/zero ' \
'of=' + os.path.join(config.usb_mount, 'multibootusb',
iso.iso_basename(config.iso_link), fs_name) +\
' bs=1M count=' + str(int(persistence))
print('Executing ==>', persistence_dd_cmd)
config.status_text = 'Creating persistence file...'
if subprocess.call(persistence_dd_cmd, shell=True) == 0:
print("\nSuccessfully created persistence file...\n")
print('Executing ==>', persistence_mkfs_cmd)
config.status_text = 'Applying filesystem to persistence file...'
if subprocess.call(persistence_mkfs_cmd, shell=True) == 0:
print("\nSuccessfully applied filesystem...\n")
def extract_file(file_path, install_dir):
"""
Function to extract persistence files to distro install directory.
:param file_path: Path to persistence file.
:param install_dir: Path to distro install directory.
:return:
"""
tar = tarfile.open(file_path, "r:bz2")
tar.extractall(install_dir)
tar.close()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save