The MyPostcards Platinum 5 web application allows you to create the most customizable web postcard service.
This manual assumes that you have a medium to advanced level of HTML skills, including knowledge of form basics.
Advanced design and consulting services are available from several experienced affiliate designers: click to view design offers.
Before starting to customize your cardshop make sure you have read the sections: Setup and Program Variables.
Important! Be very careful while editing templates. DO NOT edit those files with an HTML editor or word processor - only with plain text editor like Notepad for Windows or Textpad for Mac.
All templates for e-mail notifications are to be stored in $INC_DIR/mail.
In a default installation you will see 3 files in this sub-directory.
In custom configuration files mail1.txt is referenced to as
CARD_MAIL
This is the text of the e-mail notification that is sent to card recipients, telling them to pick up their card. This file can be edited freely.
You may remove the alternative pickup link. However, experience shows that this alternative link avoids a lot of help inquiries.
X-CardStamp is added there to facilitate tracking of spam complaints. Read more about spam issues in the troubleshooting section.
In custom configuration files mail2.txt is referenced as PICK_MAIL
This is the text of the e-mail notification that is sent to card senders, telling them that their card has been picked up. If the card has been picked up more than one time - the pickup notification will be delivered only once.
You can disable the delivery of such mails using the "nopick" variable.
In custom configuration files referenced as FWD_MAIL
Similar to mail1.txt, used for forwarding cards. The only difference is changed text.
All email templates are plain ASCII text files, size limit to 20 KB for each. You can edit headers (if you are familiar with appropriate RFCs, if you don't know what RFC is, - forget about it completely!)
Common error! The first line of the file should not be blank! That results with system error and e-mail notifications not sent. In technical terms - the mail transfer agent (MTA) perceives it as request to send an e-mail without address and refuses to do it.
You can create as many email templates as you need - for different occasions,
using different languages, formatting, etc. All files should be uploaded
to $INC_DIR/mail and referenced in the appropriate custom configuration
files.
All templates for card pages layout are to be stored in $INC_DIR/html.
The size for card page templates is not limited.
When editing these pages you can use any symbols, HTML tags, CSS, Java
Script, VB Script, Java, Flash, literally anything. If some symbols produce
wrong output or don't print at all (for example % - percent
symbol) use alternative notation (© for copyright,
% for percent, etc.)
Important! Before starting to edit your cardhsop make sure you have read the section Program Variables
In the simplest setup you will need only three card templates preview.html,
receive.html, sent.html. Here is a sample composition
page for the simple setup: p5-card1.shtml, custom configuration
file: magic.txt
In the custom configuration files the preview.html
is referenced as PRE_PAGE
This is the card page shown to the card sender for final approval before sending it out. You can edit this page as you like. The order of appearance of program variables on the page is irrelevant.
At the bottom of this page you will find <FORM>
</FORM> tags. This section contains automatically
generated code which is passed to the program. You can edit INPUT field
values but do not touch anything else!
In custom configuration files the receive.htm is
referenced as REC_PAGE
This is the page on which the recipient will view his card. You can
edit this page as you like. The order of appearance of the program variables
on the page is irrelevant. The easiest way to create this page is to
simply remove the <FORM> </FORM>
tags and everything between them from the
preview.html.
In custom configuration files the sent.html is referenced
as SEN_PAGE
This is the final message to the card sender, confirming the fact the card was (or will be) sent.
You can edit this page as you like. The order of appearance of the program variables on the page is irrelevant.
There is a <!--@when--> variable
which can be used only on this particular template. Depending on when
the sender scheduled a card to be delivered either the date will be
inserted instead of this placeholder, or "now" if it should
be sent immediately.
Important! Experience shows that this is absolutely the best place for any advertising!
Everything in the "simple setup" section above applies to sample templates related to "enhanced setup" sample. Below we describe only the peculiarities of this particular set of templates.
The "enhanced setup" sample is intended to demonstrate as many features
of Platinum software as possible. The files preview-enh.html,
sent-enh.html and receive-enh.html are
located in $INC_DIR/html. There are more variables used, compared
to the simple set (for example custom colors).
The custom configuration file magic-enh.txt for this setup
can be found in $INC_DIR/conf. If you compare the content of
custom configuration files for both simple and enhanced configuration you
will notice that the one for enhanced setup contains more parameters. Parameters
are explained in details in the following sections of the manual. Depending
on your particular design you can use all as in magic-enh.txt
or only some of them.
The most different from simple setup is the code on the receive-enh.html template. Notice the links on the bottom - forwarding, saving and printing cards. You can use any of them in combination or none at all. The code for the links should be used exactly as on receive-enh.html, without any alterations otherwise it won't work.
When the user clicks the link to forward a received card, the template
of the page that appears next and prompts him to enter the recipients details
is referenced in custom configuration file magic-enh.txt
as FWD|forward.html. It is stored in $INC_DIR/html
directory (as all other HTML templates).
The code on this page does not differ much from similar pages. The mandatory variable used only on this page is "fwd", all others are not different from templates described above. The "config" variable used on this particular template refers to the custom configuration for the FORWARDED card (the one the recipient will see). In enhanced setup sample it is forward.txt.
When the addresses are entered, the notification e-mail, which is sent
to the recipient of the forwarded card, is composed according to the template
that is referenced in custom configuration file magic-enh.txt
as FWD_MAIL|fwdmail1.txt. just like all other e-mail templates,
this file is stored in $INC_DIR/mail directory.
When the recipient of a forwarded card opens it, he sees the received
card template which is specified in a separate configuration file called
forward.txt as REC_PAGE|receive-fwd.html. The reason
for a separate configuration file is that the wording on the received card
differs from the normal card to reflect the fact it had been initially sent
to someone else and forwarded later. However in some special cases (like
forwarding jokes) you can avoid this and use the same custom configuration
file and templates for "normal" cards as well as forwarded cards.
While it may sound funny to you as an experienced webmaster there are more and more people who cannot save a page from browser. There are also the issues with particular browser and platforms like WebTV that make saving program generated pages an impossible task. That was the reason for the addition of this feature.
When a user clicks on "save this card" link the template for the page
that appears next is referenced in custom configuration file magic-enh.txt
as SAVE|save.html.
The code on this page does not differ a lot from the received page template. You should make sure you reference all outside links correctly.
The actual file for this card is written to your webserver to directory
at the server path which is specified in your global configuration file
magics.cfg as SAVE_DIR. It is important that
this directory should have write permissions for the user that the main
program runs from. The URL for that server path that is prepended to the
generated filename and is specified there as well as SAVE_URL.
The resulting URL will appear in the "address" ("location") window of user's
browser as SAVE_URL/somecode.html. All existing browsers allow
to save such "static" page easily.
If you are running some membership service or have some other reason for doing that, you can allow those pages to be stored on the server for indefinite time and therefore to be accessible to the recipient at any time. They can save those pages as their "favorites" ("bookmarks").
Otherwise you should clean up those pages yourself from time to time or set a simple shell script to perform this task (using file creation time as criteria for deletion). The pages are not deleted automatically by the Platinum software.
This feature is intended purely for design and advertising purposes. Of course everyone can print the received card directly without following any additional links. However you as designer may want to include some other info for such "hard" copy (e.g. - put extended server credentials, different advertising, etc.). Most important is that you may want to create a special design for printed cards. The features to avoid are dark backgrounds, animated clipart, java and flash. You may want to create a special style sheet to format print output.
When a user clicks on the "print this card" link, the template for the
page that appears next, is referenced in the custom configuration file magic-enh.txt
as PRINT|print.html.
All templates for error messages are stored in $INC_DIR/errors.
Size for all these error pages is not limited.
You can edit these pages as you like, you can completely reword error messages, but do not rename any of those files!!!. The names of these files are predefined and cannot be changed. Adding more files to this subdirectory will not be noticed by program.
The purpose of each error message is quite obvious from it's content: It's highly unlikely that you would encounter any problems customizing these files. The full list is below.
Err_CardNum.htmlErr_Code.htmlErr_Email.htmlErr_File.htmlErr_Incomp.htmlErr_NoCard.htmlErr_NoTick.htmlEdit_Email.htmlEdit_Email_Multi.html Special Note Err_Email.html
is an old versions legacy and could appear mostly on cardshops initially
setup with versions 3 and 4.
All files in $ROOT_DIR named p5-something.shtml
are sample card composition pages. See the complete list in the Setup section.
These pages are included for demonstration purposes, you can easily implement other layouts. These are regular HTML pages and you can edit them as you like.
Some of the sample pages contain SSI tags, make sure your editor renders them correctly. When editing these pages - do not save them with a browser, download with FTP ONLY!
When you have finished editing card composition pages, you can place them
inside any directory on your server, not necessarily $ROOT_DIR.
All form controls must be placed within the <FORM> and </FORM> tags. Everything outside them won't be passed to the Platinum program.
MypPostcards Platinum version 5 allows you to offer a wide variety of options for cards composition. You may choose to use only a few, or you can have all options available on your card site. You don't have to use stamps or backgrounds if you don't want to!
Before proceeding make sure you have read the section: Program Variables.
The default images directory $IMG_URL is defined in the
global configuration file magics.cfg. If you put all
images into that directory, then you do not need to include anything
other than the file name when listing options for your picture selections.
However you can put images elsewhere, which comes especially handy when you have many selections and you want to keep your files in an organized manner.
Important! Many webmasters neglect structuralization which leads to directories with tens of thousands files. Setting aside maintenance considerations - such garbage collectors slow down your site's performance drastically!
Below are 3 samples of image references in the card composition page.
Image file imageX.jpg is located in the default images
directory $IMG_URL
<input type="radio" name="filename"
value="imageX.jpg">
$IMG_URL Image file imageX.jpg is located in the sub-directory
below the default images directory $IMG_URL/subdir/
.
<input type="radio" name="filename"
value="subdir/imageX.jpg">
Note: You don't have to use the slash before subdir
.
Image file imageX.jpg is located on another server.
In this case you have to put the full URL of that file.
<input type="radio" name="filename"
value="http://otherserver.com/otherdir/imageX.jpg">
The default directory for sound files $MIDI_URL is defined
in the global configuration file magics.cfg. Otherwise the whole above
section about images applies to sound files as well.
Applies to variables: "filename", "sound", "sound_c"
If the variable passed from the card composition page starts with
http:// , then the value is passed to the generated
card page unchanged.
<input type="radio" name="filename" value="http://yoursite.com/dir/imagename.jpg">
<img src="http://yoursite.com/dir/imagename.jpg">
If the variable passed from the card composition page DOES NOT
start with http:// then the value of default image
directory $IMG_URL is prepended to the filename. In
case of "sound" and "sound_c" tags the default sound directory $MIDI_URL
is prepended.
<input type="radio" name="filename" value="imagename.jpg">
<img src="$IMG_URLimagename.jpg"> If you use background images, stamps, custom fields for graphics,
sounds or other multimedia files you should reference those elements
by relative or full URLs. There are no default directories like $IMG_URL
or $MIDI_URL for those files.
The easiest way is to use absolute URLs (relative to your domain's document root) - like this:
<input type=radio name=stamp value=/platinum/stamps/kiss.jpg>
The Platinum supports sounds in any format. The standard midi files (most popular sound format for cardshops by far) can be published with the "sound" variable.
Sound files selected with the "sound" variable are embedded into the generated card page in a browser-dependent way.
<bgsound src="song.mid" autostart="true"> <EMBED SRC="song.mid" width="200" height="55" AUTOSTART="TRUE">
The use of the "sound" variable allows you to avoid adding specific browser detection routines to card page templates (which is quite an easy task for a javascript programmer).
However this default syntax can be changed with the "sound_c" variable which does not add any HTML tags and outputs only the address for the selected sound file.
This way you can embed or use any sound formats with any plugin-specific tags.
The HTML code on card page template could look like this:
<embed src="<!--@sound_c-->" autostart="true" volume="25"
width="144" height="15" hspace="0" controls="smallconsole">
Notice: you do not need to change the HTML code on the card composition page in order to use the "sound_c" variable. Only preview and receive card page templates should be altered.
The Platinum allows you to include ready-made preformatted files with HTML code into cards. Initially this feature was used for including poems and java applets - that's how the names originated. However it can be used for many other purposes (including horoscopes, recipes, jokes, quotes, games, custom designs, flash cards, etc.)
"Poems" and "applets" are embedded into the generated card page in a way similar to Apache SSI (server side includes). The file with the preformatted portion of HTML code is being read into memory by the program and embedded into the resulting generated card page in place of the appropriate placeholder (<!--@poem--> or <--@filename-->).
"Applets" should be saved with *.jav extension, "poems" with
*.txt extension and uploaded into $POEMS_DIR.
<input type="radio" name="poem" value="poem.txt">
<input type="radio" name="filename" value="applet.jav">
Important! Be sure to include the exact codebase for the applets and swf files and upload*.classand*.jarand*.swffiles using BINARY transfer mode. Do NOT add a full URL for*.txtand*.javfiles locations!
The Platinum program includes a commercial license for the Anfy Java Collection with many dozens of unique applets and an easy to use desktop applet configurator. Please contact Customer Support for regcodes and where to download your copies of these wonderful applets.
You can use both "poems" and "applets" for Flash cards.
File extension for these files should be *.txt and *.jav
and not anything else.
Important! The files with "poems" and "applets" are NOT the full HTML documents! There shouldn't be <HEAD>, <BODY>, <HTML>, <META>, <TITLE> tags! Otherwise you are guaranteed to have Netscape 4+ crash and see weird results with IE.
The easiest way to prepare such files is to design a normal HTML page, then open it with notepad or other plain text editor and delete everything OUTSIDE the <BODY> </BODY> tags (the body tags itself inclusive).
People new to the Net clearly prefer "quick cards" to the ones with many customization features. On "quick cards" most selections are done for them by a webmaster and they only have to enter addresses and some message (or no message at all).
Creating composition pages for "quick cards" is very easy. You simply pass all preselected elements to the program using hidden form fields. Please refer to card3.shtml sample composition page and examine the code.
The quickest way of creating such "quickies" is to examine your cardshop stats, take a notice of most frequently used pictures, music clips, poems, etc., compose a card to yourself using those elements, select matching colors, hit preview and copy the code for appropriate variables from the generated page source.
Experience shows that featuring a few of these "quick cards" on your entrance page seriously encourages return visits of newbies who are clueless about the posty in particular and the web usage in general.
There are two ways to use the send later option on your cards. If you use only one composition page and not the step-by-step mode then the code for send-later is as follows:
<SELECT name="later"> <OPTION value="now" SELECTED>Right Now <!--#include virtual="/platinum/later.txt"--> </SELECT>
If you use step-by-step composition mode you don't need the above code or later.txt at all. Simply put something like this into any of the templates in a sequence :
When to send it? <!--@latercode-->
And that's all!
The actual dates are generated automatically. The number of days is defined
in the global configuration file magics.cfg as DAYS
parameter. Unless you really do know what you are doing we strongly advise
you against setting this parameter to anything greater than 60.
Refer to administration section of this manual for details.
To enable the option to send the message to many recipients (up to 25) use the variable "multi". When set to "yes" it triggers this option, when not set or set to "no" - it disables it.
The page where the sender can enter multiple addresses is generated by
the template which is referenced in the custom configuration file with parameter
MULTI. If not set, then the default "multi.html"
shows (stored as all HTML templates in $INC_DIR directory).
However you can define different templates for different configs - for example
for bilingual cardshops.
When a card is sent to multiple recipients the pickup notices are e-mailed to the sender when all individual recipients pick it up, not just the one. There is no way an individual recipient could know it was not sent to him only.
Although most senders prefer to be informed when the recipient picks up the card, you may want to allow the ability to disable this e-mail notice to be sent. The variable that turns off the pickup notice is "nopick". When its value is "yes" the pickup notice is not sent. When it is not set pickup notice is sent.
If you wish to disable the pickup notice on a sitewide scale - add "nopick" with value "yes" as a hidden field to your composition pages.
The ability to send an archive copy of a card to the sender is a widely requested and used feature, however it nevertheless creates lots of really silly questions from users. Expect to get the panic mails like "Why I am getting a card I sent to someone else?" You may be able to reduce those questions, if you word the instructions very carefully and explain clearly what they are selecting BEFORE they click "send".
The variable that turns this feature on, is "yourself". When its value is "yes" the email with pickup notice is sent to the sender as well. Both the sender and the recipient of this email notice are the same person (and indeed they are!).
However the card number differs from the one the real recipient gets and the pickup notice will not be sent when the "archive copy" of a card is picked up by the sender.
My Postcards Platinum ver. 5 provides a lot of features for advanced card customization. However we do not recommend that you start using any of the features described below, before you have a full-functioning cardshop and a good idea about the overall program performance.
The Platinum Web Application version 5 allows alternate cardshop layouts - multiple sets of HTML and email templates. Typically these alternate layouts are used either for different card categories (e.g. special holiday or topic theme) or to create a version of the same cardshop in a different language.
Important! Before starting to work on your first alternate cardshop layout make sure you have already read the sections of this manual about custom configuration files and templates.
Follow these steps to create a sample of an alternate layout:
$INC_DIR/conf/ and open with a text editor.
You will see the following:
PRE_PAGE|preview.html REC_PAGE|receive.html SEN_PAGE|sent.html CARD_MAIL|mail1.txt PICK_MAIL|mail2.txt
PRE_PAGE|previewA.html REC_PAGE|receiveA.html SEN_PAGE|sentA.html CARD_MAIL|mail1A.txt PICK_MAIL|mail2A.txt
$INC_DIR/conf/ using ASCII ftp transfer
mode $INC_DIR/html/:
preview.html, receive.html,
sent.html. $INC_DIR/html/ (ftp transfer mode does
not matter) $INC_DIR/mail/:
mail1.txt, mail2.txt. $INC_DIR/mail/ using ASCII ftp transfer
mode $ROOT_DIR <form > these tags </form>:
<input type="hidden" name="config" value="magicA">
$ROOT_DIR (or to any other directory!)
You can make different layouts or languages selectable by your visitors too: Use the following code for example
<select name="select"> <option value="magic"> English <option value="magicA"> Spanish <option value="magicB"> French </select>
The purpose of this feature still baffles the creators of this software, but we had to surrender to popular demand (yes, it IS a very popular feature at many cardshops).
The idea behind this is simple: you create a normal HTML page with
a ready-made greeting (or ready-made anything), place a "send it" button
to the bottom and let people "send this page to a friend" (yes, it can
be used for standard referrals too). After pressing "send it" people
are taken to the next page ($INC_DIR/html/email.html in
demo cardshop) where they enter email addresses.
The only peculiarity in form values usage for ICQ cards is that the
"filename" element should contain the FULL URL of this ICQ card page.
This page should have extension *.html (NOT *.htm,
NOT *.shtml).
This page will be "sent" just like a normal card and "picked up" with a card number. Pickup fact will be reflected in stats. You will see this page's popularity in "pictures usage stats".
You can separate the process of card composition (and viewing by the recipient) into any number of steps. However we do not recommend designing such a process until you are very familiar with the overall program functioning.
The composition sequence starts with the usual HTML page (like "card-custom.shtml"
in the sample cardshop) and continues with HTML templates stored in
$INC_DIR/html. The names of such templates are not predefined
you can use any. The sample sequence templates can be recognized by
"birthday" prefix in filenames.
First HTML page of the sequence (like "card-custom.shtml") should include the following variables:
<input name="pa" type="hidden" value="preview"> <input name="config" type="hidden" value="specific_configname"> <input name="next" type="hidden" value="custom"> <input name="page" type="hidden" value="step2_template_name.html">
Where "specific_configname" and "step2_template_name.html" should be replaced with real values.
All the following templates EXCEPT the last one (e.g. "birthday-address.html" in the sample) should include the following lines:
<input name="next" type="hidden" value="custom"> <input name="page" type="hidden" value="stepX_template_name.html">
Where "stepX_template_name.html" should be replaced with real values - different values for different pages!
You can use any variables on sequence templates. However better leave the address part to be the last step as in the sample.
To design a step-by step sequence for received cards follow the same technique. Use variables "next" = "custom" and "page" = "next_step_template_name.html".
In addition to program variables with "predefined" functions you can use up to 10 custom variables for any purpose. Variables are named field1 thru field10 and can be used in any order. Submitted values of those variables are passed to the program as is.
There are no restrictions or guidelines for custom variables - your
imagination is the limit. For example you may want to allow visitors
to add a custom joke to their cards. To the card composition page you
put something like: <input type=text name=field1>
and to the preview and receive templates: A custom joke from:
<!--@SENDER-->: "<!--@field1-->"
You can use custom fields in email templates as well.
Platinum 5 software includes the ability to allow uploading of files to use with cards. Typically this feature is used for uploading personal pictures, however the type of files is not restricted.
All uploaded files will inherit default umask settings
of your server, e.g. most likely will have permissions 644 and therefore
could not constitute any security risk to your server. The only security
concern could be related to uploading too many files and using too much
disk space, but in practice we have never encountered such situations.
the upload feature is not really popular on the sites where it is used.
The logic behind this, as we see it, is simple - most people who are
able to scan and upload pictures do have their own websites already.
To use the upload feature, refer to the appropriate sample cardshop page and notice the difference in <form> tag attributes. The "enctype" attribute triggers the upload capability. If the attribute is not used upload will not occur.
The directory where the files are uploaded is specified with "u_dir"
variable. This is the path to a directory, not a URL. The path is formed
as relative to main program location. If your magiccard.cgi
is in cgi-bin then you will have to provide a symlink to
this dir. the Upload storage directory must be web-visible and have
write permissions for the user the program runs from. If you do not
understand the above - simply do not change the default value provided
in the sample page!
The variable "page" specifies the next page to show
after the upload is completed. The value of this variable can be either
full or relative URL (e.g. "http://domain.com/dir/page.html"
or "/dir/page.html").
The variables "next" and "pa" should be used exactly as on the sample page in order for the software to function properly.
The size of uploaded files can be restricted during the Platinum installation. If you need this - please contact us.
With a few exceptions noted below you can translate any parts of your cardshop into any language. You can offer multilingual cardshops as well.
To add a second language to your cardshop you have to create an additional custom config file and a set of HTML and e-mail templates translated into that language.
Common error! When translating the text of email templates to languages other than English DO NOT TRANSLATE headers -To:From:Reply-to:Subject:. It won't work. Translating the NAMES of form variables will not work either! (You can edit the values)
There are a few words generated by the program which cannot be altered
with templates. Those are the words "Now" and "Today"
in relation to card delivery schedule. Words appear on the preview pages
and card sent confirmation page. Also on the card confirmation page
the phrase "your recipients" appears in place of the recipient
placeholder in case of the multisend. By default all
those words are printed in English. However we have added automated
translation into some of the most popular languages. In order to have
those words translated you have to add a parameter to your custom config
file:
LANG|SP
Files which cannot exist in multiple versions are the error messages
stored in $INC_DIR/errors directory. If you want to have
a multilingual cardshop you will have to place texts in all languages
into each of those templates.
Files Edit_Email.html and Edit_Email_Multi.html
can have multi-language versions too. For example for the Chinese version
you should create two files CN_Edit_Email.html and CN_Email_Multi.html
and upload to the $INC_DIR/errors directory (since build
5.10 only).
This section covers the issues related to Platinum software functioning, but not controlled by the program itself.
Platinum software can function without the server side includes (SSI) enabled in your webserver software (read more). However the use of SSI facilitates your website design and maintenance greatly and we include a few SSI tricks into the card composition pages included in the distribution. SSI is not enabled in Platinum HTML templates in present version of software.
SSI is supported in all popular UNIX webserver software, including Apache, Netscape Enterprise server (now IPlanet), etc. Our experience shows that Solaris-based webhosts usually turn on SSI support by default, BSD-based webhosts usually don't unless asked specifically, LINUX servers vary in this respect. At Webby we support SSI by default, and we always encourage our hosting clients to learn and use this handy feature.
The usual webhosts's excuse for not turning on SSI is "security considerations". Dated back to the stone age of WWW this fear was once seriously exaggerated by those who did not want to learn SSI, but has no realistic basis nowadays. Modern versions of Apache and OS patches handle all possible security violations gracefully. Some paranoid setups may involve disabling EXEC directive. Platinum sample cardshop does not use the EXEC directive, only INCLUDE and ECHO.
The creators of the Platinum are running and hosting many VERY high traffic sites for many years and never encountered any security / load problems related to SSI.
You won't be able to use the send later feature in all card composition samples in the default distribution with the only exception of step-by-step card composition. You won't be able to use "Quick Cards" (with preselected elements). Enabling SSI fixes all those issues ASAP. To learn how to enable SSI refer to Apache Mod_Include docs.
If you still do not want or cannot use SSI for some reason, then use java-script to pass variables between pages for quick cards (with preselected elements). Another portion of java-script code can handle dates selection for send-later function. If you cannot write this code yourself - you can order it from us as custom work (cost is not covered by Platinum license purchase). However enabling SSI is a cheaper and better solution!