Showing posts with label commercial. Show all posts
Showing posts with label commercial. Show all posts

Wednesday, 6 February 2013

Saphirion

Today I'll post an interview to Mr. Robert M. Münch CEO of Saphirion AG:
Mr. Münch:
Hi Max, nice to hear from you. Of course I know your blog about Rebol. And great to hear, that you want to write a bit about Saphirion and what we do with Rebol etc.

I'll write down here the main questions about your company I receive from readers:

Mr. Münch:
Ok, I hope I can answer most of them down to the point.

Your site is only in German language, so it's difficult for many people understand your site. What is your company about?

Mr. Münch:
Yes, I know. I need to translate it into English. This is on our todo list.
Since our main target at the moment is Europe and there mostly Germany, Austria and Switzerland, who all speak german, the site is german only at the moment. For the rest of the world we are seeking partners and will translate the content into english.
Now, to what does Saphirion do? Saphirion is specialized in cost-management solutions for companies. So, our service and product is a B2B product. We are answering questions like:
  • How much should a part I buy from a supplier be?
  • What's the difference to the actual price we pay?
  • What's an expected price in the market for a part like ABC?
  • How much savings potential do we see in a product group?
By answering these questions, companies get a clear view and understanding on their cost situation and see where optimization efforts make sense and where not.

What is your relation between you and Reboltech company?

Mr. Münch:
None with respect to active business relations. I know Carl for about 15 years now and since then I use Rebol. We are using Rebol to build our products hence the interest in it and why we drive the R3 development as we do.
I was in long contact to get access to the R3 sources, to IOS sources etc. as I think / thought that there is more in the products than what RT has made out of it. If you want, I was an unofficial business management consultant for Carl. Not sure if it had any impact but I always felt like he was interested in my opinion about these things.
There is http://development.saphirion.com site, why don't you emphasize more it on your main site?


Mr. Münch:
Saphirion is not a technology company. We build and sell B2B services and solutions for cost-management, cost-optimzation. That we use Rebol to build our tools is of no interest to our customers. To keep the strategy clear, I have separated both topics. That's why development.saphirion.com is in english, where the main site for the B2B product is in german.
There is the Saphir R3, may you write about it? (http://development.saphirion.com/resources/r3-view.exe)At the moment is only for windows, will it be also on other platform? Will it be open source? Do you need help from community? Do you need money? What about using kickstarter (http://www.kickstarter.com)?


Mr. Münch:
Lot's of questions. So let me start:

1. The Saphir R3 is a fork of the official R3, that we keep in sync with Carl's line in that we merge his changes into our code-line as soon as we recognize a change on GitHub.

2. At the moment the GUI version (View) is Windows only. The Core version runs on different platforms. We are currently porting the Core version to Android. (http://development.saphirion.com/experimental/r3-droid.apk)
If this is done (we are mostly through) we will bring the GUI version to Android as well. With this experience we will bring View version to OSX and Linux as well. But both don't have highest priority for us.

3. Our Saphir is / will be open-source. We are setting up the internal infrastructure. That means: Source-Code handling with the other R3 forks, test-framework, documentation etc. This still needs to settle down a bit before being ready for prime-time. For this we use http://development.saphirion.com as the central place where you can find all information. We are planning to setup an own Saphir R3 web-site later the year.

4. Yes, we can always use help from the community. There are tons of things that need to be done, which are not our primary focus at the moment. That means, Saphirion is sponsoring mostly all efforts of Saphir R3 development at the moment. So, we focus on what we need to drive our business. Nevertheless, the community could help in these areas:

- Write test-cases or our R3 test-framework. This will help in porting it to other platforms and when we extend it.

- Write documentation for R3-GUI. I think the framework is ready for real world applications (we did one as test-case, see: http://www.tree-mapper.com), needs more testing, and people who write about it. We will bring the documentation to GitHub so we can accept pull-requests to it.

- Write styles for R3-GUI. There are still a lot of styles that would make sense for R3-GUI. Every style we add, makes it more robust and better useable for all of us. So, the more, the broader, the better.

5. Yes, we could use money to drive some developments further faster. For this I have setup the donation shop. And there are already a couple of people who support our efforts to make the Android port. That was a big motivator for us and really helps to push it forward. So, we want to do more with Saphir R3 and every USD, EUR helps in doing this.

6. I would love to use Kickstarter for Saphir R3. The thing, that needs to be done is, what's the business model behind it? Or, why should people support us on Kickstarter? And who are those people? The thing with programming languages is, it's not a business. Most are free, and only few make some bucks from developer tools. Overall I don't see the business case for a programming language. If someone does, I'm more than happy to better understand it. RT failed because they thought, that people are paying for a non-mainstream programming language.

If you want to try SaphireR3, go to http://development.saphirion.com/resources/r3-view.exe, launch it and digit:
load-gui

then you can test your VID code or follow the guide:
Here an example of Saphire Rebol 3 GUI:


Thursday, 25 October 2012

FastCGI

FastCGI is a new CGI protocol that replace and improve CGI in webservers (Apache, ISS, Lighttpd), and rebol can use it!
FastCGI is especially focused for high value application: greater scurity, distributed computing and extensible
You can  read more information here:
The FastCGI is one of the reserved features in commercial Rebol:
If you need this feature just go to the www.rebol.com and buy one of them.

Wednesday, 10 October 2012

Steganography

Steganography is a technique to insert a secret message inside an image.
TGD Consulting is a software house that use a lo Rebol, they made the following software in pure Rebol.
To send a secret message you have to:
  1. load an image
  2. write you message
  3. choose a secret key
 Only your friend, with this software and knowing the key, can read your secret message.
Here the source:
REBOL [
    Title: "Stegano-It!"
    Version: 1.4.2
    Date: 5-Aug-2007/8:49:19+1:00
    Name: "Stegano-It!"
    File: %SteganoIt.r
    Author: "Dirk Weyand"
    Rights: "TGD-Consulting"
    Home: http://www.TGD-Consulting.DE/Download.html
    Needs: 'View
    Purpose: "A tool to hide information in images."
    Comment: {
TGD-Consulting's Stegano-It! is
based on REBOL/View. This tool
allows you to hide information in
images using steganography algorithms.
With Stegano-It! you can easily
share confidental messages with
friends, business partners and
nobody else will recognise it.
Only four steps are necessary
to get a steganographic image:
1. Load an image . . . . . . . . . . . . . . . . .
2. Enter your private-key . . . . . . . . . .
3. Type & encrypt your message . . .
4. Save the new image . . . . . . . . . . . .
Try Stegano-It! and reap the benefits.}
    Language: 'en
    History: [
        {0.0.1   ^-26-Jun-2005 ^-"initial release"^/}
        {0.1.0   ^-02-Jul-2005 ^-"added IO-handling"^/}
        {0.1.1   ^-03-Jul-2005 ^-"enhanced GUI-skin"^/}
        {0.2.0   ^-10-Jul-2005 ^-"added private-key"^/}
        {0.2.1   ^-11-Jul-2005 ^-"optimized en/decoding"^/}
        {0.3.0   ^-12-Jul-2005 ^-"added clipboard-support"^/}
        {0.4.0   ^-13-Jul-2005 ^-"added View 1.3 workarounds"^/}
        {0.5.0   ^-14-Jul-2005 ^-"added random noise"^/}
        {0.5.1   ^-15-Jul-2005 ^-"fixed to run on AmigaOS"^/}
        {1.0.0   ^-17-Jul-2005 ^-"first public-release"^/}
        {1.1.0   ^-23-Jul-2005 ^-"enhanced encoding density"^/}
        {1.1.1   ^-07-Aug-2005 ^-"fixed image loading"^/}
        {1.1.2   ^-23-Aug-2005 ^-"optimized code"^/}
        {1.1.3   ^-01-Sep-2005 ^-"fixed hash-table bug"^/}
        {1.1.4   ^-14-Oct-2005 ^-"fixed sliders"^/}
        {1.2.0   ^-23-Dec-2005 ^-"added ESC-key control"^/}
        {1.3.0   ^-29-Jan-2006 ^-"added REBOL/View check"^/}
        {1.3.1   ^-16-Feb-2006 ^-"fixed ? hot-key"^/}
        {1.4.0   ^-18-Feb-2006 ^-"added mouse-wheel support"^/}
        {1.4.1   ^-08-Jul-2007 ^-"enhanced cipher-chaining-key"^/}
        {1.4.2   ^-05-Aug-2007 ^-"removed compress fingerprints"^/}
    ]
    License: {(C) TGD-Consulting
End User License Agreement
IMPORTANT. READ CAREFULLY.
This Lisense Agreement (AGREEMENT) is a legal contract between you and TGD-Consulting (TGD) for the limited use of this TGD software product (SOFTWARE), which includes computer software, and, as applicable, associated media, printed materials, and electronic documentation.
This SOFTWARE is licensed, not sold, to you. TGD retains all right, title and interest in and to the SOFTWARE including, without limitation, all intellectual property rights relating to or embodied in the SOFTWARE.
TGD grants you an non-exclusice license to use the SOFTWARE for personal use only. Commercial use requires seperate licensing from TGD. This AGREEMENT is not assignable or transferable without prior written approval of TGD.
The copyright, trademark, and other proprietary rights notices contained in the SOFTWARE may not be removed, altered, or added to in any way. You may not reverse engineer, decompress, decompile, or disassemble the SOFTWARE. You may not redistribute the SOFTWARE without prior written approval of TGD.
The SOFTWARE key that unlocks additional features and components may not be distributed, published, or transferred. Only the registered licensee of the SOFTWARE key may enable or use the additional features and components of this SOFTWARE.
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND. IN NO EVENT WILL TGD OR THE AUTHOR OF THE SOFTWARE BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS SOFTWARE.
You agree to use the SOFTWARE in compliance with all applicable laws and regulations including all laws governing the export or re-export of the SOFTWARE. You agree to indemnify TGD from and against your violation of any such laws or regulations.
This AGREEMENT contains the entire agreement between the parties with respect to the license of the SOFTWARE. This AGREEMENT supercedes any prior license agreement of the SOFTWARE.
By installing or using the SOFTWARE, you are consenting to be bound by and are becoming a party to this AGREEMENT. IF YOU DO NOT AGREE TO ALL OF THE TERMS OF THIS AGREEMENT, DO NOT INSTALL OR USE THE SOFTWARE.}
]
if not all [value? 'view? view?] [
    until [
        print "^L^/Stegano-It! requires REBOL/View !!!^/"
        wait 0.15
        print "^L^/^/"
        not none? wait [system/ports/input 0.15]
    ]
    quit
]
view: func do head insert find mold third :view "/new" {/kf "Keeps feel of window face"
    }
do head replace mold second :view "view-face/feel: window-feel" {if not kf [view-face/feel: system/view/window-feel]}
pixels: make hash! []
color-index: none
key-index: none
wraped: false
noise: true
noise-ratio: 5
main-offset: none
img: none
img-index: 0
img-index-max: 0
crypt-img: none
current-img: none
last-img: %./My-Image.jpg
bg-color: farbe: sky
bg-effect: compose [gradient 0x-1 (farbe) (farbe * 0.6) grid 700x4 690x2 0x1 (farbe / 2) blur blur blur]
e-color: add farbe / 2 farbe / 6
debug: false
lic-read: ulf: false
copydate: copy find/tail second system/script/Header/History "^-"
clear find copydate " "
copydate: to date! copydate
either greater? now/year copydate/year [copydate: join form copydate/year ["-" now/year]] [copydate: form copydate/year]
random/seed now/precise
btn-styles: stylize [
    btn: button 80x26 no-wrap font [size: 16 colors/1: (farbe + 80)] edge [size: 1x1 effect: 'bevel color: farbe / 3] effect [merge gradcol -1x0 45.45.45 120.120.120] with [
        init: [
            edge: make edge []
            font/color: first font/colors
            if all [image not effect] [
                effect: copy [fit]
                if color [append effect reduce ['colorize color]]
                if all [colors greater? length? colors 1] [
                    effects: compose/deep [[fit colorize (first colors)]
                        [fit colorize (second colors)]]
                ]
            ]
            if not any [color colors effect effects] [
                effects: [[gradient 0x1 66.120.192 44.80.132] [gradient 0x-1 66.120.192 44.80.132]]
            ]
        ]
    ]
    small-btn: btn 19x19
]
either found? suffix: find/last system/script/Header/File "." [filename: copy/part system/script/Header/File subtract length? system/script/Header/File length? suffix ] [filename: copy system/script/Header/File ]
config-file: join filename ".config"
message: func [
    "Display a message window"
    str [string! block! object!] "Message to display"
    /offset xy [pair!] "Offset of window"
    /color colors [tuple! block!] "Used colors"
    /timeout time
    /local lay result hdl msg c1 c2 c3 f x-hdl x-txt x-p
] [
    lay: either all [object? str in str 'type str/type = 'face]
    [str] [
        c1: green c2: c3: farbe + 80
        hdl: " N O T E : "
        if color [either block? colors [set [c1 c2 c3] colors] [c1: colors]]
        either block? str [
            str: reduce str
            set [hdl msg] str
            str: reform next next str
            foreach n [hdl msg str] [
                if all [found? get n not string? get n] [set n form get n]
            ]
        ] [
            msg: str
            str: ""
        ]
        f: layout [h1 copy hdl c1 center middle edge [color: e-color size: 1x1 effect: 'bevel]]
        x-hdl: 20 - 44 + first f/size
        either empty? str
        [f: layout [across text bold copy msg c2 middle]]
        [f: layout [across text bold copy msg c2 middle text copy str c3 middle]]
        x-txt: subtract first f/size 44
        either greater? x-txt x-hdl [x-p: to integer! (x-txt - x-hdl / 2)] [x-p: 0]
        result: copy [
            styles btn-styles
            backdrop effect bg-effect
            across
            pad x-p
            btn x-hdl keycode #"^M" copy hdl center middle font [size: 20 colors: compose [(c1) (c1 - 40)]] [result: true hide-popup] [result: true hide-popup] return
            text bold copy msg c2 middle with [feel: none]
        ]
        if not empty? str [insert tail result [text copy str c3 middle with [feel: none]]]
        layout result
    ]
    result: none
    either offset [inform/offset/timeout lay xy time] [inform/timeout lay time]
    result
]
scroll-slider-text: func [tf sf /local tmp size sms] [
    if none? tf/para [exit]
    size: size-text tf
    sms: subtract sf/size 2 * sf/edge/size
    tmp: min 0x0 tf/size - size - 0x8
    either sf/size/x > sf/size/y [
        tf/para/scroll/x: sf/data * first tmp
        either any [system/version > 1.3.0 link?] [sf/pane/1/size/x: max 10 to integer! divide sms/x max 1 (first size) / tf/size/x ] [sf/pane/size/x: max 10 to integer! divide sms/x max 1 (first size) / tf/size/x ]
    ] [
        tf/para/scroll/y: sf/data * second tmp
        either any [system/version > 1.3.0 link?] [sf/pane/1/size/y: max 10 to integer! divide sms/y max 1 (second size) / tf/size/y ] [sf/pane/size/y: max 10 to integer! divide sms/y max 1 (second size) / tf/size/y ]
    ]
    sf/state: -1
    show [tf sf]
]
scroll-smooth: func [dx tf sf /init /local d] [
    d: divide 2 max sf/size/x sf/size/y
    either positive? dx [
        while [all [lesser? sf/data 1 positive? dx]] [
            sf/data: min 1 sf/data + d
            dx: subtract dx d
            scroll-slider-text tf sf
        ]
    ] [
        while [all [positive? sf/data 1 negative? dx]] [
            sf/data: max 0 sf/data - d
            dx: add dx d
            scroll-slider-text tf sf
        ]
    ]
    if init [tf/para/scroll: 0x0]
]
scroll-wheel: func [page n tf sf /init /end] [
    either init [
        either end [
            scroll-smooth/init (n * (either page [tf/size/y] [tf/font/size])) tf sf
        ] [
            scroll-smooth/init divide (n * (either page [tf/size/y] [tf/font/size])) max 1 second size-text tf tf sf
        ]
        if all [not lic-read greater? sf/data 0.97] [lic-read: true]
    ] [
        either end [
            scroll-smooth (n * (either page [tf/size/y] [tf/font/size])) tf sf
        ] [
            scroll-smooth divide (n * (either page [tf/size/y] [tf/font/size])) max 1 second size-text tf tf sf
        ]
    ]
]
scroll-area: func [page n af /local d size] [
    if none? af/para [exit]
    size: size-text af
    d: (n * (either page [af/size/y] [af/font/size]))
    either positive? d [
        while [all [positive? add size/y - af/size/y + 8 af/para/scroll/y positive? d]] [
            d: subtract d 2
            af/para/scroll/y: max subtract af/para/scroll/y 2 negate size/y - af/size/y + 8
            show af
        ]
    ] [
        while [all [negative? af/para/scroll/y negative? d]] [
            d: add d 2
            af/para/scroll/y: min add af/para/scroll/y 2 0
            show af
        ]
    ]
]
license-agreement: layout [
    styles btn-styles
    backdrop effect bg-effect
    across
    banner join system/script/header/Name "   -   E U L A" 416 either any [system/version > 1.3.0 link?] [255.240.180] [yellow + 100] no-wrap with [feel: none]
    return
    space 0
    f-txt: text 400x150 bg-color / 3 bg-color + 80 edge [color: e-color size: 2x2 effect: 'ibevel] with [feel: none]
    f-sld: slider f-txt/size/y * 0x1 + 16x0 bg-color / 3 bg-color / 2 edge [color: e-color] [scroll-slider-text f-txt f-sld f-txt/para/scroll: 0x0 if greater? face/data 0.97 [lic-read: true]] return
    pad 1x10 return
    btn "ACCEPT" "ACCEPTED" keycode [#"^M"] font [size: 12] edge [size: 2x2] [either lic-read [unview license-agreement] [message/timeout {Read the complete EULA before you accept the agreement !!!} 0:00:06 hide-popup]] [either lic-read [unview license-agreement] [message/timeout {Read the complete EULA, before you accept the agreement!!!} 0:00:06 hide-popup]]
    pad 256
    btn 80 "Cancel" "Canceld" keycode [#"^["] font [size: 12] edge [size: 2x2] [unview/all quit] [unview/all quit]
    key keycode [up page-up] [scroll-wheel/init true -1 f-txt f-sld]
    key keycode [down page-down] [scroll-wheel/init true 1 f-txt f-sld]
    key keycode [home] [scroll-wheel/init/end true -1 f-txt f-sld]
    key keycode [end] [if lic-read [scroll-wheel/init/end true 1 f-txt f-sld]]
]
insert find/tail system/script/header/license "(C)" join " " copydate
f-txt/text: copy system/script/header/license
either any [system/version > 1.3.0 link?] [f-sld/pane/1/edge/color: e-color ] [f-sld/pane/edge/color: e-color ]
license-agreement/feel: make license-agreement/feel [
    detect: func [face event /local rc] [
        rc: true
        switch event/type [
            scroll-line [scroll-wheel/init false event/offset/y f-txt f-sld]
            scroll-page [scroll-wheel/init true event/offset/y f-txt f-sld]
            key [if found? face: find-key-face face event/key [
                    if get in face 'action [do-face face event/key]
                    rc: false
                ]
            ]
            close [quit]
        ]
        if rc [event]
    ]
]
m: 0
either exists? join filename ".license" [
    either all [not error? try [do load join filename ".license" ulf: false] value? 'expiry value? 'license-key value? 'licensee] [
        either date? expiry [
            either greater? now/date expiry [
                m: 3
            ] [
                either equal? license-key checksum/key read system/options/script join system/script/Header/Name [user-prefs/name expiry licensee] [ulf: true ] [m: 2 ]
            ]
        ] [
            either equal? license-key checksum/key read system/options/script join system/script/Header/Name [user-prefs/name licensee] [ulf: true ] [m: 2 ]
        ]
    ] [m: 2 ]
] [m: 1 ]
if any [not ulf not exists? config-file] [
    scroll-slider-text f-txt f-sld
    view/kf center-face license-agreement
]
switch m [
    1 [message/color reduce [" A T T E N T I O N : " reform [system/script/Header/Name "license-file not found !!!"] reform ["Please contact" system/script/Header/Rights "to purchase a license."]] yellow
    ]
    2 [message/color reduce [" A T T E N T I O N : " reform ["Your" system/script/Header/Name "license-key is not valid !!!"] reform ["Please contact" system/script/Header/Rights "to get a new license-file."]] yellow
    ]
    3 [message/color reduce [" A T T E N T I O N : " reform ["Your" system/script/Header/Name "license-key is expired !!!"] reform ["Please contact" system/script/Header/Rights "to get a new license-file."]] yellow
    ]
]
hot-key-wrapped?: func [
    key [string! char!]
] [
    either all [found? system/view/focal-face system/view/caret] [
        if all [found? system/view/highlight-start found? system/view/highlight-end] [
            system/view/caret: remove/part system/view/highlight-start subtract index? system/view/highlight-end index? system/view/highlight-start
            system/view/highlight-start: system/view/highlight-end: none
        ]
        insert system/view/caret form key
        system/view/caret: next system/view/caret
        show system/view/focal-face
        true
    ] [false ]
]
either equal? (xor 64#{//8=} 64#{AAA=}) 64#{//8=} [nxor: :xor ] [
    nxor: func [
        {Returns the first value exclusive ORed with the second.}
        value1 [binary!]
        value2 [binary!]
        /local rc i bit a b exp byte
    ] [
        rc: make binary! []
        i: 0
        loop min length? value1 length? value2 [
            i: i + 1
            a: enbase/base to string! to char! pick value1 i 2
            b: enbase/base to string! to char! pick value2 i 2
            bit: 0
            byte: 0
            loop exp: 8 [
                bit: bit + 1
                exp: exp - 1
                if not equal? pick a bit pick b bit [
                    byte: byte + power 2 exp
                ]
            ]
            insert tail rc to char! byte
        ]
        return rc
    ]
]
compress~: func [
    data
    /local rc
] [
    rc: compress data
    remove/part skip tail rc -2 2
    remove/part rc 2
]
decompress~: func [
    data
    /local rc
] [
    rc: copy data
    insert tail rc 64#{AAA=}
    insert rc 64#{eJw=}
    decompress head rc
]
load-config: func [
    "Loads the configuration file."
    myfile [file! string!] "The configuration file."
    /local mylastimg myoffset mynoise mysnr
] [
    if not error? try [set [mylastimg myoffset mynoise mysnr] read/direct/lines to file! myfile] [
        if found? mylastimg [error? try [last-img: to file! mylastimg]]
        if found? myoffset [error? try [main-offset: to pair! myoffset]]
        if found? mynoise [error? try [noise: to logic! to integer! mynoise]]
        if found? mysnr [error? try [noise-ratio: to integer! mysnr]]
    ]
]
shutdown: func ["exit the programm." ] [
    if ulf [write config-file reduce [last-img newline lay-main/offset newline]]
    unview/all
    either debug [halt] [quit]
]
connect?: does [
    if request ["Connect to the homepage of TGD-Consulting ?" "Browse" "Cancel"] [
        error? try [browse system/script/header/Home]
    ]
]
display: func [
    "displays the image as thumb preview."
    img
    /local ratio
] [
    if image? img [
        img-index: index? img
        img-index-max: multiply img/size/1 img/size/2
        ratio: divide first img/size second img/size
        either greater-or-equal? ratio divide 240 200 [
            pnl-img/size: to pair! reduce [230 min 190 to integer! divide 230 ratio]
        ] [
            pnl-img/size: to pair! reduce [min 230 to integer! multiply 190 ratio 190]
        ]
        pnl-img/image: img
        clear pnl-img/text
        pnl-img/offset: max 0x0 pnl-img/parent-face/size - 5 - pnl-img/size / 2
        show [pnl-img]
    ]
]
load-image: func [
    "load a image."
    /local path file
] [
    set [path file] request-file/title/file/filter/path "Choose an image to load:" "Load" last-img ["*.jpg" "*.png" "*.gif" "*.bmp"]
    if all [found? file exists? join path file] [
        last-img: current-img: join path file
        crypt-img: none
        img: load current-img
    ]
]
save-image: func [
    "load a image."
    /local path file suffix
] [
    either found? current-img [
        set [path file] split-path current-img
        if found? suffix: find/last file "." [file: copy/part file subtract length? file length? suffix ]
        either image? crypt-img [save/png join file %_crypt.png crypt-img ] [
            message/color/timeout [" A T T E N T I O N : " "No encrypted image to save !!!" "Please encrypt your message first."] yellow 0:00:06
            hide-popup
            focus smsg
        ]
    ] [
        message/color/timeout [" A T T E N T I O N : " "No image to save !!!" "Please load an image first."] yellow 0:00:06
        hide-popup
    ]
]
get-key-stream: func [
    len [integer!] "Länge des zu erzeugenden Key Streams."
    key [binary!] "Der Key."
    /local rc
] [
    rc: copy 64#{}
    insert/dup rc key to integer! 1 + divide len length? key
    rc: copy/part rc len
]
get-key-chain: func [
    "Erzeugt Cipher-Block-Chaining Key."
    IV [series!] "initial Vektor."
    l [number!] "Länge des Key."
    /local i cbc key
] [
    cbc: copy IV
    i: l - length? IV
    key: copy cbc
    while [positive? i] [
        insert tail cbc key: copy/part checksum/method key 'md5 i
        i: i - length? key
    ]
    return copy/part cbc l
]
to-pixel: func [
    val [integer!] "Wert der in Pixel kodiert wird."
    /no-tuple "Rückgabewert vom Typ block!"
    /local r g b
] [
    r: (to integer! power val (1 / 3))
    g: (to integer! power (val: val - power r 3) (1 / 2))
    b: (to integer! val - power g 2)
    either no-tuple [reduce [r g b]] [to tuple! reduce [r g b]]
]
from-pixel: func [
    pix [tuple! block!] "RGB-Farbwert"
] [to integer! ((power pix/1 3) + (power pix/2 2) + pix/3) ]
get-bit: func [
    {Liest verstecktes Bit aus dem RGB-Farbwert des Pixel.}
    i [integer!] "genaue Position RGB-Farbwertes."
] [odd? pick pick img img-index i ]
set-even-color: func [
    {Versteckt ein "0"-Bit im RGB-Farbwert des Pixel.}
    i [integer!] "genaue Position RGB-Farbwertes."
    /local col pxl
] [
    pxl: pick img img-index
    col: pick pxl i
    if odd? col [
        either equal? col 255 [col: col - 1] [col: col + 1]
        pxl: poke pxl i col
        poke img img-index pxl
    ]
]
set-odd-color: func [
    {Versteckt ein "1"-Bit im RGB-Farbwert des Pixel.}
    i [integer!] "genaue Position RGB-Farbwertes."
    /local col pxl
] [
    pxl: pick img img-index
    col: pick pxl i
    if even? col [
        col: col + 1
        pxl: poke pxl i col
        poke img img-index pxl
    ]
]
wrap-next: func [
    "Liefert das nächste Element in der Liste."
    lst [series!]
] [
    if tail? lst: next lst [lst: head lst]
    return lst
]
decode-byte: func [
    "Decodes a byte from the datastream."
    /group "no gap between the bits."
    /local rc exp offset
] [
    rc: 0
    loop exp: 8 [
        exp: exp - 1
        if get-bit color-index [rc: rc + power 2 exp]
        insert tail pixels img-index
        either group [
            if equal? color-index: add color-index // 3 1 1 [img-index: add img-index 1]
        ] [
            offset: first key-index: wrap-next key-index
            color-index: add offset // 3 1
            if greater? img-index: add img-index offset img-index-max [
                img-index: subtract img-index img-index-max
                wraped: true
            ]
            if wraped [
                while [found? find pixels img-index] [img-index: img-index + 1]
            ]
        ]
    ]
    return rc
]
encode-byte: func [
    "Encodes a byte in the datastream."
    val [integer!] "The byte to hide."
    /group "no gap between encoded bits."
    /local offset
] [
    foreach bit enbase/base to string! to char! val 2 [
        either zero? to integer! form bit [
            set-even-color color-index
        ] [set-odd-color color-index ]
        insert tail pixels img-index
        either group [
            if equal? color-index: add color-index // 3 1 1 [img-index: add img-index 1]
        ] [
            offset: first key-index: wrap-next key-index
            color-index: add offset // 3 1
            if greater? img-index: add img-index offset img-index-max [
                img-index: subtract img-index img-index-max
                wraped: true
            ]
            if wraped [
                while [found? find pixels img-index] [img-index: img-index + 1]
            ]
        ]
    ]
]
encode-noise: func [
    {Fügt zusätzliches Rauschen zur Verschleierung der Nachricht ins Bild ein.}
    n [integer!] "Anzahl der Pixel, die verrauscht werden."
] [
    loop n [
        img-index: random img-index-max
        either random false [
            set-odd-color random 3
        ] [set-even-color random 3 ]
    ]
]
encode-msg: func [
    "Verschlüsselt eine Nachricht im Datenstrom."
    msg [series!] "Die zu codierende Nachricht."
    key [series!] "Der symmetrische Schlüssel."
    /local l hash stream cmsg
] [
    cmsg: compress~ msg
    l: length? msg
    if lesser? l length? cmsg [cmsg: msg]
    hash: get-key-chain key l: length? cmsg
    stream: (nxor to binary! cmsg hash)
    clear pixels
    wraped: false
    color-index: 1
    key-index: head hash
    img-index: 1
    foreach element to-pixel/no-tuple l [encode-byte/group element ]
    color-index: 1
    foreach byte stream [encode-byte byte ]
    head img
]
decode-msg: func [
    "Extrahiert eine Nachricht aus dem Bild"
    key [series!] "Der symmetrische Schlüssel."
    /old "Kompatibilitäts-Modus"
    /local hash l stream err
] [
    clear pixels
    wraped: false
    color-index: 1
    img-index: 1
    stream: make binary! []
    clear stream
    l: from-pixel reduce [decode-byte/group decode-byte/group decode-byte/group]
    either old [
        hash: get-key-stream l key
        key-index: head key
    ] [
        hash: get-key-chain key l
        key-index: head hash
    ]
    loop l [insert tail stream to char! decode-byte ]
    stream: nxor stream hash
    either error? err: try [either all [equal? copy/part stream 2 64#{eJw=} equal? copy/part skip tail stream -2 2 64#{AAA=}] [decompress stream] [decompress~ stream]] [to string! stream ] [err ]
]
encrypt: func [
    "enrypts the message in the image."
    /local msg
] [
    either none? img [
        message/color [" E R R O R : " "Not able to encrypt the message !!!" "Please load an image first."] red
    ] [
        either empty? smsg/text [
            message/color/timeout [" A T T E N T I O N : " "No message to encrypt !!!" "Please enter your message first."] yellow 0:00:06
            hide-popup
            focus smsg
        ] [
            either ulf [msg: copy smsg/text] [msg: join copy/part smsg/text min 50 to integer! multiply length? smsg/text 0.25 ["...<SNIP>" newline newline system/script/header/Name " DEMO-Version !!!"]]
            either lesser? multiply length? msg 8 (divide img-index-max noise-ratio) - 8 [
                if noise [encode-noise multiply length? msg noise-ratio]
                crypt-img: encode-msg msg checksum/method pkey/text 'md5
            ] [
                message/color [" E R R O R : " "Not able to encrypt this message !!!" "Please shorten it or load a larger image."] red
                focus smsg
            ]
        ]
    ]
]
decrypt: func [
    "decrypts a message from the image."
    /old "Kompatibilitäts-Modus"
    /local err
] [
    either none? img [
        message/color [" E R R O R : " "Not able to decrypt a message !!!" "Please load an image first!"] red
    ] [
        either any [all [old not error? err: try [decode-msg/old checksum/method pkey/text 'md5]]
            not error? err: try [decode-msg checksum/method pkey/text 'md5]] [
            smsg/texts: reduce [smsg/text: copy err]
            smsg/para/scroll: 0x0
            show [smsg]
            focus smsg
        ] [
            message/color [" E R R O R : " "Not able to decrypt a message !!!" "Invalid image or wrong key!"] red
        ]
    ]
]
sendmail: layout [
    styles btn-styles
    backdrop effect bg-effect
    vh2 reform ["Send email to" system/script/header/Name "author:"] bg-color + 80 with [feel: none]
    msg: area "Type your message here ..." 250x60 bg-color + 80 wrap font [color: bg-color / 3] edge [color: e-color]
    across return
    btn 80 "Send" "Send ..." [
        unfocus
        sending: flash "Sending ..."
        either error? try [
            hdr: make system/standard/email [subject: reform [system/script/header/Name system/script/header/Version]]
            send/header D.Weyand@TGD-Consulting.de msg/text hdr
        ] [
            unview/only sending
            message/color [" E R R O R :" "Error sending email !!!" "Check your REBOL network setup."] red
        ] [
            unview/only sending
            message/color/timeout [" O K A Y " "Your email has been sent!" "Thanx 4 Your message."] green 0:00:06
            hide-popup
            unview/only sendmail
        ]
    ] [
        unfocus
        sending: flash "Sending ..."
        either error? try [
            hdr: make system/standard/email [subject: reform [system/script/header/Name system/script/header/Version "(" user-prefs/name ")"]]
            send/header D.Weyand@TGD-Consulting.de msg/text hdr
        ] [
            unview/only sending
            message/color [" E R R O R :" "Error sending email !!!" "Check your REBOL network setup."] red
        ] [
            unview/only sending
            message/color/timeout [" O K A Y " "Your email has been sent!" "Thanx 4 Your message."] green 0:00:06
            hide-popup
            unview/only sendmail
        ]
    ]
    pad 82 btn 80 "Cancel" "Canceled" keycode [#"^["] [unfocus unview/only sendmail] [unfocus unview/only sendmail]
]
sendmail/feel: make sendmail/feel [
    detect: func [face event /local rc] [
        rc: true
        switch event/type [
            scroll-line [scroll-area false event/offset/y msg]
            scroll-page [scroll-area true event/offset/y msg]
            key [if found? face: find-key-face face event/key [
                    if get in face 'action [do-face face event/key]
                    rc: false
                ]
            ]
        ]
        if rc [event]
    ]
]
history: layout [
    size 350x150
    styles btn-styles
    backdrop effect bg-effect
    across
    banner "History ..." 308 bg-color + 80 with [feel: none] return
    pad 0x-5 h-txt: text 294x80 bg-color / 3 bg-color + 80 no-wrap edge [color: e-color size: 2x2 effect: 'ibevel] with [feel: none]
    pad -8x0 h-sld: slider h-txt/size/y * 0x1 + 16x0 bg-color / 3 bg-color / 2 edge [color: e-color] [scroll-slider-text h-txt h-sld]
    at 0x0
    key keycode [up page-up] [scroll-wheel true -1 h-txt h-sld]
    key keycode [down page-down] [scroll-wheel true 1 h-txt h-sld]
    key keycode [home] [scroll-wheel/end true -1 h-txt h-sld]
    key keycode [end] [scroll-wheel/end true 1 h-txt h-sld]
    at 328x3 small-btn "X" keycode [#"^["] [unview/only history] [unview/only history]
]
h-txt/text: system/script/header/History
either any [system/version > 1.3.0 link?] [h-sld/pane/1/edge/color: e-color] [h-sld/pane/edge/color: e-color]
scroll-slider-text h-txt h-sld
history/feel: make history/feel [
    detect: func [face event /local rc] [
        rc: true
        switch event/type [
            scroll-line [scroll-wheel false event/offset/y h-txt h-sld]
            scroll-page [scroll-wheel true event/offset/y h-txt h-sld]
            key [if found? face: find-key-face face event/key [
                    if get in face 'action [do-face face event/key]
                    rc: false
                ]
            ]
        ]
        if rc [event]
    ]
]
about-box: layout [
    size 342x275
    styles btn-styles
    backdrop effect bg-effect
    banner "About ..." 300 bg-color + 80 with [feel: none]
    pad 0x-5 panel 300x205 edge [size: 2x2 effect: 'ibevel color: e-color] [
        style link text bold font [colors: reduce [0.0.0 (bg-color / 4)]]
        backdrop (bg-color + 80) effect reduce ['gradient 0x1 (bg-color + 65) (bg-color + 80)]
        origin 23
        across
        at 23x10
        pa-hd1: h2 underline form system/script/header/Name (bg-color / 2.7) with [feel: none]
        pa-hd2: h2 reform ["Version:" system/script/header/Version] (bg-color / 2.7) font [colors: reduce [(bg-color / 2.7) (bg-color / 4)]] [unfocus view/kf/new/options center-face history [no-title]] return
        space 0
        box 250x3 edge [size: 1x1 color: bg-color + 55 effect: 'bevel] return
        credits: text (bg-color / 2.7) center bold no-wrap 250x80 rate 30 para [origin: 0x10]
        feel [engage: func [face action event] [
                if action = 'time [
                    face/para/origin: face/para/origin - 0x1
                    if lesser? second face/para/origin negate second size-text credits [face/para/origin: 0x70]
                    show face]
            ]
        ] return
        space 8
        box 250x3 edge [size: 1x1 color: bg-color + 55 effect: 'bevel] return
        space 0
        pad 15 text (bg-color / 2.7) bold "written by" with [feel: none]
        link (bg-color / 2.5) system/script/header/Author [unfocus sendmail/offset: about-box/offset + 200x220 view/kf/new/options sendmail [no-title]] return
        pad 15 text (bg-color / 2.7) bold reform ["Copyright" copydate ","] with [feel: none]
        space 8 link (bg-color / 2.7) system/script/header/Rights [
            unfocus
            connect?
        ] return
        pad 15 text (bg-color / 2.7) bold no-wrap reform ["Updated: " to-idate system/script/header/Date] with [feel: none] return
    ]
    at 299x3
    small-btn "?" keycode [#"?"] [view/kf/new/options center-face history [no-title]] [view/kf/new/options center-face history [no-title]]
    at 320x3
    small-btn "X" keycode [#"^["] [unview/only about-box] [unview/only about-box]
]
xsize: to integer! ((300 - (first pa-hd2/offset + first pa-hd2/size - first pa-hd1/offset)) / 2)
pa-hd2/offset: to pair! join xsize + first pa-hd2/offset - first
pa-hd1/offset ["x" second pa-hd2/offset]
pa-hd1/offset: to pair! join xsize ["x" second pa-hd1/offset]
show [pa-hd1 pa-hd2]
credits/text: {
- - - - - -
}

insert credits/text form system/script/header/Comment
insert credits/text reform [">>> " system/script/Header/Name " <<<" newline]
insert credits/text {
\|/
@ @
----------oOO-(_)-OOo----------
-= T G D =-
is proud to
present
}

either ulf [
    insert tail credits/text reform ["This software is registered to" newline licensee "."]
    if date? expiry [
        insert tail credits/text reform [newline "Your license will expire at" newline expiry "!"]
    ]
] [
    either all [value? 'expiry date? expiry] [insert tail credits/text reform ["This software has been registered to" newline licensee "," newline "but your license expired !" newline ]
    ] [
        insert tail credits/text {This software is not registered yet
and runs in D E M O - mode only !
}

    ]
    insert tail credits/text reform ["^/To register and run the full version of"
        newline system/script/Header/Name {, contact TGD-Consulting
at the following email address :
info@TGD-Consulting.de}
]
]
insert tail credits/text "^/^/- - - - - -"
lay-main: layout [
    size 640x300
    styles btn-styles
    backdrop effect bg-effect
    across
    banner 600 farbe + 80 underline bold "Stegano-It!" with [feel: none] return
    guide 280x50
    pad 0x50 btn "Load" [unfocus display load-image] [unfocus display load-image] return
    btn "Encrypt ->" [unfocus encrypt] [unfocus encrypt] return
    btn "<- Decrypt" [unfocus decrypt] [unfocus decrypt/old] return
    btn "Save" [unfocus save-image] [unfocus save-image] return
    guide 20x50
    at 20x50
    vh4 240 farbe + 80 "Secret - Message" "copied to clipboard" center [
        if not empty? smsg/text [write clipboard:// smsg/text]
    ] [
        either empty? smsg/text [
            smsg/text: read clipboard://
        ] [
            foo: copy smsg/text
            smsg/texts: reduce [smsg/text: read clipboard://]
            write clipboard:// foo
        ]
        show [smsg]
        focus smsg
    ] return
    pad 0x-6 smsg: area 240x170 farbe + 80 wrap font [color: farbe / 3] edge [size: 2x2 effect: 'ibevel color: e-color] "Type your secret message here ..." return
    pad 0x-2 vh4 32 farbe + 80 "Key" no-wrap center with [feel: none]
    pkey: field farbe + 80 font [color: farbe / 3] edge [size: 2x2 effect: 'ibevel color: e-color] "Enter your private-key here ..."
    guide 380x50
    at 380x50
    vh4 240 farbe + 80 "Thumb - Image" center with [feel: none] return
    pad 0x-6 panel 240x200 farbe / 2 edge [size: 2x2 effect: 'ibevel color: e-color] [
        origin 0x0
        space 0x0
        pnl-img: box 240x200 farbe / 2 "No Picture!" font [color: farbe + 80]
    ] return
    pad -360x1 text 600 center farbe + 80 no-wrap join "(c) " [copydate " " system/script/header/Rights] with [feel: none] [connect?] [connect?]
    key keycode [#"?"] [if not hot-key-wrapped? #"?" [view/new/offset/title about-box (lay-main/offset + 590x37) join "about " system/script/header/Name]]
    at 618x3
    small-btn "X" keycode [#"^["] [
        if confirm reform ["Do you really want to quit" system/script/title "?"] [shutdown]
    ] [
        if confirm reform ["Do you really want to quit" system/script/title "?"] [shutdown]
    ]
    at 597x3
    small-btn "?" [view/new/offset/title about-box (lay-main/offset + face/offset + face/size + -50x15) join "about " system/script/header/Name] [view/new/offset/title about-box (lay-main/offset + face/offset + face/size + 20x60) join "about " system/script/header/Name]
]
lay-main/feel: make lay-main/feel [
    detect: func [face event /local rc] [
        rc: true
        switch event/type [
            scroll-line [scroll-area false event/offset/y smsg]
            scroll-page [scroll-area true event/offset/y smsg]
            key [if found? face: find-key-face face event/key [
                    if get in face 'action [do-face face event/key]
                    rc: false
                ]
            ]
            close [rc: false
                either confirm reform ["Do you really want to quit" system/script/title "?"] [shutdown] [view/kf/new lay-main]]
        ]
        if rc [event]
    ]
]
if ulf [load-config config-file]
either main-offset [lay-main/offset: main-offset] [center-face lay-main]
view/kf lay-main
shutdown